]> Pileus Git - ~andy/linux/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Mon, 12 Sep 2005 22:55:33 +0000 (15:55 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 12 Sep 2005 22:55:33 +0000 (15:55 -0700)
244 files changed:
Documentation/aoe/mkshelf.sh
Documentation/connector/cn_test.c [new file with mode: 0644]
Documentation/connector/connector.txt [new file with mode: 0644]
Documentation/fb/intel810.txt
Documentation/firmware_class/firmware_sample_driver.c
Documentation/input/appletouch.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/usb/proc_usb_info.txt
Documentation/x86_64/boot-options.txt
MAINTAINERS
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/entry.S
arch/i386/kernel/io_apic.c
arch/i386/kernel/setup.c
arch/i386/kernel/srat.c
arch/i386/pci/acpi.c
arch/i386/pci/mmconfig.c
arch/ia64/ia32/sys_ia32.c
arch/m68knommu/platform/68360/head-ram.S [new file with mode: 0644]
arch/m68knommu/platform/68360/head-rom.S [new file with mode: 0644]
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/maple_pci.c
arch/ppc64/kernel/pSeries_setup.c
arch/ppc64/kernel/pSeries_smp.c
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pmac_pci.c
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/ptrace.c
arch/ppc64/kernel/ptrace32.c
arch/ppc64/kernel/ras.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal32.c
arch/ppc64/kernel/xics.c
arch/ppc64/mm/fault.c
arch/ppc64/xmon/privinst.h
arch/ppc64/xmon/xmon.c
arch/s390/kernel/compat_linux.c
arch/x86_64/boot/Makefile
arch/x86_64/boot/compressed/misc.c
arch/x86_64/defconfig
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/acpi/sleep.c
arch/x86_64/kernel/aperture.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/asm-offsets.c
arch/x86_64/kernel/crash.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/genapic.c
arch/x86_64/kernel/genapic_cluster.c
arch/x86_64/kernel/genapic_flat.c
arch/x86_64/kernel/head.S
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/init_task.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/irq.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/msr.c [deleted file]
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/suspend.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vsyscall.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/srat.c
arch/x86_64/pci/k8-bus.c
arch/x86_64/pci/mmconfig.c
drivers/Kconfig
drivers/Makefile
drivers/block/aoe/aoe.h
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Makefile
drivers/char/watchdog/mpcore_wdt.c [new file with mode: 0644]
drivers/connector/Kconfig [new file with mode: 0644]
drivers/connector/Makefile [new file with mode: 0644]
drivers/connector/cn_queue.c [new file with mode: 0644]
drivers/connector/connector.c [new file with mode: 0644]
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/hdaps.c [new file with mode: 0644]
drivers/hwmon/sis5595.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/via686a.c
drivers/hwmon/w83627hf.c
drivers/i2c/busses/i2c-nforce2.c
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
drivers/mtd/maps/uclinux.c
drivers/net/Kconfig
drivers/net/bnx2.c
drivers/net/fec.c
drivers/net/fec.h
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/tg3.c
drivers/serial/mcfserial.c
drivers/usb/class/audio.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/gadget/inode.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci.h
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci.h
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-q.c
drivers/usb/input/Kconfig
drivers/usb/input/Makefile
drivers/usb/input/appletouch.c [new file with mode: 0644]
drivers/usb/input/hid-core.c
drivers/usb/misc/sisusbvga/Kconfig
drivers/usb/misc/sisusbvga/Makefile
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb.h
drivers/usb/misc/sisusbvga/sisusb_con.c [new file with mode: 0644]
drivers/usb/misc/sisusbvga/sisusb_init.c [new file with mode: 0644]
drivers/usb/misc/sisusbvga/sisusb_init.h [new file with mode: 0644]
drivers/usb/misc/sisusbvga/sisusb_struct.h [new file with mode: 0644]
drivers/usb/misc/uss720.c
drivers/usb/mon/mon_text.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/video/console/Kconfig
drivers/video/console/Makefile
drivers/video/i810/i810_main.c
drivers/w1/w1_ds2433.c
fs/ntfs/ChangeLog
fs/ntfs/malloc.h
fs/ntfs/super.c
include/asm-generic/tlb.h
include/asm-i386/apic.h
include/asm-i386/numa.h [new file with mode: 0644]
include/asm-i386/topology.h
include/asm-i386/unistd.h
include/asm-m68knommu/bitops.h
include/asm-m68knommu/checksum.h
include/asm-m68knommu/m527xsim.h
include/asm-m68knommu/m528xsim.h
include/asm-m68knommu/mcfcache.h
include/asm-m68knommu/mcfdma.h
include/asm-powerpc/siginfo.h
include/asm-ppc/ptrace.h
include/asm-ppc64/hvcall.h
include/asm-ppc64/machdep.h
include/asm-ppc64/pci-bridge.h
include/asm-ppc64/plpar_wrappers.h
include/asm-ppc64/processor.h
include/asm-ppc64/ptrace-common.h
include/asm-ppc64/ptrace.h
include/asm-ppc64/system.h
include/asm-x86_64/apic.h
include/asm-x86_64/apicdef.h
include/asm-x86_64/bug.h
include/asm-x86_64/calling.h
include/asm-x86_64/desc.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/dwarf2.h
include/asm-x86_64/fixmap.h
include/asm-x86_64/hardirq.h
include/asm-x86_64/hw_irq.h
include/asm-x86_64/io.h
include/asm-x86_64/ipi.h
include/asm-x86_64/kdebug.h
include/asm-x86_64/local.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/msr.h
include/asm-x86_64/numa.h
include/asm-x86_64/page.h
include/asm-x86_64/pci.h
include/asm-x86_64/pda.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor.h
include/asm-x86_64/proto.h
include/asm-x86_64/signal.h
include/asm-x86_64/smp.h
include/asm-x86_64/system.h
include/asm-x86_64/timex.h
include/asm-x86_64/tlbflush.h
include/asm-x86_64/topology.h
include/asm-x86_64/vsyscall.h
include/linux/connector.h [new file with mode: 0644]
include/linux/crc16.h
include/linux/dmi.h
include/linux/interrupt.h
include/linux/netlink.h
include/linux/sched.h
include/linux/sysctl.h
include/linux/usbdevice_fs.h
include/net/ax25.h
include/net/netrom.h
kernel/cpuset.c
kernel/sched.c
kernel/softirq.c
lib/Kconfig.debug
mm/bootmem.c
mm/nommu.c
net/ax25/af_ax25.c
net/ax25/ax25_ip.c
net/core/pktgen.c
net/dccp/ccids/ccid3.c
net/ipv4/ipconfig.c
net/irda/ircomm/ircomm_tty.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_subr.c
net/netrom/sysctl_net_netrom.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/sunrpc/svcsock.c

index 8bacf9f2c7cc971ef25aefb445f550815bb4fdf3..32615814271cce1f90e6be56d5a26eb15c12de3d 100644 (file)
@@ -8,13 +8,15 @@ fi
 n_partitions=${n_partitions:-16}
 dir=$1
 shelf=$2
+nslots=16
+maxslot=`echo $nslots 1 - p | dc`
 MAJOR=152
 
 set -e
 
-minor=`echo 10 \* $shelf \* $n_partitions | bc`
+minor=`echo $nslots \* $shelf \* $n_partitions | bc`
 endp=`echo $n_partitions - 1 | bc`
-for slot in `seq 0 9`; do
+for slot in `seq 0 $maxslot`; do
        for part in `seq 0 $endp`; do
                name=e$shelf.$slot
                test "$part" != "0" && name=${name}p$part
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
new file mode 100644 (file)
index 0000000..b7de82e
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *     cn_test.c
+ * 
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+
+#include "connector.h"
+
+static struct cb_id cn_test_id = { 0x123, 0x456 };
+static char cn_test_name[] = "cn_test";
+static struct sock *nls;
+static struct timer_list cn_test_timer;
+
+void cn_test_callback(void *data)
+{
+       struct cn_msg *msg = (struct cn_msg *)data;
+
+       printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
+              __func__, jiffies, msg->id.idx, msg->id.val,
+              msg->seq, msg->ack, msg->len, (char *)msg->data);
+}
+
+static int cn_test_want_notify(void)
+{
+       struct cn_ctl_msg *ctl;
+       struct cn_notify_req *req;
+       struct cn_msg *msg = NULL;
+       int size, size0;
+       struct sk_buff *skb;
+       struct nlmsghdr *nlh;
+       u32 group = 1;
+
+       size0 = sizeof(*msg) + sizeof(*ctl) + 3 * sizeof(*req);
+
+       size = NLMSG_SPACE(size0);
+
+       skb = alloc_skb(size, GFP_ATOMIC);
+       if (!skb) {
+               printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",
+                      size);
+
+               return -ENOMEM;
+       }
+
+       nlh = NLMSG_PUT(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh));
+
+       msg = (struct cn_msg *)NLMSG_DATA(nlh);
+
+       memset(msg, 0, size0);
+
+       msg->id.idx = -1;
+       msg->id.val = -1;
+       msg->seq = 0x123;
+       msg->ack = 0x345;
+       msg->len = size0 - sizeof(*msg);
+
+       ctl = (struct cn_ctl_msg *)(msg + 1);
+
+       ctl->idx_notify_num = 1;
+       ctl->val_notify_num = 2;
+       ctl->group = group;
+       ctl->len = msg->len - sizeof(*ctl);
+
+       req = (struct cn_notify_req *)(ctl + 1);
+
+       /*
+        * Idx.
+        */
+       req->first = cn_test_id.idx;
+       req->range = 10;
+
+       /*
+        * Val 0.
+        */
+       req++;
+       req->first = cn_test_id.val;
+       req->range = 10;
+
+       /*
+        * Val 1.
+        */
+       req++;
+       req->first = cn_test_id.val + 20;
+       req->range = 10;
+
+       NETLINK_CB(skb).dst_groups = ctl->group;
+       //netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
+       netlink_unicast(nls, skb, 0, 0);
+
+       printk(KERN_INFO "Request was sent. Group=0x%x.\n", ctl->group);
+
+       return 0;
+
+nlmsg_failure:
+       printk(KERN_ERR "Failed to send %u.%u\n", msg->seq, msg->ack);
+       kfree_skb(skb);
+       return -EINVAL;
+}
+
+static u32 cn_test_timer_counter;
+static void cn_test_timer_func(unsigned long __data)
+{
+       struct cn_msg *m;
+       char data[32];
+
+       m = kmalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
+       if (m) {
+               memset(m, 0, sizeof(*m) + sizeof(data));
+
+               memcpy(&m->id, &cn_test_id, sizeof(m->id));
+               m->seq = cn_test_timer_counter;
+               m->len = sizeof(data);
+
+               m->len =
+                   scnprintf(data, sizeof(data), "counter = %u",
+                             cn_test_timer_counter) + 1;
+
+               memcpy(m + 1, data, m->len);
+
+               cn_netlink_send(m, 0, gfp_any());
+               kfree(m);
+       }
+
+       cn_test_timer_counter++;
+
+       mod_timer(&cn_test_timer, jiffies + HZ);
+}
+
+static int cn_test_init(void)
+{
+       int err;
+
+       err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
+       if (err)
+               goto err_out;
+       cn_test_id.val++;
+       err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
+       if (err) {
+               cn_del_callback(&cn_test_id);
+               goto err_out;
+       }
+
+       init_timer(&cn_test_timer);
+       cn_test_timer.function = cn_test_timer_func;
+       cn_test_timer.expires = jiffies + HZ;
+       cn_test_timer.data = 0;
+       add_timer(&cn_test_timer);
+
+       return 0;
+
+      err_out:
+       if (nls && nls->sk_socket)
+               sock_release(nls->sk_socket);
+
+       return err;
+}
+
+static void cn_test_fini(void)
+{
+       del_timer_sync(&cn_test_timer);
+       cn_del_callback(&cn_test_id);
+       cn_test_id.val--;
+       cn_del_callback(&cn_test_id);
+       if (nls && nls->sk_socket)
+               sock_release(nls->sk_socket);
+}
+
+module_init(cn_test_init);
+module_exit(cn_test_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Connector's test module");
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
new file mode 100644 (file)
index 0000000..54a0a14
--- /dev/null
@@ -0,0 +1,133 @@
+/*****************************************/
+Kernel Connector.
+/*****************************************/
+
+Kernel connector - new netlink based userspace <-> kernel space easy
+to use communication module.
+
+Connector driver adds possibility to connect various agents using
+netlink based network.  One must register callback and
+identifier. When driver receives special netlink message with
+appropriate identifier, appropriate callback will be called.
+
+From the userspace point of view it's quite straightforward:
+
+       socket();
+       bind();
+       send();
+       recv();
+
+But if kernelspace want to use full power of such connections, driver
+writer must create special sockets, must know about struct sk_buff
+handling...  Connector allows any kernelspace agents to use netlink
+based networking for inter-process communication in a significantly
+easier way:
+
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
+void cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask);
+
+struct cb_id
+{
+       __u32                   idx;
+       __u32                   val;
+};
+
+idx and val are unique identifiers which must be registered in
+connector.h for in-kernel usage.  void (*callback) (void *) - is a
+callback function which will be called when message with above idx.val
+will be received by connector core.  Argument for that function must
+be dereferenced to struct cn_msg *.
+
+struct cn_msg
+{
+       struct cb_id            id;
+
+       __u32                   seq;
+       __u32                   ack;
+
+       __u32                   len;            /* Length of the following data */
+       __u8                    data[0];
+};
+
+/*****************************************/
+Connector interfaces.
+/*****************************************/
+
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
+
+Registers new callback with connector core.
+
+struct cb_id *id               - unique connector's user identifier.
+                                 It must be registered in connector.h for legal in-kernel users.
+char *name                     - connector's callback symbolic name.
+void (*callback) (void *)      - connector's callback.
+                                 Argument must be dereferenced to struct cn_msg *.
+
+void cn_del_callback(struct cb_id *id);
+
+Unregisters new callback with connector core.
+
+struct cb_id *id               - unique connector's user identifier.
+
+void cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
+
+Sends message to the specified groups.  It can be safely called from
+any context, but may silently fail under strong memory pressure.
+
+struct cn_msg *                        - message header(with attached data).
+u32 __group                    - destination group.
+                                 If __group is zero, then appropriate group will
+                                 be searched through all registered connector users,
+                                 and message will be delivered to the group which was
+                                 created for user with the same ID as in msg.
+                                 If __group is not zero, then message will be delivered
+                                 to the specified group.
+int gfp_mask                   - GFP mask.
+
+Note: When registering new callback user, connector core assigns
+netlink group to the user which is equal to it's id.idx.
+
+/*****************************************/
+Protocol description.
+/*****************************************/
+
+Current offers transport layer with fixed header.  Recommended
+protocol which uses such header is following:
+
+msg->seq and msg->ack are used to determine message genealogy.  When
+someone sends message it puts there locally unique sequence and random
+acknowledge numbers.  Sequence number may be copied into
+nlmsghdr->nlmsg_seq too.
+
+Sequence number is incremented with each message to be sent.
+
+If we expect reply to our message, then sequence number in received
+message MUST be the same as in original message, and acknowledge
+number MUST be the same + 1.
+
+If we receive message and it's sequence number is not equal to one we
+are expecting, then it is new message.  If we receive message and it's
+sequence number is the same as one we are expecting, but it's
+acknowledge is not equal acknowledge number in original message + 1,
+then it is new message.
+
+Obviously, protocol header contains above id.
+
+connector allows event notification in the following form: kernel
+driver or userspace process can ask connector to notify it when
+selected id's will be turned on or off(registered or unregistered it's
+callback). It is done by sending special command to connector
+driver(it also registers itself with id={-1, -1}).
+
+As example of usage Documentation/connector now contains cn_test.c -
+testing module which uses connector to request notification and to
+send messages.
+
+/*****************************************/
+Reliability.
+/*****************************************/
+
+Netlink itself is not reliable protocol, that means that messages can
+be lost due to memory pressure or process' receiving queue overflowed,
+so caller is warned must be prepared. That is why struct cn_msg [main
+connector's message header] contains u32 seq and u32 ack fields.
index fd68b162e4a13ce7cbf028405a14724224542e1f..4f0d6bc789ef0fadf101eaa362fa3d829dc8a588 100644 (file)
@@ -5,6 +5,7 @@ Intel 810/815 Framebuffer driver
        March 17, 2002
 
        First Released: July 2001
+       Last Update:    September 12, 2005
 ================================================================
 
 A. Introduction
@@ -44,6 +45,8 @@ B.  Features
 
        - Hardware Cursor Support
  
+       - Supports EDID probing either by DDC/I2C or through the BIOS
+
 C.  List of available options
        
    a. "video=i810fb"  
@@ -52,14 +55,17 @@ C.  List of available options
        Recommendation: required
  
    b. "xres:<value>"  
-       select horizontal resolution in pixels
+       select horizontal resolution in pixels. (This parameter will be
+       ignored if 'mode_option' is specified.  See 'o' below).
 
        Recommendation: user preference 
        (default = 640)
 
    c. "yres:<value>"
        select vertical resolution in scanlines. If Discrete Video Timings
-       is enabled, this will be ignored and computed as 3*xres/4.  
+       is enabled, this will be ignored and computed as 3*xres/4.  (This
+       parameter will be ignored if 'mode_option' is specified.  See 'o'
+       below)  
 
        Recommendation: user preference
        (default = 480)
@@ -86,7 +92,8 @@ C.  List of available options
    g. "hsync1/hsync2:<value>" 
        select the minimum and maximum Horizontal Sync Frequency of the 
        monitor in KHz.  If a using a fixed frequency monitor, hsync1 must 
-       be equal to hsync2. 
+       be equal to hsync2. If EDID probing is successful, these will be
+       ignored and values will be taken from the EDID block.
 
        Recommendation: check monitor manual for correct values
        default (29/30)
@@ -94,7 +101,8 @@ C.  List of available options
    h. "vsync1/vsync2:<value>" 
        select the minimum and maximum Vertical Sync Frequency of the monitor
        in Hz. You can also use this option to lock your monitor's refresh 
-       rate.
+       rate. If EDID probing is successful, these will be ignored and values
+       will be taken from the EDID block.
 
        Recommendation: check monitor manual for correct values
        (default = 60/60)
@@ -154,7 +162,11 @@ C.  List of available options
 
        Recommendation: do not set
        (default = not set)
-                       
+   o. <xres>x<yres>[-<bpp>][@<refresh>]
+       The driver will now accept specification of boot mode option.  If this
+       is specified, the options 'xres' and 'yres' will be ignored. See
+       Documentation/fb/modedb.txt for usage.
+
 D. Kernel booting
 
 Separate each option/option-pair by commas (,) and the option from its value
@@ -176,7 +188,10 @@ will be computed based on the hsync1/hsync2 and vsync1/vsync2 values.
 
 IMPORTANT:
 You must include hsync1, hsync2, vsync1 and vsync2 to enable video modes
-better than 640x480 at 60Hz.
+better than 640x480 at 60Hz. HOWEVER, if your chipset/display combination
+supports I2C and has an EDID block, you can safely exclude hsync1, hsync2,
+vsync1 and vsync2 parameters.  These parameters will be taken from the EDID
+block.
 
 E.  Module options
        
@@ -217,32 +232,21 @@ F.  Setup
           This is required.  The option is under "Character Devices"
 
        d. Under "Graphics Support", select "Intel 810/815" either statically
-          or as a module.  Choose "use VESA GTF for video timings"  if you 
-          need to maximize the capability of your display.  To be on the 
+          or as a module.  Choose "use VESA Generalized Timing Formula" if
+          you need to maximize the capability of your display.  To be on the 
           safe side, you can leave this unselected.  
   
-        e. If you want a framebuffer console, enable it under "Console 
+       e. If you want support for DDC/I2C probing (Plug and Play Displays),
+          set 'Enable DDC Support' to 'y'. To make this option appear, set
+          'use VESA Generalized Timing Formula' to 'y'.
+
+        f. If you want a framebuffer console, enable it under "Console 
           Drivers"
 
-       f. Compile your kernel. 
+       g. Compile your kernel. 
                
-       g. Load the driver as described in section D and E.
+       h. Load the driver as described in section D and E.
        
-       Optional:       
-       h.  If you are going to run XFree86 with its native drivers, the 
-           standard XFree86 4.1.0 and 4.2.0 drivers should work as is.
-            However, there's a bug in the XFree86 i810 drivers.  It attempts 
-           to use XAA even when switched to the console. This will crash
-           your server. I have a fix at this site:  
-           
-           http://i810fb.sourceforge.net.  
-
-           You can either use the patch, or just replace 
-           
-            /usr/X11R6/lib/modules/drivers/i810_drv.o
-
-           with the one provided at the website.       
-
        i.  Try the DirectFB (http://www.directfb.org) + the i810 gfxdriver
            patch to see the chipset in action (or inaction :-).
 
index e1c56a7e6583dce3b9212d0702a75d9b628c81a4..4bef8c25172c8e472b09f068e0a34e2e5e8b08ee 100644 (file)
@@ -32,14 +32,14 @@ static void sample_firmware_load(char *firmware, int size)
        u8 buf[size+1];
        memcpy(buf, firmware, size);
        buf[size] = '\0';
-       printk("firmware_sample_driver: firmware: %s\n", buf);
+       printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
 }
 
 static void sample_probe_default(void)
 {
        /* uses the default method to get the firmware */
         const struct firmware *fw_entry;
-       printk("firmware_sample_driver: a ghost device got inserted :)\n");
+       printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
 
         if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0)
        {
@@ -61,7 +61,7 @@ static void sample_probe_specific(void)
 
        /* NOTE: This currently doesn't work */
 
-       printk("firmware_sample_driver: a ghost device got inserted :)\n");
+       printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
 
         if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0)
        {
@@ -83,7 +83,7 @@ static void sample_probe_async_cont(const struct firmware *fw, void *context)
                return;
        }
 
-       printk("firmware_sample_driver: device pointer \"%s\"\n",
+       printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
               (char *)context);
        sample_firmware_load(fw->data, fw->size);
 }
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
new file mode 100644 (file)
index 0000000..b48d11d
--- /dev/null
@@ -0,0 +1,84 @@
+Apple Touchpad Driver (appletouch)
+----------------------------------
+       Copyright (C) 2005 Stelian Pop <stelian@popies.net>
+
+appletouch is a Linux kernel driver for the USB touchpad found on post
+February 2005 Apple Alu Powerbooks.
+
+This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
+been improved in some areas:
+       * appletouch is a full kernel driver, no userspace program is necessary
+       * appletouch can be interfaced with the synaptics X11 driver, in order
+         to have touchpad acceleration, scrolling, etc.
+
+Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
+Frank Arnold for further improvements, and Alex Harper for some additional
+information about the inner workings of the touchpad sensors.
+
+Usage:
+------
+
+In order to use the touchpad in the basic mode, compile the driver and load
+the module. A new input device will be detected and you will be able to read
+the mouse data from /dev/input/mice (using gpm, or X11).
+
+In X11, you can configure the touchpad to use the synaptics X11 driver, which
+will give additional functionalities, like acceleration, scrolling, 2 finger
+tap for middle button mouse emulation, 3 finger tap for right button mouse
+emulation, etc. In order to do this, make sure you're using a recent version of
+the synaptics driver (tested with 0.14.2, available from [2]), and configure a
+new input device in your X11 configuration file (take a look below for an
+example). For additional configuration, see the synaptics driver documentation.
+
+       Section "InputDevice"
+               Identifier      "Synaptics Touchpad"
+               Driver          "synaptics"
+               Option          "SendCoreEvents"        "true"
+               Option          "Device"                "/dev/input/mice"
+               Option          "Protocol"              "auto-dev"
+               Option          "LeftEdge"              "0"
+               Option          "RightEdge"             "850"
+               Option          "TopEdge"               "0"
+               Option          "BottomEdge"            "645"
+               Option          "MinSpeed"              "0.4"
+               Option          "MaxSpeed"              "1"
+               Option          "AccelFactor"           "0.02"
+               Option          "FingerLow"             "0"
+               Option          "FingerHigh"            "30"
+               Option          "MaxTapMove"            "20"
+               Option          "MaxTapTime"            "100"
+               Option          "HorizScrollDelta"      "0"
+               Option          "VertScrollDelta"       "30"
+               Option          "SHMConfig"             "on"
+       EndSection
+
+       Section "ServerLayout"
+               ...
+               InputDevice     "Mouse"
+               InputDevice     "Synaptics Touchpad"
+       ...
+       EndSection
+
+Fuzz problems:
+--------------
+
+The touchpad sensors are very sensitive to heat, and will generate a lot of
+noise when the temperature changes. This is especially true when you power-on
+the laptop for the first time.
+
+The appletouch driver tries to handle this noise and auto adapt itself, but it
+is not perfect. If finger movements are not recognized anymore, try reloading
+the driver.
+
+You can activate debugging using the 'debug' module parameter. A value of 0
+deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
+full tracing (each sample is being traced):
+       modprobe appletouch debug=1
+               or
+       echo "1" > /sys/module/appletouch/parameters/debug
+
+Links:
+------
+
+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
+[2]: http://web.telia.com/~u89404340/touchpad/index.html
index db2603ceabba6f6743438a4e74d458865ba504bb..7086f0a90d14a47d6ba3295e624a7bda414062a9 100644 (file)
@@ -164,6 +164,15 @@ running once the system is up.
                        over-ride platform specific driver.
                        See also Documentation/acpi-hotkey.txt.
 
+       enable_timer_pin_1 [i386,x86-64]
+                       Enable PIN 1 of APIC timer
+                       Can be useful to work around chipset bugs (in particular on some ATI chipsets)
+                       The kernel tries to set a reasonable default.
+
+       disable_timer_pin_1 [i386,x86-64]
+                       Disable PIN 1 of APIC timer
+                       Can be useful to work around chipset bugs.
+
        ad1816=         [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma2>
                        See also Documentation/sound/oss/AD1816.
index 729c72d34c89237912a3bb5dc501405dfeff0384..f86550fe38ee21afc0381a991ac4e58b07426f57 100644 (file)
@@ -20,7 +20,7 @@ the /proc/bus/usb/BBB/DDD files.
 
          to /etc/fstab.  This will mount usbfs at each reboot.
          You can then issue `cat /proc/bus/usb/devices` to extract
-         USB device information, and user mode drivers can use usbfs 
+         USB device information, and user mode drivers can use usbfs
          to interact with USB devices.
 
          There are a number of mount options supported by usbfs.
@@ -32,7 +32,7 @@ the /proc/bus/usb/BBB/DDD files.
          still see references to the older "usbdevfs" name.
 
 For more information on mounting the usbfs file system, see the
-"USB Device Filesystem" section of the USB Guide. The latest copy 
+"USB Device Filesystem" section of the USB Guide. The latest copy
 of the USB Guide can be found at http://www.linux-usb.org/
 
 
@@ -133,7 +133,7 @@ B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
     are the only transfers that reserve bandwidth.  Control and bulk
     transfers use all other bandwidth, including reserved bandwidth that
     is not used for transfers (such as for short packets).
-    
+
     The percentage is how much of the "reserved" bandwidth is scheduled by
     those transfers.  For a low or full speed bus (loosely, "USB 1.1"),
     90% of the bus bandwidth is reserved.  For a high speed bus (loosely,
@@ -197,7 +197,7 @@ C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
 | | |__NumberOfInterfaces
 | |__ "*" indicates the active configuration (others are " ")
 |__Config info tag
-    
+
     USB devices may have multiple configurations, each of which act
     rather differently.  For example, a bus-powered configuration
     might be much less capable than one that is self-powered.  Only
@@ -228,7 +228,7 @@ I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
     For example, default settings may not use more than a small
     amount of periodic bandwidth.  To use significant fractions
     of bus bandwidth, drivers must select a non-default altsetting.
-    
+
     Only one setting for an interface may be active at a time, and
     only one driver may bind to an interface at a time.  Most devices
     have only one alternate setting per interface.
@@ -297,18 +297,21 @@ S:  SerialNumber=dce0
 C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
+
 T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
+
 T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=04b4 ProdID=0001 Rev= 0.00
 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
+
 T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0565 ProdID=0001 Rev= 1.08
index 678e8f192db2917c741ca0b88ddc97f761a4a8d7..ffe1c062088b9daa52954b2dd6054975f52b9a7b 100644 (file)
@@ -11,6 +11,11 @@ Machine check
                If your BIOS doesn't do that it's a good idea to enable though
                to make sure you log even machine check events that result
                in a reboot.
+   mce=tolerancelevel (number)
+               0: always panic, 1: panic if deadlock possible,
+               2: try to avoid panic, 3: never panic or exit (for testing)
+               default is 1
+               Can be also set using sysfs which is preferable.
 
    nomce (for compatibility with i386): same as mce=off
 
index f038dca34ee826b543db0d54f40623e954e5bf72..a67bf7d315d7ee14923789fc66eb08649178f4ce 100644 (file)
@@ -964,6 +964,13 @@ L: lm-sensors@lm-sensors.org
 W:     http://www.lm-sensors.nu/
 S:     Maintained
 
+HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
+P:     Robert Love
+M:     rlove@rlove.org
+M:     linux-kernel@vger.kernel.org
+W:     http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
+S:     Maintained
+
 HARMONY SOUND DRIVER
 P:     Kyle McMartin
 M:     kyle@parisc-linux.org
index f1b9d2a46dab860c0cbf100e1bf6b9b0b220c024..1ae2aeeda18bddbbc23ec37702d2ed4878ee23d0 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
+#include <asm/apic.h>
 
 static int __init check_bridge(int vendor, int device)
 {
@@ -15,6 +16,15 @@ static int __init check_bridge(int vendor, int device)
        if (vendor == PCI_VENDOR_ID_NVIDIA) {
                acpi_skip_timer_override = 1;
        }
+#ifdef CONFIG_X86_LOCAL_APIC
+       /*
+        * ATI IXP chipsets get double timer interrupts.
+        * For now just do this for all ATI chipsets.
+        * FIXME: this needs to be checked for the non ACPI case too.
+        */
+       if (vendor == PCI_VENDOR_ID_ATI)
+               disable_timer_pin_1 = 1;
+#endif
        return 0;
 }
 
index 3aad03839660de38dd8c24361ecbd6814de5eb52..9e24f7b207ee1636eabcafc48f6f630b56ed8d3e 100644 (file)
@@ -319,7 +319,7 @@ work_notifysig:                             # deal with pending signals and
                                        # vm86-space
        xorl %edx, %edx
        call do_notify_resume
-       jmp restore_all
+       jmp resume_userspace
 
        ALIGN
 work_notifysig_v86:
@@ -329,7 +329,7 @@ work_notifysig_v86:
        movl %eax, %esp
        xorl %edx, %edx
        call do_notify_resume
-       jmp restore_all
+       jmp resume_userspace
 
        # perform syscall exit tracing
        ALIGN
index 35d3ce26a544aed8d45b3428444d0211c3593e3c..378313b0cce9ac9ba8de933303e5e432959cfa05 100644 (file)
@@ -60,6 +60,8 @@ int sis_apic_bug = -1;
  */
 int nr_ioapic_registers[MAX_IO_APICS];
 
+int disable_timer_pin_1 __initdata;
+
 /*
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
@@ -2211,6 +2213,8 @@ static inline void check_timer(void)
                                setup_nmi();
                                enable_8259A_irq(0);
                        }
+                       if (disable_timer_pin_1 > 0)
+                               clear_IO_APIC_pin(0, pin1);
                        return;
                }
                clear_IO_APIC_pin(0, pin1);
index f3d808451d253ecc08ae6ab30b68eba39f351e69..dc39ca6a7eca82f546c649cb6b2e1b3c6a20b4a2 100644 (file)
@@ -851,6 +851,11 @@ static void __init parse_cmdline_early (char ** cmdline_p)
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
+               if (!memcmp(from, "disable_timer_pin_1", 19))
+                       disable_timer_pin_1 = 1;
+               if (!memcmp(from, "enable_timer_pin_1", 18))
+                       disable_timer_pin_1 = -1;
+
                /* disable IO-APIC */
                else if (!memcmp(from, "noapic", 6))
                        disable_ioapic_setup();
index 7b3b27d64409381a9a557a58b6543feade5e6b9f..516bf5653b0266ea1f4beb9258bd6577c0b3e6ab 100644 (file)
@@ -213,12 +213,18 @@ static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_c
                node_end_pfn[nid] = memory_chunk->end_pfn;
 }
 
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+       return pxm_to_nid_map[pxm];
+}
+
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
        u8 *start, *end, *p;
        int i, j, nid;
-       u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
        u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
        start = (u8 *)(&(sratp->reserved) + 1); /* skip header */
index 42913f43feb0edca0015a1f2013c609cc361d802..2941674f35eb5aae272a3000edd491993ec1b0aa 100644 (file)
@@ -3,16 +3,31 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
+#include <asm/numa.h>
 #include "pci.h"
 
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 {
+       struct pci_bus *bus;
+
        if (domain != 0) {
                printk(KERN_WARNING "PCI: Multiple domains not supported\n");
                return NULL;
        }
 
-       return pcibios_scan_root(busnum);
+       bus = pcibios_scan_root(busnum);
+#ifdef CONFIG_ACPI_NUMA
+       if (bus != NULL) {
+               int pxm = acpi_get_pxm(device->handle);
+               if (pxm >= 0) {
+                       bus->sysdata = (void *)(unsigned long)pxm_to_node(pxm);
+                       printk("bus %d -> pxm %d -> node %ld\n",
+                               busnum, pxm, (long)(bus->sysdata));
+               }
+       }
+#endif
+       
+       return bus;
 }
 
 extern int pci_routeirq;
index 60f0e7a1162aafa3be94b2806384106dc1aee172..dfbf80cff8346af0504df3601e6e251becc7de06 100644 (file)
@@ -127,13 +127,6 @@ static int __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                goto out;
 
-       /* Kludge for now. Don't use mmconfig on AMD systems because
-          those have some busses where mmconfig doesn't work,
-          and we don't parse ACPI MCFG well enough to handle that. 
-          Remove when proper handling is added. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               goto out; 
-
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index e29a8a55486a5e35fdc8eac3a2bb0acefc5cb062..3fa67ecebc838043c99fab4589e9d334dbd31604 100644 (file)
@@ -2327,7 +2327,7 @@ sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count)
        ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
        set_fs(old_fs);
 
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
 
        return ret;
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
new file mode 100644 (file)
index 0000000..a5c639a
--- /dev/null
@@ -0,0 +1,408 @@
+/* arch/m68knommu/platform/68360/head-ram.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#define ASSEMBLY
+#include <linux/config.h>
+
+.global _stext
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000002
+#define SIM_BR0_MASK                0x00000001
+
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+       
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+       .text
+_start:
+_stext:
+       nop
+       ori.w   #MCU_DISABLE_INTRPTS, %sr       /* disable interrupts: */
+       /* We should not need to setup the boot stack the reset should do it. */
+       movea.l #__ramend, %sp                  /*set up stack at the end of DRAM:*/
+
+set_mbar_register:
+       moveq.l #0x07, %d1                      /* Setup MBAR */
+       movec   %d1, %dfc
+
+       lea.l   MCU_SIM_MBAR_ADRS, %a0
+       move.l  #_dprbase, %d0
+       andi.l  #MCU_SIM_MBAR_BA_MASK, %d0
+       ori.l   #MCU_SIM_MBAR_AS_MASK, %d0
+       moves.l %d0, %a0@
+
+       moveq.l #0x05, %d1
+       movec.l %d1, %dfc
+
+       /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+       /* Set Module Configuration Register */
+       move.l  #MCU_SIM_MCR, MCR
+
+       /* to do:       Determine cause of reset */
+
+       /*
+        *       configure system clock MC68360 p. 6-40
+        *       (value +1)*osc/128 = system clock
+        */
+set_sim_clock:
+       move.w  #MCU_SIM_PLLCR, PLLCR
+       move.b  #MCU_SIM_CLKOCR, CLKOCR
+       move.w  #MCU_SIM_CDVCR, CDVCR
+
+       /* Wait for the PLL to settle */
+       move.w  #16384, %d0
+pll_settle_wait:
+       subi.w  #1, %d0
+       bne     pll_settle_wait
+
+       /* Setup the system protection register, and watchdog timer register */
+       move.b  #MCU_SIM_SWIV, SWIV
+       move.w  #MCU_SIM_PICR, PICR
+       move.w  #MCU_SIM_PITR, PITR
+       move.w  #MCU_SIM_SYPCR, SYPCR
+
+       /* Clear DPRAM - system + parameter */
+       movea.l #_dprbase, %a0
+       movea.l #_dprbase+0x2000, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     clear_dpram
+
+configure_memory_controller:    
+       /* Set up Global Memory Register (GMR) */
+       move.l  #MCU_SIM_GMR, %d0
+       move.l  %d0, GMR
+
+configure_chip_select_0:
+       move.l  #__ramend, %d0
+       subi.l  #__ramstart, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR0_MASK, %d0
+       move.l  %d0, OR0
+
+       move.l  #__ramstart, %d0
+       ori.l   #SIM_BR0_MASK, %d0
+       move.l  %d0, BR0
+
+configure_chip_select_1:
+       move.l  #__rom_end, %d0
+       subi.l  #__rom_start, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR1_MASK, %d0
+       move.l  %d0, OR1
+
+       move.l  #__rom_start, %d0
+       ori.l   #SIM_BR1_MASK, %d0
+       move.l  %d0, BR1
+
+       move.w  #MCU_SIM_PEPAR, PEPAR 
+
+       /* point to vector table: */
+       move.l  #_romvec, %a0
+       move.l  #_ramvec, %a1
+copy_vectors:
+       move.l  %a0@, %d0
+       move.l  %d0, %a1@
+       move.l  %a0@, %a1@
+       addq.l  #0x04, %a0
+       addq.l  #0x04, %a1
+       cmp.l   #_start, %a0
+       blt     copy_vectors
+
+       move.l  #_ramvec, %a1
+       movec   %a1, %vbr
+
+
+       /* Copy data segment from ROM to RAM */
+       moveal  #_stext, %a0
+       moveal  #_sdata, %a1
+       moveal  #_edata, %a2
+
+       /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+       move.l  %a0@, %d0
+       addq.l  #0x04, %a0
+       move.l  %d0, %a1@
+       addq.l  #0x04, %a1
+       cmp.l   #_edata, %a1
+       blt     LD1
+
+       moveal  #_sbss, %a0
+       moveal  #_ebss, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     L1
+
+load_quicc:
+       move.l  #_dprbase, _quicc_base
+
+store_ram_size:
+       /* Set ram size information */
+       move.l  #_sdata, _rambase
+       move.l  #_ebss, _ramstart
+       move.l  #__ramend, %d0
+       sub.l   #0x1000, %d0                    /* Reserve 4K for stack space.*/
+       move.l  %d0, _ramend                    /* Different from __ramend.*/
+
+store_flash_size:
+       /* Set rom size information */
+       move.l  #__rom_end, %d0
+       sub.l   #__rom_start, %d0
+       move.l  %d0, rom_length
+    
+       pea     0
+       pea     env
+       pea     %sp@(4)
+       pea     0
+
+       lea     init_thread_union, %a2
+       lea     0x2000(%a2), %sp
+
+lp:
+       jsr     start_kernel
+
+_exit:
+       jmp     _exit
+
+
+       .data
+       .align 4
+env:
+       .long   0
+_quicc_base:
+       .long   0
+_periph_base:
+       .long   0
+_ramvec:
+       .long   0
+_rambase:
+       .long   0
+_ramstart:
+       .long   0
+_ramend:
+       .long   0
+_dprbase:
+       .long   0xffffe000
+
+       .text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+.section ".data.initvect","awx"
+    .long   __ramend   /* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
new file mode 100644 (file)
index 0000000..0da357a
--- /dev/null
@@ -0,0 +1,420 @@
+/* arch/m68knommu/platform/68360/head-rom.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#include <linux/config.h>
+
+.global _stext
+.global _sbss
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+
+#define OR2                         (_dprbase + REGB + 0x0074)
+#define BR2                         (_dprbase + REGB + 0x0070)
+
+#define OR3                         (_dprbase + REGB + 0x0084)
+#define BR3                         (_dprbase + REGB + 0x0080)
+
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+
+#define OR5                         (_dprbase + REGB + 0x00A4)
+#define BR5                         (_dprbase + REGB + 0x00A0)
+
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000000
+#define SIM_BR0_MASK                0x00000001
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+       
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+       .text
+_start:
+_stext:
+       nop
+       ori.w   #MCU_DISABLE_INTRPTS, %sr       /* disable interrupts: */
+       /* We should not need to setup the boot stack the reset should do it. */
+       movea.l #__ramend, %sp          /* set up stack at the end of DRAM:*/
+
+
+set_mbar_register:
+       moveq.l #0x07, %d1                      /* Setup MBAR */
+       movec   %d1, %dfc
+
+       lea.l   MCU_SIM_MBAR_ADRS, %a0
+       move.l  #_dprbase, %d0
+       andi.l  #MCU_SIM_MBAR_BA_MASK, %d0
+       ori.l   #MCU_SIM_MBAR_AS_MASK, %d0
+       moves.l %d0, %a0@
+
+       moveq.l #0x05, %d1
+       movec.l %d1, %dfc
+
+       /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+       /* Set Module Configuration Register */
+       move.l  #MCU_SIM_MCR, MCR
+
+       /* to do:       Determine cause of reset */
+
+       /*
+        *      configure system clock MC68360 p. 6-40
+        *      (value +1)*osc/128 = system clock
+        *                    or
+        *      (value + 1)*osc = system clock
+        *      You do not need to divide the oscillator by 128 unless you want to.
+        */
+set_sim_clock:
+       move.w  #MCU_SIM_PLLCR, PLLCR
+       move.b  #MCU_SIM_CLKOCR, CLKOCR
+       move.w  #MCU_SIM_CDVCR, CDVCR
+
+       /* Wait for the PLL to settle */
+       move.w  #16384, %d0
+pll_settle_wait:
+       subi.w  #1, %d0
+       bne     pll_settle_wait
+
+       /* Setup the system protection register, and watchdog timer register */
+       move.b  #MCU_SIM_SWIV, SWIV
+       move.w  #MCU_SIM_PICR, PICR
+       move.w  #MCU_SIM_PITR, PITR
+       move.w  #MCU_SIM_SYPCR, SYPCR
+
+       /* Clear DPRAM - system + parameter */
+       movea.l #_dprbase, %a0
+       movea.l #_dprbase+0x2000, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     clear_dpram
+
+configure_memory_controller:    
+       /* Set up Global Memory Register (GMR) */
+       move.l  #MCU_SIM_GMR, %d0
+       move.l  %d0, GMR
+
+configure_chip_select_0:
+       move.l  #0x00400000, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR0_MASK, %d0
+       move.l  %d0, OR0
+
+       move.l  #__rom_start, %d0
+       ori.l   #SIM_BR0_MASK, %d0
+       move.l  %d0, BR0
+
+       move.l  #0x0, BR1
+       move.l  #0x0, BR2
+       move.l  #0x0, BR3
+       move.l  #0x0, BR4
+       move.l  #0x0, BR5
+       move.l  #0x0, BR6
+       move.l  #0x0, BR7
+
+       move.w  #MCU_SIM_PEPAR, PEPAR 
+
+       /* point to vector table: */
+       move.l  #_romvec, %a0
+       move.l  #_ramvec, %a1
+copy_vectors:
+       move.l  %a0@, %d0
+       move.l  %d0, %a1@
+       move.l  %a0@, %a1@
+       addq.l  #0x04, %a0
+       addq.l  #0x04, %a1
+       cmp.l   #_start, %a0
+       blt     copy_vectors
+
+       move.l  #_ramvec, %a1
+       movec   %a1, %vbr
+
+
+       /* Copy data segment from ROM to RAM */
+       moveal  #_etext, %a0
+       moveal  #_sdata, %a1
+       moveal  #_edata, %a2
+
+       /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+       move.l  %a0@, %d0
+       addq.l  #0x04, %a0
+       move.l  %d0, %a1@
+       addq.l  #0x04, %a1
+       cmp.l   #_edata, %a1
+       blt     LD1
+
+       moveal  #_sbss, %a0
+       moveal  #_ebss, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     L1
+
+load_quicc:
+       move.l  #_dprbase, _quicc_base
+
+store_ram_size:
+       /* Set ram size information */
+       move.l  #_sdata, _rambase
+       move.l  #_ebss, _ramstart
+       move.l  #__ramend, %d0
+       sub.l   #0x1000, %d0                    /* Reserve 4K for stack space.*/
+       move.l  %d0, _ramend                    /* Different from __ramend.*/
+
+store_flash_size:
+       /* Set rom size information */
+       move.l  #__rom_end, %d0
+       sub.l   #__rom_start, %d0
+       move.l  %d0, rom_length
+    
+       pea     0
+       pea     env
+       pea     %sp@(4)
+       pea     0
+
+       lea     init_thread_union, %a2
+       lea     0x2000(%a2), %sp
+
+lp:
+       jsr     start_kernel
+
+_exit:
+       jmp     _exit
+
+
+       .data
+       .align 4
+env:
+       .long   0
+_quicc_base:
+       .long   0
+_periph_base:
+       .long   0
+_ramvec:
+       .long   0
+_rambase:
+       .long   0
+_ramstart:
+       .long   0
+_ramend:
+       .long   0
+_dprbase:
+       .long   0xffffe000
+
+
+       .text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+.section ".data.initvect","awx"
+    .long   __ramend   /* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
index 356e4fd9a94fecc763e90a13bb79860ba2880f7b..fbc273c32bcc176556a5949b0fc2c7b78a331bfb 100644 (file)
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void)
                        phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
                        if (phb == NULL)
                                return -ENOMEM;
-                               pci_setup_pci_controller(phb);
+                       pci_setup_pci_controller(phb);
 
                        phb->pci_mem_offset = phb->local_number = bus;
                        phb->first_busno = bus;
index 5a8b4d8c2dd62042e8b67a237fa51d89b8797884..1d297e0edfc0d272e9676562a08866ee6acbf31d 100644 (file)
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
         * the reg address cell, we shall fix that by killing struct
         * reg_property and using some accessor functions instead
         */
-               hose->first_busno = 0xf0;
+       hose->first_busno = 0xf0;
        hose->last_busno = 0xff;
        hose->ops = &u3_agp_pci_ops;
        hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev)
        char* disp_name;
        int *bus_range;
        int primary = 1;
-       struct property *of_prop;
+       struct property *of_prop;
 
        DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-               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);
-               }
+       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 = alloc_bootmem(sizeof(struct pci_controller));
        if (hose == NULL)
                return -ENOMEM;
-               pci_setup_pci_controller(hose);
+       pci_setup_pci_controller(hose);
 
-               hose->arch_data = dev;
-               hose->first_busno = bus_range ? bus_range[0] : 0;
-               hose->last_busno = bus_range ? bus_range[1] : 0xff;
+       hose->arch_data = dev;
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        of_prop = alloc_bootmem(sizeof(struct property) +
                                sizeof(hose->global_number));
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev)
        }
 
        disp_name = NULL;
-               if (device_is_compatible(dev, "u3-agp")) {
-                       setup_u3_agp(hose);
-                       disp_name = "U3-AGP";
-                       primary = 0;
-               } else if (device_is_compatible(dev, "u3-ht")) {
-                       setup_u3_ht(hose);
-                       disp_name = "U3-HT";
-                       primary = 1;
-               }
-               printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-                       disp_name, 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);
+       if (device_is_compatible(dev, "u3-agp")) {
+               setup_u3_agp(hose);
+               disp_name = "U3-AGP";
+               primary = 0;
+       } else if (device_is_compatible(dev, "u3-ht")) {
+               setup_u3_ht(hose);
+               disp_name = "U3-HT";
+               primary = 1;
+       }
+       printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+               disp_name, 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);
        pci_setup_phb_io(hose, primary);
 
-               /* Fixup "bus-range" OF property */
-               fixup_bus_range(dev);
+       /* Fixup "bus-range" OF property */
+       fixup_bus_range(dev);
 
        return 0;
 }
index 9490b6c5b1736ae7fa5b42b7cbdf9a02020bd791..bfadccc7b8be78e4683fcb0bac7f1fd5189ab3ab 100644 (file)
@@ -590,6 +590,13 @@ static int pseries_shared_idle(void)
        return 0;
 }
 
+static int pSeries_pci_probe_mode(struct pci_bus *bus)
+{
+       if (systemcfg->platform & PLATFORM_LPAR)
+               return PCI_PROBE_DEVTREE;
+       return PCI_PROBE_NORMAL;
+}
+
 struct machdep_calls __initdata pSeries_md = {
        .probe                  = pSeries_probe,
        .setup_arch             = pSeries_setup_arch,
@@ -597,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = {
        .get_cpuinfo            = pSeries_get_cpuinfo,
        .log_error              = pSeries_log_error,
        .pcibios_fixup          = pSeries_final_fixup,
+       .pci_probe_mode         = pSeries_pci_probe_mode,
        .irq_bus_setup          = pSeries_irq_bus_setup,
        .restart                = rtas_restart,
        .power_off              = rtas_power_off,
index 79c7f32236658805bab9f783d80cb3d42091893a..d2c7e2c4733b72130cbd90020b0ae61cc7ed4897 100644 (file)
@@ -272,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
        unsigned long start_here = __pa((u32)*((unsigned long *)
                                               pSeries_secondary_smp_init));
        unsigned int pcpu;
+       int start_cpu;
 
        if (cpu_isset(lcpu, of_spin_map))
                /* Already started by OF and sitting in spin loop */
@@ -282,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
        /* Fixup atomic count: it exited inside IRQ handler. */
        paca[lcpu].__current->thread_info->preempt_count        = 0;
 
-       status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
-                          pcpu, start_here, lcpu);
+       /* 
+        * If the RTAS start-cpu token does not exist then presume the
+        * cpu is already spinning.
+        */
+       start_cpu = rtas_token("start-cpu");
+       if (start_cpu == RTAS_UNKNOWN_SERVICE)
+               return 1;
+
+       status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
        if (status != 0) {
                printk(KERN_ERR "start-cpu failed: %i\n", status);
                return 0;
        }
+
        return 1;
 }
 
index 8447dcc2c2b3f7db34086a997030c7d92742dd0a..861138ad092c597efcaee48d9d6496e9f41a7057 100644 (file)
@@ -51,6 +51,10 @@ unsigned long io_page_mask;
 
 EXPORT_SYMBOL(io_page_mask);
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static void fixup_resource(struct resource *res, struct pci_dev *dev);
+static void do_bus_setup(struct pci_bus *bus);
+#endif
 
 unsigned int pcibios_assign_all_busses(void)
 {
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void)
 }
 #endif
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
+{
+       u32 *prop;
+       int len;
+
+       prop = (u32 *) get_property(np, name, &len);
+       if (prop && len >= 4)
+               return *prop;
+       return def;
+}
+
+static unsigned int pci_parse_of_flags(u32 addr0)
+{
+       unsigned int flags = 0;
+
+       if (addr0 & 0x02000000) {
+               flags |= IORESOURCE_MEM;
+               if (addr0 & 0x40000000)
+                       flags |= IORESOURCE_PREFETCH;
+       } else if (addr0 & 0x01000000)
+               flags |= IORESOURCE_IO;
+       return flags;
+}
+
+#define GET_64BIT(prop, i)     ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
+
+static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
+{
+       u64 base, size;
+       unsigned int flags;
+       struct resource *res;
+       u32 *addrs, i;
+       int proplen;
+
+       addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
+       if (!addrs)
+               return;
+       for (; proplen >= 20; proplen -= 20, addrs += 5) {
+               flags = pci_parse_of_flags(addrs[0]);
+               if (!flags)
+                       continue;
+               base = GET_64BIT(addrs, 1);
+               size = GET_64BIT(addrs, 3);
+               if (!size)
+                       continue;
+               i = addrs[0] & 0xff;
+               if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
+                       res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
+               } else if (i == dev->rom_base_reg) {
+                       res = &dev->resource[PCI_ROM_RESOURCE];
+                       flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+               } else {
+                       printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
+                       continue;
+               }
+               res->start = base;
+               res->end = base + size - 1;
+               res->flags = flags;
+               res->name = pci_name(dev);
+               fixup_resource(res, dev);
+       }
+}
+
+static struct pci_dev *of_create_pci_dev(struct device_node *node,
+                                        struct pci_bus *bus, int devfn)
+{
+       struct pci_dev *dev;
+       const char *type;
+
+       dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+       type = get_property(node, "device_type", NULL);
+       if (type == NULL)
+               type = "";
+
+       memset(dev, 0, sizeof(struct pci_dev));
+       dev->bus = bus;
+       dev->sysdata = node;
+       dev->dev.parent = bus->bridge;
+       dev->dev.bus = &pci_bus_type;
+       dev->devfn = devfn;
+       dev->multifunction = 0;         /* maybe a lie? */
+
+       dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
+       dev->device = get_int_prop(node, "device-id", 0xffff);
+       dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
+       dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
+
+       dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+
+       sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+               dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+       dev->class = get_int_prop(node, "class-code", 0);
+
+       dev->current_state = 4;         /* unknown power state */
+
+       if (!strcmp(type, "pci")) {
+               /* a PCI-PCI bridge */
+               dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+               dev->rom_base_reg = PCI_ROM_ADDRESS1;
+       } else if (!strcmp(type, "cardbus")) {
+               dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+       } else {
+               dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+               dev->rom_base_reg = PCI_ROM_ADDRESS;
+               dev->irq = NO_IRQ;
+               if (node->n_intrs > 0) {
+                       dev->irq = node->intrs[0].line;
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+                                             dev->irq);
+               }
+       }
+
+       pci_parse_of_addrs(node, dev);
+
+       pci_device_add(dev, bus);
+
+       /* XXX pci_scan_msi_device(dev); */
+
+       return dev;
+}
+
+static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev);
+
+static void __devinit of_scan_bus(struct device_node *node,
+                                 struct pci_bus *bus)
+{
+       struct device_node *child = NULL;
+       u32 *reg;
+       int reglen, devfn;
+       struct pci_dev *dev;
+
+       while ((child = of_get_next_child(node, child)) != NULL) {
+               reg = (u32 *) get_property(child, "reg", &reglen);
+               if (reg == NULL || reglen < 20)
+                       continue;
+               devfn = (reg[0] >> 8) & 0xff;
+               /* create a new pci_dev for this device */
+               dev = of_create_pci_dev(child, bus, devfn);
+               if (!dev)
+                       continue;
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+                   dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                       of_scan_pci_bridge(child, dev);
+       }
+
+       do_bus_setup(bus);
+}
+
+static void __devinit of_scan_pci_bridge(struct device_node *node,
+                                        struct pci_dev *dev)
+{
+       struct pci_bus *bus;
+       u32 *busrange, *ranges;
+       int len, i, mode;
+       struct resource *res;
+       unsigned int flags;
+       u64 size;
+
+       /* parse bus-range property */
+       busrange = (u32 *) get_property(node, "bus-range", &len);
+       if (busrange == NULL || len != 8) {
+               printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+                      node->full_name);
+               return;
+       }
+       ranges = (u32 *) get_property(node, "ranges", &len);
+       if (ranges == NULL) {
+               printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+                      node->full_name);
+               return;
+       }
+
+       bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+       if (!bus) {
+               printk(KERN_ERR "Failed to create pci bus for %s\n",
+                      node->full_name);
+               return;
+       }
+
+       bus->primary = dev->bus->number;
+       bus->subordinate = busrange[1];
+       bus->bridge_ctl = 0;
+       bus->sysdata = node;
+
+       /* parse ranges property */
+       /* PCI #address-cells == 3 and #size-cells == 2 always */
+       res = &dev->resource[PCI_BRIDGE_RESOURCES];
+       for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) {
+               res->flags = 0;
+               bus->resource[i] = res;
+               ++res;
+       }
+       i = 1;
+       for (; len >= 32; len -= 32, ranges += 8) {
+               flags = pci_parse_of_flags(ranges[0]);
+               size = GET_64BIT(ranges, 6);
+               if (flags == 0 || size == 0)
+                       continue;
+               if (flags & IORESOURCE_IO) {
+                       res = bus->resource[0];
+                       if (res->flags) {
+                               printk(KERN_ERR "PCI: ignoring extra I/O range"
+                                      " for bridge %s\n", node->full_name);
+                               continue;
+                       }
+               } else {
+                       if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
+                               printk(KERN_ERR "PCI: too many memory ranges"
+                                      " for bridge %s\n", node->full_name);
+                               continue;
+                       }
+                       res = bus->resource[i];
+                       ++i;
+               }
+               res->start = GET_64BIT(ranges, 1);
+               res->end = res->start + size - 1;
+               res->flags = flags;
+               fixup_resource(res, dev);
+       }
+       sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
+               bus->number);
+
+       mode = PCI_PROBE_NORMAL;
+       if (ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+       if (mode == PCI_PROBE_DEVTREE)
+               of_scan_bus(node, bus);
+       else if (mode == PCI_PROBE_NORMAL)
+               pci_scan_child_bus(bus);
+}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+static void __devinit scan_phb(struct pci_controller *hose)
+{
+       struct pci_bus *bus;
+       struct device_node *node = hose->arch_data;
+       int i, mode;
+       struct resource *res;
+
+       bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
+       if (bus == NULL) {
+               printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+                      hose->global_number);
+               return;
+       }
+       bus->secondary = hose->first_busno;
+       hose->bus = bus;
+
+       bus->resource[0] = res = &hose->io_resource;
+       if (res->flags && request_resource(&ioport_resource, res))
+               printk(KERN_ERR "Failed to request PCI IO region "
+                      "on PCI domain %04x\n", hose->global_number);
+
+       for (i = 0; i < 3; ++i) {
+               res = &hose->mem_resources[i];
+               bus->resource[i+1] = res;
+               if (res->flags && request_resource(&iomem_resource, res))
+                       printk(KERN_ERR "Failed to request PCI memory region "
+                              "on PCI domain %04x\n", hose->global_number);
+       }
+
+       mode = PCI_PROBE_NORMAL;
+#ifdef CONFIG_PPC_MULTIPLATFORM
+       if (ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+       if (mode == PCI_PROBE_DEVTREE) {
+               bus->subordinate = hose->last_busno;
+               of_scan_bus(node, bus);
+       }
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+       if (mode == PCI_PROBE_NORMAL)
+               hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+       pci_bus_add_devices(bus);
+}
+
 static int __init pcibios_init(void)
 {
        struct pci_controller *hose, *tmp;
-       struct pci_bus *bus;
 
        /* For now, override phys_mem_access_prot. If we need it,
         * later, we may move that initialization to each ppc_md
@@ -242,13 +523,8 @@ static int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               hose->last_busno = 0xff;
-               bus = pci_scan_bus(hose->first_busno, hose->ops,
-                                  hose->arch_data);
-               hose->bus = bus;
-               hose->last_busno = bus->subordinate;
-       }
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+               scan_phb(hose);
 
 #ifndef CONFIG_PPC_ISERIES
        if (pci_probe_only)
@@ -820,120 +1096,89 @@ void phbs_remap_io(void)
 /*
  * ppc64 can have multifunction devices that do not respond to function 0.
  * In this case we must scan all functions.
+ * XXX this can go now, we use the OF device tree in all the
+ * cases that caused problems. -- paulus
  */
 int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
 {
-       struct device_node *busdn, *dn;
-
-       if (bus->self)
-               busdn = pci_device_to_OF_node(bus->self);
-       else
-               busdn = bus->sysdata;   /* must be a phb */
-
-       if (busdn == NULL)
-              return 0;
-
-       /*
-        * Check to see if there is any of the 8 functions are in the
-        * device tree.  If they are then we need to scan all the
-        * functions of this slot.
-        */
-       for (dn = busdn->child; dn; dn = dn->sibling) {
-              struct pci_dn *pdn = dn->data;
-              if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
-                       return 1;
-       }
-
        return 0;
 }
 
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       unsigned long start, end, mask, offset;
+
+       if (res->flags & IORESOURCE_IO) {
+               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+               start = res->start += offset;
+               end = res->end += offset;
+
+               /* Need to allow IO access to pages that are in the
+                  ISA range */
+               if (start < MAX_ISA_PORT) {
+                       if (end > MAX_ISA_PORT)
+                               end = MAX_ISA_PORT;
+
+                       start >>= PAGE_SHIFT;
+                       end >>= PAGE_SHIFT;
+
+                       /* get the range of pages for the map */
+                       mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
+                       io_page_mask |= mask;
+               }
+       } else if (res->flags & IORESOURCE_MEM) {
+               res->start += hose->pci_mem_offset;
+               res->end += hose->pci_mem_offset;
+       }
+}
 
 void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-                                          struct pci_bus *bus)
+                                             struct pci_bus *bus)
 {
        /* Update device resources.  */
-       struct pci_controller *hose = pci_bus_to_host(bus);
        int i;
 
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               if (dev->resource[i].flags & IORESOURCE_IO) {
-                       unsigned long offset = (unsigned long)hose->io_base_virt
-                               - pci_io_base;
-                        unsigned long start, end, mask;
-
-                        start = dev->resource[i].start += offset;
-                        end = dev->resource[i].end += offset;
-
-                        /* Need to allow IO access to pages that are in the
-                           ISA range */
-                        if (start < MAX_ISA_PORT) {
-                                if (end > MAX_ISA_PORT)
-                                        end = MAX_ISA_PORT;
-
-                                start >>= PAGE_SHIFT;
-                                end >>= PAGE_SHIFT;
-
-                                /* get the range of pages for the map */
-                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
-                                io_page_mask |= mask;
-                        }
-               }
-                else if (dev->resource[i].flags & IORESOURCE_MEM) {
-                       dev->resource[i].start += hose->pci_mem_offset;
-                       dev->resource[i].end += hose->pci_mem_offset;
-               }
-        }
+       for (i = 0; i < PCI_NUM_RESOURCES; i++)
+               if (dev->resource[i].flags)
+                       fixup_resource(&dev->resource[i], dev);
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+static void __devinit do_bus_setup(struct pci_bus *bus)
 {
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pci_dev *dev = bus->self;
-       struct resource *res;
-       int i;
+       struct pci_dev *dev;
 
-       if (!dev) {
-               /* Root bus. */
+       ppc_md.iommu_bus_setup(bus);
 
-               hose->bus = bus;
-               bus->resource[0] = res = &hose->io_resource;
+       list_for_each_entry(dev, &bus->devices, bus_list)
+               ppc_md.iommu_dev_setup(dev);
 
-               if (res->flags && request_resource(&ioport_resource, res))
-                       printk(KERN_ERR "Failed to request IO on "
-                                       "PCI domain %d\n", pci_domain_nr(bus));
+       if (ppc_md.irq_bus_setup)
+               ppc_md.irq_bus_setup(bus);
+}
 
-               for (i = 0; i < 3; ++i) {
-                       res = &hose->mem_resources[i];
-                       bus->resource[i+1] = res;
-                       if (res->flags && request_resource(&iomem_resource, res))
-                               printk(KERN_ERR "Failed to request MEM on "
-                                               "PCI domain %d\n",
-                                               pci_domain_nr(bus));
-               }
-       } else if (pci_probe_only &&
-                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev = bus->self;
+
+       if (dev && pci_probe_only &&
+           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
                /* This is a subordinate bridge */
 
                pci_read_bridge_bases(bus);
                pcibios_fixup_device_resources(dev, bus);
        }
 
-       ppc_md.iommu_bus_setup(bus);
-
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               ppc_md.iommu_dev_setup(dev);
-
-       if (ppc_md.irq_bus_setup)
-               ppc_md.irq_bus_setup(bus);
+       do_bus_setup(bus);
 
        if (!pci_probe_only)
                return;
 
-       list_for_each_entry(dev, &bus->devices, bus_list) {
+       list_for_each_entry(dev, &bus->devices, bus_list)
                if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
                        pcibios_fixup_device_resources(dev, bus);
-       }
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
index d37bff2d7d40c3ae9af84e8b9d047fa53766bdb2..dc40a0cad0b47e387e2b207e43f0d70eebdf80ac 100644 (file)
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
         * the reg address cell, we shall fix that by killing struct
         * reg_property and using some accessor functions instead
         */
-               hose->first_busno = 0xf0;
+       hose->first_busno = 0xf0;
        hose->last_busno = 0xff;
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
                        continue;
                }               
                cur++;
-                       DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+               DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
                    cur-1, res->start - 1, cur, res->end + 1);
                hose->mem_resources[cur].name = np->full_name;
                hose->mem_resources[cur].flags = IORESOURCE_MEM;
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev)
        char* disp_name;
        int *bus_range;
        int primary = 1;
-       struct property *of_prop;
+       struct property *of_prop;
 
        DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-               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);
-               }
+       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 = alloc_bootmem(sizeof(struct pci_controller));
        if (hose == NULL)
                return -ENOMEM;
-               pci_setup_pci_controller(hose);
+       pci_setup_pci_controller(hose);
 
-               hose->arch_data = dev;
-               hose->first_busno = bus_range ? bus_range[0] : 0;
-               hose->last_busno = bus_range ? bus_range[1] : 0xff;
+       hose->arch_data = dev;
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        of_prop = alloc_bootmem(sizeof(struct property) +
                                sizeof(hose->global_number));
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev)
        }
 
        disp_name = NULL;
-               if (device_is_compatible(dev, "u3-agp")) {
-                       setup_u3_agp(hose);
-                       disp_name = "U3-AGP";
-                       primary = 0;
-               } else if (device_is_compatible(dev, "u3-ht")) {
-                       setup_u3_ht(hose);
-                       disp_name = "U3-HT";
-                       primary = 1;
-               }
-               printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-                       disp_name, hose->first_busno, hose->last_busno);
-
-               /* Interpret the "ranges" property */
-               /* This also maps the I/O region and sets isa_io/mem_base */
-               pmac_process_bridge_OF_ranges(hose, dev, primary);
-
-               /* Fixup "bus-range" OF property */
-               fixup_bus_range(dev);
+       if (device_is_compatible(dev, "u3-agp")) {
+               setup_u3_agp(hose);
+               disp_name = "U3-AGP";
+               primary = 0;
+       } else if (device_is_compatible(dev, "u3-ht")) {
+               setup_u3_ht(hose);
+               disp_name = "U3-HT";
+               primary = 1;
+       }
+       printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+               disp_name, hose->first_busno, hose->last_busno);
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pmac_process_bridge_OF_ranges(hose, dev, primary);
+
+       /* Fixup "bus-range" OF property */
+       fixup_bus_range(dev);
 
        return 0;
 }
index e7f695dcd8c8dd4dae28d7626e421f93397eca19..325426c7bed00f5348ac0fc2dcdb64949a3ff716 100644 (file)
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform)
        return 1;
 }
 
+static int pmac_probe_mode(struct pci_bus *bus)
+{
+       struct device_node *node = bus->sysdata;
+
+       /* We need to use normal PCI probing for the AGP bus,
+          since the device for the AGP bridge isn't in the tree. */
+       if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+               return PCI_PROBE_NORMAL;
+
+       return PCI_PROBE_DEVTREE;
+}
+
 struct machdep_calls __initdata pmac_md = {
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = generic_mach_cpu_die,
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
        .init_IRQ               = pmac_init_IRQ,
        .get_irq                = mpic_get_irq,
        .pcibios_fixup          = pmac_pcibios_fixup,
+       .pci_probe_mode         = pmac_probe_mode,
        .restart                = pmac_restart,
        .power_off              = pmac_power_off,
        .halt                   = pmac_halt,
index 7a7e027653ad922dac160da11e545401696148ed..887005358eb1faa40bdba25f77d75650f21d851a 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/time.h>
+#include <asm/plpar_wrappers.h>
 
 #ifndef CONFIG_SMP
 struct task_struct *last_task_used_math = NULL;
@@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
 
 #endif /* CONFIG_ALTIVEC */
 
+static void set_dabr_spr(unsigned long val)
+{
+       mtspr(SPRN_DABR, val);
+}
+
+int set_dabr(unsigned long dabr)
+{
+       int ret = 0;
+
+       if (firmware_has_feature(FW_FEATURE_XDABR)) {
+               /* We want to catch accesses from kernel and userspace */
+               unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
+               ret = plpar_set_xdabr(dabr, flags);
+       } else if (firmware_has_feature(FW_FEATURE_DABR)) {
+               ret = plpar_set_dabr(dabr);
+       } else {
+               set_dabr_spr(dabr);
+       }
+
+       return ret;
+}
+
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+static DEFINE_PER_CPU(unsigned long, current_dabr);
 
 struct task_struct *__switch_to(struct task_struct *prev,
                                struct task_struct *new)
@@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
                new->thread.regs->msr |= MSR_VEC;
 #endif /* CONFIG_ALTIVEC */
 
+       if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+               set_dabr(new->thread.dabr);
+               __get_cpu_var(current_dabr) = new->thread.dabr;
+       }
+
        flush_tlb_pending();
 
        new_thread = &new->thread;
@@ -334,6 +363,11 @@ void flush_thread(void)
                last_task_used_altivec = NULL;
 #endif /* CONFIG_ALTIVEC */
 #endif /* CONFIG_SMP */
+
+       if (current->thread.dabr) {
+               current->thread.dabr = 0;
+               set_dabr(0);
+       }
 }
 
 void
index 2993f108d96d309f6f333bb47b38c86373551239..85ed3188a91d0a7ef7c3799c8cf9a7992f411ac1 100644 (file)
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data)
                break;
        }
 
+       case PTRACE_GET_DEBUGREG: {
+               ret = -EINVAL;
+               /* We only support one DABR and no IABRS at the moment */
+               if (addr > 0)
+                       break;
+               ret = put_user(child->thread.dabr,
+                              (unsigned long __user *)data);
+               break;
+       }
+
+       case PTRACE_SET_DEBUGREG:
+               ret = ptrace_set_debugreg(child, addr, data);
+
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
                break;
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
                break;
        }
 
+#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETVRREGS:
+               /* Get the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = get_vrregs((unsigned long __user *)data, child);
+               break;
+
+       case PTRACE_SETVRREGS:
+               /* Set the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = set_vrregs(child, (unsigned long __user *)data);
+               break;
+#endif
+
        default:
                ret = ptrace_request(child, request, addr, data);
                break;
index 16436426c7e240db5e6599436d149e32d3412aa6..fb8c22d6084a7c280a0c74d9f9d3f1ebb523471d 100644 (file)
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
                break;
        }
 
+       case PTRACE_GET_DEBUGREG: {
+               ret = -EINVAL;
+               /* We only support one DABR and no IABRS at the moment */
+               if (addr > 0)
+                       break;
+               ret = put_user(child->thread.dabr, (u32 __user *)data);
+               break;
+       }
+
+       case PTRACE_SET_DEBUGREG:
+               ret = ptrace_set_debugreg(child, addr, data);
+               break;
+
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
                break;
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
                break;
        }
 
-       case PTRACE_GETEVENTMSG:
-                ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-                break;
+       case PTRACE_GETEVENTMSG:
+               ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+               break;
+
+#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETVRREGS:
+               /* Get the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = get_vrregs((unsigned long __user *)data, child);
+               break;
+
+       case PTRACE_SETVRREGS:
+               /* Set the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = set_vrregs(child, (unsigned long __user *)data);
+               break;
+#endif
 
        default:
                ret = ptrace_request(child, request, addr, data);
index 3c00f7bfc1b5736d43ab2011e3ac37aafe6da9cf..41b97dc9cc0a0a9735675bdee038bf7b7008007e 100644 (file)
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX]
 /* This is true if we are using the firmware NMI handler (typically LPAR) */
 extern int fwnmi_active;
 
-extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
-
 static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
 
index bfa8791c9807f865bb89085f0054759bbd452eaa..5ac48bd64891f98e0846ef8f0959ccba01da682b 100644 (file)
@@ -1064,8 +1064,6 @@ void __init setup_arch(char **cmdline_p)
 #define PPC64_LINUX_FUNCTION 0x0f000000
 #define PPC64_IPL_MESSAGE 0xc0000000
 #define PPC64_TERM_MESSAGE 0xb0000000
-#define PPC64_ATTN_MESSAGE 0xa0000000
-#define PPC64_DUMP_MESSAGE 0xd0000000
 
 static void ppc64_do_msg(unsigned int src, const char *msg)
 {
@@ -1093,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
        printk("[terminate]%04x %s\n", src, msg);
 }
 
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg)
-{
-       ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
-       printk("[attention]%04x %s\n", src, msg);
-}
-
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg)
-{
-       ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
-       printk("[dump]%04x %s\n", src, msg);
-}
-
 /* This should only be called on processor 0 during calibrate decr */
 void __init setup_default_decr(void)
 {
index 49a79a55c32de7d5ab73191dbe78047a6dcf848e..347112cca3c096ac660a3eed66d7aa4b9c0e0b26 100644 (file)
@@ -550,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
                /* Whee!  Actually deliver the signal.  */
                if (TRAP(regs) == 0x0C00)
                        syscall_restart(regs, &ka);
+
+               /*
+                * Reenable the DABR before delivering the signal to
+                * user space. The DABR will have been cleared if it
+                * triggered inside the kernel.
+                */
+               if (current->thread.dabr)
+                       set_dabr(current->thread.dabr);
+
                return handle_signal(signr, &ka, &info, oldset, regs);
        }
 
index 46f4d6cc7fc9591ce7240887a05edadcd711c6f6..a8b7a5a56bb445b90f7116c3f418fd14b41a657b 100644 (file)
@@ -970,6 +970,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
                newsp = regs->gpr[1];
        newsp &= ~0xfUL;
 
+       /*
+        * Reenable the DABR before delivering the signal to
+        * user space. The DABR will have been cleared if it
+        * triggered inside the kernel.
+        */
+       if (current->thread.dabr)
+               set_dabr(current->thread.dabr);
+
        /* Whee!  Actually deliver the signal.  */
        if (ka.sa.sa_flags & SA_SIGINFO)
                ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
index d9dc6f28d050050281ccc99e19e2d940de850abd..daf93885dcfab007cc73ddc7e446632d253b0055 100644 (file)
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq);
 static void xics_end_irq(unsigned int irq);
 static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
 
-struct hw_interrupt_type xics_pic = {
+static struct hw_interrupt_type xics_pic = {
        .typename = " XICS     ",
        .startup = xics_startup,
        .enable = xics_enable_irq,
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = {
        .set_affinity = xics_set_affinity
 };
 
-struct hw_interrupt_type xics_8259_pic = {
+static struct hw_interrupt_type xics_8259_pic = {
        .typename = " XICS/8259",
        .ack = xics_mask_and_ack_irq,
 };
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 static int xics_irq_8259_cascade = 0;
 static int xics_irq_8259_cascade_real = 0;
 static unsigned int default_server = 0xFF;
-/* also referenced in smp.c... */
-unsigned int default_distrib_server = 0;
-unsigned int interrupt_server_size = 8;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
 
 /*
  * XICS only has a single IPI, so encode the messages per CPU
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8;
 struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 /* RTAS service tokens */
-int ibm_get_xive;
-int ibm_set_xive;
-int ibm_int_on;
-int ibm_int_off;
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
 
 typedef struct {
        int (*xirr_info_get)(int cpu);
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
                                DEFAULT_PRIORITY);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive "
-                      "returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
+                      "returned %d\n", irq, call_status);
+               printk("set_xive %x, server %x\n", ibm_set_xive, server);
                return;
        }
 
        /* Now unmask the interrupt (often a no-op) */
        call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on "
-                      "returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
+                      "returned %d\n", irq, call_status);
                return;
        }
 }
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq)
 
        call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_real_irq: irq=%d: "
-                      "ibm_int_off returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
+                      "ibm_int_off returned %d\n", irq, call_status);
                return;
        }
 
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq)
        /* Have to set XIVE to 0xff to be able to remove a slot */
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)"
-                      " returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
+                      " returned %d\n", irq, call_status);
                return;
        }
 }
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs)
                if (irq == NO_IRQ)
                        irq = real_irq_to_virt_slowpath(vec);
                if (irq == NO_IRQ) {
-                       printk(KERN_ERR "Interrupt %d (real) is invalid,"
+                       printk(KERN_ERR "Interrupt %u (real) is invalid,"
                               " disabling it.\n", vec);
                        xics_disable_real_irq(vec);
                } else
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive "
+               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
                       "returns %d\n", irq, status);
                return;
        }
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
                                irq, newmask, xics_status[1]);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive "
+               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
                       "returns %d\n", irq, status);
                return;
        }
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void)
 
                status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
                if (status) {
-                       printk(KERN_ERR "migrate_irqs_away: irq=%d "
+                       printk(KERN_ERR "migrate_irqs_away: irq=%u "
                                        "ibm,get-xive returns %d\n",
                                        virq, status);
                        goto unlock;
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void)
                if (xics_status[0] != get_hard_smp_processor_id(cpu))
                        goto unlock;
 
-               printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n",
+               printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
                       virq, cpu);
 
                /* Reset affinity to all cpus */
index 772f0714a5b7d4be9231b362650c920c1c70cb9c..7fbc68bbb7391cef88ee614d2ec54f291f54c7dc 100644 (file)
@@ -77,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs)
        return 0;
 }
 
+static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+{
+       siginfo_t info;
+
+       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+                       11, SIGSEGV) == NOTIFY_STOP)
+               return;
+
+       if (debugger_dabr_match(regs))
+               return;
+
+       /* Clear the DABR */
+       set_dabr(0);
+
+       /* Deliver the signal to userspace */
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_HWBKPT;
+       info.si_addr = (void __user *)regs->nip;
+       force_sig_info(SIGTRAP, &info, current);
+}
+
 /*
  * The error_code parameter is
  *  - DSISR for a non-SLB data access fault,
@@ -111,12 +133,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
        if (!user_mode(regs) && (address >= TASK_SIZE))
                return SIGSEGV;
 
-       if (error_code & DSISR_DABRMATCH) {
-               if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
-                                       11, SIGSEGV) == NOTIFY_STOP)
-                       return 0;
-               if (debugger_dabr_match(regs))
-                       return 0;
+       if (error_code & DSISR_DABRMATCH) {
+               do_dabr(regs, error_code);
+               return 0;
        }
 
        if (in_atomic() || mm == NULL) {
index 183c3e40025881daab3b80ec360a47f2d380af1e..02eb40dac0b304fbcab0b3cf0d136bc312a9eb79 100644 (file)
@@ -46,7 +46,6 @@ GSETSPR(287, pvr)
 GSETSPR(1008, hid0)
 GSETSPR(1009, hid1)
 GSETSPR(1010, iabr)
-GSETSPR(1013, dabr)
 GSETSPR(1023, pir)
 
 static inline void store_inst(void *p)
index 45908b10acd345970da83c6d5369fc850e6b072a..74e63a886a69ae4b9769cacd3b6f2df44bcec48d 100644 (file)
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs)
 {
        if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
                return 0;
+       if (dabr.enabled == 0)
+               return 0;
        xmon_core(regs, 0);
        return 1;
 }
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs)
        return 0;
 }
 
-/* On systems with a hypervisor, we can't set the DABR
-   (data address breakpoint register) directly. */
-static void set_controlled_dabr(unsigned long val)
-{
-#ifdef CONFIG_PPC_PSERIES
-       if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-               int rc = plpar_hcall_norets(H_SET_DABR, val);
-               if (rc != H_Success)
-                       xmon_printf("Warning: setting DABR failed (%d)\n", rc);
-       } else
-#endif
-               set_dabr(val);
-}
-
 static struct bpt *at_breakpoint(unsigned long pc)
 {
        int i;
@@ -728,7 +716,7 @@ static void insert_bpts(void)
 static void insert_cpu_bpts(void)
 {
        if (dabr.enabled)
-               set_controlled_dabr(dabr.address | (dabr.enabled & 7));
+               set_dabr(dabr.address | (dabr.enabled & 7));
        if (iabr && cpu_has_feature(CPU_FTR_IABR))
                set_iabr(iabr->address
                         | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -756,7 +744,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-       set_controlled_dabr(0);
+       set_dabr(0);
        if (cpu_has_feature(CPU_FTR_IABR))
                set_iabr(0);
 }
index 18610cea03a21d6d59bfb23224ecf1672678c7bc..ed877d0f27e6e038b12c24489ac1e3914d7ba478 100644 (file)
@@ -678,7 +678,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size
        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
        set_fs(old_fs);
        
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
                
        return ret;
index f4399c701b77957d01d93fa7ada889bd6d47e443..18c6e915d69b84260a43b979b28e5058c60a193a 100644 (file)
@@ -46,7 +46,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
 $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
                              $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
-       @echo 'Kernel: $@ is ready'
+       @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
index b38d5b8b5fb844ebf92ed2221faa1bcf2d274e6a..0e10fd84c7cc79e2ee31832e6104c915f3c50597 100644 (file)
@@ -83,7 +83,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
 #endif
 #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
 
-extern char input_data[];
+extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
@@ -288,7 +288,7 @@ void setup_normal_output_buffer(void)
 #else
        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
-       output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
+       output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
        free_mem_end_ptr = (long)real_mode;
 }
 
@@ -305,7 +305,7 @@ void setup_output_buffer_if_we_run_high(struct moveparams *mv)
 #else
        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
 #endif 
-       mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+       mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
        low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
          ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
        low_buffer_size = low_buffer_end - LOW_BUFFER_START;
index bf57e2362bf4cbd79bc9f5e02d7f11b8b18abc0b..f8db7e500fbfdd727e16ac7a9c71f1cab078f243 100644 (file)
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-git3
-# Fri Aug 12 16:40:34 2005
+# Linux kernel version: 2.6.13-git11
+# Mon Sep 12 16:16:16 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
 CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -13,6 +14,7 @@ CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -37,6 +40,7 @@ CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -102,6 +106,7 @@ CONFIG_DISCONTIGMEM_MANUAL=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=32
@@ -122,6 +127,7 @@ CONFIG_HZ=250
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Power management options
@@ -194,7 +200,6 @@ CONFIG_UNORDERED_IO=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -234,7 +239,10 @@ 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_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
@@ -244,8 +252,8 @@ CONFIG_IP_FIB_HASH=y
 # 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=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
@@ -257,6 +265,11 @@ CONFIG_IPV6=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -280,9 +293,11 @@ CONFIG_IPV6=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
@@ -329,7 +344,6 @@ 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_LBD=y
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -409,6 +423,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -432,7 +447,7 @@ CONFIG_BLK_DEV_SD=y
 #
 # SCSI Transport Attributes
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 
@@ -458,6 +473,7 @@ CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
@@ -536,6 +552,11 @@ CONFIG_TUN=y
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -586,6 +607,7 @@ CONFIG_E1000=y
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -595,6 +617,7 @@ CONFIG_TIGON3=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
@@ -749,7 +772,6 @@ CONFIG_MAX_RAW_DEVS=256
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -760,6 +782,7 @@ CONFIG_MAX_RAW_DEVS=256
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -767,6 +790,10 @@ CONFIG_HWMON=y
 #
 # CONFIG_IBM_ASM is not set
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -858,9 +885,8 @@ CONFIG_USB_UHCI_HCD=y
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=y
 
@@ -877,6 +903,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -893,6 +920,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
@@ -976,6 +1004,8 @@ CONFIG_USB_MON=y
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+CONFIG_DCDBAS=m
 
 #
 # File systems
@@ -1000,10 +1030,6 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 # CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1012,6 +1038,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1037,12 +1064,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1074,6 +1100,7 @@ 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=y
@@ -1086,6 +1113,7 @@ CONFIG_SUNRPC=y
 # 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
@@ -1150,6 +1178,7 @@ CONFIG_OPROFILE=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1157,6 +1186,7 @@ CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_INIT_DEBUG=y
 # CONFIG_IOMMU_DEBUG is not set
 CONFIG_KPROBES=y
@@ -1180,5 +1210,6 @@ CONFIG_KPROBES=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
index 5244f803203d652d13ec08917eac18633865b774..e0eb0c712fe91fbddfc74beb9048eace392e1566 100644 (file)
  * with the int 0x80 path.
  */    
 ENTRY(ia32_sysenter_target)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rsp,rbp
        swapgs
        movq    %gs:pda_kernelstack, %rsp
        addq    $(PDA_STACKOFFSET),%rsp 
        sti     
        movl    %ebp,%ebp               /* zero extension */
        pushq   $__USER32_DS
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET ss,0*/
        pushq   %rbp
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rsp,0
        pushfq
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET rflags,0*/
        movl    $VSYSCALL32_SYSEXIT, %r10d
+       CFI_REGISTER rip,r10
        pushq   $__USER32_CS
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET cs,0*/
        movl    %eax, %eax
        pushq   %r10
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip,0
        pushq   %rax
+       CFI_ADJUST_CFA_OFFSET 8
        cld
        SAVE_ARGS 0,0,1
        /* no need to do an access_ok check here because rbp has been
@@ -79,6 +93,7 @@ ENTRY(ia32_sysenter_target)
        .previous       
        GET_THREAD_INFO(%r10)
        testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+       CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
 sysenter_do_call:      
        cmpl    $(IA32_NR_syscalls),%eax
@@ -94,14 +109,20 @@ sysenter_do_call:
        andl  $~0x200,EFLAGS-R11(%rsp) 
        RESTORE_ARGS 1,24,1,1,1,1
        popfq
+       CFI_ADJUST_CFA_OFFSET -8
+       /*CFI_RESTORE rflags*/
        popq    %rcx                            /* User %esp */
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rsp,rcx
        movl    $VSYSCALL32_SYSEXIT,%edx        /* User %eip */
+       CFI_REGISTER rip,rdx
        swapgs
        sti             /* sti only takes effect after the next instruction */
        /* sysexit */
        .byte   0xf, 0x35
 
 sysenter_tracesys:
+       CFI_RESTORE_STATE
        SAVE_REST
        CLEAR_RREGS
        movq    $-ENOSYS,RAX(%rsp)      /* really needed? */
@@ -140,21 +161,28 @@ sysenter_tracesys:
  * with the int 0x80 path.     
  */    
 ENTRY(ia32_cstar_target)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rip,rcx
+       /*CFI_REGISTER  rflags,r11*/
        swapgs
        movl    %esp,%r8d
+       CFI_REGISTER    rsp,r8
        movq    %gs:pda_kernelstack,%rsp
        sti
        SAVE_ARGS 8,1,1
        movl    %eax,%eax       /* zero extension */
        movq    %rax,ORIG_RAX-ARGOFFSET(%rsp)
        movq    %rcx,RIP-ARGOFFSET(%rsp)
+       CFI_REL_OFFSET rip,RIP-ARGOFFSET
        movq    %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
        movl    %ebp,%ecx
        movq    $__USER32_CS,CS-ARGOFFSET(%rsp)
        movq    $__USER32_DS,SS-ARGOFFSET(%rsp)
        movq    %r11,EFLAGS-ARGOFFSET(%rsp)
+       /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
        movq    %r8,RSP-ARGOFFSET(%rsp) 
+       CFI_REL_OFFSET rsp,RSP-ARGOFFSET
        /* no need to do an access_ok check here because r8 has been
           32bit zero extended */ 
        /* hardware stack frame is complete now */      
@@ -164,6 +192,7 @@ ENTRY(ia32_cstar_target)
        .previous       
        GET_THREAD_INFO(%r10)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+       CFI_REMEMBER_STATE
        jnz   cstar_tracesys
 cstar_do_call: 
        cmpl $IA32_NR_syscalls,%eax
@@ -177,12 +206,16 @@ cstar_do_call:
        jnz  int_ret_from_sys_call
        RESTORE_ARGS 1,-ARG_SKIP,1,1,1
        movl RIP-ARGOFFSET(%rsp),%ecx
+       CFI_REGISTER rip,rcx
        movl EFLAGS-ARGOFFSET(%rsp),%r11d       
+       /*CFI_REGISTER rflags,r11*/
        movl RSP-ARGOFFSET(%rsp),%esp
+       CFI_RESTORE rsp
        swapgs
        sysretl
        
 cstar_tracesys:        
+       CFI_RESTORE_STATE
        SAVE_REST
        CLEAR_RREGS
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
@@ -226,11 +259,18 @@ ia32_badarg:
  */                            
 
 ENTRY(ia32_syscall)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8-RIP
+       /*CFI_REL_OFFSET        ss,SS-RIP*/
+       CFI_REL_OFFSET  rsp,RSP-RIP
+       /*CFI_REL_OFFSET        rflags,EFLAGS-RIP*/
+       /*CFI_REL_OFFSET        cs,CS-RIP*/
+       CFI_REL_OFFSET  rip,RIP-RIP
        swapgs  
        sti
        movl %eax,%eax
        pushq %rax
+       CFI_ADJUST_CFA_OFFSET 8
        cld
        /* note the registers are not zero extended to the sf.
           this could be a problem. */
@@ -278,6 +318,8 @@ quiet_ni_syscall:
        jmp  ia32_ptregs_common 
        .endm
 
+       CFI_STARTPROC
+
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
        PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
        PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
@@ -290,8 +332,9 @@ quiet_ni_syscall:
        PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
 
 ENTRY(ia32_ptregs_common)
-       CFI_STARTPROC
        popq %r11
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        call *%rax
        RESTORE_REST
index 04d80406ce4fed4c1a6ce646253675c65b074269..5389df610e78277d0a6329f98a16d3f1f52c27d0 100644 (file)
@@ -751,7 +751,7 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
        set_fs(old_fs);
        
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
                
        return ret;
index 1579bdd0adcde450ad0a4991e1b6986895800822..bcdd0a805fe70c7357b0aab2adefa59ab081d31e 100644 (file)
@@ -46,3 +46,4 @@ microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
 intel_cacheinfo-y              += ../../i386/kernel/cpu/intel_cacheinfo.o
 quirks-y                       += ../../i386/kernel/quirks.o
 i8237-y                                += ../../i386/kernel/i8237.o
+msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
index 148f6f7ea315889f1bf0d0d64d92b6b44db7bad2..867a0ebee1773c2a1a678245a665abc8dfbe1df8 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/bootmem.h>
-#include <linux/irq.h>
 #include <linux/acpi.h>
 #include <asm/mpspec.h>
 #include <asm/io.h>
index c9a6b812e926cf3f5c79493433cda35b5c9c7e3b..962ad4823b6a567d4f340bca8d101a2e958dfbd2 100644 (file)
@@ -245,6 +245,8 @@ void __init iommu_hole_init(void)
                
        if (aper_alloc) { 
                /* Got the aperture from the AGP bridge */
+       } else if (swiotlb && !valid_agp) {
+               /* Do nothing */
        } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
                   force_iommu ||
                   valid_agp ||
index 375d369570ca3dbbb365b363585d5b6ecff1ef57..b6e7715d877f38a0d191616c22dc7f9fe98e4509 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -109,11 +108,8 @@ void clear_local_APIC(void)
        if (maxlvt >= 4)
                apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
        v = GET_APIC_VERSION(apic_read(APIC_LVR));
-       if (APIC_INTEGRATED(v)) {       /* !82489DX */
-               if (maxlvt > 3)         /* Due to Pentium errata 3AP and 11AP. */
-                       apic_write(APIC_ESR, 0);
-               apic_read(APIC_ESR);
-       }
+       apic_write(APIC_ESR, 0);
+       apic_read(APIC_ESR);
 }
 
 void __init connect_bsp_APIC(void)
@@ -316,8 +312,6 @@ void __init init_bsp_APIC(void)
         */
        apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
        value = APIC_DM_NMI;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
-               value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 }
 
@@ -325,14 +319,6 @@ void __cpuinit setup_local_APIC (void)
 {
        unsigned int value, ver, maxlvt;
 
-       /* Pound the ESR really hard over the head with a big hammer - mbligh */
-       if (esr_disable) {
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-       }
-
        value = apic_read(APIC_LVR);
        ver = GET_APIC_VERSION(value);
 
@@ -430,15 +416,11 @@ void __cpuinit setup_local_APIC (void)
                value = APIC_DM_NMI;
        else
                value = APIC_DM_NMI | APIC_LVT_MASKED;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
-               value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 
-       if (APIC_INTEGRATED(ver) && !esr_disable) {             /* !82489DX */
+       {
                unsigned oldvalue;
                maxlvt = get_maxlvt();
-               if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
-                       apic_write(APIC_ESR, 0);
                oldvalue = apic_read(APIC_ESR);
                value = ERROR_APIC_VECTOR;      // enables sending errors
                apic_write_around(APIC_LVTERR, value);
@@ -452,17 +434,6 @@ void __cpuinit setup_local_APIC (void)
                        apic_printk(APIC_VERBOSE,
                        "ESR value after enabling vector: %08x, after %08x\n",
                        oldvalue, value);
-       } else {
-               if (esr_disable)        
-                       /* 
-                        * Something untraceble is creating bad interrupts on 
-                        * secondary quads ... for the moment, just leave the
-                        * ESR disabled - we can't do anything useful with the
-                        * errors anyway - mbligh
-                        */
-                       apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
-               else 
-                       apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
        }
 
        nmi_watchdog_default();
@@ -650,8 +621,7 @@ void __init init_apic_mappings(void)
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
-       if (boot_cpu_id == -1U)
-               boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+       boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
 
 #ifdef CONFIG_X86_IO_APIC
        {
@@ -693,8 +663,6 @@ static void __setup_APIC_LVTT(unsigned int clocks)
 
        ver = GET_APIC_VERSION(apic_read(APIC_LVR));
        lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-       if (!APIC_INTEGRATED(ver))
-               lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
        apic_write_around(APIC_LVTT, lvtt_value);
 
        /*
@@ -1081,7 +1049,7 @@ int __init APIC_init_uniprocessor (void)
 
        connect_bsp_APIC();
 
-       phys_cpu_present_map = physid_mask_of_physid(0);
+       phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
        apic_write_around(APIC_ID, boot_cpu_id);
 
        setup_local_APIC();
index 35b4c3fcbb37ff95dbd556b87da576db49cfe3ba..aaa6d383351798dca10eb8f7402a5c90a0ac1f95 100644 (file)
@@ -39,7 +39,6 @@ int main(void)
        ENTRY(kernelstack); 
        ENTRY(oldrsp); 
        ENTRY(pcurrent); 
-       ENTRY(irqrsp);
        ENTRY(irqcount);
        ENTRY(cpunumber);
        ENTRY(irqstackptr);
index d7fa4248501cc300ad4470fc38820b16a6a57c8c..535e04466079857a09d3f9b0c6649f15f36301e6 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/kexec.h>
 
index bb0ae18ec02b90efd04cbf7cce43f0490095fa88..eb7929eea7b33c4743b533a0d39bf8c22c42707c 100644 (file)
@@ -131,7 +131,7 @@ void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned lon
 
                if (ei->type != E820_RAM || 
                    ei->addr+ei->size <= start || 
-                   ei->addr > end)
+                   ei->addr >= end)
                        continue;
 
                addr = round_up(ei->addr, PAGE_SIZE);
index 9631c747c5e3750580cf06dea4b0e8e1324a757f..9cd968dd0f5a4bd3b9d4b83525f94ee5386fec14 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <asm/fcntl.h>
 
 /* Simple VGA output */
 
@@ -158,6 +159,47 @@ static struct console early_serial_console = {
        .index =        -1,
 };
 
+/* Console interface to a host file on AMD's SimNow! */
+
+static int simnow_fd;
+
+enum {
+       MAGIC1 = 0xBACCD00A,
+       MAGIC2 = 0xCA110000,
+       XOPEN = 5,
+       XWRITE = 4,
+};
+
+static noinline long simnow(long cmd, long a, long b, long c)
+{
+       long ret;
+       asm volatile("cpuid" :
+                    "=a" (ret) :
+                    "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+       return ret;
+}
+
+void __init simnow_init(char *str)
+{
+       char *fn = "klog";
+       if (*str == '=')
+               fn = ++str;
+       /* error ignored */
+       simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
+}
+
+static void simnow_write(struct console *con, const char *s, unsigned n)
+{
+       simnow(XWRITE, simnow_fd, (unsigned long)s, n);
+}
+
+static struct console simnow_console = {
+       .name =         "simnow",
+       .write =        simnow_write,
+       .flags =        CON_PRINTBUFFER,
+       .index =        -1,
+};
+
 /* Direct interface for emergencies */
 struct console *early_console = &early_vga_console;
 static int early_console_initialized = 0;
@@ -205,6 +247,10 @@ int __init setup_early_printk(char *opt)
                max_xpos = SCREEN_INFO.orig_video_cols;
                max_ypos = SCREEN_INFO.orig_video_lines;
                early_console = &early_vga_console; 
+       } else if (!strncmp(buf, "simnow", 6)) {
+               simnow_init(buf + 6);
+               early_console = &simnow_console;
+               keep_early = 1;
        }
        early_console_initialized = 1;
        register_console(early_console);       
index 3620508c8bd9b29e26bcf73892f8c4f88f8800bf..7937971d1853bd5187cfe615e24c4a5cf35689be 100644 (file)
        xorl %eax, %eax
        pushq %rax /* ss */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        ss,0*/
        pushq %rax /* rsp */
        CFI_ADJUST_CFA_OFFSET   8
-       CFI_OFFSET      rip,0
+       CFI_REL_OFFSET  rsp,0
        pushq $(1<<9) /* eflags - interrupts on */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        rflags,0*/
        pushq $__KERNEL_CS /* cs */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        cs,0*/
        pushq \child_rip /* rip */
        CFI_ADJUST_CFA_OFFSET   8
-       CFI_OFFSET      rip,0
+       CFI_REL_OFFSET  rip,0
        pushq   %rax /* orig rax */
        CFI_ADJUST_CFA_OFFSET   8
        .endm
        CFI_ADJUST_CFA_OFFSET   -(6*8)
        .endm
 
-       .macro  CFI_DEFAULT_STACK
-       CFI_ADJUST_CFA_OFFSET  (SS)
-       CFI_OFFSET      r15,R15-SS
-       CFI_OFFSET      r14,R14-SS
-       CFI_OFFSET      r13,R13-SS
-       CFI_OFFSET      r12,R12-SS
-       CFI_OFFSET      rbp,RBP-SS
-       CFI_OFFSET      rbx,RBX-SS
-       CFI_OFFSET      r11,R11-SS
-       CFI_OFFSET      r10,R10-SS
-       CFI_OFFSET      r9,R9-SS
-       CFI_OFFSET      r8,R8-SS
-       CFI_OFFSET      rax,RAX-SS
-       CFI_OFFSET      rcx,RCX-SS
-       CFI_OFFSET      rdx,RDX-SS
-       CFI_OFFSET      rsi,RSI-SS
-       CFI_OFFSET      rdi,RDI-SS
-       CFI_OFFSET      rsp,RSP-SS
-       CFI_OFFSET      rip,RIP-SS
+       .macro  CFI_DEFAULT_STACK start=1
+       .if \start
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8
+       .else
+       CFI_DEF_CFA_OFFSET SS+8
+       .endif
+       CFI_REL_OFFSET  r15,R15
+       CFI_REL_OFFSET  r14,R14
+       CFI_REL_OFFSET  r13,R13
+       CFI_REL_OFFSET  r12,R12
+       CFI_REL_OFFSET  rbp,RBP
+       CFI_REL_OFFSET  rbx,RBX
+       CFI_REL_OFFSET  r11,R11
+       CFI_REL_OFFSET  r10,R10
+       CFI_REL_OFFSET  r9,R9
+       CFI_REL_OFFSET  r8,R8
+       CFI_REL_OFFSET  rax,RAX
+       CFI_REL_OFFSET  rcx,RCX
+       CFI_REL_OFFSET  rdx,RDX
+       CFI_REL_OFFSET  rsi,RSI
+       CFI_REL_OFFSET  rdi,RDI
+       CFI_REL_OFFSET  rip,RIP
+       /*CFI_REL_OFFSET        cs,CS*/
+       /*CFI_REL_OFFSET        rflags,EFLAGS*/
+       CFI_REL_OFFSET  rsp,RSP
+       /*CFI_REL_OFFSET        ss,SS*/
        .endm
 /*
  * A newly forked process directly context switches into this.
  */    
 /* rdi:        prev */ 
 ENTRY(ret_from_fork)
-       CFI_STARTPROC
        CFI_DEFAULT_STACK
        call schedule_tail
        GET_THREAD_INFO(%rcx)
@@ -172,16 +182,21 @@ rff_trace:
  */                                    
 
 ENTRY(system_call)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rip,rcx
+       /*CFI_REGISTER  rflags,r11*/
        swapgs
        movq    %rsp,%gs:pda_oldrsp 
        movq    %gs:pda_kernelstack,%rsp
        sti                                     
        SAVE_ARGS 8,1
        movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
-       movq  %rcx,RIP-ARGOFFSET(%rsp)  
+       movq  %rcx,RIP-ARGOFFSET(%rsp)
+       CFI_REL_OFFSET rip,RIP-ARGOFFSET
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+       CFI_REMEMBER_STATE
        jnz tracesys
        cmpq $__NR_syscall_max,%rax
        ja badsys
@@ -201,9 +216,12 @@ sysret_check:
        cli
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
+       CFI_REMEMBER_STATE
        jnz  sysret_careful 
        movq RIP-ARGOFFSET(%rsp),%rcx
+       CFI_REGISTER    rip,rcx
        RESTORE_ARGS 0,-ARG_SKIP,1
+       /*CFI_REGISTER  rflags,r11*/
        movq    %gs:pda_oldrsp,%rsp
        swapgs
        sysretq
@@ -211,12 +229,15 @@ sysret_check:
        /* Handle reschedules */
        /* edx: work, edi: workmask */  
 sysret_careful:
+       CFI_RESTORE_STATE
        bt $TIF_NEED_RESCHED,%edx
        jnc sysret_signal
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        call schedule
        popq  %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        jmp sysret_check
 
        /* Handle a signal */ 
@@ -234,8 +255,13 @@ sysret_signal:
 1:     movl $_TIF_NEED_RESCHED,%edi
        jmp sysret_check
        
+badsys:
+       movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+       jmp ret_from_sys_call
+
        /* Do syscall tracing */
 tracesys:                       
+       CFI_RESTORE_STATE
        SAVE_REST
        movq $-ENOSYS,RAX(%rsp)
        FIXUP_TOP_OF_STACK %rdi
@@ -254,16 +280,29 @@ tracesys:
        RESTORE_TOP_OF_STACK %rbx
        RESTORE_REST
        jmp ret_from_sys_call
+       CFI_ENDPROC
                
-badsys:
-       movq $-ENOSYS,RAX-ARGOFFSET(%rsp)       
-       jmp ret_from_sys_call
-
 /* 
  * Syscall return path ending with IRET.
  * Has correct top of stack, but partial stack frame.
  */    
-ENTRY(int_ret_from_sys_call)   
+ENTRY(int_ret_from_sys_call)
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
+       /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
+       CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
+       /*CFI_REL_OFFSET        rflags,EFLAGS-ARGOFFSET*/
+       /*CFI_REL_OFFSET        cs,CS-ARGOFFSET*/
+       CFI_REL_OFFSET  rip,RIP-ARGOFFSET
+       CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
+       CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
+       CFI_REL_OFFSET  rax,RAX-ARGOFFSET
+       CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
+       CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
+       CFI_REL_OFFSET  r8,R8-ARGOFFSET
+       CFI_REL_OFFSET  r9,R9-ARGOFFSET
+       CFI_REL_OFFSET  r10,R10-ARGOFFSET
+       CFI_REL_OFFSET  r11,R11-ARGOFFSET
        cli
        testl $3,CS-ARGOFFSET(%rsp)
        je retint_restore_args
@@ -284,8 +323,10 @@ int_careful:
        jnc  int_very_careful
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        call schedule
        popq %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        cli
        jmp int_with_check
 
@@ -297,9 +338,11 @@ int_very_careful:
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
        jz int_signal
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        leaq 8(%rsp),%rdi       # &ptregs -> arg1       
        call syscall_trace_leave
        popq %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
        cli
        jmp int_restore_rest
@@ -329,6 +372,8 @@ int_restore_rest:
        jmp     ptregscall_common
        .endm
 
+       CFI_STARTPROC
+
        PTREGSCALL stub_clone, sys_clone, %r8
        PTREGSCALL stub_fork, sys_fork, %rdi
        PTREGSCALL stub_vfork, sys_vfork, %rdi
@@ -337,40 +382,49 @@ int_restore_rest:
        PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
-       CFI_STARTPROC
        popq %r11
-       CFI_ADJUST_CFA_OFFSET   -8
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        movq %r11, %r15
+       CFI_REGISTER rip, r15
        FIXUP_TOP_OF_STACK %r11
        call *%rax
        RESTORE_TOP_OF_STACK %r11
        movq %r15, %r11
+       CFI_REGISTER rip, r11
        RESTORE_REST
        pushq %r11
-       CFI_ADJUST_CFA_OFFSET   8
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip, 0
        ret
        CFI_ENDPROC
        
 ENTRY(stub_execve)
        CFI_STARTPROC
        popq %r11
-       CFI_ADJUST_CFA_OFFSET   -8
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        movq %r11, %r15
+       CFI_REGISTER rip, r15
        FIXUP_TOP_OF_STACK %r11
        call sys_execve
        GET_THREAD_INFO(%rcx)
        bt $TIF_IA32,threadinfo_flags(%rcx)
+       CFI_REMEMBER_STATE
        jc exec_32bit
        RESTORE_TOP_OF_STACK %r11
        movq %r15, %r11
+       CFI_REGISTER rip, r11
        RESTORE_REST
-       push %r11
+       pushq %r11
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip, 0
        ret
 
 exec_32bit:
-       CFI_ADJUST_CFA_OFFSET   REST_SKIP
+       CFI_RESTORE_STATE
        movq %rax,RAX(%rsp)
        RESTORE_REST
        jmp int_ret_from_sys_call
@@ -382,7 +436,8 @@ exec_32bit:
  */                
 ENTRY(stub_rt_sigreturn)
        CFI_STARTPROC
-       addq $8, %rsp           
+       addq $8, %rsp
+       CFI_ADJUST_CFA_OFFSET   -8
        SAVE_REST
        movq %rsp,%rdi
        FIXUP_TOP_OF_STACK %r11
@@ -392,6 +447,25 @@ ENTRY(stub_rt_sigreturn)
        jmp int_ret_from_sys_call
        CFI_ENDPROC
 
+/*
+ * initial frame state for interrupts and exceptions
+ */
+       .macro _frame ref
+       CFI_STARTPROC simple
+       CFI_DEF_CFA rsp,SS+8-\ref
+       /*CFI_REL_OFFSET ss,SS-\ref*/
+       CFI_REL_OFFSET rsp,RSP-\ref
+       /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+       /*CFI_REL_OFFSET cs,CS-\ref*/
+       CFI_REL_OFFSET rip,RIP-\ref
+       .endm
+
+/* initial frame state for interrupts (and exceptions without error code) */
+#define INTR_FRAME _frame RIP
+/* initial frame state for exceptions with error code (and interrupts with
+   vector already pushed) */
+#define XCPT_FRAME _frame ORIG_RAX
+
 /* 
  * Interrupt entry/exit.
  *
@@ -402,10 +476,6 @@ ENTRY(stub_rt_sigreturn)
 
 /* 0(%rsp): interrupt number */ 
        .macro interrupt func
-       CFI_STARTPROC   simple
-       CFI_DEF_CFA     rsp,(SS-RDI)
-       CFI_REL_OFFSET  rsp,(RSP-ORIG_RAX)
-       CFI_REL_OFFSET  rip,(RIP-ORIG_RAX)
        cld
 #ifdef CONFIG_DEBUG_INFO
        SAVE_ALL        
@@ -425,23 +495,27 @@ ENTRY(stub_rt_sigreturn)
        swapgs  
 1:     incl    %gs:pda_irqcount        # RED-PEN should check preempt count
        movq %gs:pda_irqstackptr,%rax
-       cmoveq %rax,%rsp                                                        
+       cmoveq %rax,%rsp /*todo This needs CFI annotation! */
        pushq %rdi                      # save old stack        
+       CFI_ADJUST_CFA_OFFSET   8
        call \func
        .endm
 
 ENTRY(common_interrupt)
+       XCPT_FRAME
        interrupt do_IRQ
        /* 0(%rsp): oldrsp-ARGOFFSET */
-ret_from_intr:         
+ret_from_intr:
        popq  %rdi
+       CFI_ADJUST_CFA_OFFSET   -8
        cli     
        decl %gs:pda_irqcount
 #ifdef CONFIG_DEBUG_INFO
        movq RBP(%rdi),%rbp
+       CFI_DEF_CFA_REGISTER    rsp
 #endif
-       leaq ARGOFFSET(%rdi),%rsp
-exit_intr:             
+       leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
+exit_intr:
        GET_THREAD_INFO(%rcx)
        testl $3,CS-ARGOFFSET(%rsp)
        je retint_kernel
@@ -453,9 +527,10 @@ exit_intr:
         */             
 retint_with_reschedule:
        movl $_TIF_WORK_MASK,%edi
-retint_check:                  
+retint_check:
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
+       CFI_REMEMBER_STATE
        jnz  retint_careful
 retint_swapgs:         
        swapgs 
@@ -476,14 +551,17 @@ bad_iret:
        jmp do_exit                     
        .previous       
        
-       /* edi: workmask, edx: work */  
+       /* edi: workmask, edx: work */
 retint_careful:
+       CFI_RESTORE_STATE
        bt    $TIF_NEED_RESCHED,%edx
        jnc   retint_signal
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET   8
        call  schedule
        popq %rdi               
+       CFI_ADJUST_CFA_OFFSET   -8
        GET_THREAD_INFO(%rcx)
        cli
        jmp retint_check
@@ -523,7 +601,9 @@ retint_kernel:
  * APIC interrupts.
  */            
        .macro apicinterrupt num,func
+       INTR_FRAME
        pushq $\num-256
+       CFI_ADJUST_CFA_OFFSET 8
        interrupt \func
        jmp ret_from_intr
        CFI_ENDPROC
@@ -536,8 +616,19 @@ ENTRY(thermal_interrupt)
 ENTRY(reschedule_interrupt)
        apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
 
-ENTRY(invalidate_interrupt)
-       apicinterrupt INVALIDATE_TLB_VECTOR,smp_invalidate_interrupt
+       .macro INVALIDATE_ENTRY num
+ENTRY(invalidate_interrupt\num)
+       apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt 
+       .endm
+
+       INVALIDATE_ENTRY 0
+       INVALIDATE_ENTRY 1
+       INVALIDATE_ENTRY 2
+       INVALIDATE_ENTRY 3
+       INVALIDATE_ENTRY 4
+       INVALIDATE_ENTRY 5
+       INVALIDATE_ENTRY 6
+       INVALIDATE_ENTRY 7
 
 ENTRY(call_function_interrupt)
        apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
@@ -558,16 +649,23 @@ ENTRY(spurious_interrupt)
  * Exception entry points.
  */            
        .macro zeroentry sym
+       INTR_FRAME
        pushq $0        /* push error code/oldrax */ 
+       CFI_ADJUST_CFA_OFFSET 8
        pushq %rax      /* push real oldrax to the rdi slot */ 
+       CFI_ADJUST_CFA_OFFSET 8
        leaq  \sym(%rip),%rax
        jmp error_entry
+       CFI_ENDPROC
        .endm   
 
        .macro errorentry sym
+       XCPT_FRAME
        pushq %rax
+       CFI_ADJUST_CFA_OFFSET 8
        leaq  \sym(%rip),%rax
        jmp error_entry
+       CFI_ENDPROC
        .endm
 
        /* error code is on the stack already */
@@ -594,10 +692,7 @@ ENTRY(spurious_interrupt)
  * and the exception handler in %rax.  
  */                                            
 ENTRY(error_entry)
-       CFI_STARTPROC   simple
-       CFI_DEF_CFA     rsp,(SS-RDI)
-       CFI_REL_OFFSET  rsp,(RSP-RDI)
-       CFI_REL_OFFSET  rip,(RIP-RDI)
+       _frame RDI
        /* rdi slot contains rax, oldrax contains error code */
        cld     
        subq  $14*8,%rsp
@@ -679,7 +774,9 @@ error_kernelspace:
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
 ENTRY(load_gs_index)
+       CFI_STARTPROC
        pushf
+       CFI_ADJUST_CFA_OFFSET 8
        cli
         swapgs
 gs_change:     
@@ -687,7 +784,9 @@ gs_change:
 2:     mfence          /* workaround */
        swapgs
         popf
+       CFI_ADJUST_CFA_OFFSET -8
         ret
+       CFI_ENDPROC
        
         .section __ex_table,"a"
         .align 8
@@ -799,7 +898,7 @@ ENTRY(device_not_available)
 
        /* runs on exception stack */
 KPROBE_ENTRY(debug)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug
@@ -809,9 +908,9 @@ KPROBE_ENTRY(debug)
 
        /* runs on exception stack */   
 ENTRY(nmi)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $-1
-       CFI_ADJUST_CFA_OFFSET 8         
+       CFI_ADJUST_CFA_OFFSET 8
        paranoidentry do_nmi
        /*
         * "Paranoid" exit path from exception stack.
@@ -877,7 +976,7 @@ ENTRY(reserved)
 
        /* runs on exception stack */
 ENTRY(double_fault)
-       CFI_STARTPROC
+       XCPT_FRAME
        paranoidentry do_double_fault
        jmp paranoid_exit
        CFI_ENDPROC
@@ -890,7 +989,7 @@ ENTRY(segment_not_present)
 
        /* runs on exception stack */
 ENTRY(stack_segment)
-       CFI_STARTPROC
+       XCPT_FRAME
        paranoidentry do_stack_segment
        jmp paranoid_exit
        CFI_ENDPROC
@@ -911,7 +1010,7 @@ ENTRY(spurious_interrupt_bug)
 #ifdef CONFIG_X86_MCE
        /* runs on exception stack */
 ENTRY(machine_check)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8 
        paranoidentry do_machine_check
@@ -923,14 +1022,19 @@ ENTRY(call_debug)
        zeroentry do_call_debug
 
 ENTRY(call_softirq)
+       CFI_STARTPROC
        movq %gs:pda_irqstackptr,%rax
        pushq %r15
+       CFI_ADJUST_CFA_OFFSET 8
        movq %rsp,%r15
+       CFI_DEF_CFA_REGISTER    r15
        incl %gs:pda_irqcount
        cmove %rax,%rsp
        call __do_softirq
        movq %r15,%rsp
+       CFI_DEF_CFA_REGISTER    rsp
        decl %gs:pda_irqcount
        popq %r15
+       CFI_ADJUST_CFA_OFFSET -8
        ret
-
+       CFI_ENDPROC
index b1c144f73149854da5e9bb277e4309e281b60ba3..7a64ea181788c62e3c6a8e9e07a378ffa0a23ac0 100644 (file)
@@ -45,7 +45,7 @@ void __init clustered_apic_check(void)
        u8 clusters, max_cluster;
        u8 id;
        u8 cluster_cnt[NUM_APIC_CLUSTERS];
-       int num_cpus = 0;
+       int max_apic = 0;
 
 #if defined(CONFIG_ACPI)
        /*
@@ -64,14 +64,15 @@ void __init clustered_apic_check(void)
                id = bios_cpu_apicid[i];
                if (id == BAD_APICID)
                        continue;
-               num_cpus++;
+               if (id > max_apic)
+                       max_apic = id;
                cluster_cnt[APIC_CLUSTERID(id)]++;
        }
 
        /* Don't use clustered mode on AMD platforms. */
        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
                genapic = &apic_physflat;
-#ifndef CONFIG_CPU_HOTPLUG
+#ifndef CONFIG_HOTPLUG_CPU
                /* In the CPU hotplug case we cannot use broadcast mode
                   because that opens a race when a CPU is removed.
                   Stay at physflat mode in this case.
@@ -79,7 +80,7 @@ void __init clustered_apic_check(void)
                   we have ACPI platform support for CPU hotplug
                   we should detect hotplug capablity from ACPI tables and
                   only do this when really needed. -AK */
-               if (num_cpus <= 8)
+               if (max_apic <= 8)
                        genapic = &apic_flat;
 #endif
                goto print;
@@ -103,9 +104,14 @@ void __init clustered_apic_check(void)
         * (We don't use lowest priority delivery + HW APIC IRQ steering, so
         * can ignore the clustered logical case and go straight to physical.)
         */
-       if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
+       if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
+#ifdef CONFIG_HOTPLUG_CPU
+               /* Don't use APIC shortcuts in CPU hotplug to avoid races */
+               genapic = &apic_physflat;
+#else
                genapic = &apic_flat;
-       else
+#endif
+       } else
                genapic = &apic_cluster;
 
 print:
index f6523dd1bc0938fb6f21ff811af0b8292d77ca46..a472d62f899a87a8037a737663c09c3f507bbd77 100644 (file)
@@ -51,10 +51,10 @@ static void cluster_init_apic_ldr(void)
                count = 3;
        id = my_cluster | (1UL << count);
        x86_cpu_to_log_apicid[smp_processor_id()] = id;
-       apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+       apic_write(APIC_DFR, APIC_DFR_CLUSTER);
        val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
        val |= SET_APIC_LOGICAL_ID(id);
-       apic_write_around(APIC_LDR, val);
+       apic_write(APIC_LDR, val);
 }
 
 /* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
index 6d57da96bf8c7e6ad655ffb78fd635727e65bb67..9da3edb799ea543042776664db789a59b7418163 100644 (file)
@@ -38,10 +38,10 @@ static void flat_init_apic_ldr(void)
        num = smp_processor_id();
        id = 1UL << num;
        x86_cpu_to_log_apicid[num] = id;
-       apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+       apic_write(APIC_DFR, APIC_DFR_FLAT);
        val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
        val |= SET_APIC_LOGICAL_ID(id);
-       apic_write_around(APIC_LDR, val);
+       apic_write(APIC_LDR, val);
 }
 
 static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
@@ -62,7 +62,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
         * prepare target chip field
         */
        cfg = __prepare_ICR2(mask);
-       apic_write_around(APIC_ICR2, cfg);
+       apic_write(APIC_ICR2, cfg);
 
        /*
         * program the ICR
@@ -72,7 +72,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write_around(APIC_ICR, cfg);
+       apic_write(APIC_ICR, cfg);
        local_irq_restore(flags);
 }
 
@@ -177,9 +177,9 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
 
 struct genapic apic_physflat =  {
        .name = "physical flat",
-       .int_delivery_mode = dest_LowestPrio,
+       .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST,
+       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
        .target_cpus = physflat_target_cpus,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
index 98ff5eb32b9af5db22035c0da04cfe2bf9764367..4592bf21fcafa32e34d580a113255e6f61d1b754 100644 (file)
@@ -270,7 +270,7 @@ ENTRY(level3_kernel_pgt)
 .org 0x4000
 ENTRY(level2_ident_pgt)
        /* 40MB for bootup.     */
-       .quad   0x0000000000000283
+       .quad   0x0000000000000183
        .quad   0x0000000000200183
        .quad   0x0000000000400183
        .quad   0x0000000000600183
index a891690951299912495b8da4915210e73b524988..b2a238b5a17ed36cc7a071be01f62231d80cc5c0 100644 (file)
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/apic.h>
 
-#include <linux/irq.h>
-
 /*
  * Common place to define all x86 IRQ vectors
  *
@@ -486,7 +483,14 @@ void spurious_interrupt(void);
 void error_interrupt(void);
 void reschedule_interrupt(void);
 void call_function_interrupt(void);
-void invalidate_interrupt(void);
+void invalidate_interrupt0(void);
+void invalidate_interrupt1(void);
+void invalidate_interrupt2(void);
+void invalidate_interrupt3(void);
+void invalidate_interrupt4(void);
+void invalidate_interrupt5(void);
+void invalidate_interrupt6(void);
+void invalidate_interrupt7(void);
 void thermal_interrupt(void);
 void i8254_timer_resume(void);
 
@@ -562,8 +566,15 @@ void __init init_IRQ(void)
         */
        set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
 
-       /* IPI for invalidation */
-       set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+       /* IPIs for invalidation */
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
 
        /* IPI for generic function call */
        set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
index c4dc9149115741cf4b48c385adf8a49ec91979a8..e0ba5c1043fd23f71e48e236aebcb18b41d3934a 100644 (file)
@@ -44,6 +44,6 @@ EXPORT_SYMBOL(init_task);
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
 
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
index 5f1529be1237495ba9a81757ec91c89c684dc1ef..522944a000ad9c8755ad529ba0c74bff3353c897 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -45,6 +44,8 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
 
 static int no_timer_check;
 
+int disable_timer_pin_1 __initdata;
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -298,6 +299,15 @@ void __init check_ioapic(void)
 #endif
                                        /* RED-PEN skip them on mptables too? */
                                        return;
+                               case PCI_VENDOR_ID_ATI:
+                                       /* All timer interrupts on atiixp
+                                          are doubled. Disable one. */
+                                       if (disable_timer_pin_1 == 0) {
+                                               disable_timer_pin_1 = 1;
+                                               printk(KERN_INFO
+               "ATI board detected. Disabling timer pin 1.\n");
+                                       }
+                                       return;
                                } 
 
                                /* No multi-function device? */
@@ -1022,13 +1032,11 @@ void __apicdebuginit print_local_APIC(void * dummy)
        v = apic_read(APIC_TASKPRI);
        printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
-       if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
-               v = apic_read(APIC_ARBPRI);
-               printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-                       v & APIC_ARBPRI_MASK);
-               v = apic_read(APIC_PROCPRI);
-               printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
-       }
+       v = apic_read(APIC_ARBPRI);
+       printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+               v & APIC_ARBPRI_MASK);
+       v = apic_read(APIC_PROCPRI);
+       printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
 
        v = apic_read(APIC_EOI);
        printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
@@ -1048,12 +1056,8 @@ void __apicdebuginit print_local_APIC(void * dummy)
        printk(KERN_DEBUG "... APIC IRR field:\n");
        print_APIC_bitfield(APIC_IRR);
 
-       if (APIC_INTEGRATED(ver)) {             /* !82489DX */
-               if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
-                       apic_write(APIC_ESR, 0);
-               v = apic_read(APIC_ESR);
-               printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
-       }
+       v = apic_read(APIC_ESR);
+       printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
 
        v = apic_read(APIC_ICR);
        printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
@@ -1665,6 +1669,8 @@ static inline void check_timer(void)
                                setup_nmi();
                                enable_8259A_irq(0);
                        }
+                       if (disable_timer_pin_1 > 0)
+                               clear_IO_APIC_pin(0, pin1);
                        return;
                }
                clear_IO_APIC_pin(0, pin1);
index 849a20aec7ca05e4cb5067f44010e2ca830f34e6..d6a04a8320a38d475a3780488b856ecba23fe66b 100644 (file)
@@ -99,7 +99,6 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
        unsigned irq = regs->orig_rax & 0xff;
 
        irq_enter();
-       BUG_ON(irq > 256);
 
        __do_IRQ(irq, regs);
        irq_exit();
index 8aa56736cde3805fe8b38b84733e176914ae14be..969365c0771b242f5b64071e294bba4cd114fca9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/cpu.h>
 #include <linux/percpu.h>
+#include <linux/ctype.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -56,15 +57,19 @@ void mce_log(struct mce *mce)
        smp_wmb();
        for (;;) {
                entry = rcu_dereference(mcelog.next);
-               /* When the buffer fills up discard new entries. Assume 
-                  that the earlier errors are the more interesting. */
-               if (entry >= MCE_LOG_LEN) {
-                       set_bit(MCE_OVERFLOW, &mcelog.flags);
-                       return;
+               for (;;) {
+                       /* When the buffer fills up discard new entries. Assume
+                          that the earlier errors are the more interesting. */
+                       if (entry >= MCE_LOG_LEN) {
+                               set_bit(MCE_OVERFLOW, &mcelog.flags);
+                               return;
+                       }
+                       /* Old left over entry. Skip. */
+                       if (mcelog.entry[entry].finished) {
+                               entry++;
+                               continue;
+                       }
                }
-               /* Old left over entry. Skip. */
-               if (mcelog.entry[entry].finished)
-                       continue;
                smp_rmb();
                next = entry + 1;
                if (cmpxchg(&mcelog.next, entry, next) == entry)
@@ -404,9 +409,15 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
        }
 
        err = 0;
-       for (i = 0; i < next; i++) {
-               if (!mcelog.entry[i].finished)
-                       continue;
+       for (i = 0; i < next; i++) {            
+               unsigned long start = jiffies;
+               while (!mcelog.entry[i].finished) {
+                       if (!time_before(jiffies, start + 2)) {
+                               memset(mcelog.entry + i,0, sizeof(struct mce));
+                               continue;
+                       }
+                       cpu_relax();
+               }
                smp_rmb();
                err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
                buf += sizeof(struct mce); 
@@ -479,6 +490,7 @@ static int __init mcheck_disable(char *str)
 
 /* mce=off disables machine check. Note you can reenable it later
    using sysfs.
+   mce=TOLERANCELEVEL (number, see above)
    mce=bootlog Log MCEs from before booting. Disabled by default to work
    around buggy BIOS that leave bogus MCEs.  */
 static int __init mcheck_enable(char *str)
@@ -489,6 +501,8 @@ static int __init mcheck_enable(char *str)
                mce_dont_init = 1;
        else if (!strcmp(str, "bootlog"))
                mce_bootlog = 1;
+       else if (isdigit(str[0]))
+               get_option(&str, &tolerant);
        else
                printk("mce= argument %s ignored. Please use /sys", str); 
        return 0;
@@ -501,10 +515,12 @@ __setup("mce", mcheck_enable);
  * Sysfs support
  */ 
 
-/* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
+/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
+   Only one CPU is active at this time, the others get readded later using
+   CPU hotplug. */
 static int mce_resume(struct sys_device *dev)
 {
-       on_each_cpu(mce_init, NULL, 1, 1);
+       mce_init(NULL);
        return 0;
 }
 
index 8d8ed6ae1d0c8d880f96558b7a8f865a80ea2ac5..f16d38d09dafeadcafc6d1e6413617c96eeeb8d4 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/config.h>
@@ -46,8 +45,6 @@ int acpi_found_madt;
 int apic_version [MAX_APICS];
 unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-unsigned char pci_bus_to_node [256];
-EXPORT_SYMBOL(pci_bus_to_node);
 
 static int mp_current_pci_id = 0;
 /* I/O APIC entries */
@@ -705,7 +702,7 @@ void __init mp_register_lapic (
 
        processor.mpc_type = MP_PROCESSOR;
        processor.mpc_apicid = id;
-       processor.mpc_apicver = 0x10; /* TBD: lapic version */
+       processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
        processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
        processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
        processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
deleted file mode 100644 (file)
index 598953a..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *   
- *   Copyright 2000 H. Peter Anvin - 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, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * msr.c
- *
- * x86 MSR access device
- *
- * This device is accessed by lseek() to the appropriate register number
- * and then read/write in chunks of 8 bytes.  A larger size means multiple
- * reads or writes of the same register.
- *
- * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
- * an SMP box will direct the access to CPU %d.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* Note: "err" is handled in a funny way below.  Otherwise one version
-   of gcc or another breaks. */
-
-static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
-{
-       int err;
-
-       asm volatile ("1:       wrmsr\n"
-                     "2:\n"
-                     ".section .fixup,\"ax\"\n"
-                     "3:       movl %4,%0\n"
-                     " jmp 2b\n"
-                     ".previous\n"
-                     ".section __ex_table,\"a\"\n"
-                     " .align 8\n" "   .quad 1b,3b\n" ".previous":"=&bDS" (err)
-                     :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
-
-       return err;
-}
-
-static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
-{
-       int err;
-
-       asm volatile ("1:       rdmsr\n"
-                     "2:\n"
-                     ".section .fixup,\"ax\"\n"
-                     "3:       movl %4,%0\n"
-                     " jmp 2b\n"
-                     ".previous\n"
-                     ".section __ex_table,\"a\"\n"
-                     " .align 8\n"
-                     " .quad 1b,3b\n"
-                     ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
-                     :"c"(reg), "i"(-EIO), "0"(0));
-
-       return err;
-}
-
-#ifdef CONFIG_SMP
-
-struct msr_command {
-       int cpu;
-       int err;
-       u32 reg;
-       u32 data[2];
-};
-
-static void msr_smp_wrmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
-}
-
-static void msr_smp_rdmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
-}
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = wrmsr_eio(reg, eax, edx);
-       } else {
-               cmd.cpu = cpu;
-               cmd.reg = reg;
-               cmd.data[0] = eax;
-               cmd.data[1] = edx;
-
-               smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = rdmsr_eio(reg, eax, edx);
-       } else {
-               cmd.cpu = cpu;
-               cmd.reg = reg;
-
-               smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-
-               *eax = cmd.data[0];
-               *edx = cmd.data[1];
-
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-#else                          /* ! CONFIG_SMP */
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       return wrmsr_eio(reg, eax, edx);
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
-{
-       return rdmsr_eio(reg, eax, edx);
-}
-
-#endif                         /* ! CONFIG_SMP */
-
-static loff_t msr_seek(struct file *file, loff_t offset, int orig)
-{
-       loff_t ret = -EINVAL;
-
-       lock_kernel();
-       switch (orig) {
-       case 0:
-               file->f_pos = offset;
-               ret = file->f_pos;
-               break;
-       case 1:
-               file->f_pos += offset;
-               ret = file->f_pos;
-       }
-       unlock_kernel();
-       return ret;
-}
-
-static ssize_t msr_read(struct file *file, char __user * buf,
-                       size_t count, loff_t * ppos)
-{
-       u32 __user *tmp = (u32 __user *) buf;
-       u32 data[2];
-       size_t rv;
-       u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
-       int err;
-
-       if (count % 8)
-               return -EINVAL; /* Invalid chunk size */
-
-       for (rv = 0; count; count -= 8) {
-               err = do_rdmsr(cpu, reg, &data[0], &data[1]);
-               if (err)
-                       return err;
-               if (copy_to_user(tmp, &data, 8))
-                       return -EFAULT;
-               tmp += 2;
-       }
-
-       return ((char __user *)tmp) - buf;
-}
-
-static ssize_t msr_write(struct file *file, const char __user *buf,
-                        size_t count, loff_t *ppos)
-{
-       const u32 __user *tmp = (const u32 __user *)buf;
-       u32 data[2];
-       size_t rv;
-       u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
-       int err;
-
-       if (count % 8)
-               return -EINVAL; /* Invalid chunk size */
-
-       for (rv = 0; count; count -= 8) {
-               if (copy_from_user(&data, tmp, 8))
-                       return -EFAULT;
-               err = do_wrmsr(cpu, reg, data[0], data[1]);
-               if (err)
-                       return err;
-               tmp += 2;
-       }
-
-       return ((char __user *)tmp) - buf;
-}
-
-static int msr_open(struct inode *inode, struct file *file)
-{
-       unsigned int cpu = iminor(file->f_dentry->d_inode);
-       struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-
-       if (cpu >= NR_CPUS || !cpu_online(cpu))
-               return -ENXIO;  /* No such CPU */
-       if (!cpu_has(c, X86_FEATURE_MSR))
-               return -EIO;    /* MSR not supported */
-
-       return 0;
-}
-
-/*
- * File operations we support
- */
-static struct file_operations msr_fops = {
-       .owner = THIS_MODULE,
-       .llseek = msr_seek,
-       .read = msr_read,
-       .write = msr_write,
-       .open = msr_open,
-};
-
-static int __init msr_init(void)
-{
-       if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
-               printk(KERN_ERR "msr: unable to get major %d for msr\n",
-                      MSR_MAJOR);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static void __exit msr_exit(void)
-{
-       unregister_chrdev(MSR_MAJOR, "cpu/msr");
-}
-
-module_init(msr_init);
-module_exit(msr_exit)
-
-MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
-MODULE_DESCRIPTION("x86 generic MSR driver");
-MODULE_LICENSE("GPL");
index caf164959e197d25f100b54c1195ef19257e9c72..4388b8a5bae761fd04a7ab70af00d5a0b8b04043 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -488,8 +487,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
                                                        == NOTIFY_STOP) {
                                local_set(&__get_cpu_var(alert_counter), 0);
                                return;
-                       } 
-                       die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
+                       }
+                       die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
                }
        } else {
                __get_cpu_var(last_irq_sum) = sum;
index 57f35c68aa34d0eb4255a919e9bca929622feed1..cf0a0315d586a15bc17dcd2de072956a00dc0d2e 100644 (file)
@@ -191,11 +191,9 @@ static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
 {
        struct page *page;
        int node;
-       if (dev->bus == &pci_bus_type) {
-               cpumask_t mask;
-               mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
-               node = cpu_to_node(first_cpu(mask));
-       } else
+       if (dev->bus == &pci_bus_type)
+               node = pcibus_to_node(to_pci_dev(dev)->bus);
+       else
                node = numa_node_id();
        page = alloc_pages_node(node, gfp, order);
        return page ? page_address(page) : NULL;
index 8661f82ac70b409d96a70b31b84ad87c485fbd30..b5a89c0bdf5914851fe32710b0b808587dfb6c32 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/random.h>
@@ -123,6 +122,7 @@ static void poll_idle (void)
                        : :
                        "i" (_TIF_NEED_RESCHED), 
                        "m" (current_thread_info()->flags));
+               clear_thread_flag(TIF_POLLING_NRFLAG);
        } else {
                set_need_resched();
        }
@@ -271,8 +271,11 @@ void __show_regs(struct pt_regs * regs)
 
        printk("\n");
        print_modules();
-       printk("Pid: %d, comm: %.20s %s %s\n", 
-              current->pid, current->comm, print_tainted(), system_utsname.release);
+       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+               current->pid, current->comm, print_tainted(),
+               system_utsname.release,
+               (int)strcspn(system_utsname.version, " "),
+               system_utsname.version);
        printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
        printk_address(regs->rip); 
        printk("\nRSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags);
@@ -482,33 +485,6 @@ out:
        return err;
 }
 
-/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
-                              struct task_struct *next_p)
-{
-       struct thread_info *prev, *next;
-
-       /*
-        * gcc should eliminate the ->thread_info dereference if
-        * has_secure_computing returns 0 at compile time (SECCOMP=n).
-        */
-       prev = prev_p->thread_info;
-       next = next_p->thread_info;
-
-       if (has_secure_computing(prev) || has_secure_computing(next)) {
-               /* slow path here */
-               if (has_secure_computing(prev) &&
-                   !has_secure_computing(next)) {
-                       write_cr4(read_cr4() & ~X86_CR4_TSD);
-               } else if (!has_secure_computing(prev) &&
-                          has_secure_computing(next))
-                       write_cr4(read_cr4() | X86_CR4_TSD);
-       }
-}
-
 /*
  * This special macro can be used to load a debugging register
  */
@@ -627,8 +603,6 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
                }
        }
 
-       disable_tsc(prev_p, next_p);
-
        return prev_p;
 }
 
index 9aec524be3ebbbb653bcd32b42e44ea51324f442..351d8d64c2fbf45cff433c18fe38cba1156f2b7f 100644 (file)
@@ -336,6 +336,11 @@ static __init void parse_cmdline_early (char ** cmdline_p)
 #endif
 #endif
 
+               if (!memcmp(from, "disable_timer_pin_1", 19))
+                       disable_timer_pin_1 = 1;
+               if (!memcmp(from, "enable_timer_pin_1", 18))
+                       disable_timer_pin_1 = -1;
+
                if (!memcmp(from, "nolapic", 7) ||
                    !memcmp(from, "disableapic", 11))
                        disable_apic = 1;
@@ -755,6 +760,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
        }
 }
 
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+       int i;
+       for (i = apicid - 1; i >= 0; i--) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -763,8 +786,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        int cpu = smp_processor_id();
-       int node = 0;
        unsigned bits;
+#ifdef CONFIG_NUMA
+       int node = 0;
+       unsigned apicid = phys_proc_id[cpu];
+#endif
 
        bits = 0;
        while ((1 << bits) < c->x86_num_cores)
@@ -776,20 +802,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
        phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
-       /* When an ACPI SRAT table is available use the mappings from SRAT
-          instead. */
-       if (acpi_numa <= 0) {
-               node = phys_proc_id[cpu];
-               if (!node_online(node))
-                       node = first_node(node_online_map);
-               cpu_to_node[cpu] = node;
-       } else {
-               node = cpu_to_node[cpu];
-       }
+       node = phys_proc_id[cpu];
+       if (apicid_to_node[apicid] != NUMA_NO_NODE)
+               node = apicid_to_node[apicid];
+       if (!node_online(node)) {
+               /* Two possibilities here:
+                  - The CPU is missing memory and no node was created.
+                  In that case try picking one from a nearby CPU
+                  - The APIC IDs differ from the HyperTransport node IDs
+                  which the K8 northbridge parsing fills in.
+                  Assume they are all increased by a constant offset,
+                  but in the same order as the HT nodeids.
+                  If that doesn't result in a usable node fall back to the
+                  path for the previous case.  */
+               int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+               if (ht_nodeid >= 0 &&
+                   apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+                       node = apicid_to_node[ht_nodeid];
+               /* Pick a nearby node */
+               if (!node_online(node))
+                       node = nearby_node(apicid);
+       }
+       cpu_to_node[cpu] = node;
+
+       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
-
-       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
-                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
 }
 
@@ -909,6 +947,25 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
                return 1;
 }
 
+static void srat_detect_node(void)
+{
+#ifdef CONFIG_NUMA
+       unsigned apicid, node;
+       int cpu = smp_processor_id();
+
+       /* Don't do the funky fallback heuristics the AMD version employs
+          for now. */
+       apicid = phys_proc_id[cpu];
+       node = apicid_to_node[apicid];
+       if (node == NUMA_NO_NODE)
+               node = 0;
+       cpu_to_node[cpu] = node;
+
+       if (acpi_numa > 0)
+               printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
+#endif
+}
+
 static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
        /* Cache sizes */
@@ -927,6 +984,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        if (c->x86 >= 15)
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
        c->x86_num_cores = intel_num_cpu_cores(c);
+
+       srat_detect_node();
 }
 
 static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
index e3ffcacc8c90bf40d17a778c684401a9d66b17d3..bd33be24a386717d3c402059ce49ba0dad3ab838 100644 (file)
@@ -94,7 +94,7 @@ void __init setup_per_cpu_areas(void)
                size = PERCPU_ENOUGH_ROOM;
 #endif
 
-       for (i = 0; i < NR_CPUS; i++) { 
+       for_each_cpu_mask (i, cpu_possible_map) {
                char *ptr;
 
                if (!NODE_DATA(cpu_to_node(i))) {
@@ -119,7 +119,6 @@ void pda_init(int cpu)
        asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); 
        wrmsrl(MSR_GS_BASE, cpu_pda + cpu);
 
-       pda->me = pda;
        pda->cpunumber = cpu; 
        pda->irqcount = -1;
        pda->kernelstack = 
index e5958220d6b8b8eaaca2f70d956efc249c3faa40..9db9dda161b40fe59df298406518bb4a867b0b61 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
@@ -29,6 +28,8 @@
 #include <asm/proto.h>
 #include <asm/apicdef.h>
 
+#define __cpuinit __init
+
 /*
  *     Smarter SMP flushing macros. 
  *             c/o Linus Torvalds.
  *     writing to user space from interrupts. (Its not allowed anyway).
  *
  *     Optimizations Manfred Spraul <manfred@colorfullife.com>
+ *
+ *     More scalable flush, from Andi Kleen
+ *
+ *     To avoid global state use 8 different call vectors.
+ *     Each CPU uses a specific vector to trigger flushes on other
+ *     CPUs. Depending on the received vector the target CPUs look into
+ *     the right per cpu variable for the flush data.
+ *
+ *     With more than 8 CPUs they are hashed to the 8 available
+ *     vectors. The limited global vector space forces us to this right now.
+ *     In future when interrupts are split into per CPU domains this could be
+ *     fixed, at the cost of triggering multiple IPIs in some cases.
  */
 
-static cpumask_t flush_cpumask;
-static struct mm_struct * flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
+union smp_flush_state {
+       struct {
+               cpumask_t flush_cpumask;
+               struct mm_struct *flush_mm;
+               unsigned long flush_va;
 #define FLUSH_ALL      -1ULL
+               spinlock_t tlbstate_lock;
+       };
+       char pad[SMP_CACHE_BYTES];
+} ____cacheline_aligned;
+
+/* State is put into the per CPU data section, but padded
+   to a full cache line because other CPUs can access it and we don't
+   want false sharing in the per cpu data segment. */
+static DEFINE_PER_CPU(union smp_flush_state, flush_state);
 
 /*
  * We cannot call mmdrop() because we are in interrupt context, 
  * instead update mm->cpu_vm_mask.
  */
-static inline void leave_mm (unsigned long cpu)
+static inline void leave_mm(int cpu)
 {
        if (read_pda(mmu_state) == TLBSTATE_OK)
                BUG();
@@ -101,15 +124,25 @@ static inline void leave_mm (unsigned long cpu)
  *
  * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
  * 2) Leave the mm if we are in the lazy tlb mode.
+ *
+ * Interrupts are disabled.
  */
 
-asmlinkage void smp_invalidate_interrupt (void)
+asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
 {
-       unsigned long cpu;
+       int cpu;
+       int sender;
+       union smp_flush_state *f;
 
-       cpu = get_cpu();
+       cpu = smp_processor_id();
+       /*
+        * orig_rax contains the interrupt vector - 256.
+        * Use that to determine where the sender put the data.
+        */
+       sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
+       f = &per_cpu(flush_state, sender);
 
-       if (!cpu_isset(cpu, flush_cpumask))
+       if (!cpu_isset(cpu, f->flush_cpumask))
                goto out;
                /* 
                 * This was a BUG() but until someone can quote me the
@@ -120,64 +153,63 @@ asmlinkage void smp_invalidate_interrupt (void)
                 * BUG();
                 */
                 
-       if (flush_mm == read_pda(active_mm)) {
+       if (f->flush_mm == read_pda(active_mm)) {
                if (read_pda(mmu_state) == TLBSTATE_OK) {
-                       if (flush_va == FLUSH_ALL)
+                       if (f->flush_va == FLUSH_ALL)
                                local_flush_tlb();
                        else
-                               __flush_tlb_one(flush_va);
+                               __flush_tlb_one(f->flush_va);
                } else
                        leave_mm(cpu);
        }
 out:
        ack_APIC_irq();
-       cpu_clear(cpu, flush_cpumask);
-       put_cpu_no_resched();
+       cpu_clear(cpu, f->flush_cpumask);
 }
 
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
                                                unsigned long va)
 {
-       cpumask_t tmp;
-       /*
-        * A couple of (to be removed) sanity checks:
-        *
-        * - we do not send IPIs to not-yet booted CPUs.
-        * - current CPU must not be in mask
-        * - mask must exist :)
-        */
-       BUG_ON(cpus_empty(cpumask));
-       cpus_and(tmp, cpumask, cpu_online_map);
-       BUG_ON(!cpus_equal(tmp, cpumask));
-       BUG_ON(cpu_isset(smp_processor_id(), cpumask));
-       if (!mm)
-               BUG();
+       int sender;
+       union smp_flush_state *f;
 
-       /*
-        * I'm not happy about this global shared spinlock in the
-        * MM hot path, but we'll see how contended it is.
-        * Temporarily this turns IRQs off, so that lockups are
-        * detected by the NMI watchdog.
-        */
-       spin_lock(&tlbstate_lock);
-       
-       flush_mm = mm;
-       flush_va = va;
-       cpus_or(flush_cpumask, cpumask, flush_cpumask);
+       /* Caller has disabled preemption */
+       sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+       f = &per_cpu(flush_state, sender);
+
+       /* Could avoid this lock when
+          num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+          probably not worth checking this for a cache-hot lock. */
+       spin_lock(&f->tlbstate_lock);
+
+       f->flush_mm = mm;
+       f->flush_va = va;
+       cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
 
        /*
         * We have to send the IPI only to
         * CPUs affected.
         */
-       send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+       send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+
+       while (!cpus_empty(f->flush_cpumask))
+               cpu_relax();
 
-       while (!cpus_empty(flush_cpumask))
-               mb();   /* nothing. lockup detection does not belong here */;
+       f->flush_mm = NULL;
+       f->flush_va = 0;
+       spin_unlock(&f->tlbstate_lock);
+}
 
-       flush_mm = NULL;
-       flush_va = 0;
-       spin_unlock(&tlbstate_lock);
+int __cpuinit init_smp_flush(void)
+{
+       int i;
+       for_each_cpu_mask(i, cpu_possible_map) {
+               spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+       }
+       return 0;
 }
+
+core_initcall(init_smp_flush);
        
 void flush_tlb_current_task(void)
 {
@@ -295,8 +327,11 @@ void unlock_ipi_call_lock(void)
 /*
  * this function sends a 'generic call function' IPI to one other CPU
  * in the system.
+ *
+ * cpu is a standard Linux logical CPU number.
  */
-static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+static void
+__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
                                int nonatomic, int wait)
 {
        struct call_data_struct data;
index 4fb34b5cb1f964e8093bc73bfd5219649a952efa..e12d7baeb33ec47ca0dc935f267dcc874693d5f6 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-#include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
@@ -58,6 +57,8 @@
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -413,8 +414,13 @@ void __cpuinit smp_callin(void)
 
        /*
         * Get our bogomips.
+        *
+        * Need to enable IRQs because it can take longer and then
+        * the NMI watchdog might kill us.
         */
+       local_irq_enable();
        calibrate_delay();
+       local_irq_disable();
        Dprintk("Stack at about %p\n",&cpuid);
 
        disable_APIC_timer();
@@ -540,8 +546,8 @@ static void inquire_remote_apic(int apicid)
                 */
                apic_wait_icr_idle();
 
-               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-               apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+               apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
 
                timeout = 0;
                do {
@@ -574,12 +580,12 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        /*
         * Turn INIT on target chip
         */
-       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /*
         * Send IPI
         */
-       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
@@ -595,10 +601,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        Dprintk("Deasserting INIT.\n");
 
        /* Target chip */
-       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /* Send IPI */
-       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
        timeout = 0;
@@ -610,16 +616,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
 
        atomic_set(&init_deasserted, 1);
 
-       /*
-        * Should we send STARTUP IPIs ?
-        *
-        * Determine this based on the APIC version.
-        * If we don't have an integrated APIC, don't send the STARTUP IPIs.
-        */
-       if (APIC_INTEGRATED(apic_version[phys_apicid]))
-               num_starts = 2;
-       else
-               num_starts = 0;
+       num_starts = 2;
 
        /*
         * Run STARTUP IPI loop.
@@ -640,12 +637,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                 */
 
                /* Target chip */
-               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
                /* Boot on the stack */
                /* Kick the second */
-               apic_write_around(APIC_ICR, APIC_DM_STARTUP
-                                       | (start_rip >> 12));
+               apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -864,17 +860,6 @@ static __cpuinit void smp_cleanup_boot(void)
         * Reset trampoline flag
         */
        *((volatile int *) phys_to_virt(0x467)) = 0;
-
-#ifndef CONFIG_HOTPLUG_CPU
-       /*
-        * Free pages reserved for SMP bootup.
-        * When you add hotplug CPU support later remove this
-        * Note there is more work to be done for later CPU bootup.
-        */
-
-       free_page((unsigned long) __va(PAGE_SIZE));
-       free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
-#endif
 }
 
 /*
index 0612640d91b1c31262d3022edd6ffac685190514..ebb9abf3ce6dae3269711f583b0ef2f827d148cb 100644 (file)
@@ -8,23 +8,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/sysrq.h>
-#include <linux/proc_fs.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/device.h>
+#include <linux/smp.h>
 #include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/acpi.h>
-#include <asm/tlbflush.h>
-#include <asm/io.h>
 #include <asm/proto.h>
 
 struct saved_context saved_context;
index 7b6abe0582536f54f5c5aea12587d22d3ab92f1d..2373cb8b86250744018a1ecdd48fc7b6da21248a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -937,7 +936,6 @@ void __init time_init(void)
        vxtime.mode = VXTIME_TSC;
        vxtime.quot = (1000000L << 32) / vxtime_hz;
        vxtime.tsc_quot = (1000L << 32) / cpu_khz;
-       vxtime.hz = vxtime_hz;
        rdtscll_sync(&vxtime.last_tsc);
        setup_irq(0, &irq0);
 
index f238d6078a5a921fcf94c935903b9aaa3aac5bf0..b5e09e6b55368fbd58572ac8c775bd1fc77ab4a7 100644 (file)
@@ -47,9 +47,6 @@
 #include <asm/proto.h>
 #include <asm/nmi.h>
 
-#include <linux/irq.h>
-
-
 extern struct gate_struct idt_table[256]; 
 
 asmlinkage void divide_error(void);
@@ -324,13 +321,13 @@ void handle_BUG(struct pt_regs *regs)
        if (__copy_from_user(&f, (struct bug_frame *) regs->rip, 
                             sizeof(struct bug_frame)))
                return; 
-       if ((unsigned long)f.filename < __PAGE_OFFSET || 
+       if (f.filename >= 0 ||
            f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
                return;
-       if (__get_user(tmp, f.filename))
-               f.filename = "unmapped filename"; 
+       if (__get_user(tmp, (char *)(long)f.filename))
+               f.filename = (int)(long)"unmapped filename";
        printk("----------- [cut here ] --------- [please bite here ] ---------\n");
-       printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
+       printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
 } 
 
 #ifdef CONFIG_BUG
@@ -343,30 +340,33 @@ void out_of_line_bug(void)
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 
-void oops_begin(void)
+unsigned long oops_begin(void)
 {
-       int cpu = safe_smp_processor_id(); 
-       /* racy, but better than risking deadlock. */ 
-       local_irq_disable();
+       int cpu = safe_smp_processor_id();
+       unsigned long flags;
+
+       /* racy, but better than risking deadlock. */
+       local_irq_save(flags);
        if (!spin_trylock(&die_lock)) { 
                if (cpu == die_owner) 
                        /* nested oops. should stop eventually */;
                else
-                       spin_lock(&die_lock); 
+                       spin_lock(&die_lock);
        }
-       die_owner = cpu; 
+       die_owner = cpu;
        console_verbose();
-       bust_spinlocks(1); 
+       bust_spinlocks(1);
+       return flags;
 }
 
-void oops_end(void)
+void oops_end(unsigned long flags)
 { 
        die_owner = -1;
-       bust_spinlocks(0); 
-       spin_unlock(&die_lock); 
+       bust_spinlocks(0);
+       spin_unlock_irqrestore(&die_lock, flags);
        if (panic_on_oops)
-               panic("Oops"); 
-} 
+               panic("Oops");
+}
 
 void __die(const char * str, struct pt_regs * regs, long err)
 {
@@ -392,10 +392,11 @@ void __die(const char * str, struct pt_regs * regs, long err)
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        handle_BUG(regs);
        __die(str, regs, err);
-       oops_end();
+       oops_end(flags);
        do_exit(SIGSEGV); 
 }
 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -406,7 +407,8 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
 
 void die_nmi(char *str, struct pt_regs *regs)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        /*
         * We are in trouble anyway, lets at least try
         * to get a message out.
@@ -416,7 +418,7 @@ void die_nmi(char *str, struct pt_regs *regs)
        if (panic_on_timeout || panic_on_oops)
                panic("nmi watchdog");
        printk("console shuts up ...\n");
-       oops_end();
+       oops_end(flags);
        do_exit(SIGSEGV);
 }
 
@@ -790,13 +792,16 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
         */
        cwd = get_fpu_cwd(task);
        swd = get_fpu_swd(task);
-       switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+       switch (swd & ~cwd & 0x3f) {
                case 0x000:
                default:
                        break;
                case 0x001: /* Invalid Op */
-               case 0x041: /* Stack Fault */
-               case 0x241: /* Stack Fault | Direction */
+                       /*
+                        * swd & 0x240 == 0x040: Stack Underflow
+                        * swd & 0x240 == 0x240: Stack Overflow
+                        * User must clear the SF bit (0x40) if set
+                        */
                        info.si_code = FPE_FLTINV;
                        break;
                case 0x002: /* Denormalize */
index 2e5734425949648ea92bd8d7fd9e65e6f99a8ed5..70a0bd16085fbd3a4fe9bf6c7719e5b33cb54965 100644 (file)
@@ -107,7 +107,7 @@ static force_inline long time_syscall(long *t)
        return secs;
 }
 
-static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
        if (unlikely(!__sysctl_vsyscall))
                return gettimeofday(tv,tz);
@@ -120,7 +120,7 @@ static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz
 
 /* This will break when the xtime seconds get inaccurate, but that is
  * unlikely */
-static time_t __vsyscall(1) vtime(time_t *t)
+time_t __vsyscall(1) vtime(time_t *t)
 {
        if (unlikely(!__sysctl_vsyscall))
                return time_syscall(t);
@@ -129,12 +129,12 @@ static time_t __vsyscall(1) vtime(time_t *t)
        return __xtime.tv_sec;
 }
 
-static long __vsyscall(2) venosys_0(void)
+long __vsyscall(2) venosys_0(void)
 {
        return -ENOSYS;
 }
 
-static long __vsyscall(3) venosys_1(void)
+long __vsyscall(3) venosys_1(void)
 {
        return -ENOSYS;
 }
index 816732d8858c3195c7b6d78419b2b0b537de3f10..b75b872ec154f8e004fc04a29375eb97f7f468bb 100644 (file)
@@ -221,12 +221,13 @@ int unhandled_signal(struct task_struct *tsk, int sig)
 static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
                                 unsigned long error_code)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
               current->comm, address);
        dump_pagetable(address);
        __die("Bad pagetable", regs, error_code);
-       oops_end();
+       oops_end(flags);
        do_exit(SIGKILL);
 }
 
@@ -304,6 +305,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        unsigned long address;
        const struct exception_table_entry *fixup;
        int write;
+       unsigned long flags;
        siginfo_t info;
 
 #ifdef CONFIG_CHECKING
@@ -521,7 +523,7 @@ no_context:
  * terminate things with extreme prejudice.
  */
 
-       oops_begin(); 
+       flags = oops_begin();
 
        if (address < PAGE_SIZE)
                printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
@@ -534,7 +536,7 @@ no_context:
        __die("Oops", regs, error_code);
        /* Executive summary in case the body of the oops scrolled away */
        printk(KERN_EMERG "CR2: %016lx\n", address);
-       oops_end(); 
+       oops_end(flags);
        do_exit(SIGKILL);
 
 /*
index aa4a5189ecee2640503d053bf6c79b233aa99f99..e60a1a848de8f622ce87bd7616b7c32b0dea6e0e 100644 (file)
@@ -57,31 +57,31 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 void show_mem(void)
 {
-       int i, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
+       long i, total = 0, reserved = 0;
+       long shared = 0, cached = 0;
        pg_data_t *pgdat;
        struct page *page;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 
        for_each_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
                        page = pfn_to_page(pgdat->node_start_pfn + i);
                        total++;
-                       if (PageReserved(page))
-                       reserved++;
-                       else if (PageSwapCache(page))
-                       cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (PageSwapCache(page))
+                               cached++;
+                       else if (page_count(page))
+                               shared += page_count(page) - 1;
                }
        }
-       printk("%d pages of RAM\n", total);
-       printk("%d reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
+       printk(KERN_INFO "%lu pages of RAM\n", total);
+       printk(KERN_INFO "%lu reserved pages\n",reserved);
+       printk(KERN_INFO "%lu pages shared\n",shared);
+       printk(KERN_INFO "%lu pages swap cached\n",cached);
 }
 
 /* References to section boundaries */
@@ -381,41 +381,14 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
        __flush_tlb_all();
 } 
 
-static inline int page_is_ram (unsigned long pagenr)
-{
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long addr, end;
-
-               if (e820.map[i].type != E820_RAM)       /* not usable memory */
-                       continue;
-               /*
-                *      !!!FIXME!!! Some BIOSen report areas as RAM that
-                *      are not. Notably the 640->1Mb area. We need a sanity
-                *      check here.
-                */
-               addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
-               end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
-               if  ((pagenr >= addr) && (pagenr < end))
-                       return 1;
-       }
-       return 0;
-}
-
-extern int swiotlb_force;
-
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
                         kcore_vsyscall;
 
 void __init mem_init(void)
 {
-       int codesize, reservedpages, datasize, initsize;
-       int tmp;
+       long codesize, reservedpages, datasize, initsize;
 
 #ifdef CONFIG_SWIOTLB
-       if (swiotlb_force)
-               swiotlb = 1;
        if (!iommu_aperture &&
            (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
               swiotlb = 1;
@@ -436,25 +409,11 @@ void __init mem_init(void)
 
        /* this will put all low memory onto the freelists */
 #ifdef CONFIG_NUMA
-       totalram_pages += numa_free_all_bootmem();
-       tmp = 0;
-       /* should count reserved pages here for all nodes */ 
+       totalram_pages = numa_free_all_bootmem();
 #else
-
-#ifdef CONFIG_FLATMEM
-       max_mapnr = end_pfn;
-       if (!mem_map) BUG();
-#endif
-
-       totalram_pages += free_all_bootmem();
-
-       for (tmp = 0; tmp < end_pfn; tmp++)
-               /*
-                * Only count reserved RAM pages
-                */
-               if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
-                       reservedpages++;
+       totalram_pages = free_all_bootmem();
 #endif
+       reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
 
        after_bootmem = 1;
 
@@ -471,7 +430,7 @@ void __init mem_init(void)
        kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 
                                 VSYSCALL_END - VSYSCALL_START);
 
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+       printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                end_pfn << (PAGE_SHIFT-10),
                codesize >> 10,
index ec35747aacd764b0aedf1824e604b704e5a164e9..65417b040c1bffd171f0ce46d590a57e174c742b 100644 (file)
@@ -45,10 +45,12 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        unsigned long prevbase;
        struct node nodes[8];
        int nodeid, i, nb; 
+       unsigned char nodeids[8];
        int found = 0;
        u32 reg;
        unsigned numnodes;
        nodemask_t nodes_parsed;
+       unsigned dualcore = 0;
 
        nodes_clear(nodes_parsed);
 
@@ -67,11 +69,15 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        prevbase = 0;
        for (i = 0; i < 8; i++) { 
                unsigned long base,limit; 
-
+               u32 nodeid;
+               
+               /* Undefined before E stepping, but hopefully 0 */
+               dualcore |= ((read_pci_config(0, nb, 3, 0xe8) >> 12) & 3) == 1;
                base = read_pci_config(0, nb, 1, 0x40 + i*8);
                limit = read_pci_config(0, nb, 1, 0x44 + i*8);
 
                nodeid = limit & 7; 
+               nodeids[i] = nodeid;
                if ((base & 3) == 0) { 
                        if (i < numnodes)
                                printk("Skipping disabled node %d\n", i); 
@@ -157,8 +163,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 
        for (i = 0; i < 8; i++) {
                if (nodes[i].start != nodes[i].end) { 
-                       /* assume 1:1 NODE:CPU */
-                       cpu_to_node[i] = i; 
+                       nodeid = nodeids[i];
+                       apicid_to_node[nodeid << dualcore] = i;
+                       apicid_to_node[(nodeid << dualcore) + dualcore] = i;
                        setup_node_bootmem(i, nodes[i].start, nodes[i].end); 
                } 
        }
index 04f7a33e144c4bbbd05befd65d6c396184e6e75d..80a49d9bd8a77941a89794b32eba75e0cc2490aa 100644 (file)
@@ -28,8 +28,13 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 int memnode_shift;
 u8  memnodemap[NODEMAPSIZE];
 
-unsigned char cpu_to_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
-cpumask_t     node_to_cpumask[MAX_NUMNODES] __read_mostly;
+unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
+       [0 ... NR_CPUS-1] = NUMA_NO_NODE
+};
+unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+       [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
 
index 8e3d097a9ddddc5ef1c179cd24ae28a6d7902163..4b2e844c15a75707de27bccac2dcccd750db480c 100644 (file)
 
 static struct acpi_table_slit *acpi_slit;
 
-/* Internal processor count */
-static unsigned int __initdata num_processors = 0;
-
 static nodemask_t nodes_parsed __initdata;
 static nodemask_t nodes_found __initdata;
 static struct node nodes[MAX_NUMNODES] __initdata;
 static __u8  pxm2node[256] = { [0 ... 255] = 0xff };
 
+static int node_to_pxm(int n);
+
+int pxm_to_node(int pxm)
+{
+       if ((unsigned)pxm >= 256)
+               return 0;
+       return pxm2node[pxm];
+}
+
 static __init int setup_node(int pxm)
 {
        unsigned node = pxm2node[pxm];
@@ -44,14 +50,14 @@ static __init int setup_node(int pxm)
 static __init int conflicting_nodes(unsigned long start, unsigned long end)
 {
        int i;
-       for_each_online_node(i) {
+       for_each_node_mask(i, nodes_parsed) {
                struct node *nd = &nodes[i];
                if (nd->start == nd->end)
                        continue;
                if (nd->end > start && nd->start < end)
-                       return 1;
+                       return i;
                if (nd->end == end && nd->start == start)
-                       return 1;
+                       return i;
        }
        return -1;
 }
@@ -75,8 +81,11 @@ static __init void cutoff_node(int i, unsigned long start, unsigned long end)
 
 static __init void bad_srat(void)
 {
+       int i;
        printk(KERN_ERR "SRAT: SRAT not used.\n");
        acpi_numa = -1;
+       for (i = 0; i < MAX_LOCAL_APIC; i++)
+               apicid_to_node[i] = NUMA_NO_NODE;
 }
 
 static __init inline int srat_disabled(void)
@@ -104,18 +113,10 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
                bad_srat();
                return;
        }
-       if (num_processors >= NR_CPUS) {
-               printk(KERN_ERR "SRAT: Processor #%d (lapic %u) INVALID. (Max ID: %d).\n",
-                       num_processors, pa->apic_id, NR_CPUS);
-               bad_srat();
-               return;
-       }
-       cpu_to_node[num_processors] = node;
+       apicid_to_node[pa->apic_id] = node;
        acpi_numa = 1;
-       printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> CPU %u -> Node %u\n",
-              pxm, pa->apic_id, num_processors, node);
-
-       num_processors++;
+       printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+              pxm, pa->apic_id, node);
 }
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
@@ -143,10 +144,15 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
                printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
                                start, end);
        i = conflicting_nodes(start, end);
-       if (i >= 0) {
+       if (i == node) {
+               printk(KERN_WARNING
+               "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+                       pxm, start, end, nodes[i].start, nodes[i].end);
+       } else if (i >= 0) {
                printk(KERN_ERR
-                      "SRAT: pxm %d overlap %lx-%lx with node %d(%Lx-%Lx)\n",
-                      pxm, start, end, i, nodes[i].start, nodes[i].end);
+                      "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
+                      pxm, start, end, node_to_pxm(i),
+                       nodes[i].start, nodes[i].end);
                bad_srat();
                return;
        }
@@ -174,6 +180,14 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        int i;
        if (acpi_numa <= 0)
                return -1;
+
+       /* First clean up the node list */
+       for_each_node_mask(i, nodes_parsed) {
+               cutoff_node(i, start, end);
+               if (nodes[i].start == nodes[i].end)
+                       node_clear(i, nodes_parsed);
+       }
+
        memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
        if (memnode_shift < 0) {
                printk(KERN_ERR
@@ -181,16 +195,10 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
                bad_srat();
                return -1;
        }
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               if (!node_isset(i, nodes_parsed))
-                       continue;
-               cutoff_node(i, start, end);
-               if (nodes[i].start == nodes[i].end) { 
-                       node_clear(i, nodes_parsed);
-                       continue;
-               }
+
+       /* Finally register nodes */
+       for_each_node_mask(i, nodes_parsed)
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-       }
        for (i = 0; i < NR_CPUS; i++) { 
                if (cpu_to_node[i] == NUMA_NO_NODE)
                        continue;
@@ -201,7 +209,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        return 0;
 }
 
-int node_to_pxm(int n)
+static int node_to_pxm(int n)
 {
        int i;
        if (pxm2node[n] == n)
index d80c323669e0c5e741a33f8c5700b2c8b8784007..3acf60ded2a0b54144a72b5b0faf5f8bc2c00933 100644 (file)
@@ -58,10 +58,16 @@ fill_mp_bus_to_cpumask(void)
                                for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
                                     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
                                     j++) { 
-                                       int node = NODE_ID(nid);
+                                       struct pci_bus *bus;
+                                       long node = NODE_ID(nid);
+                                       /* Algorithm a bit dumb, but
+                                          it shouldn't matter here */
+                                       bus = pci_find_bus(0, j);
+                                       if (!bus)
+                                               continue;
                                        if (!node_online(node))
                                                node = 0;
-                                       pci_bus_to_node[j] = node;
+                                       bus->sysdata = (void *)node;
                                }               
                        }
                }
index 657e88aa09022ba67df0fcc8dca7d20e44ecef53..a0838c4a94e4c032d9d6024fb0eaed96b0d3dab3 100644 (file)
@@ -111,13 +111,6 @@ static int __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return 0;
 
-       /* Kludge for now. Don't use mmconfig on AMD systems because
-          those have some busses where mmconfig doesn't work,
-          and we don't parse ACPI MCFG well enough to handle that. 
-          Remove when proper handling is added. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               return 0; 
-
        /* RED-PEN i386 doesn't do _nocache right now */
        pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
index 46d655fab1159c54768d08d226ac3bc36a393b2a..48f446d3c671ade5a5198384c729f83118a35033 100644 (file)
@@ -4,6 +4,8 @@ menu "Device Drivers"
 
 source "drivers/base/Kconfig"
 
+source "drivers/connector/Kconfig"
+
 source "drivers/mtd/Kconfig"
 
 source "drivers/parport/Kconfig"
index 86c8654a0ca940d183adb4f945fa757b358e0d48..1a109a6dd953d90c4bb74146ccdbc6699f02a9e4 100644 (file)
@@ -17,6 +17,8 @@ obj-$(CONFIG_PNP)             += pnp/
 # default.
 obj-y                          += char/
 
+obj-$(CONFIG_CONNECTOR)                += connector/
+
 # i810fb and intelfb depend on char/agp/
 obj-$(CONFIG_FB_I810)           += video/i810/
 obj-$(CONFIG_FB_INTEL)          += video/intelfb/
index 721ba8086043bd714c06e5353f60a348e7989f50..0e9e586e9ba362a52bbac71e1bb169451fdbe6c5 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "10"
+#define VERSION "12"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -7,12 +7,12 @@
  * default is 16, which is 15 partitions plus the whole disk
  */
 #ifndef AOE_PARTITIONS
-#define AOE_PARTITIONS 16
+#define AOE_PARTITIONS (16)
 #endif
 
-#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor))
-#define AOEMAJOR(sysminor) ((sysminor) / 10)
-#define AOEMINOR(sysminor) ((sysminor) % 10)
+#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
+#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
+#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
 #define WHITESPACE " \t\v\f\n"
 
 enum {
@@ -83,7 +83,7 @@ enum {
 
 enum {
        MAXATADATA = 1024,
-       NPERSHELF = 10,
+       NPERSHELF = 16,         /* number of slots per shelf address */
        FREETAG = -1,
        MIN_BUFS = 8,
 };
index c3898afce3aed341e06e56a7d03b0425f27296b4..fa789ea36bbe3169490c02204e9e6209cd860eb9 100644 (file)
@@ -139,6 +139,15 @@ config SA1100_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called sa1100_wdt.
 
+config MPCORE_WATCHDOG
+       tristate "MPcore watchdog"
+       depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+       help
+         Watchdog timer embedded into the MPcore system.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mpcore_wdt.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
index cfeac6f10137e5fc30862d8f287a53d3c084e73a..bc6f5fe88c8c24f200c13a0caf38fc3c02d6344a 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
+obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
 
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
new file mode 100644 (file)
index 0000000..c694eee
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ *     Watchdog driver for the mpcore watchdog timer
+ *
+ *     (c) Copyright 2004 ARM Limited
+ *
+ *     Based on the SoftDog driver:
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.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.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+
+struct mpcore_wdt {
+       unsigned long   timer_alive;
+       struct device   *dev;
+       void __iomem    *base;
+       int             irq;
+       unsigned int    perturb;
+       char            expect_close;
+};
+
+static struct platform_device *mpcore_wdt_dev;
+
+extern unsigned int mpcore_timer_rate;
+
+#define TIMER_MARGIN   60
+static int mpcore_margin = TIMER_MARGIN;
+module_param(mpcore_margin, int, 0);
+MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define ONLY_TESTING   0
+static int mpcore_noboot = ONLY_TESTING;
+module_param(mpcore_noboot, int, 0);
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+
+/*
+ *     This is the interrupt handler.  Note that we only use this
+ *     in testing mode, so don't actually do a reboot here.
+ */
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
+{
+       struct mpcore_wdt *wdt = arg;
+
+       /* Check it really was our interrupt */
+       if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
+               dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
+
+               /* Clear the interrupt on the watchdog */
+               writel(1, wdt->base + TWD_WDOG_INTSTAT);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+/*
+ *     mpcore_wdt_keepalive - reload the timer
+ *
+ *     Note that the spec says a DIFFERENT value must be written to the reload
+ *     register each time.  The "perturb" variable deals with this by adding 1
+ *     to the count every other time the function is called.
+ */
+static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
+{
+       unsigned int count;
+
+       /* Assume prescale is set to 256 */
+       count = (mpcore_timer_rate / 256) * mpcore_margin;
+
+       /* Reload the counter */
+       writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
+
+       wdt->perturb = wdt->perturb ? 0 : 1;
+}
+
+static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
+{
+       writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
+       writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
+       writel(0x0, wdt->base + TWD_WDOG_CONTROL);
+}
+
+static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+{
+       dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+       /* This loads the count register but does NOT start the count yet */
+       mpcore_wdt_keepalive(wdt);
+
+       if (mpcore_noboot) {
+               /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+               writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+       } else {
+               /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+               writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+       }
+}
+
+static int mpcore_wdt_set_heartbeat(int t)
+{
+       if (t < 0x0001 || t > 0xFFFF)
+               return -EINVAL;
+
+       mpcore_margin = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+static int mpcore_wdt_open(struct inode *inode, struct file *file)
+{
+       struct mpcore_wdt *wdt = dev_get_drvdata(&mpcore_wdt_dev->dev);
+
+       if (test_and_set_bit(0, &wdt->timer_alive))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       file->private_data = wdt;
+
+       /*
+        *      Activate timer
+        */
+       mpcore_wdt_start(wdt);
+
+       return nonseekable_open(inode, file);
+}
+
+static int mpcore_wdt_release(struct inode *inode, struct file *file)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if (wdt->expect_close == 42) {
+               mpcore_wdt_stop(wdt);
+       } else {
+               dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
+               mpcore_wdt_keepalive(wdt);
+       }
+       clear_bit(0, &wdt->timer_alive);
+       wdt->expect_close = 0;
+       return 0;
+}
+
+static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /*
+        *      Refresh the timer.
+        */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       wdt->expect_close = 0;
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       wdt->expect_close = 42;
+                       }
+               }
+               mpcore_wdt_keepalive(wdt);
+       }
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options                = WDIOF_SETTIMEOUT |
+                                 WDIOF_KEEPALIVEPING |
+                                 WDIOF_MAGICCLOSE,
+       .identity               = "MPcore Watchdog",
+};
+
+static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+       int ret;
+       union {
+               struct watchdog_info ident;
+               int i;
+       } uarg;
+
+       if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+               return -ENOIOCTLCMD;
+
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
+               ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+               if (ret)
+                       return -EFAULT;
+       }
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               uarg.ident = ident;
+               ret = 0;
+               break;
+
+       case WDIOC_SETOPTIONS:
+               ret = -EINVAL;
+               if (uarg.i & WDIOS_DISABLECARD) {
+                       mpcore_wdt_stop(wdt);
+                       ret = 0;
+               }
+               if (uarg.i & WDIOS_ENABLECARD) {
+                       mpcore_wdt_start(wdt);
+                       ret = 0;
+               }
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               uarg.i = 0;
+               ret = 0;
+               break;
+
+       case WDIOC_KEEPALIVE:
+               mpcore_wdt_keepalive(wdt);
+               ret = 0;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = mpcore_wdt_set_heartbeat(uarg.i);
+               if (ret)
+                       break;
+
+               mpcore_wdt_keepalive(wdt);
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               uarg.i = mpcore_margin;
+               ret = 0;
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+               ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
+               if (ret)
+                       ret = -EFAULT;
+       }
+       return ret;
+}
+
+/*
+ *     System shutdown handler.  Turn off the watchdog if we're
+ *     restarting or halting the system.
+ */
+static void mpcore_wdt_shutdown(struct device *_dev)
+{
+       struct mpcore_wdt *wdt = dev_get_drvdata(_dev);
+
+       if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
+               mpcore_wdt_stop(wdt);
+}
+
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations mpcore_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = mpcore_wdt_write,
+       .ioctl          = mpcore_wdt_ioctl,
+       .open           = mpcore_wdt_open,
+       .release        = mpcore_wdt_release,
+};
+
+static struct miscdevice mpcore_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &mpcore_wdt_fops,
+};
+
+static int __devinit mpcore_wdt_probe(struct device *_dev)
+{
+       struct platform_device *dev = to_platform_device(_dev);
+       struct mpcore_wdt *wdt;
+       struct resource *res;
+       int ret;
+
+       /* We only accept one device, and it must have an id of -1 */
+       if (dev->id != -1)
+               return -ENODEV;
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto err_out;
+       }
+
+       wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
+       if (!wdt) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
+       memset(wdt, 0, sizeof(struct mpcore_wdt));
+
+       wdt->dev = &dev->dev;
+       wdt->irq = platform_get_irq(dev, 0);
+       wdt->base = ioremap(res->start, res->end - res->start + 1);
+       if (!wdt->base) {
+               ret = -ENOMEM;
+               goto err_free;
+       }
+
+       mpcore_wdt_miscdev.dev = &dev->dev;
+       ret = misc_register(&mpcore_wdt_miscdev);
+       if (ret) {
+               dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
+                          WATCHDOG_MINOR, ret);
+               goto err_misc;
+       }
+
+       ret = request_irq(wdt->irq, mpcore_wdt_fire, SA_INTERRUPT, "mpcore_wdt", wdt);
+       if (ret) {
+               dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
+               goto err_irq;
+       }
+
+       mpcore_wdt_stop(wdt);
+       dev_set_drvdata(&dev->dev, wdt);
+       mpcore_wdt_dev = dev;
+
+       return 0;
+
+ err_irq:
+       misc_deregister(&mpcore_wdt_miscdev);
+ err_misc:
+       iounmap(wdt->base);
+ err_free:
+       kfree(wdt);
+ err_out:
+       return ret;
+}
+
+static int __devexit mpcore_wdt_remove(struct device *dev)
+{
+       struct mpcore_wdt *wdt = dev_get_drvdata(dev);
+
+       dev_set_drvdata(dev, NULL);
+
+       misc_deregister(&mpcore_wdt_miscdev);
+
+       mpcore_wdt_dev = NULL;
+
+       free_irq(wdt->irq, wdt);
+       iounmap(wdt->base);
+       kfree(wdt);
+       return 0;
+}
+
+static struct device_driver mpcore_wdt_driver = {
+       .name           = "mpcore_wdt",
+       .bus            = &platform_bus_type,
+       .probe          = mpcore_wdt_probe,
+       .remove         = __devexit_p(mpcore_wdt_remove),
+       .shutdown       = mpcore_wdt_shutdown,
+};
+
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+
+static int __init mpcore_wdt_init(void)
+{
+       /*
+        * Check that the margin value is within it's range;
+        * if not reset to the default
+        */
+       if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
+               mpcore_wdt_set_heartbeat(TIMER_MARGIN);
+               printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
+                       TIMER_MARGIN);
+       }
+
+       printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+
+       return driver_register(&mpcore_wdt_driver);
+}
+
+static void __exit mpcore_wdt_exit(void)
+{
+       driver_unregister(&mpcore_wdt_driver);
+}
+
+module_init(mpcore_wdt_init);
+module_exit(mpcore_wdt_exit);
+
+MODULE_AUTHOR("ARM Limited");
+MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
new file mode 100644 (file)
index 0000000..0bc2059
--- /dev/null
@@ -0,0 +1,13 @@
+menu "Connector - unified userspace <-> kernelspace linker"
+
+config CONNECTOR
+       tristate "Connector - unified userspace <-> kernelspace linker"
+       depends on NET
+       ---help---
+         This is unified userspace <-> kernelspace connector working on top
+         of the netlink socket protocol.
+
+         Connector support can also be built as a module.  If so, the module
+         will be called cn.ko.
+
+endmenu
diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile
new file mode 100644 (file)
index 0000000..12ca79e
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_CONNECTOR)                += cn.o
+
+cn-y                           += cn_queue.o connector.o
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
new file mode 100644 (file)
index 0000000..9666321
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ *     cn_queue.c
+ * 
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/suspend.h>
+#include <linux/connector.h>
+#include <linux/delay.h>
+
+static void cn_queue_wrapper(void *data)
+{
+       struct cn_callback_entry *cbq = data;
+
+       cbq->cb->callback(cbq->cb->priv);
+       cbq->destruct_data(cbq->ddata);
+       cbq->ddata = NULL;
+}
+
+static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb)
+{
+       struct cn_callback_entry *cbq;
+
+       cbq = kzalloc(sizeof(*cbq), GFP_KERNEL);
+       if (!cbq) {
+               printk(KERN_ERR "Failed to create new callback queue.\n");
+               return NULL;
+       }
+
+       cbq->cb = cb;
+       INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq);
+       return cbq;
+}
+
+static void cn_queue_free_callback(struct cn_callback_entry *cbq)
+{
+       cancel_delayed_work(&cbq->work);
+       flush_workqueue(cbq->pdev->cn_queue);
+
+       kfree(cbq);
+}
+
+int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
+{
+       return ((i1->idx == i2->idx) && (i1->val == i2->val));
+}
+
+int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
+{
+       struct cn_callback_entry *cbq, *__cbq;
+       int found = 0;
+
+       cbq = cn_queue_alloc_callback_entry(cb);
+       if (!cbq)
+               return -ENOMEM;
+
+       atomic_inc(&dev->refcnt);
+       cbq->pdev = dev;
+
+       spin_lock_bh(&dev->queue_lock);
+       list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
+               if (cn_cb_equal(&__cbq->cb->id, &cb->id)) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found)
+               list_add_tail(&cbq->callback_entry, &dev->queue_list);
+       spin_unlock_bh(&dev->queue_lock);
+
+       if (found) {
+               atomic_dec(&dev->refcnt);
+               cn_queue_free_callback(cbq);
+               return -EINVAL;
+       }
+
+       cbq->nls = dev->nls;
+       cbq->seq = 0;
+       cbq->group = cbq->cb->id.idx;
+
+       return 0;
+}
+
+void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
+{
+       struct cn_callback_entry *cbq, *n;
+       int found = 0;
+
+       spin_lock_bh(&dev->queue_lock);
+       list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
+               if (cn_cb_equal(&cbq->cb->id, id)) {
+                       list_del(&cbq->callback_entry);
+                       found = 1;
+                       break;
+               }
+       }
+       spin_unlock_bh(&dev->queue_lock);
+
+       if (found) {
+               cn_queue_free_callback(cbq);
+               atomic_dec_and_test(&dev->refcnt);
+       }
+}
+
+struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+{
+       struct cn_queue_dev *dev;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       snprintf(dev->name, sizeof(dev->name), "%s", name);
+       atomic_set(&dev->refcnt, 0);
+       INIT_LIST_HEAD(&dev->queue_list);
+       spin_lock_init(&dev->queue_lock);
+
+       dev->nls = nls;
+       dev->netlink_groups = 0;
+
+       dev->cn_queue = create_workqueue(dev->name);
+       if (!dev->cn_queue) {
+               kfree(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+
+void cn_queue_free_dev(struct cn_queue_dev *dev)
+{
+       struct cn_callback_entry *cbq, *n;
+
+       flush_workqueue(dev->cn_queue);
+       destroy_workqueue(dev->cn_queue);
+
+       spin_lock_bh(&dev->queue_lock);
+       list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)
+               list_del(&cbq->callback_entry);
+       spin_unlock_bh(&dev->queue_lock);
+
+       while (atomic_read(&dev->refcnt)) {
+               printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+                      dev->name, atomic_read(&dev->refcnt));
+               msleep(1000);
+       }
+
+       kfree(dev);
+       dev = NULL;
+}
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
new file mode 100644 (file)
index 0000000..aaf6d46
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ *     connector.c
+ * 
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/moduleparam.h>
+#include <linux/connector.h>
+
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+
+static u32 cn_idx = CN_IDX_CONNECTOR;
+static u32 cn_val = CN_VAL_CONNECTOR;
+
+module_param(cn_idx, uint, 0);
+module_param(cn_val, uint, 0);
+MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
+MODULE_PARM_DESC(cn_val, "Connector's main device val.");
+
+static DECLARE_MUTEX(notify_lock);
+static LIST_HEAD(notify_list);
+
+static struct cn_dev cdev;
+
+int cn_already_initialized = 0;
+
+/*
+ * msg->seq and msg->ack are used to determine message genealogy.
+ * When someone sends message it puts there locally unique sequence
+ * and random acknowledge numbers.  Sequence number may be copied into
+ * nlmsghdr->nlmsg_seq too.
+ *
+ * Sequence number is incremented with each message to be sent.
+ *
+ * If we expect reply to our message then the sequence number in
+ * received message MUST be the same as in original message, and
+ * acknowledge number MUST be the same + 1.
+ *
+ * If we receive a message and its sequence number is not equal to the
+ * one we are expecting then it is a new message.
+ *
+ * If we receive a message and its sequence number is the same as one
+ * we are expecting but it's acknowledgement number is not equal to
+ * the acknowledgement number in the original message + 1, then it is
+ * a new message.
+ *
+ */
+int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
+{
+       struct cn_callback_entry *__cbq;
+       unsigned int size;
+       struct sk_buff *skb;
+       struct nlmsghdr *nlh;
+       struct cn_msg *data;
+       struct cn_dev *dev = &cdev;
+       u32 group = 0;
+       int found = 0;
+
+       if (!__group) {
+               spin_lock_bh(&dev->cbdev->queue_lock);
+               list_for_each_entry(__cbq, &dev->cbdev->queue_list,
+                                   callback_entry) {
+                       if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
+                               found = 1;
+                               group = __cbq->group;
+                       }
+               }
+               spin_unlock_bh(&dev->cbdev->queue_lock);
+
+               if (!found)
+                       return -ENODEV;
+       } else {
+               group = __group;
+       }
+
+       size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+
+       skb = alloc_skb(size, gfp_mask);
+       if (!skb)
+               return -ENOMEM;
+
+       nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
+
+       data = NLMSG_DATA(nlh);
+
+       memcpy(data, msg, sizeof(*data) + msg->len);
+
+       NETLINK_CB(skb).dst_group = group;
+
+       netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
+
+       return 0;
+
+nlmsg_failure:
+       kfree_skb(skb);
+       return -EINVAL;
+}
+
+/*
+ * Callback helper - queues work and setup destructor for given data.
+ */
+static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
+{
+       struct cn_callback_entry *__cbq;
+       struct cn_dev *dev = &cdev;
+       int found = 0;
+
+       spin_lock_bh(&dev->cbdev->queue_lock);
+       list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
+               if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
+                       /*
+                        * Let's scream if there is some magic and the
+                        * data will arrive asynchronously here.
+                        * [i.e. netlink messages will be queued].
+                        * After the first warning I will fix it
+                        * quickly, but now I think it is
+                        * impossible. --zbr (2004_04_27).
+                        */
+                       if (likely(!test_bit(0, &__cbq->work.pending) &&
+                                       __cbq->ddata == NULL)) {
+                               __cbq->cb->priv = msg;
+
+                               __cbq->ddata = data;
+                               __cbq->destruct_data = destruct_data;
+
+                               if (queue_work(dev->cbdev->cn_queue,
+                                               &__cbq->work))
+                                       found = 1;
+                       } else {
+                               printk("%s: cbq->data=%p, "
+                                      "work->pending=%08lx.\n",
+                                      __func__, __cbq->ddata,
+                                      __cbq->work.pending);
+                               WARN_ON(1);
+                       }
+                       break;
+               }
+       }
+       spin_unlock_bh(&dev->cbdev->queue_lock);
+
+       return found ? 0 : -ENODEV;
+}
+
+/*
+ * Skb receive helper - checks skb and msg size and calls callback
+ * helper.
+ */
+static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+       u32 pid, uid, seq, group;
+       struct cn_msg *msg;
+
+       pid = NETLINK_CREDS(skb)->pid;
+       uid = NETLINK_CREDS(skb)->uid;
+       seq = nlh->nlmsg_seq;
+       group = NETLINK_CB((skb)).dst_group;
+       msg = NLMSG_DATA(nlh);
+
+       return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+}
+
+/*
+ * Main netlink receiving function.
+ *
+ * It checks skb and netlink header sizes and calls the skb receive
+ * helper with a shared skb.
+ */
+static void cn_rx_skb(struct sk_buff *__skb)
+{
+       struct nlmsghdr *nlh;
+       u32 len;
+       int err;
+       struct sk_buff *skb;
+
+       skb = skb_get(__skb);
+
+       if (skb->len >= NLMSG_SPACE(0)) {
+               nlh = (struct nlmsghdr *)skb->data;
+
+               if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
+                   skb->len < nlh->nlmsg_len ||
+                   nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
+                       kfree_skb(skb);
+                       goto out;
+               }
+
+               len = NLMSG_ALIGN(nlh->nlmsg_len);
+               if (len > skb->len)
+                       len = skb->len;
+
+               err = __cn_rx_skb(skb, nlh);
+               if (err < 0)
+                       kfree_skb(skb);
+       }
+
+out:
+       kfree_skb(__skb);
+}
+
+/*
+ * Netlink socket input callback - dequeues the skbs and calls the
+ * main netlink receiving function.
+ */
+static void cn_input(struct sock *sk, int len)
+{
+       struct sk_buff *skb;
+
+       while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
+               cn_rx_skb(skb);
+}
+
+/*
+ * Notification routing.
+ *
+ * Gets id and checks if there are notification request for it's idx
+ * and val.  If there are such requests notify the listeners with the
+ * given notify event.
+ *
+ */
+static void cn_notify(struct cb_id *id, u32 notify_event)
+{
+       struct cn_ctl_entry *ent;
+
+       down(&notify_lock);
+       list_for_each_entry(ent, &notify_list, notify_entry) {
+               int i;
+               struct cn_notify_req *req;
+               struct cn_ctl_msg *ctl = ent->msg;
+               int idx_found, val_found;
+
+               idx_found = val_found = 0;
+
+               req = (struct cn_notify_req *)ctl->data;
+               for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
+                       if (id->idx >= req->first && 
+                                       id->idx < req->first + req->range) {
+                               idx_found = 1;
+                               break;
+                       }
+               }
+
+               for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
+                       if (id->val >= req->first && 
+                                       id->val < req->first + req->range) {
+                               val_found = 1;
+                               break;
+                       }
+               }
+
+               if (idx_found && val_found) {
+                       struct cn_msg m = { .ack = notify_event, };
+
+                       memcpy(&m.id, id, sizeof(m.id));
+                       cn_netlink_send(&m, ctl->group, GFP_KERNEL);
+               }
+       }
+       up(&notify_lock);
+}
+
+/*
+ * Callback add routing - adds callback with given ID and name.
+ * If there is registered callback with the same ID it will not be added.
+ *
+ * May sleep.
+ */
+int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
+{
+       int err;
+       struct cn_dev *dev = &cdev;
+       struct cn_callback *cb;
+
+       cb = kzalloc(sizeof(*cb), GFP_KERNEL);
+       if (!cb)
+               return -ENOMEM;
+
+       scnprintf(cb->name, sizeof(cb->name), "%s", name);
+
+       memcpy(&cb->id, id, sizeof(cb->id));
+       cb->callback = callback;
+
+       err = cn_queue_add_callback(dev->cbdev, cb);
+       if (err) {
+               kfree(cb);
+               return err;
+       }
+
+       cn_notify(id, 0);
+
+       return 0;
+}
+
+/*
+ * Callback remove routing - removes callback
+ * with given ID.
+ * If there is no registered callback with given
+ * ID nothing happens.
+ *
+ * May sleep while waiting for reference counter to become zero.
+ */
+void cn_del_callback(struct cb_id *id)
+{
+       struct cn_dev *dev = &cdev;
+
+       cn_queue_del_callback(dev->cbdev, id);
+       cn_notify(id, 1);
+}
+
+/*
+ * Checks two connector's control messages to be the same.
+ * Returns 1 if they are the same or if the first one is corrupted.
+ */
+static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
+{
+       int i;
+       struct cn_notify_req *req1, *req2;
+
+       if (m1->idx_notify_num != m2->idx_notify_num)
+               return 0;
+
+       if (m1->val_notify_num != m2->val_notify_num)
+               return 0;
+
+       if (m1->len != m2->len)
+               return 0;
+
+       if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
+           m1->len)
+               return 1;
+
+       req1 = (struct cn_notify_req *)m1->data;
+       req2 = (struct cn_notify_req *)m2->data;
+
+       for (i = 0; i < m1->idx_notify_num; ++i) {
+               if (req1->first != req2->first || req1->range != req2->range)
+                       return 0;
+               req1++;
+               req2++;
+       }
+
+       for (i = 0; i < m1->val_notify_num; ++i) {
+               if (req1->first != req2->first || req1->range != req2->range)
+                       return 0;
+               req1++;
+               req2++;
+       }
+
+       return 1;
+}
+
+/*
+ * Main connector device's callback.
+ *
+ * Used for notification of a request's processing.
+ */
+static void cn_callback(void *data)
+{
+       struct cn_msg *msg = data;
+       struct cn_ctl_msg *ctl;
+       struct cn_ctl_entry *ent;
+       u32 size;
+
+       if (msg->len < sizeof(*ctl))
+               return;
+
+       ctl = (struct cn_ctl_msg *)msg->data;
+
+       size = (sizeof(*ctl) + ((ctl->idx_notify_num +
+                                ctl->val_notify_num) *
+                               sizeof(struct cn_notify_req)));
+
+       if (msg->len != size)
+               return;
+
+       if (ctl->len + sizeof(*ctl) != msg->len)
+               return;
+
+       /*
+        * Remove notification.
+        */
+       if (ctl->group == 0) {
+               struct cn_ctl_entry *n;
+
+               down(&notify_lock);
+               list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
+                       if (cn_ctl_msg_equals(ent->msg, ctl)) {
+                               list_del(&ent->notify_entry);
+                               kfree(ent);
+                       }
+               }
+               up(&notify_lock);
+
+               return;
+       }
+
+       size += sizeof(*ent);
+
+       ent = kzalloc(size, GFP_KERNEL);
+       if (!ent)
+               return;
+
+       ent->msg = (struct cn_ctl_msg *)(ent + 1);
+
+       memcpy(ent->msg, ctl, size - sizeof(*ent));
+
+       down(&notify_lock);
+       list_add(&ent->notify_entry, &notify_list);
+       up(&notify_lock);
+}
+
+static int __init cn_init(void)
+{
+       struct cn_dev *dev = &cdev;
+       int err;
+
+       dev->input = cn_input;
+       dev->id.idx = cn_idx;
+       dev->id.val = cn_val;
+
+       dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
+                                        CN_NETLINK_USERS + 0xf,
+                                        dev->input, THIS_MODULE);
+       if (!dev->nls)
+               return -EIO;
+
+       dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
+       if (!dev->cbdev) {
+               if (dev->nls->sk_socket)
+                       sock_release(dev->nls->sk_socket);
+               return -EINVAL;
+       }
+
+       err = cn_add_callback(&dev->id, "connector", &cn_callback);
+       if (err) {
+               cn_queue_free_dev(dev->cbdev);
+               if (dev->nls->sk_socket)
+                       sock_release(dev->nls->sk_socket);
+               return -EINVAL;
+       }
+
+       cn_already_initialized = 1;
+
+       return 0;
+}
+
+static void __exit cn_fini(void)
+{
+       struct cn_dev *dev = &cdev;
+
+       cn_already_initialized = 0;
+
+       cn_del_callback(&dev->id);
+       cn_queue_free_dev(dev->cbdev);
+       if (dev->nls->sk_socket)
+               sock_release(dev->nls->sk_socket);
+}
+
+module_init(cn_init);
+module_exit(cn_fini);
+
+EXPORT_SYMBOL_GPL(cn_add_callback);
+EXPORT_SYMBOL_GPL(cn_del_callback);
+EXPORT_SYMBOL_GPL(cn_netlink_send);
index 138dc50270e3e51e714893602c937b5fa95ec14e..7e72e922b41c2ca603c8bcde49aa549005d52dbf 100644 (file)
@@ -411,6 +411,23 @@ config SENSORS_W83627EHF
          This driver can also be built as a module.  If so, the module
          will be called w83627ehf.
 
+config SENSORS_HDAPS
+       tristate "IBM Hard Drive Active Protection System (hdaps)"
+       depends on HWMON && INPUT && X86
+       default n
+       help
+         This driver provides support for the IBM Hard Drive Active Protection
+         System (hdaps), which provides an accelerometer and other misc. data.
+         Supported laptops include the IBM ThinkPad T41, T42, T43, and R51.
+         The accelerometer data is readable via sysfs.
+
+         This driver also provides an input class device, allowing the
+         laptop to act as a pinball machine-esque mouse.  This is off by
+         default but enabled via sysfs or the module parameter "mousedev".
+
+         Say Y here if you have an applicable laptop and want to experience
+         the awesome power of hdaps.
+
 config HWMON_DEBUG_CHIP
        bool "Hardware Monitoring Chip debugging messages"
        depends on HWMON
index 381f1bf04cc5531f2f4f2376f2c0afc61fff57b7..f7d6a2f61ee74b4f442f25213b40f66b761fc36a 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_SENSORS_FSCHER)  += fscher.o
 obj-$(CONFIG_SENSORS_FSCPOS)   += fscpos.o
 obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
+obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_SENSORS_IT87)     += it87.o
 obj-$(CONFIG_SENSORS_LM63)     += lm63.o
 obj-$(CONFIG_SENSORS_LM75)     += lm75.o
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
new file mode 100644 (file)
index 0000000..eaebfc1
--- /dev/null
@@ -0,0 +1,739 @@
+/*
+ * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
+ *
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
+ * T41, T42, T43, R51, and X40, at least.  It provides a basic two-axis
+ * accelerometer and other data, such as the device's temperature.
+ *
+ * Based on the document by Mark A. Smith available at
+ * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
+ * and error.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+#define HDAPS_LOW_PORT         0x1600  /* first port used by hdaps */
+#define HDAPS_NR_PORTS         0x30    /* 0x1600 - 0x162f */
+
+#define STATE_FRESH            0x50    /* accelerometer data is fresh */
+
+#define REFRESH_ASYNC          0x00    /* do asynchronous refresh */
+#define REFRESH_SYNC           0x01    /* do synchronous refresh */
+
+#define HDAPS_PORT_STATE       0x1611  /* device state */
+#define HDAPS_PORT_YPOS                0x1612  /* y-axis position */
+#define        HDAPS_PORT_XPOS         0x1614  /* x-axis position */
+#define HDAPS_PORT_TEMP1       0x1616  /* device temperature, in celcius */
+#define HDAPS_PORT_YVAR                0x1617  /* y-axis variance (what is this?) */
+#define HDAPS_PORT_XVAR                0x1619  /* x-axis variance (what is this?) */
+#define HDAPS_PORT_TEMP2       0x161b  /* device temperature (again?) */
+#define HDAPS_PORT_UNKNOWN     0x161c  /* what is this? */
+#define HDAPS_PORT_KMACT       0x161d  /* keyboard or mouse activity */
+
+#define HDAPS_READ_MASK                0xff    /* some reads have the low 8 bits set */
+
+#define KEYBD_MASK             0x20    /* set if keyboard activity */
+#define MOUSE_MASK             0x40    /* set if mouse activity */
+#define KEYBD_ISSET(n)         (!! (n & KEYBD_MASK))   /* keyboard used? */
+#define MOUSE_ISSET(n)         (!! (n & MOUSE_MASK))   /* mouse used? */
+
+#define INIT_TIMEOUT_MSECS     4000    /* wait up to 4s for device init ... */
+#define INIT_WAIT_MSECS                200     /* ... in 200ms increments */
+
+static struct platform_device *pdev;
+static struct input_dev hdaps_idev;
+static struct timer_list hdaps_timer;
+static unsigned int hdaps_mousedev_threshold = 4;
+static unsigned long hdaps_poll_ms = 50;
+static unsigned int hdaps_mousedev;
+static unsigned int hdaps_invert;
+static u8 km_activity;
+static int rest_x;
+static int rest_y;
+
+static DECLARE_MUTEX(hdaps_sem);
+
+/*
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_sem.
+ */
+static inline u8 __get_latch(u16 port)
+{
+       return inb(port) & HDAPS_READ_MASK;
+}
+
+/*
+ * __check_latch - Check a port latch for a given value.  Callers must hold
+ * hdaps_sem.  Returns zero if the port contains the given value.
+ */
+static inline unsigned int __check_latch(u16 port, u8 val)
+{
+       if (__get_latch(port) == val)
+               return 0;
+       return -EINVAL;
+}
+
+/*
+ * __wait_latch - Wait up to 100us for a port latch to get a certain value,
+ * returning zero if the value is obtained.  Callers must hold hdaps_sem.
+ */
+static unsigned int __wait_latch(u16 port, u8 val)
+{
+       unsigned int i;
+
+       for (i = 0; i < 20; i++) {
+               if (!__check_latch(port, val))
+                       return 0;
+               udelay(5);
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * __device_refresh - Request a refresh from the accelerometer.
+ *
+ * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
+ * Returns zero if successful and nonzero on error.
+ *
+ * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
+ * not up-to-date.  Always returns zero.
+ *
+ * Callers must hold hdaps_sem.
+ */
+static int __device_refresh(unsigned int sync)
+{
+       u8 state;
+
+       udelay(100);
+
+       state = inb(0x1604);
+       if (state == STATE_FRESH)
+               return 0;
+
+       outb(0x11, 0x1610);
+       outb(0x01, 0x161f);
+       if (sync == REFRESH_ASYNC)
+               return 0;
+
+       return __wait_latch(0x1604, STATE_FRESH);
+}
+
+/*
+ * __device_complete - Indicate to the accelerometer that we are done reading
+ * data, and then initiate an async refresh.  Callers must hold hdaps_sem.
+ */
+static inline void __device_complete(void)
+{
+       inb(0x161f);
+       inb(0x1604);
+       __device_refresh(REFRESH_ASYNC);
+}
+
+static int __hdaps_readb_one(unsigned int port, u8 *val)
+{
+       /* do a sync refresh -- we need to be sure that we read fresh data */
+       if (__device_refresh(REFRESH_SYNC))
+               return -EIO;
+
+       *val = inb(port);
+       __device_complete();
+
+       return 0;
+}
+
+/*
+ * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
+ * the given pointer.  Returns zero on success or a negative error on failure.
+ * Can sleep.
+ */
+static int hdaps_readb_one(unsigned int port, u8 *val)
+{
+       int ret;
+
+       down(&hdaps_sem);
+       ret = __hdaps_readb_one(port, val);
+       up(&hdaps_sem);
+
+       return ret;
+}
+
+static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
+                            int *x, int *y)
+{
+       /* do a sync refresh -- we need to be sure that we read fresh data */
+       if (__device_refresh(REFRESH_SYNC))
+               return -EIO;
+
+       *y = inw(port2);
+       *x = inw(port1);
+       km_activity = inb(HDAPS_PORT_KMACT);
+       __device_complete();
+
+       /* if hdaps_invert is set, negate the two values */
+       if (hdaps_invert) {
+               *x = -*x;
+               *y = -*y;
+       }
+
+       return 0;
+}
+
+/*
+ * hdaps_read_pair - reads the values from a pair of ports, placing the values
+ * in the given pointers.  Returns zero on success.  Can sleep.
+ */
+static int hdaps_read_pair(unsigned int port1, unsigned int port2,
+                          int *val1, int *val2)
+{
+       int ret;
+
+       down(&hdaps_sem);
+       ret = __hdaps_read_pair(port1, port2, val1, val2);
+       up(&hdaps_sem);
+
+       return ret;
+}
+
+/* initialize the accelerometer */
+static int hdaps_device_init(void)
+{
+       unsigned int total_msecs = INIT_TIMEOUT_MSECS;
+       int ret = -ENXIO;
+
+       down(&hdaps_sem);
+
+       outb(0x13, 0x1610);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+
+       /*
+        * The 0x03 value appears to only work on some thinkpads, such as the
+        * T42p.  Others return 0x01.
+        *
+        * The 0x02 value occurs when the chip has been previously initialized.
+        */
+       if (__check_latch(0x1611, 0x03) &&
+                    __check_latch(0x1611, 0x02) &&
+                    __check_latch(0x1611, 0x01))
+               goto out;
+
+       printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
+              __get_latch(0x1611));
+
+       outb(0x17, 0x1610);
+       outb(0x81, 0x1611);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       if (__wait_latch(0x1611, 0x00))
+               goto out;
+       if (__wait_latch(0x1612, 0x60))
+               goto out;
+       if (__wait_latch(0x1613, 0x00))
+               goto out;
+       outb(0x14, 0x1610);
+       outb(0x01, 0x1611);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       outb(0x10, 0x1610);
+       outb(0xc8, 0x1611);
+       outb(0x00, 0x1612);
+       outb(0x02, 0x1613);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       if (__device_refresh(REFRESH_SYNC))
+               goto out;
+       if (__wait_latch(0x1611, 0x00))
+               goto out;
+
+       /* we have done our dance, now let's wait for the applause */
+       while (total_msecs > 0) {
+               u8 ignored;
+
+               /* a read of the device helps push it into action */
+               __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+               if (!__wait_latch(0x1611, 0x02)) {
+                       ret = 0;
+                       break;
+               }
+
+               msleep(INIT_WAIT_MSECS);
+               total_msecs -= INIT_WAIT_MSECS;
+       }
+
+out:
+       up(&hdaps_sem);
+       return ret;
+}
+
+
+/* Input class stuff */
+
+/*
+ * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+       int x, y;
+
+       if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+               return;
+
+       rest_x = x;
+       rest_y = y;
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+       int x, y;
+
+       /* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
+       if (down_trylock(&hdaps_sem)) {
+               mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
+               return;
+       }
+
+       if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+               goto out;
+
+       x -= rest_x;
+       y -= rest_y;
+       if (abs(x) > hdaps_mousedev_threshold)
+               input_report_rel(&hdaps_idev, REL_X, x);
+       if (abs(y) > hdaps_mousedev_threshold)
+               input_report_rel(&hdaps_idev, REL_Y, y);
+       input_sync(&hdaps_idev);
+
+       mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
+
+out:
+       up(&hdaps_sem);
+}
+
+/*
+ * hdaps_mousedev_enable - enable the input class device.  Can sleep.
+ */
+static void hdaps_mousedev_enable(void)
+{
+       down(&hdaps_sem);
+
+       /* calibrate the device before enabling */
+       hdaps_calibrate();
+
+       /* initialize the input class */
+       init_input_dev(&hdaps_idev);
+       hdaps_idev.dev = &pdev->dev;
+       hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+       hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
+       input_register_device(&hdaps_idev);
+
+       /* start up our timer */
+       init_timer(&hdaps_timer);
+       hdaps_timer.function = hdaps_mousedev_poll;
+       hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
+       add_timer(&hdaps_timer);
+
+       hdaps_mousedev = 1;
+
+       up(&hdaps_sem);
+
+       printk(KERN_INFO "hdaps: input device enabled.\n");
+}
+
+/*
+ * hdaps_mousedev_disable - disable the input class device.  Caller must hold
+ * hdaps_sem.
+ */
+static void hdaps_mousedev_disable(void)
+{
+       down(&hdaps_sem);
+       if (hdaps_mousedev) {
+               hdaps_mousedev = 0;
+               del_timer_sync(&hdaps_timer);
+               input_unregister_device(&hdaps_idev);
+       }
+       up(&hdaps_sem);
+}
+
+
+/* Device model stuff */
+
+static int hdaps_probe(struct device *dev)
+{
+       int ret;
+
+       ret = hdaps_device_init();
+       if (ret)
+               return ret;
+
+       printk(KERN_INFO "hdaps: device successfully initialized.\n");
+       return 0;
+}
+
+static int hdaps_resume(struct device *dev, u32 level)
+{
+       if (level == RESUME_ENABLE)
+               return hdaps_device_init();
+       return 0;
+}
+
+static struct device_driver hdaps_driver = {
+       .name = "hdaps",
+       .bus = &platform_bus_type,
+       .owner = THIS_MODULE,
+       .probe = hdaps_probe,
+       .resume = hdaps_resume
+};
+
+
+/* Sysfs Files */
+
+static ssize_t hdaps_position_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret, x, y;
+
+       ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_variance_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret, x, y;
+
+       ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_temp1_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u8 temp;
+       int ret;
+
+       ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_temp2_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u8 temp;
+       int ret;
+
+       ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_keyboard_activity_show(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
+}
+
+static ssize_t hdaps_mouse_activity_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
+}
+
+static ssize_t hdaps_calibrate_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t hdaps_calibrate_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       down(&hdaps_sem);
+       hdaps_calibrate();
+       up(&hdaps_sem);
+
+       return count;
+}
+
+static ssize_t hdaps_invert_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", hdaps_invert);
+}
+
+static ssize_t hdaps_invert_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       int invert;
+
+       if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0))
+               return -EINVAL;
+
+       hdaps_invert = invert;
+       hdaps_calibrate();
+
+       return count;
+}
+
+static ssize_t hdaps_mousedev_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", hdaps_mousedev);
+}
+
+static ssize_t hdaps_mousedev_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int enable;
+
+       if (sscanf(buf, "%d", &enable) != 1)
+               return -EINVAL;
+
+       if (enable == 1)
+               hdaps_mousedev_enable();
+       else if (enable == 0)
+               hdaps_mousedev_disable();
+       else
+               return -EINVAL;
+
+       return count;
+}
+
+static ssize_t hdaps_poll_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lu\n", hdaps_poll_ms);
+}
+
+static ssize_t hdaps_poll_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       unsigned int poll;
+
+       if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
+               return -EINVAL;
+       hdaps_poll_ms = poll;
+
+       return count;
+}
+
+static ssize_t hdaps_threshold_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
+}
+
+static ssize_t hdaps_threshold_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       unsigned int threshold;
+
+       if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
+               return -EINVAL;
+       hdaps_mousedev_threshold = threshold;
+
+       return count;
+}
+
+static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
+static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
+static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
+static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
+static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
+static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
+static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
+static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
+static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
+static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
+static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
+                  hdaps_threshold_store);
+
+static struct attribute *hdaps_attributes[] = {
+       &dev_attr_position.attr,
+       &dev_attr_variance.attr,
+       &dev_attr_temp1.attr,
+       &dev_attr_temp2.attr,
+       &dev_attr_keyboard_activity.attr,
+       &dev_attr_mouse_activity.attr,
+       &dev_attr_calibrate.attr,
+       &dev_attr_mousedev.attr,
+       &dev_attr_mousedev_threshold.attr,
+       &dev_attr_mousedev_poll_ms.attr,
+       &dev_attr_invert.attr,
+       NULL,
+};
+
+static struct attribute_group hdaps_attribute_group = {
+       .attrs = hdaps_attributes,
+};
+
+
+/* Module stuff */
+
+/*
+ * XXX: We should be able to return nonzero and halt the detection process.
+ * But there is a bug in dmi_check_system() where a nonzero return from the
+ * first match will result in a return of failure from dmi_check_system().
+ * I fixed this; the patch is in 2.6-mm.  Once in Linus's tree we can make
+ * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
+ */
+static int hdaps_dmi_match(struct dmi_system_id *id)
+{
+       printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
+       return 0;
+}
+
+static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+{
+       hdaps_invert = 1;
+       printk(KERN_INFO "hdaps: inverting axis readings.\n");
+       return 0;
+}
+
+#define HDAPS_DMI_MATCH_NORMAL(model)  {               \
+       .ident = "IBM " model,                          \
+       .callback = hdaps_dmi_match,                    \
+       .matches = {                                    \
+               DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),     \
+               DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
+       }                                               \
+}
+
+#define HDAPS_DMI_MATCH_INVERT(model)  {               \
+       .ident = "IBM " model,                          \
+       .callback = hdaps_dmi_match_invert,             \
+       .matches = {                                    \
+               DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),     \
+               DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
+       }                                               \
+}
+
+static int __init hdaps_init(void)
+{
+       int ret;
+
+       /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
+       struct dmi_system_id hdaps_whitelist[] = {
+               HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
+               HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
+               HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+               HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+               { .ident = NULL }
+       };
+
+       if (!dmi_check_system(hdaps_whitelist)) {
+               printk(KERN_WARNING "hdaps: supported laptop not found!\n");
+               ret = -ENXIO;
+               goto out;
+       }
+
+       if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       ret = driver_register(&hdaps_driver);
+       if (ret)
+               goto out_region;
+
+       pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
+       if (IS_ERR(pdev)) {
+               ret = PTR_ERR(pdev);
+               goto out_driver;
+       }
+
+       ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
+       if (ret)
+               goto out_device;
+
+       if (hdaps_mousedev)
+               hdaps_mousedev_enable();
+
+       printk(KERN_INFO "hdaps: driver successfully loaded.\n");
+       return 0;
+
+out_device:
+       platform_device_unregister(pdev);
+out_driver:
+       driver_unregister(&hdaps_driver);
+out_region:
+       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+out:
+       printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
+       return ret;
+}
+
+static void __exit hdaps_exit(void)
+{
+       hdaps_mousedev_disable();
+
+       sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+       platform_device_unregister(pdev);
+       driver_unregister(&hdaps_driver);
+       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+
+       printk(KERN_INFO "hdaps: driver unloaded.\n");
+}
+
+module_init(hdaps_init);
+module_exit(hdaps_exit);
+
+module_param_named(mousedev, hdaps_mousedev, bool, 0);
+MODULE_PARM_DESC(mousedev, "enable the input class device");
+
+module_param_named(invert, hdaps_invert, bool, 0);
+MODULE_PARM_DESC(invert, "invert data along each axis");
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
+MODULE_LICENSE("GPL v2");
index 8610bce08244d1bb3f74dcca18ef48112c717073..21aa9a41f62cbc5e7432a73e93318de9be0cf666 100644 (file)
@@ -758,11 +758,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
                return -ENODEV;
        }
 
-       if (!address) {
-               dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
-               return -ENODEV;
-       }
-
        s_bridge = pci_dev_get(dev);
        if (i2c_isa_add_driver(&sis5595_driver)) {
                pci_dev_put(s_bridge);
index 7e699a8ede262916369a88c57001f6de86eafbad..c9cc683eba4a9f85d7cda47ef9c1a3023402221f 100644 (file)
@@ -2,8 +2,8 @@
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
                  for hardware monitoring
 
-    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
-    Super-I/O chips.
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
+    LPC47M15x and LPC47M192 Super-I/O chips.
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
index eb84997627c8245456ab40c3d402d72b51104ce9..05ddc88e7dd2e4bc5aa7504041c24cdff17467d1 100644 (file)
@@ -812,11 +812,6 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
                return -ENODEV;
        }
 
-       if (!address) {
-               dev_err(&dev->dev, "No Via 686A sensors found.\n");
-               return -ENODEV;
-       }
-
        s_bridge = pci_dev_get(dev);
        if (i2c_isa_add_driver(&via686a_driver)) {
                pci_dev_put(s_bridge);
index 02bd5c0239a2daba693652cdafb431efd75e77a4..3479dc5208e2d3a9ac8d707177a9b17948e7c65f 100644 (file)
@@ -64,6 +64,10 @@ static unsigned short address;
 /* Insmod parameters */
 enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
 
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
+
 static int init = 1;
 module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
@@ -1279,7 +1283,15 @@ static void w83627hf_init_client(struct i2c_client *client)
        int type = data->type;
        u8 tmp;
 
-       if(init) {
+       if (reset) {
+               /* Resetting the chip has been the default for a long time,
+                  but repeatedly caused problems (fans going to full
+                  speed...) so it is now optional. It might even go away if
+                  nobody reports it as being useful, as I see very little
+                  reason why this would be needed at all. */
+               dev_info(&client->dev, "If reset=1 solved a problem you were "
+                        "having, please report!\n");
+
                /* save this register */
                i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
                /* Reset all except Watchdog values and last conversion values
index e0b7a913431e0c1c7664f474a904e8db44a57c92..fe9c0f42a2b7735e746a2a8ac5ddce404b7044f4 100644 (file)
@@ -98,11 +98,6 @@ struct nforce2_smbus {
 #define NVIDIA_SMB_PRTCL_PEC                   0x80
 
 
-/* Other settings */
-#define MAX_TIMEOUT 256
-
-
-
 static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
                       unsigned short flags, char read_write,
                       u8 command, int size, union i2c_smbus_data *data);
index e11e55dc89249279fdbc9fb8c1c807cfb3e74dc1..3cbca7cbea801798bb7a1c7fb05462ed98fb89dd 100644 (file)
@@ -93,7 +93,7 @@ static int dma = 2;
 static inline void wbsd_unlock_config(struct wbsd_host* host)
 {
        BUG_ON(host->config == 0);
-       
+
        outb(host->unlock_code, host->config);
        outb(host->unlock_code, host->config);
 }
@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
 static inline void wbsd_lock_config(struct wbsd_host* host)
 {
        BUG_ON(host->config == 0);
-       
+
        outb(LOCK_CODE, host->config);
 }
 
 static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
 {
        BUG_ON(host->config == 0);
-       
+
        outb(reg, host->config);
        outb(value, host->config + 1);
 }
@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
 static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
 {
        BUG_ON(host->config == 0);
-       
+
        outb(reg, host->config);
        return inb(host->config + 1);
 }
@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
 static void wbsd_init_device(struct wbsd_host* host)
 {
        u8 setup, ier;
-       
+
        /*
         * Reset chip (SD/MMC part) and fifo.
         */
        setup = wbsd_read_index(host, WBSD_IDX_SETUP);
        setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-       
+
        /*
         * Set DAT3 to input
         */
        setup &= ~WBSD_DAT3_H;
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
        host->flags &= ~WBSD_FIGNORE_DETECT;
-       
+
        /*
         * Read back default clock.
         */
@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
         * Power down port.
         */
        outb(WBSD_POWER_N, host->base + WBSD_CSR);
-       
+
        /*
         * Set maximum timeout.
         */
        wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
-       
+
        /*
         * Test for card presence
         */
@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
                host->flags |= WBSD_FCARD_PRESENT;
        else
                host->flags &= ~WBSD_FCARD_PRESENT;
-       
+
        /*
         * Enable interesting interrupts.
         */
@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
 static void wbsd_reset(struct wbsd_host* host)
 {
        u8 setup;
-       
+
        printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
-       
+
        /*
         * Soft reset of chip (SD/MMC part).
         */
@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
 static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
 {
        unsigned long dmaflags;
-       
+
        DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-       
+
        if (host->dma >= 0)
        {
                /*
@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
                 */
                wbsd_write_index(host, WBSD_IDX_DMA, 0);
        }
-       
+
        host->mrq = NULL;
 
        /*
@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
            host->offset = 0;
            host->remain = host->cur_sg->length;
          }
-       
+
        return host->num_sg;
 }
 
@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
        struct scatterlist* sg;
        char* dmabuf = host->dma_buffer;
        char* sgbuf;
-       
+
        size = host->size;
-       
+
        sg = data->sg;
        len = data->sg_len;
-       
+
        /*
         * Just loop through all entries. Size might not
         * be the entire list though so make sure that
@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
                        memcpy(dmabuf, sgbuf, sg[i].length);
                kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
                dmabuf += sg[i].length;
-               
+
                if (size < sg[i].length)
                        size = 0;
                else
                        size -= sg[i].length;
-       
+
                if (size == 0)
                        break;
        }
-       
+
        /*
         * Check that we didn't get a request to transfer
         * more data than can fit into the SG list.
         */
-       
+
        BUG_ON(size != 0);
-       
+
        host->size -= size;
 }
 
@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
        struct scatterlist* sg;
        char* dmabuf = host->dma_buffer;
        char* sgbuf;
-       
+
        size = host->size;
-       
+
        sg = data->sg;
        len = data->sg_len;
-       
+
        /*
         * Just loop through all entries. Size might not
         * be the entire list though so make sure that
@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
                        memcpy(sgbuf, dmabuf, sg[i].length);
                kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
                dmabuf += sg[i].length;
-               
+
                if (size < sg[i].length)
                        size = 0;
                else
                        size -= sg[i].length;
-               
+
                if (size == 0)
                        break;
        }
-       
+
        /*
         * Check that we didn't get a request to transfer
         * more data than can fit into the SG list.
         */
-       
+
        BUG_ON(size != 0);
-       
+
        host->size -= size;
 }
 
 /*
  * Command handling
  */
+
 static inline void wbsd_get_short_reply(struct wbsd_host* host,
        struct mmc_command* cmd)
 {
@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
                cmd->error = MMC_ERR_INVALID;
                return;
        }
-       
+
        cmd->resp[0] =
                wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
        cmd->resp[0] |=
@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
        struct mmc_command* cmd)
 {
        int i;
-       
+
        /*
         * Correct response type?
         */
@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
                cmd->error = MMC_ERR_INVALID;
                return;
        }
-       
+
        for (i = 0;i < 4;i++)
        {
                cmd->resp[i] =
@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
 {
        int i;
        u8 status, isr;
-       
+
        DBGF("Sending cmd (%x)\n", cmd->opcode);
 
        /*
@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
         * transfer.
         */
        host->isr = 0;
-       
+
        /*
         * Send the command (CRC calculated by host).
         */
        outb(cmd->opcode, host->base + WBSD_CMDR);
        for (i = 3;i >= 0;i--)
                outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
-       
+
        cmd->error = MMC_ERR_NONE;
-       
+
        /*
         * Wait for the request to complete.
         */
@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
                 * Read back status.
                 */
                isr = host->isr;
-               
+
                /* Card removed? */
                if (isr & WBSD_INT_CARD)
                        cmd->error = MMC_ERR_TIMEOUT;
@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
        struct mmc_data* data = host->mrq->cmd->data;
        char* buffer;
        int i, fsr, fifo;
-       
+
        /*
         * Handle excessive data.
         */
        if (data->bytes_xfered == host->size)
                return;
-       
+
        buffer = wbsd_kmap_sg(host) + host->offset;
 
        /*
@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
                /*
                 * The size field in the FSR is broken so we have to
                 * do some guessing.
-                */             
+                */
                if (fsr & WBSD_FIFO_FULL)
                        fifo = 16;
                else if (fsr & WBSD_FIFO_FUTHRE)
                        fifo = 8;
                else
                        fifo = 1;
-               
+
                for (i = 0;i < fifo;i++)
                {
                        *buffer = inb(host->base + WBSD_DFR);
@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
                        host->remain--;
 
                        data->bytes_xfered++;
-                       
+
                        /*
                         * Transfer done?
                         */
                        if (data->bytes_xfered == host->size)
                        {
-                               wbsd_kunmap_sg(host);                           
+                               wbsd_kunmap_sg(host);
                                return;
                        }
-                       
+
                        /*
                         * End of scatter list entry?
                         */
                        if (host->remain == 0)
                        {
                                wbsd_kunmap_sg(host);
-                               
+
                                /*
                                 * Get next entry. Check if last.
                                 */
@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
                                         * into the scatter list.
                                         */
                                        BUG_ON(1);
-                                       
+
                                        host->size = data->bytes_xfered;
-                                       
+
                                        return;
                                }
-                               
+
                                buffer = wbsd_kmap_sg(host);
                        }
                }
        }
-       
+
        wbsd_kunmap_sg(host);
 
        /*
@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
        struct mmc_data* data = host->mrq->cmd->data;
        char* buffer;
        int i, fsr, fifo;
-       
+
        /*
         * Check that we aren't being called after the
         * entire buffer has been transfered.
@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
                /*
                 * The size field in the FSR is broken so we have to
                 * do some guessing.
-                */             
+                */
                if (fsr & WBSD_FIFO_EMPTY)
                        fifo = 0;
                else if (fsr & WBSD_FIFO_EMTHRE)
@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
                        buffer++;
                        host->offset++;
                        host->remain--;
-                       
+
                        data->bytes_xfered++;
-                       
+
                        /*
                         * Transfer done?
                         */
@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
                        if (host->remain == 0)
                        {
                                wbsd_kunmap_sg(host);
-                               
+
                                /*
                                 * Get next entry. Check if last.
                                 */
@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
                                         * into the scatter list.
                                         */
                                        BUG_ON(1);
-                                       
+
                                        host->size = data->bytes_xfered;
-                                       
+
                                        return;
                                }
-                               
+
                                buffer = wbsd_kmap_sg(host);
                        }
                }
        }
-       
+
        wbsd_kunmap_sg(host);
-       
+
        /*
         * The controller stops sending interrupts for
         * 'FIFO empty' under certain conditions. So we
@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
                1 << data->blksz_bits, data->blocks, data->flags);
        DBGF("tsac %d ms nsac %d clk\n",
                data->timeout_ns / 1000000, data->timeout_clks);
-       
+
        /*
         * Calculate size.
         */
@@ -708,12 +708,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
                wbsd_write_index(host, WBSD_IDX_TAAC, 127);
        else
                wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
-       
+
        if (data->timeout_clks > 255)
                wbsd_write_index(host, WBSD_IDX_NSAC, 255);
        else
                wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
-       
+
        /*
         * Inform the chip of how large blocks will be
         * sent. It needs this to determine when to
@@ -732,7 +732,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
        else if (host->bus_width == MMC_BUS_WIDTH_4)
        {
                blksize = (1 << data->blksz_bits) + 2 * 4;
-       
+
                wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
                        | WBSD_DATA_WIDTH);
                wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
@@ -751,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
        setup = wbsd_read_index(host, WBSD_IDX_SETUP);
        setup |= WBSD_FIFO_RESET;
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-       
+
        /*
         * DMA transfer?
         */
        if (host->dma >= 0)
-       {       
+       {
                /*
                 * The buffer for DMA is only 64 kB.
                 */
@@ -766,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
                        data->error = MMC_ERR_INVALID;
                        return;
                }
-               
+
                /*
                 * Transfer data from the SG list to
                 * the DMA buffer.
                 */
                if (data->flags & MMC_DATA_WRITE)
                        wbsd_sg_to_dma(host, data);
-               
+
                /*
                 * Initialise the ISA DMA controller.
-                */     
+                */
                dmaflags = claim_dma_lock();
                disable_dma(host->dma);
                clear_dma_ff(host->dma);
@@ -802,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
                 * output to a minimum.
                 */
                host->firsterr = 1;
-               
+
                /*
                 * Initialise the SG list.
                 */
                wbsd_init_sg(host, data);
-       
+
                /*
                 * Turn off DMA.
                 */
                wbsd_write_index(host, WBSD_IDX_DMA, 0);
-       
+
                /*
                 * Set up FIFO threshold levels (and fill
                 * buffer if doing a write).
@@ -828,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
                                WBSD_FIFOEN_EMPTY | 8);
                        wbsd_fill_fifo(host);
                }
-       }       
-               
+       }
+
        data->error = MMC_ERR_NONE;
 }
 
@@ -838,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
        unsigned long dmaflags;
        int count;
        u8 status;
-       
+
        WARN_ON(host->mrq == NULL);
 
        /*
@@ -855,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
        {
                status = wbsd_read_index(host, WBSD_IDX_STATUS);
        } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
-       
+
        /*
         * DMA transfer?
         */
@@ -865,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
                 * Disable DMA on the host.
                 */
                wbsd_write_index(host, WBSD_IDX_DMA, 0);
-               
+
                /*
                 * Turn of ISA DMA controller.
                 */
@@ -874,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
                clear_dma_ff(host->dma);
                count = get_dma_residue(host->dma);
                release_dma_lock(dmaflags);
-               
+
                /*
                 * Any leftover data?
                 */
@@ -882,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
                {
                        printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
                                "transfer. %d bytes left.\n", count);
-                       
+
                        data->error = MMC_ERR_FAILED;
                }
                else
@@ -893,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
                         */
                        if (data->flags & MMC_DATA_READ)
                                wbsd_dma_to_sg(host, data);
-                       
+
                        data->bytes_xfered = host->size;
                }
        }
-       
+
        DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-       
+
        wbsd_request_end(host, host->mrq);
 }
 
@@ -924,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
        cmd = mrq->cmd;
 
        host->mrq = mrq;
-       
+
        /*
         * If there is no card in the slot then
         * timeout immediatly.
@@ -941,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
        if (cmd->data)
        {
                wbsd_prepare_data(host, cmd->data);
-               
+
                if (cmd->data->error != MMC_ERR_NONE)
                        goto done;
        }
-       
+
        wbsd_send_command(host, cmd);
 
        /*
         * If this is a data transfer the request
         * will be finished after the data has
         * transfered.
-        */     
+        */
        if (cmd->data && (cmd->error == MMC_ERR_NONE))
        {
                /*
@@ -965,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
 
                return;
        }
-               
+
 done:
        wbsd_request_end(host, mrq);
 
@@ -976,7 +976,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 {
        struct wbsd_host* host = mmc_priv(mmc);
        u8 clk, setup, pwr;
-       
+
        DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
             ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
             ios->vdd, ios->bus_width);
@@ -989,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
         */
        if (ios->power_mode == MMC_POWER_OFF)
                wbsd_init_device(host);
-       
+
        if (ios->clock >= 24000000)
                clk = WBSD_CLK_24M;
        else if (ios->clock >= 16000000)
@@ -1042,7 +1042,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
                mod_timer(&host->ignore_timer, jiffies + HZ/100);
        }
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-       
+
        /*
         * Store bus width for later. Will be used when
         * setting up the data transfer.
@@ -1128,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
        WARN_ON(!host->mrq->cmd->data);
        if (!host->mrq->cmd->data)
                return NULL;
-       
+
        return host->mrq->cmd->data;
 }
 
@@ -1136,72 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        u8 csr;
-       
+       int delay = -1;
+
        spin_lock(&host->lock);
-       
+
        if (host->flags & WBSD_FIGNORE_DETECT)
        {
                spin_unlock(&host->lock);
                return;
        }
-       
+
        csr = inb(host->base + WBSD_CSR);
        WARN_ON(csr == 0xff);
-       
+
        if (csr & WBSD_CARDPRESENT)
        {
                if (!(host->flags & WBSD_FCARD_PRESENT))
                {
                        DBG("Card inserted\n");
                        host->flags |= WBSD_FCARD_PRESENT;
-                       
-                       spin_unlock(&host->lock);
 
-                       /*
-                        * Delay card detection to allow electrical connections
-                        * to stabilise.
-                        */
-                       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+                       delay = 500;
                }
-               else
-                       spin_unlock(&host->lock);
        }
        else if (host->flags & WBSD_FCARD_PRESENT)
        {
                DBG("Card removed\n");
                host->flags &= ~WBSD_FCARD_PRESENT;
-               
+
                if (host->mrq)
                {
                        printk(KERN_ERR DRIVER_NAME
                                ": Card removed during transfer!\n");
                        wbsd_reset(host);
-                       
+
                        host->mrq->cmd->error = MMC_ERR_FAILED;
                        tasklet_schedule(&host->finish_tasklet);
                }
-               
-               /*
-                * Unlock first since we might get a call back.
-                */
-               spin_unlock(&host->lock);
 
-               mmc_detect_change(host->mmc, 0);
+               delay = 0;
        }
-       else
-               spin_unlock(&host->lock);
+
+       /*
+        * Unlock first since we might get a call back.
+        */
+
+       spin_unlock(&host->lock);
+
+       if (delay != -1)
+               mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
 }
 
 static void wbsd_tasklet_fifo(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        struct mmc_data* data;
-       
+
        spin_lock(&host->lock);
-               
+
        if (!host->mrq)
                goto end;
-       
+
        data = wbsd_get_data(host);
        if (!data)
                goto end;
@@ -1220,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
                tasklet_schedule(&host->finish_tasklet);
        }
 
-end:   
+end:
        spin_unlock(&host->lock);
 }
 
@@ -1228,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        struct mmc_data* data;
-       
+
        spin_lock(&host->lock);
-       
+
        if (!host->mrq)
                goto end;
-       
+
        data = wbsd_get_data(host);
        if (!data)
                goto end;
-       
+
        DBGF("CRC error\n");
 
        data->error = MMC_ERR_BADCRC;
-       
+
        tasklet_schedule(&host->finish_tasklet);
 
-end:           
+end:
        spin_unlock(&host->lock);
 }
 
@@ -1252,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        struct mmc_data* data;
-       
+
        spin_lock(&host->lock);
-       
+
        if (!host->mrq)
                goto end;
-       
+
        data = wbsd_get_data(host);
        if (!data)
                goto end;
-       
+
        DBGF("Timeout\n");
 
        data->error = MMC_ERR_TIMEOUT;
-       
+
        tasklet_schedule(&host->finish_tasklet);
 
-end:   
+end:
        spin_unlock(&host->lock);
 }
 
@@ -1276,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        struct mmc_data* data;
-       
+
        spin_lock(&host->lock);
-       
+
        WARN_ON(!host->mrq);
        if (!host->mrq)
                goto end;
-       
+
        data = wbsd_get_data(host);
        if (!data)
                goto end;
 
        wbsd_finish_data(host, data);
-       
-end:   
+
+end:
        spin_unlock(&host->lock);
 }
 
@@ -1297,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        struct mmc_data* data;
-       
+
        spin_lock(&host->lock);
 
        if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
@@ -1306,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param)
                data = wbsd_get_data(host);
                if (!data)
                        goto end;
-               
+
                DBGF("CRC error\n");
 
                data->error = MMC_ERR_BADCRC;
-       
+
                tasklet_schedule(&host->finish_tasklet);
        }
 
-end:   
+end:
        spin_unlock(&host->lock);
 }
 
@@ -1326,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct wbsd_host* host = dev_id;
        int isr;
-       
+
        isr = inb(host->base + WBSD_ISR);
 
        /*
@@ -1334,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
         */
        if (isr == 0xff || isr == 0x00)
                return IRQ_NONE;
-       
+
        host->isr |= isr;
 
        /*
@@ -1352,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
                tasklet_hi_schedule(&host->block_tasklet);
        if (isr & WBSD_INT_TC)
                tasklet_schedule(&host->finish_tasklet);
-       
+
        return IRQ_HANDLED;
 }
 
@@ -1370,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
 {
        struct mmc_host* mmc;
        struct wbsd_host* host;
-       
+
        /*
         * Allocate MMC structure.
         */
        mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
        if (!mmc)
                return -ENOMEM;
-       
+
        host = mmc_priv(mmc);
        host->mmc = mmc;
 
@@ -1391,37 +1386,37 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
        mmc->f_max = 24000000;
        mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
        mmc->caps = MMC_CAP_4_BIT_DATA;
-       
+
        spin_lock_init(&host->lock);
-       
+
        /*
         * Set up timers
         */
        init_timer(&host->ignore_timer);
        host->ignore_timer.data = (unsigned long)host;
        host->ignore_timer.function = wbsd_reset_ignore;
-       
+
        /*
         * Maximum number of segments. Worst case is one sector per segment
         * so this will be 64kB/512.
         */
        mmc->max_hw_segs = 128;
        mmc->max_phys_segs = 128;
-       
+
        /*
         * Maximum number of sectors in one transfer. Also limited by 64kB
         * buffer.
         */
        mmc->max_sectors = 128;
-       
+
        /*
         * Maximum segment size. Could be one segment with the maximum number
         * of segments.
         */
        mmc->max_seg_size = mmc->max_sectors * 512;
-       
+
        dev_set_drvdata(dev, mmc);
-       
+
        return 0;
 }
 
@@ -1429,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
 {
        struct mmc_host* mmc;
        struct wbsd_host* host;
-       
+
        mmc = dev_get_drvdata(dev);
        if (!mmc)
                return;
-       
+
        host = mmc_priv(mmc);
        BUG_ON(host == NULL);
-       
+
        del_timer_sync(&host->ignore_timer);
-       
+
        mmc_free_host(mmc);
-       
+
        dev_set_drvdata(dev, NULL);
 }
 
@@ -1452,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
 {
        int i, j, k;
        int id;
-       
+
        /*
         * Iterate through all ports, all codes to
         * find hardware that is in our known list.
@@ -1461,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
        {
                if (!request_region(config_ports[i], 2, DRIVER_NAME))
                        continue;
-                       
+
                for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
                {
                        id = 0xFFFF;
-                       
+
                        outb(unlock_codes[j], config_ports[i]);
                        outb(unlock_codes[j], config_ports[i]);
-                       
+
                        outb(WBSD_CONF_ID_HI, config_ports[i]);
                        id = inb(config_ports[i] + 1) << 8;
 
                        outb(WBSD_CONF_ID_LO, config_ports[i]);
                        id |= inb(config_ports[i] + 1);
-                       
+
                        for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
                        {
                                if (id == valid_ids[k])
-                               {                               
+                               {
                                        host->chip_id = id;
                                        host->config = config_ports[i];
                                        host->unlock_code = unlock_codes[i];
-                               
+
                                        return 0;
                                }
                        }
-                       
+
                        if (id != 0xFFFF)
                        {
                                DBG("Unknown hardware (id %x) found at %x\n",
@@ -1495,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
 
                        outb(LOCK_CODE, config_ports[i]);
                }
-               
+
                release_region(config_ports[i], 2);
        }
-       
+
        return -ENODEV;
 }
 
@@ -1510,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
 {
        if (io & 0x7)
                return -EINVAL;
-       
+
        if (!request_region(base, 8, DRIVER_NAME))
                return -EIO;
-       
+
        host->base = io;
-               
+
        return 0;
 }
 
@@ -1523,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
 {
        if (host->base)
                release_region(host->base, 8);
-       
+
        host->base = 0;
 
        if (host->config)
                release_region(host->config, 2);
-       
+
        host->config = 0;
 }
 
@@ -1540,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
 {
        if (dma < 0)
                return;
-       
+
        if (request_dma(dma, DRIVER_NAME))
                goto err;
-       
+
        /*
         * We need to allocate a special buffer in
         * order for ISA to be able to DMA to it.
@@ -1558,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
         */
        host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
                WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-                       
+
        /*
         * ISA DMA must be aligned on a 64k basis.
         */
@@ -1571,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
                goto kfree;
 
        host->dma = dma;
-       
+
        return;
-       
+
 kfree:
        /*
         * If we've gotten here then there is some kind of alignment bug
         */
        BUG_ON(1);
-       
+
        dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
                DMA_BIDIRECTIONAL);
        host->dma_addr = (dma_addr_t)NULL;
-       
+
        kfree(host->dma_buffer);
        host->dma_buffer = NULL;
 
@@ -1604,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
                kfree(host->dma_buffer);
        if (host->dma >= 0)
                free_dma(host->dma);
-       
+
        host->dma = -1;
        host->dma_buffer = NULL;
        host->dma_addr = (dma_addr_t)NULL;
@@ -1617,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
 static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
 {
        int ret;
-       
+
        /*
         * Allocate interrupt.
         */
@@ -1625,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
        ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
        if (ret)
                return ret;
-       
+
        host->irq = irq;
 
        /*
@@ -1637,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
        tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
        tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
        tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
-       
+
        return 0;
 }
 
@@ -1647,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
                return;
 
        free_irq(host->irq, host);
-       
+
        host->irq = 0;
-               
+
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->fifo_tasklet);
        tasklet_kill(&host->crc_tasklet);
@@ -1666,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
        int base, int irq, int dma)
 {
        int ret;
-       
+
        /*
         * Allocate I/O ports.
         */
@@ -1685,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
         * Allocate DMA.
         */
        wbsd_request_dma(host, dma);
-       
+
        return 0;
 }
 
@@ -1708,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
 {
        /*
         * Reset the chip.
-        */     
+        */
        wbsd_write_config(host, WBSD_CONF_SWRST, 1);
        wbsd_write_config(host, WBSD_CONF_SWRST, 0);
 
@@ -1716,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
         * Select SD/MMC function.
         */
        wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-       
+
        /*
         * Set up card detection.
         */
        wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
-       
+
        /*
         * Configure chip
         */
        wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
        wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-       
+
        wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
-       
+
        if (host->dma >= 0)
                wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
-       
+
        /*
         * Enable and power up chip.
         */
@@ -1743,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
 /*
  * Check that configured resources are correct.
  */
+
 static int __devinit wbsd_chip_validate(struct wbsd_host* host)
 {
        int base, irq, dma;
-       
+
        /*
         * Select SD/MMC function.
         */
        wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-       
+
        /*
         * Read configuration.
         */
        base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
        base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
-       
+
        irq = wbsd_read_config(host, WBSD_CONF_IRQ);
-       
+
        dma = wbsd_read_config(host, WBSD_CONF_DRQ);
-       
+
        /*
         * Validate against given configuration.
         */
@@ -1772,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
                return 0;
        if ((dma != host->dma) && (host->dma != -1))
                return 0;
-       
+
        return 1;
 }
 
@@ -1788,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
        struct wbsd_host* host = NULL;
        struct mmc_host* mmc = NULL;
        int ret;
-       
+
        ret = wbsd_alloc_mmc(dev);
        if (ret)
                return ret;
-       
+
        mmc = dev_get_drvdata(dev);
        host = mmc_priv(mmc);
-       
+
        /*
         * Scan for hardware.
         */
@@ -1814,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
                        return ret;
                }
        }
-       
+
        /*
         * Request resources.
         */
@@ -1825,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
                wbsd_free_mmc(dev);
                return ret;
        }
-       
+
        /*
         * See if chip needs to be configured.
         */
@@ -1842,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
        }
        else
                wbsd_chip_config(host);
-       
+
        /*
         * Power Management stuff. No idea how this works.
         * Not tested.
@@ -1860,7 +1855,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
         * Reset the chip into a known state.
         */
        wbsd_init_device(host);
-       
+
        mmc_add_host(mmc);
 
        printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
@@ -1882,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
 {
        struct mmc_host* mmc = dev_get_drvdata(dev);
        struct wbsd_host* host;
-       
+
        if (!mmc)
                return;
 
        host = mmc_priv(mmc);
-       
+
        mmc_remove_host(mmc);
 
        if (!pnp)
@@ -1900,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
                wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
                wbsd_lock_config(host);
        }
-       
+
        wbsd_release_resources(host);
-       
+
        wbsd_free_mmc(dev);
 }
 
@@ -1932,7 +1927,7 @@ static int __devinit
 wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
 {
        int io, irq, dma;
-       
+
        /*
         * Get resources from PnP layer.
         */
@@ -1942,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
                dma = pnp_dma(pnpdev, 0);
        else
                dma = -1;
-       
+
        DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
-       
+
        return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
 }
 
@@ -1985,7 +1980,7 @@ static struct device_driver wbsd_driver = {
        .bus            = &platform_bus_type,
        .probe          = wbsd_probe,
        .remove         = wbsd_remove,
-       
+
        .suspend        = wbsd_suspend,
        .resume         = wbsd_resume,
 };
@@ -2008,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = {
 static int __init wbsd_drv_init(void)
 {
        int result;
-       
+
        printk(KERN_INFO DRIVER_NAME
                ": Winbond W83L51xD SD/MMC card interface driver, "
                DRIVER_VERSION "\n");
@@ -2023,8 +2018,8 @@ static int __init wbsd_drv_init(void)
                        return result;
        }
 
-#endif /* CONFIG_PNP */        
-       
+#endif /* CONFIG_PNP */
+
        if (nopnp)
        {
                result = driver_register(&wbsd_driver);
@@ -2046,13 +2041,13 @@ static void __exit wbsd_drv_exit(void)
 
        if (!nopnp)
                pnp_unregister_driver(&wbsd_pnp_driver);
-       
-#endif /* CONFIG_PNP */        
+
+#endif /* CONFIG_PNP */
 
        if (nopnp)
        {
                platform_device_unregister(wbsd_device);
-       
+
                driver_unregister(&wbsd_driver);
        }
 
index 9005b5241b3cce44c132f13be7e9b5270cfc691c..249baa701cb0be7f5930e6282c944f499365119a 100644 (file)
 struct wbsd_host
 {
        struct mmc_host*        mmc;            /* MMC structure */
-       
+
        spinlock_t              lock;           /* Mutex */
 
        int                     flags;          /* Driver states */
 
 #define WBSD_FCARD_PRESENT     (1<<0)          /* Card is present */
 #define WBSD_FIGNORE_DETECT    (1<<1)          /* Ignore card detection */
-       
+
        struct mmc_request*     mrq;            /* Current request */
-       
+
        u8                      isr;            /* Accumulated ISR */
-       
+
        struct scatterlist*     cur_sg;         /* Current SG entry */
        unsigned int            num_sg;         /* Number of entries left */
        void*                   mapped_sg;      /* vaddr of mapped sg */
-       
+
        unsigned int            offset;         /* Offset into current entry */
        unsigned int            remain;         /* Data left in curren entry */
 
        int                     size;           /* Total size of transfer */
-       
+
        char*                   dma_buffer;     /* ISA DMA buffer */
        dma_addr_t              dma_addr;       /* Physical address for same */
 
        int                     firsterr;       /* See fifo functions */
-       
+
        u8                      clk;            /* Current clock speed */
        unsigned char           bus_width;      /* Current bus width */
-       
+
        int                     config;         /* Config port */
        u8                      unlock_code;    /* Code to unlock config */
 
        int                     chip_id;        /* ID of controller */
-       
+
        int                     base;           /* I/O port base */
        int                     irq;            /* Interrupt */
        int                     dma;            /* DMA channel */
-       
+
        struct tasklet_struct   card_tasklet;   /* Tasklet structures */
        struct tasklet_struct   fifo_tasklet;
        struct tasklet_struct   crc_tasklet;
        struct tasklet_struct   timeout_tasklet;
        struct tasklet_struct   finish_tasklet;
        struct tasklet_struct   block_tasklet;
-       
-       struct timer_list       detect_timer;   /* Card detection timer */
+
        struct timer_list       ignore_timer;   /* Ignore detection timer */
 };
index 811d92e5f5b1426c83bd0f1992ee00859227733b..cc372136e852750f87f42dd3d69c0d917d074908 100644 (file)
@@ -23,9 +23,6 @@
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
 
-/****************************************************************************/
-
-
 /****************************************************************************/
 
 struct map_info uclinux_ram_map = {
@@ -60,14 +57,15 @@ int __init uclinux_mtd_init(void)
        struct mtd_info *mtd;
        struct map_info *mapp;
        extern char _ebss;
+       unsigned long addr = (unsigned long) &_ebss;
 
        mapp = &uclinux_ram_map;
-       mapp->phys = (unsigned long) &_ebss;
-       mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
+       mapp->phys = addr;
+       mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
        mapp->bankwidth = 4;
 
        printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
-               (int) mapp->map_priv_2, (int) mapp->size);
+               (int) mapp->phys, (int) mapp->size);
 
        mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
 
@@ -95,7 +93,6 @@ int __init uclinux_mtd_init(void)
        printk("uclinux[mtd]: set %s to be root filesystem\n",
                uclinux_romfs[0].name);
        ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
-       put_mtd_device(mtd);
 
        return(0);
 }
@@ -109,7 +106,7 @@ void __exit uclinux_mtd_cleanup(void)
                map_destroy(uclinux_ram_mtdinfo);
                uclinux_ram_mtdinfo = NULL;
        }
-       if (uclinux_ram_map.map_priv_1) {
+       if (uclinux_ram_map.virt) {
                iounmap((void *) uclinux_ram_map.virt);
                uclinux_ram_map.virt = 0;
        }
index 6bb9232514b4e95a1b6506fe792e61a5f46779e5..54fff9c2e8028cb0a7509dae5cb5ed017bab39ab 100644 (file)
@@ -1738,11 +1738,18 @@ config 68360_ENET
          the Motorola 68360 processor.
 
 config FEC
-       bool "FEC ethernet controller (of ColdFire 5272)"
-       depends on M5272 || M5282
+       bool "FEC ethernet controller (of ColdFire CPUs)"
+       depends on M523x || M527x || M5272 || M528x
        help
          Say Y here if you want to use the built-in 10/100 Fast ethernet
-         controller on the Motorola ColdFire 5272 processor.
+         controller on some Motorola ColdFire processors.
+
+config FEC2
+       bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+       depends on FEC
+       help
+         Say Y here if you want to use the second built-in 10/100 Fast
+         ethernet controller on some Motorola ColdFire processors.
 
 config NE_H8300
        tristate "NE2000 compatible support for H8/300"
index 83598e32179cee8c1f81b851e37c67f8fc736f87..3a2ace01e444d082daaa31dc30de97c542d19054 100644 (file)
@@ -5015,6 +5015,7 @@ static struct ethtool_ops bnx2_ethtool_ops = {
        .phys_id                = bnx2_phys_id,
        .get_stats_count        = bnx2_get_stats_count,
        .get_ethtool_stats      = bnx2_get_ethtool_stats,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 /* Called with rtnl_lock */
@@ -5442,6 +5443,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_drvdata(pdev, dev);
 
        memcpy(dev->dev_addr, bp->mac_addr, 6);
+       memcpy(dev->perm_addr, bp->mac_addr, 6);
        bp->name = board_info[ent->driver_data].name,
        printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
                "IRQ %d, ",
index 2c7008491378fef4cf71050582e6f88fb9f3e3c7..85504fb900dab5a62402a2ddc60e7ec5febe52e3 100644 (file)
@@ -8,7 +8,7 @@
  * describes connections using the internal parallel port I/O, which
  * is basically all of Port D.
  *
- * Right now, I am very watseful with the buffers.  I allocate memory
+ * Right now, I am very wasteful with the buffers.  I allocate memory
  * pages and then divide them into 2K frame buffers.  This way I know I
  * have buffers large enough to hold one frame within one buffer descriptor.
  * Once I get this working, I will use 64 or 128 byte CPM buffers, which
  * Copyright (c) 2000 Ericsson Radio Systems AB.
  *
  * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2005 Macq Electronique SA.
  */
 
 #include <linux/config.h>
@@ -46,7 +49,8 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+    defined(CONFIG_M5272) || defined(CONFIG_M528x)
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include "fec.h"
@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
 #elif defined(CONFIG_M527x)
        (MCF_MBAR + 0x1000),
        (MCF_MBAR + 0x1800),
-#elif defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
        (MCF_MBAR + 0x1000),
 #else
        &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@ static unsigned char        fec_mac_default[] = {
 #define        FEC_FLASHMAC    0xffe04000
 #elif defined(CONFIG_CANCam)
 #define        FEC_FLASHMAC    0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define        FEC_FLASHMAC    (0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC   0xffc0406b
 #else
 #define        FEC_FLASHMAC    0
 #endif
 
-unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
-
 /* Forward declarations of some structures to support different PHYs
 */
 
@@ -158,7 +164,7 @@ typedef struct {
  * size bits. Other FEC hardware does not, so we need to take that into
  * account when setting it.
  */
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define        OPT_FRAME_SIZE  (PKT_MAXBUF_SIZE << 16)
 #else
 #define        OPT_FRAME_SIZE  0
@@ -196,7 +202,7 @@ struct fec_enet_private {
        uint    phy_id_done;
        uint    phy_status;
        uint    phy_speed;
-       phy_info_t      *phy;
+       phy_info_t const        *phy;
        struct work_struct phy_task;
 
        uint    sequence_done;
@@ -209,7 +215,6 @@ struct fec_enet_private {
        int     link;
        int     old_link;
        int     full_duplex;
-       unsigned char mac_addr[ETH_ALEN];
 };
 
 static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@ typedef struct mii_list {
 } mii_list_t;
 
 #define                NMII    20
-mii_list_t     mii_cmds[NMII];
-mii_list_t     *mii_free;
-mii_list_t     *mii_head;
-mii_list_t     *mii_tail;
+static mii_list_t      mii_cmds[NMII];
+static mii_list_t      *mii_free;
+static mii_list_t      *mii_head;
+static mii_list_t      *mii_tail;
 
 static int     mii_queue(struct net_device *dev, int request, 
                                void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
        }
        }
 #endif
-       fec_restart(dev, 0);
+       fec_restart(dev, fep->full_duplex);
        netif_wake_queue(dev);
 }
 
@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
 
        if (mii_reg & 0x0004)
-               *s |= PHY_STAT_LINK;
+               status |= PHY_STAT_LINK;
        if (mii_reg & 0x0010)
-               *s |= PHY_STAT_FAULT;
+               status |= PHY_STAT_FAULT;
        if (mii_reg & 0x0020)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
+
+       *s = status;
 }
 
 static void mii_parse_cr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+       status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
 
        if (mii_reg & 0x1000)
-               *s |= PHY_CONF_ANE;
+               status |= PHY_CONF_ANE;
        if (mii_reg & 0x4000)
-               *s |= PHY_CONF_LOOP;
+               status |= PHY_CONF_LOOP;
+       *s = status;
 }
 
 static void mii_parse_anar(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_CONF_SPMASK);
+       status = *s & ~(PHY_CONF_SPMASK);
 
        if (mii_reg & 0x0020)
-               *s |= PHY_CONF_10HDX;
+               status |= PHY_CONF_10HDX;
        if (mii_reg & 0x0040)
-               *s |= PHY_CONF_10FDX;
+               status |= PHY_CONF_10FDX;
        if (mii_reg & 0x0080)
-               *s |= PHY_CONF_100HDX;
+               status |= PHY_CONF_100HDX;
        if (mii_reg & 0x00100)
-               *s |= PHY_CONF_100FDX;
+               status |= PHY_CONF_100FDX;
+       *s = status;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK);
-
+       status = *s & ~(PHY_STAT_SPMASK);
        if (mii_reg & 0x0800) {
                if (mii_reg & 0x1000)
-                       *s |= PHY_STAT_100FDX;
+                       status |= PHY_STAT_100FDX;
                else
-                       *s |= PHY_STAT_100HDX;
+                       status |= PHY_STAT_100HDX;
        } else {
                if (mii_reg & 0x1000)
-                       *s |= PHY_STAT_10FDX;
+                       status |= PHY_STAT_10FDX;
                else
-                       *s |= PHY_STAT_10HDX;
+                       status |= PHY_STAT_10HDX;
        }
+       *s = status;
 }
 
-static phy_info_t phy_info_lxt970 = {
-       0x07810000, 
-       "LXT970",
-
-       (const phy_cmd_t []) {  /* config */
+static phy_cmd_t const phy_cmd_lxt970_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
                { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
                /* read SR and ISR to acknowledge */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
                /* find out the current status */
                { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_lxt970 = {
+       .id = 0x07810000, 
+       .name = "LXT970",
+       .config = phy_cmd_lxt970_config,
+       .startup = phy_cmd_lxt970_startup,
+       .ack_int = phy_cmd_lxt970_ack_int,
+       .shutdown = phy_cmd_lxt970_shutdown
 };
        
 /* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
 
        if (mii_reg & 0x0400) {
                fep->link = 1;
-               *s |= PHY_STAT_LINK;
+               status |= PHY_STAT_LINK;
        } else {
                fep->link = 0;
        }
        if (mii_reg & 0x0080)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
        if (mii_reg & 0x4000) {
                if (mii_reg & 0x0200)
-                       *s |= PHY_STAT_100FDX;
+                       status |= PHY_STAT_100FDX;
                else
-                       *s |= PHY_STAT_100HDX;
+                       status |= PHY_STAT_100HDX;
        } else {
                if (mii_reg & 0x0200)
-                       *s |= PHY_STAT_10FDX;
+                       status |= PHY_STAT_10FDX;
                else
-                       *s |= PHY_STAT_10HDX;
+                       status |= PHY_STAT_10HDX;
        }
        if (mii_reg & 0x0008)
-               *s |= PHY_STAT_FAULT;
-}
+               status |= PHY_STAT_FAULT;
 
-static phy_info_t phy_info_lxt971 = {
-       0x0001378e, 
-       "LXT971",
+       *s = status;
+}
        
-       (const phy_cmd_t []) {  /* config */  
-               /* limit to 10MBit because my protorype board 
+static phy_cmd_t const phy_cmd_lxt971_config[] = {
+               /* limit to 10MBit because my prototype board 
                 * doesn't work with 100. */
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt971_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
                 * read here to get a valid value in ack_int */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
+               /* acknowledge the int before reading status ! */
+               { mk_mii_read(MII_LXT971_ISR), NULL },
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
-               /* we only need to read ISR to acknowledge */
-               { mk_mii_read(MII_LXT971_ISR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_lxt971 = {
+       .id = 0x0001378e, 
+       .name = "LXT971",
+       .config = phy_cmd_lxt971_config,
+       .startup = phy_cmd_lxt971_startup,
+       .ack_int = phy_cmd_lxt971_ack_int,
+       .shutdown = phy_cmd_lxt971_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK);
+       status = *s & ~(PHY_STAT_SPMASK);
 
        switch((mii_reg >> 2) & 7) {
-       case 1: *s |= PHY_STAT_10HDX; break;
-       case 2: *s |= PHY_STAT_100HDX; break;
-       case 5: *s |= PHY_STAT_10FDX; break;
-       case 6: *s |= PHY_STAT_100FDX; break;
-       }
+       case 1: status |= PHY_STAT_10HDX; break;
+       case 2: status |= PHY_STAT_100HDX; break;
+       case 5: status |= PHY_STAT_10FDX; break;
+       case 6: status |= PHY_STAT_100FDX; break;
 }
 
-static phy_info_t phy_info_qs6612 = {
-       0x00181440, 
-       "QS6612",
-       
-       (const phy_cmd_t []) {  /* config */  
+       *s = status;
+}
+
+static phy_cmd_t const phy_cmd_qs6612_config[] = {
                /* The PHY powers up isolated on the RPX, 
                 * so send a command to allow operation.
                 */
@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_qs6612_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
                /* we need to read ISR, SR and ANER to acknowledge */
                { mk_mii_read(MII_QS6612_ISR), NULL },
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
                /* read pcr to get info */
                { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_qs6612 = {
+       .id = 0x00181440, 
+       .name = "QS6612",
+       .config = phy_cmd_qs6612_config,
+       .startup = phy_cmd_qs6612_startup,
+       .ack_int = phy_cmd_qs6612_ack_int,
+       .shutdown = phy_cmd_qs6612_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
 
        if (mii_reg & 0x0080)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
        if (mii_reg & 0x0400)
-               *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
+               status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
        else
-               *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+               status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+
+       *s = status;
 }
 
-static phy_info_t phy_info_am79c874 = {
-       0x00022561, 
-       "AM79C874",
-       
-       (const phy_cmd_t []) {  /* config */  
-               /* limit to 10MBit because my protorype board 
-                * doesn't work with 100. */
+static phy_cmd_t const phy_cmd_am79c874_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_am79c874_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
                /* we only need to read ISR to acknowledge */
                { mk_mii_read(MII_AM79C874_ICSR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_am79c874 = {
+       .id = 0x00022561,
+       .name = "AM79C874",
+       .config = phy_cmd_am79c874_config,
+       .startup = phy_cmd_am79c874_startup,
+       .ack_int = phy_cmd_am79c874_ack_int,
+       .shutdown = phy_cmd_am79c874_shutdown
 };
 
+
 /* ------------------------------------------------------------------------- */
 /* Kendin KS8721BL phy                                                       */
 
@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
 #define MII_KS8721BL_ICSR      22
 #define        MII_KS8721BL_PHYCR      31
 
-static phy_info_t phy_info_ks8721bl = {
-       0x00022161, 
-       "KS8721BL",
-       
-       (const phy_cmd_t []) {  /* config */  
+static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                /* we only need to read ISR to acknowledge */
                { mk_mii_read(MII_KS8721BL_ICSR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_ks8721bl = {
+       .id = 0x00022161, 
+       .name = "KS8721BL",
+       .config = phy_cmd_ks8721bl_config,
+       .startup = phy_cmd_ks8721bl_startup,
+       .ack_int = phy_cmd_ks8721bl_ack_int,
+       .shutdown = phy_cmd_ks8721bl_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
 
-static phy_info_t *phy_info[] = {
+static phy_info_t const * const phy_info[] = {
        &phy_info_lxt970,
        &phy_info_lxt971,
        &phy_info_qs6612,
@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
        volatile unsigned long *icrp;
+       static const struct idesc {
+               char *name;
+               unsigned short irq;
+               irqreturn_t (*handler)(int, void *, struct pt_regs *);
+       } *idp, id[] = {
+               { "fec(RX)", 86, fec_enet_interrupt },
+               { "fec(TX)", 87, fec_enet_interrupt },
+               { "fec(OTHER)", 88, fec_enet_interrupt },
+               { "fec(MII)", 66, mii_link_interrupt },
+               { NULL },
+       };
 
        /* Setup interrupt handlers. */
-       if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n");
-       if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n");
-       if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
-               printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
-       if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
-               printk("FEC: Could not allocate MII IRQ(66)!\n");
+       for (idp = id; idp->name; idp++) {
+               if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
+                       printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
+       }
 
        /* Unmask interrupt at ColdFire 5272 SIM */
        icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile fec_t *fecp;
-       unsigned char *iap, tmpaddr[6];
-       int i;
+       unsigned char *iap, tmpaddr[ETH_ALEN];
 
        fecp = fep->hwp;
 
-       if (fec_flashmac) {
+       if (FEC_FLASHMAC) {
                /*
                 * Get MAC address from FLASH.
                 * If it is all 1's or 0's, use the default.
                 */
-               iap = fec_flashmac;
+               iap = (unsigned char *)FEC_FLASHMAC;
                if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
                    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
                        iap = fec_mac_default;
@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                iap = &tmpaddr[0];
        }
 
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+       memcpy(dev->dev_addr, iap, ETH_ALEN);
 
        /* Adjust MAC if using default MAC address */
-       if (iap == fec_mac_default) {
-               dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-                       iap[ETH_ALEN-1] + fep->index;
-       }
+       if (iap == fec_mac_default)
+                dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
 
 /* ------------------------------------------------------------------------- */
 
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 
 /*
- *     Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups.
+ *     Code specific to Coldfire 5230/5231/5232/5234/5235,
+ *     the 5270/5271/5274/5275 and 5280/5282 setups.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
        struct fec_enet_private *fep;
        int b;
+       static const struct idesc {
+               char *name;
+               unsigned short irq;
+       } *idp, id[] = {
+               { "fec(TXF)", 23 },
+               { "fec(TXB)", 24 },
+               { "fec(TXFIFO)", 25 },
+               { "fec(TXCR)", 26 },
+               { "fec(RXF)", 27 },
+               { "fec(RXB)", 28 },
+               { "fec(MII)", 29 },
+               { "fec(LC)", 30 },
+               { "fec(HBERR)", 31 },
+               { "fec(GRA)", 32 },
+               { "fec(EBERR)", 33 },
+               { "fec(BABT)", 34 },
+               { "fec(BABR)", 35 },
+               { NULL },
+       };
 
        fep = netdev_priv(dev);
        b = (fep->index) ? 128 : 64;
 
        /* Setup interrupt handlers. */
-       if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b);
-       if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b);
-       if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
-       if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
-
-       if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
-       if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
-
-       if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
-               printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
-       if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
-               printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
-       if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
-       if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
-               printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
-       if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
-       if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
-               printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
-       if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
+       for (idp = id; idp->name; idp++) {
+               if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
+                       printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+       }
 
        /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
        {
@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
 #if defined(CONFIG_M528x)
        /* Set up gpio outputs for MII lines */
        {
-               volatile unsigned short *gpio_paspar;
+               volatile u16 *gpio_paspar;
+               volatile u8 *gpio_pehlpar;
   
-               gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR +
-                       0x100056);
-               *gpio_paspar = 0x0f00;
+               gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
+               gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+               *gpio_paspar |= 0x0f00;
+               *gpio_pehlpar = 0xc0;
        }
 #endif
 }
@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile fec_t *fecp;
-       unsigned char *iap, tmpaddr[6];
-       int i;
+       unsigned char *iap, tmpaddr[ETH_ALEN];
 
        fecp = fep->hwp;
 
-       if (fec_flashmac) {
+       if (FEC_FLASHMAC) {
                /*
                 * Get MAC address from FLASH.
                 * If it is all 1's or 0's, use the default.
                 */
-               iap = fec_flashmac;
+               iap = FEC_FLASHMAC;
                if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
                    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
                        iap = fec_mac_default;
@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                iap = &tmpaddr[0];
        }
 
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+       memcpy(dev->dev_addr, iap, ETH_ALEN);
 
        /* Adjust MAC if using default MAC address */
-       if (iap == fec_mac_default) {
-               dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-                       iap[ETH_ALEN-1] + fep->index;
-       }
+       if (iap == fec_mac_default)
+               dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
 #else
 
 /*
- *     Code sepcific to the MPC860T setup.
+ *     Code specific to the MPC860T setup.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
 
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
-       struct fec_enet_private *fep = netdev_priv(dev);
-       unsigned char *iap, tmpaddr[6];
        bd_t *bd;
-       int i;
 
-       iap = bd->bi_enetaddr;
        bd = (bd_t *)__res;
+       memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
 
 #ifdef CONFIG_RPXCLASSIC
        /* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
         * the address bits above something that would have (up to
         * now) been allocated.
         */
-       for (i=0; i<6; i++)
-               tmpaddr[i] = *iap++;
-       tmpaddr[3] |= 0x80;
-       iap = tmpaddr;
+       dev->dev_adrd[3] |= 0x80;
 #endif
-
-       for (i=0; i<6; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
 }
 
 static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
 static void mii_display_config(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       volatile uint *s = &(fep->phy_status);
+       uint status = fep->phy_status;
 
        /*
        ** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
        fep->mii_phy_task_queued = 0;
        printk("%s: config: auto-negotiation ", dev->name);
 
-       if (*s & PHY_CONF_ANE)
+       if (status & PHY_CONF_ANE)
                printk("on");
        else
                printk("off");
 
-       if (*s & PHY_CONF_100FDX)
+       if (status & PHY_CONF_100FDX)
                printk(", 100FDX");
-       if (*s & PHY_CONF_100HDX)
+       if (status & PHY_CONF_100HDX)
                printk(", 100HDX");
-       if (*s & PHY_CONF_10FDX)
+       if (status & PHY_CONF_10FDX)
                printk(", 10FDX");
-       if (*s & PHY_CONF_10HDX)
+       if (status & PHY_CONF_10HDX)
                printk(", 10HDX");
-       if (!(*s & PHY_CONF_SPMASK))
+       if (!(status & PHY_CONF_SPMASK))
                printk(", No speed/duplex selected?");
 
-       if (*s & PHY_CONF_LOOP)
+       if (status & PHY_CONF_LOOP)
                printk(", loopback enabled");
        
        printk(".\n");
@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
        schedule_work(&fep->phy_task);
 }
 
-/* mii_queue_config is called in user context from fec_enet_open */
+/* mii_queue_config is called in interrupt context from fec_enet_mii */
 static void mii_queue_config(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
        schedule_work(&fep->phy_task);
 }
 
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
-                              { mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
-                              { mk_mii_end, } };
-
-
+phy_cmd_t const phy_cmd_relink[] = {
+       { mk_mii_read(MII_REG_CR), mii_queue_relink },
+       { mk_mii_end, }
+       };
+phy_cmd_t const phy_cmd_config[] = {
+       { mk_mii_read(MII_REG_CR), mii_queue_config },
+       { mk_mii_end, }
+       };
 
 /* Read remainder of PHY ID.
 */
@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
 static void
 fec_set_mac_address(struct net_device *dev)
 {
-       struct fec_enet_private *fep;
        volatile fec_t *fecp;
 
-       fep = netdev_priv(dev);
-       fecp = fep->hwp;
+       fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
 
        /* Set station address. */
-       fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-               (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-       fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-               (fep->mac_addr[4] << 24);
+       fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+               (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
+       fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
+               (dev->dev_addr[4] << 24);
 
 }
 
@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
        udelay(10);
 
        /* Clear and enable interrupts */
-       fecp->fec_ievent = 0xffc0;
+       fecp->fec_ievent = 0xffc00000;
        fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
                FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
        fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
        /* setup MII interface */
        fec_set_mii(dev, fep);
 
-       printk("%s: FEC ENET Version 0.2, ", dev->name);
-       for (i=0; i<5; i++)
-               printk("%02x:", dev->dev_addr[i]);
-       printk("%02x\n", dev->dev_addr[5]);
-
        /* Queue up command to detect the PHY and initialize the
         * remainder of the interface.
         */
@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
 
        /* Clear any outstanding interrupt.
        */
-       fecp->fec_ievent = 0xffc0;
+       fecp->fec_ievent = 0xffc00000;
        fec_enable_phy_intr();
 
        /* Set station address.
        */
-       fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-               (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-       fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-               (fep->mac_addr[4] << 24);
-
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i];
+       fec_set_mac_address(dev);
 
        /* Reset all multicast.
        */
@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
 
        fecp->fec_x_cntrl = 0x01;       /* Graceful transmit stop */
 
-       while(!(fecp->fec_ievent & 0x10000000));
+       while(!(fecp->fec_ievent & FEC_ENET_GRA));
 
        /* Whack a reset.  We should wait for this.
        */
@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
 static int __init fec_enet_module_init(void)
 {
        struct net_device *dev;
-       int i, err;
+       int i, j, err;
+
+       printk("FEC ENET Version 0.2\n");
 
        for (i = 0; (i < FEC_MAX_PORTS); i++) {
                dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
                        free_netdev(dev);
                        return -EIO;
                }
+
+               printk("%s: ethernet ", dev->name);
+               for (j = 0; (j < 5); j++)
+                       printk("%02x:", dev->dev_addr[j]);
+               printk("%02x\n", dev->dev_addr[5]);
        }
        return 0;
 }
index c6e4f979ff5d42a9942d3c1ab57182dfb7935bd1..045761b8a6004ab1f25c73bcd082d00573024589 100644 (file)
@@ -1,8 +1,9 @@
 /****************************************************************************/
 
 /*
- *     fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5270,
-                  5271, 5272, 5274, 5275, 5280 and 5282.
+ *     fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5230,
+ *                5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
+ *                5280 and 5282.
  *
  *     (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
  *     (C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
 #define        FEC_H
 /****************************************************************************/
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /*
  *     Just figures, Motorola would have to change the offsets for
  *     registers in the same peripheral device on different models
index 0b230222bfeab592fa23ec7836accddc79df7a62..90999867a32c56fd6819acee43ef1934984b061d 100644 (file)
@@ -293,7 +293,7 @@ static int sp_header(struct sk_buff *skb, struct net_device *dev,
 {
 #ifdef CONFIG_INET
        if (type != htons(ETH_P_AX25))
-               return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+               return ax25_hard_header(skb, dev, type, daddr, saddr, len);
 #endif
        return 0;
 }
index 5298096afbdb6efc7a9031ec2d746a0e3438772f..e4188d082f011f0e0fa56080db7d8f9ca9913fc0 100644 (file)
@@ -40,7 +40,7 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
+#include <linux/crc-ccitt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/parport.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
 #include <linux/if_arp.h>
-#include <linux/kmod.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
 #include <linux/jiffies.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h> 
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-#include <linux/crc-ccitt.h>
+#include <asm/uaccess.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -1177,13 +1171,8 @@ static void baycom_probe(struct net_device *dev)
        /* Fill in the fields of the device structure */
        bc->skb = NULL;
        
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-       dev->hard_header = ax25_encapsulate;
+       dev->hard_header = ax25_hard_header;
        dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-       dev->hard_header = NULL;
-       dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
        dev->set_mac_address = baycom_set_mac_address;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
index 2946e037a9b1f1e4bab304c2982a0575bf07c69d..1756f0ed54ccc7a43de7613896f090d38c98f365 100644 (file)
@@ -488,7 +488,7 @@ static void bpq_setup(struct net_device *dev)
        dev->flags      = 0;
 
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-       dev->hard_header     = ax25_encapsulate;
+       dev->hard_header     = ax25_hard_header;
        dev->rebuild_header  = ax25_rebuild_header;
 #endif
 
index f515245a3fd0997f049aaa626ba8af0300b2ad9d..3be3f916643a17fcb53574f83cf39d8c8ae5bb9e 100644 (file)
@@ -449,12 +449,12 @@ module_exit(dmascc_exit);
 static void dev_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_AX25;
-       dev->hard_header_len = 73;
+       dev->hard_header_len = AX25_MAX_HEADER_LEN;
        dev->mtu = 1500;
-       dev->addr_len = 7;
+       dev->addr_len = AX25_ADDR_LEN;
        dev->tx_queue_len = 64;
-       memcpy(dev->broadcast, ax25_broadcast, 7);
-       memcpy(dev->dev_addr, ax25_test, 7);
+       memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
 }
 
 static int __init setup_adapter(int card_base, int type, int n)
@@ -600,7 +600,7 @@ static int __init setup_adapter(int card_base, int type, int n)
                dev->do_ioctl = scc_ioctl;
                dev->hard_start_xmit = scc_send_packet;
                dev->get_stats = scc_get_stats;
-               dev->hard_header = ax25_encapsulate;
+               dev->hard_header = ax25_hard_header;
                dev->rebuild_header = ax25_rebuild_header;
                dev->set_mac_address = scc_set_mac_address;
        }
index b4c836e4fe860d4a4e7fe0d82a52736dd7432f2c..dacc7687b97f8b2bfe3290ede1cd6137c5ed08d9 100644 (file)
@@ -42,7 +42,6 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/net.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
-#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
-#include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/hdlcdrv.h>
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h> 
+#include <asm/uaccess.h>
 
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
 #include <linux/crc-ccitt.h>
 
 /* --------------------------------------------------------------------- */
@@ -708,13 +701,8 @@ static void hdlcdrv_setup(struct net_device *dev)
 
        s->skb = NULL;
        
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-       dev->hard_header = ax25_encapsulate;
+       dev->hard_header = ax25_hard_header;
        dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-       dev->hard_header = NULL;
-       dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
        dev->set_mac_address = hdlcdrv_set_mac_address;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
index 63b1a2b86acb19650fdee9e84efb2e86e7971bed..d9fe64b46f4bf4bc1505bee23f2e8e92c86fa772 100644 (file)
@@ -500,7 +500,7 @@ static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short
 {
 #ifdef CONFIG_INET
        if (type != htons(ETH_P_AX25))
-               return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+               return ax25_hard_header(skb, dev, type, daddr, saddr, len);
 #endif
        return 0;
 }
index c27e417f32bf5958e322d4277dc7a808c2777284..6ace0e914fd1f2705a00609d23df8e07f44941dd 100644 (file)
@@ -1557,7 +1557,7 @@ static void scc_net_setup(struct net_device *dev)
        dev->stop            = scc_net_close;
 
        dev->hard_start_xmit = scc_net_tx;
-       dev->hard_header     = ax25_encapsulate;
+       dev->hard_header     = ax25_hard_header;
        dev->rebuild_header  = ax25_rebuild_header;
        dev->set_mac_address = scc_net_set_mac_address;
        dev->get_stats       = scc_net_get_stats;
index f52ee3162c51dc29f2ac586be3dfc610fe3363ee..fe22479eb2028097213e5f987a1768e453477fc3 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
 
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
@@ -1116,23 +1108,17 @@ static void yam_setup(struct net_device *dev)
 
        skb_queue_head_init(&yp->send_queue);
 
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-       dev->hard_header = ax25_encapsulate;
+       dev->hard_header = ax25_hard_header;
        dev->rebuild_header = ax25_rebuild_header;
-#else                                                  /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-       dev->hard_header = NULL;
-       dev->rebuild_header = NULL;
-#endif                                                 /* CONFIG_AX25 || CONFIG_AX25_MODULE */
 
        dev->set_mac_address = yam_set_mac_address;
 
-       dev->type = ARPHRD_AX25;        /* AF_AX25 device */
-       dev->hard_header_len = 73;      /* We do digipeaters now */
-       dev->mtu = 256;                         /* AX25 is the default */
-       dev->addr_len = 7;                      /* sizeof an ax.25 address */
-       memcpy(dev->broadcast, ax25_bcast, 7);
-       memcpy(dev->dev_addr, ax25_test, 7);
-
+       dev->type = ARPHRD_AX25;
+       dev->hard_header_len = AX25_MAX_HEADER_LEN;
+       dev->mtu = AX25_MTU;
+       dev->addr_len = AX25_ADDR_LEN;
+       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
 }
 
 static int __init yam_init_driver(void)
index dc57352e5a974e8f7c64433e71cda98728ac5d0b..7599f52e15b3ca65abd356ce4e13d424e064a21c 100644 (file)
@@ -6893,8 +6893,7 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
                get_stat64(&hw_stats->tx_octets);
 
        stats->rx_errors = old_stats->rx_errors +
-               get_stat64(&hw_stats->rx_errors) +
-               get_stat64(&hw_stats->rx_discards);
+               get_stat64(&hw_stats->rx_errors);
        stats->tx_errors = old_stats->tx_errors +
                get_stat64(&hw_stats->tx_errors) +
                get_stat64(&hw_stats->tx_mac_errors) +
@@ -6922,6 +6921,9 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
        stats->rx_crc_errors = old_stats->rx_crc_errors +
                calc_crc_errors(tp);
 
+       stats->rx_missed_errors = old_stats->rx_missed_errors +
+               get_stat64(&hw_stats->rx_discards);
+
        return stats;
 }
 
@@ -8303,6 +8305,7 @@ static struct ethtool_ops tg3_ethtool_ops = {
        .get_ethtool_stats      = tg3_get_ethtool_stats,
        .get_coalesce           = tg3_get_coalesce,
        .set_coalesce           = tg3_set_coalesce,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -9781,6 +9784,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
                if (prom_getproplen(node, "local-mac-address") == 6) {
                        prom_getproperty(node, "local-mac-address",
                                         dev->dev_addr, 6);
+                       memcpy(dev->perm_addr, dev->dev_addr, 6);
                        return 0;
                }
        }
@@ -9792,6 +9796,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
        struct net_device *dev = tp->dev;
 
        memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
+       memcpy(dev->perm_addr, idprom->id_ethaddr, 6);
        return 0;
 }
 #endif
@@ -9861,6 +9866,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #endif
                return -EINVAL;
        }
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
        return 0;
 }
 
index 43b03c55f453859a2902c7dc50d72f741b508e20..e2ebdcad553c405b012a83c7674fe69472b42a1f 100644 (file)
@@ -63,8 +63,13 @@ struct timer_list mcfrs_timer_struct;
 #endif
 
 #if defined(CONFIG_HW_FEITH)
-  #define      CONSOLE_BAUD_RATE       38400
-  #define      DEFAULT_CBAUD           B38400
+#define        CONSOLE_BAUD_RATE       38400
+#define        DEFAULT_CBAUD           B38400
+#endif
+
+#if defined(CONFIG_MOD5272)
+#define CONSOLE_BAUD_RATE      115200
+#define DEFAULT_CBAUD          B115200
 #endif
 
 #ifndef CONSOLE_BAUD_RATE
@@ -90,7 +95,7 @@ static struct tty_driver *mcfrs_serial_driver;
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define        IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
 #else
 #define        IRQBASE 73
@@ -1510,7 +1515,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
        *portp = (*portp & ~0x000000ff) | 0x00000055;
        portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
        *portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
        volatile unsigned char *icrp, *uartp;
        volatile unsigned long *imrp;
 
index f8f21567cc22489c505d104851c80ab03fe8e47f..50858273f8d3e980ea1651f6b47b51ff2656623c 100644 (file)
@@ -631,8 +631,10 @@ static void usbin_stop(struct usb_audiodev *as)
        i = u->flags;
        spin_unlock_irqrestore(&as->lock, flags);
        while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-               set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               if (notkilled)
+                       schedule_timeout_interruptible(1);
+               else
+                       schedule_timeout_uninterruptible(1);
                spin_lock_irqsave(&as->lock, flags);
                i = u->flags;
                spin_unlock_irqrestore(&as->lock, flags);
@@ -1102,8 +1104,10 @@ static void usbout_stop(struct usb_audiodev *as)
        i = u->flags;
        spin_unlock_irqrestore(&as->lock, flags);
        while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-               set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               if (notkilled)
+                       schedule_timeout_interruptible(1);
+               else
+                       schedule_timeout_uninterruptible(1);
                spin_lock_irqsave(&as->lock, flags);
                i = u->flags;
                spin_unlock_irqrestore(&as->lock, flags);
index 12ecdb03ee5f20afd3bcef220e8aded0bb30857c..1017a97a418b110e7e5d6a55b56727d2bf17e79f 100644 (file)
@@ -1606,7 +1606,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
                return IRQ_NONE;
 
        hcd->saw_irq = 1;
-       if (hcd->state != start && hcd->state == HC_STATE_HALT)
+       if (hcd->state == HC_STATE_HALT)
                usb_hc_died (hcd);
        return IRQ_HANDLED;
 }
@@ -1630,7 +1630,6 @@ void usb_hc_died (struct usb_hcd *hcd)
        spin_lock_irqsave (&hcd_root_hub_lock, flags);
        if (hcd->rh_registered) {
                hcd->poll_rh = 0;
-               del_timer(&hcd->rh_timer);
 
                /* make khubd clean up old urbs and devices */
                usb_set_device_state (hcd->self.root_hub,
index 758c7f0ed1597d7a5b40028fd60df841236c6423..a12cab5314e98720fb87b78c05a542789c53f395 100644 (file)
@@ -435,6 +435,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
 static void hub_power_on(struct usb_hub *hub)
 {
        int port1;
+       unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
 
        /* if hub supports power switching, enable power on each port */
        if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
@@ -444,8 +445,8 @@ static void hub_power_on(struct usb_hub *hub)
                                        USB_PORT_FEAT_POWER);
        }
 
-       /* Wait for power to be enabled */
-       msleep(hub->descriptor->bPwrOn2PwrGood * 2);
+       /* Wait at least 100 msec for power to become stable */
+       msleep(max(pgood_delay, (unsigned) 100));
 }
 
 static void hub_quiesce(struct usb_hub *hub)
@@ -1460,7 +1461,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                                        port1, status);
                else {
                        status = hub_port_wait_reset(hub, port1, udev, delay);
-                       if (status)
+                       if (status && status != -ENOTCONN)
                                dev_dbg(hub->intfdev,
                                                "port_wait_reset: err = %d\n",
                                                status);
@@ -1469,8 +1470,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                /* return on disconnect or reset */
                switch (status) {
                case 0:
-                       /* TRSTRCY = 10 ms */
-                       msleep(10);
+                       /* TRSTRCY = 10 ms; plus some extra */
+                       msleep(10 + 40);
                        /* FALL THROUGH */
                case -ENOTCONN:
                case -ENODEV:
index 020815397a49ddf59743ecb1d4d0ce9443856adc..5c40980a5bd94f263e3f7618dff22a96896fa9c1 100644 (file)
@@ -483,6 +483,7 @@ ep_release (struct inode *inode, struct file *fd)
                data->state = STATE_EP_DISABLED;
                data->desc.bDescriptorType = 0;
                data->hs_desc.bDescriptorType = 0;
+               usb_ep_disable(data->ep);
        }
        put_ep (data);
        return 0;
index 2507e898af09b3cc591826d95fb562e32d1af6de..b948ffd94f4587ab3d07e6ccf1743a18a89e9ebd 100644 (file)
@@ -400,6 +400,23 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
                                return -EIO;
                        }
                        break;
+               case PCI_VENDOR_ID_NVIDIA:
+                       /* NVidia reports that certain chips don't handle
+                        * QH, ITD, or SITD addresses above 2GB.  (But TD,
+                        * data buffer, and periodic schedule are normal.)
+                        */
+                       switch (pdev->device) {
+                       case 0x003c:    /* MCP04 */
+                       case 0x005b:    /* CK804 */
+                       case 0x00d8:    /* CK8 */
+                       case 0x00e8:    /* CK8S */
+                               if (pci_set_consistent_dma_mask(pdev,
+                                                       DMA_31BIT_MASK) < 0)
+                                       ehci_warn (ehci, "can't enable NVidia "
+                                               "workaround for >2GB RAM\n");
+                               break;
+                       }
+                       break;
                }
 
                /* optional debug port, normally in the first BAR */
@@ -759,12 +776,16 @@ static int ehci_resume (struct usb_hcd *hcd)
        if (time_before (jiffies, ehci->next_statechange))
                msleep (100);
 
-       /* If any port is suspended, we know we can/must resume the HC. */
+       /* If any port is suspended (or owned by the companion),
+        * we know we can/must resume the HC (and mustn't reset it).
+        */
        for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
                u32     status;
                port--;
                status = readl (&ehci->regs->port_status [port]);
-               if (status & PORT_SUSPEND) {
+               if (!(status & PORT_POWER))
+                       continue;
+               if (status & (PORT_SUSPEND | PORT_OWNER)) {
                        down (&hcd->self.root_hub->serialize);
                        retval = ehci_hub_resume (hcd);
                        up (&hcd->self.root_hub->serialize);
@@ -1126,8 +1147,7 @@ rescan:
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
 idle_timeout:
                spin_unlock_irqrestore (&ehci->lock, flags);
-               set_current_state (TASK_UNINTERRUPTIBLE);
-               schedule_timeout (1);
+               schedule_timeout_uninterruptible(1);
                goto rescan;
        case QH_STATE_IDLE:             /* fully unlinked */
                if (list_empty (&qh->qtd_list)) {
index 36cc1f2218d55d203434aafb0698773291b48e4b..18d3f22703160af0c8ac55fd8f425a5d20e8c369 100644 (file)
@@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
        /* suspend any active/unsuspended ports, maybe allow wakeup */
        while (port--) {
                u32 __iomem     *reg = &ehci->regs->port_status [port];
-               u32             t1 = readl (reg);
+               u32             t1 = readl (reg) & ~PORT_RWC_BITS;
                u32             t2 = t1;
 
                if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
        i = HCS_N_PORTS (ehci->hcs_params);
        while (i--) {
                temp = readl (&ehci->regs->port_status [i]);
-               temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
+               temp &= ~(PORT_RWC_BITS
+                       | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
                if (temp & PORT_SUSPEND) {
                        ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
                        temp |= PORT_RESUME;
@@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
                temp = readl (&ehci->regs->port_status [i]);
                if ((temp & PORT_SUSPEND) == 0)
                        continue;
-               temp &= ~PORT_RESUME;
+               temp &= ~(PORT_RWC_BITS | PORT_RESUME);
                writel (temp, &ehci->regs->port_status [i]);
                ehci_vdbg (ehci, "resumed port %d\n", i + 1);
        }
@@ -191,6 +192,7 @@ static int check_reset_complete (
 
                // what happens if HCS_N_CC(params) == 0 ?
                port_status |= PORT_OWNER;
+               port_status &= ~PORT_RWC_BITS;
                writel (port_status, &ehci->regs->port_status [index]);
 
        } else
@@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                if (temp & PORT_OWNER) {
                        /* don't report this in GetPortStatus */
                        if (temp & PORT_CSC) {
-                               temp &= ~PORT_CSC;
+                               temp &= ~PORT_RWC_BITS;
+                               temp |= PORT_CSC;
                                writel (temp, &ehci->regs->port_status [i]);
                        }
                        continue;
@@ -343,7 +346,7 @@ static int ehci_hub_control (
                                &ehci->regs->port_status [wIndex]);
                        break;
                case USB_PORT_FEAT_C_ENABLE:
-                       writel (temp | PORT_PEC,
+                       writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
                                &ehci->regs->port_status [wIndex]);
                        break;
                case USB_PORT_FEAT_SUSPEND:
@@ -353,7 +356,8 @@ static int ehci_hub_control (
                                if ((temp & PORT_PE) == 0)
                                        goto error;
                                /* resume signaling for 20 msec */
-                               writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
+                               temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+                               writel (temp | PORT_RESUME,
                                        &ehci->regs->port_status [wIndex]);
                                ehci->reset_done [wIndex] = jiffies
                                                + msecs_to_jiffies (20);
@@ -364,15 +368,15 @@ static int ehci_hub_control (
                        break;
                case USB_PORT_FEAT_POWER:
                        if (HCS_PPC (ehci->hcs_params))
-                               writel (temp & ~PORT_POWER,
+                               writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
                                        &ehci->regs->port_status [wIndex]);
                        break;
                case USB_PORT_FEAT_C_CONNECTION:
-                       writel (temp | PORT_CSC,
+                       writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
                                &ehci->regs->port_status [wIndex]);
                        break;
                case USB_PORT_FEAT_C_OVER_CURRENT:
-                       writel (temp | PORT_OCC,
+                       writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
                                &ehci->regs->port_status [wIndex]);
                        break;
                case USB_PORT_FEAT_C_RESET:
@@ -416,7 +420,7 @@ static int ehci_hub_control (
 
                        /* stop resume signaling */
                        temp = readl (&ehci->regs->port_status [wIndex]);
-                       writel (temp & ~PORT_RESUME,
+                       writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
                                &ehci->regs->port_status [wIndex]);
                        retval = handshake (
                                        &ehci->regs->port_status [wIndex],
@@ -437,7 +441,7 @@ static int ehci_hub_control (
                        ehci->reset_done [wIndex] = 0;
 
                        /* force reset to complete */
-                       writel (temp & ~PORT_RESET,
+                       writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
                                        &ehci->regs->port_status [wIndex]);
                        /* REVISIT:  some hardware needs 550+ usec to clear
                         * this bit; seems too long to spin routinely...
@@ -500,6 +504,7 @@ static int ehci_hub_control (
                if (temp & PORT_OWNER)
                        break;
 
+               temp &= ~PORT_RWC_BITS;
                switch (wValue) {
                case USB_PORT_FEAT_SUSPEND:
                        if ((temp & PORT_PE) == 0
index 20c9b550097dc70e0bb3b326f144aa9628059b79..f34a0516d35ff2b63ae0355080db4016b91343a8 100644 (file)
@@ -263,6 +263,7 @@ struct ehci_regs {
 #define PORT_PE                (1<<2)          /* port enable */
 #define PORT_CSC       (1<<1)          /* connect status change */
 #define PORT_CONNECT   (1<<0)          /* device connected */
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
 } __attribute__ ((packed));
 
 /* Appendix C, Debug port ... intended for use with special "debug devices"
index 447f488f5d937f85de1e7c75348e04bf8400a040..7924c74f958eb28dc833de2059a1f269e0a040fb 100644 (file)
@@ -228,23 +228,22 @@ ohci_dump_roothub (
        char **next,
        unsigned *size)
 {
-       u32                     temp, ndp, i;
+       u32                     temp, i;
 
        temp = roothub_a (controller);
        if (temp == ~(u32)0)
                return;
-       ndp = (temp & RH_A_NDP);
 
        if (verbose) {
                ohci_dbg_sw (controller, next, size,
-                       "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+                       "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
                        ((temp & RH_A_POTPGT) >> 24) & 0xff,
                        (temp & RH_A_NOCP) ? " NOCP" : "",
                        (temp & RH_A_OCPM) ? " OCPM" : "",
                        (temp & RH_A_DT) ? " DT" : "",
                        (temp & RH_A_NPS) ? " NPS" : "",
                        (temp & RH_A_PSM) ? " PSM" : "",
-                       ndp
+                       (temp & RH_A_NDP), controller->num_ports
                        );
                temp = roothub_b (controller);
                ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@ ohci_dump_roothub (
                        );
        }
 
-       for (i = 0; i < ndp; i++) {
+       for (i = 0; i < controller->num_ports; i++) {
                temp = roothub_portstatus (controller, i);
                dbg_port_sw (controller, i, temp, next, size);
        }
index 56b43f2a0e52c3eaaa750bebd7fb94e27f16d2bd..67c1aa5eb1c175994faa6593a33b009d496164cb 100644 (file)
@@ -382,8 +382,7 @@ sanitize:
                        goto sanitize;
                }
                spin_unlock_irqrestore (&ohci->lock, flags);
-               set_current_state (TASK_UNINTERRUPTIBLE);
-               schedule_timeout (1);
+               schedule_timeout_uninterruptible(1);
                goto rescan;
        case ED_IDLE:           /* fully unlinked */
                if (list_empty (&ed->td_list)) {
@@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
        // flush the writes
        (void) ohci_readl (ohci, &ohci->regs->control);
 
+       /* Read the number of ports unless overridden */
+       if (ohci->num_ports == 0)
+               ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
        if (ohci->hcca)
                return 0;
 
@@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
        msleep(temp);
        temp = roothub_a (ohci);
        if (!(temp & RH_A_NPS)) {
-               unsigned ports = temp & RH_A_NDP; 
-
                /* power down each port */
-               for (temp = 0; temp < ports; temp++)
+               for (temp = 0; temp < ohci->num_ports; temp++)
                        ohci_writel (ohci, RH_PS_LSDA,
                                &ohci->regs->roothub.portstatus [temp]);
        }
@@ -720,6 +721,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
 
        if (ints & OHCI_INTR_RD) {
                ohci_vdbg (ohci, "resume detect\n");
+               ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
                if (hcd->state != HC_STATE_QUIESCING)
                        schedule_work(&ohci->rh_resume);
        }
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
                 * and that if we try to turn them back on the root hub
                 * will respond to CSC processing.
                 */
-               i = roothub_a (ohci) & RH_A_NDP;
+               i = ohci->num_ports;
                while (i--)
                        ohci_writel (ohci, RH_PS_PSS,
                                &ohci->regs->roothub.portstatus [temp]);
index 83ca4549a50ecac5f82504ba375419ad3c9b6d0a..ce7b28da7a1540c0e00c7f8e95b030d5191fd89e 100644 (file)
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
        if (status != -EINPROGRESS)
                return status;
 
-       temp = roothub_a (ohci) & RH_A_NDP;
+       temp = ohci->num_ports;
        enables = 0;
        while (temp--) {
                u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@ static int
 ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       int             ports, i, changed = 0, length = 1;
+       int             i, changed = 0, length = 1;
        int             can_suspend = hcd->can_wakeup;
        unsigned long   flags;
 
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                goto done;
        }
 
-       ports = roothub_a (ohci) & RH_A_NDP; 
-       if (ports > MAX_ROOT_PORTS) {
-               ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+       /* undocumented erratum seen on at least rev D */
+       if ((ohci->flags & OHCI_QUIRK_AMD756)
+                       && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+               ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
                          ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
                /* retry later; "should not happen" */
                goto done;
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                buf [0] = changed = 1;
        else
                buf [0] = 0;
-       if (ports > 7) {
+       if (ohci->num_ports > 7) {
                buf [1] = 0;
                length++;
        }
 
        /* look at each port */
-       for (i = 0; i < ports; i++) {
+       for (i = 0; i < ohci->num_ports; i++) {
                u32     status = roothub_portstatus (ohci, i);
 
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
        struct usb_hub_descriptor       *desc
 ) {
        u32             rh = roothub_a (ohci);
-       int             ports = rh & RH_A_NDP; 
        u16             temp;
 
        desc->bDescriptorType = 0x29;
        desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
        desc->bHubContrCurrent = 0;
 
-       desc->bNbrPorts = ports;
-       temp = 1 + (ports / 8);
+       desc->bNbrPorts = ohci->num_ports;
+       temp = 1 + (ohci->num_ports / 8);
        desc->bDescLength = 7 + 2 * temp;
 
        temp = 0;
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
        rh = roothub_b (ohci);
        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
        desc->bitmap [0] = rh & RH_B_DR;
-       if (ports > 7) {
+       if (ohci->num_ports > 7) {
                desc->bitmap [1] = (rh & RH_B_DR) >> 8;
                desc->bitmap [2] = 0xff;
        } else
index e5bc1789d18a6532b13cdaf1e367e8002c9d9b49..2fdb262d47260afb3d3b37cb25306b0f21df3168 100644 (file)
@@ -75,33 +75,6 @@ static int pxa27x_ohci_select_pmm( int mode )
        return 0;
 }
 
-/*
-  If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_set_port_power( int port )
-{
-       if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
-            && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
-               UHCRHPS(port) |= 0x100;
-               return 0;
-       }
-       return -1;
-}
-
-/*
-  If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_clear_port_power( int port )
-{
-       if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) 
-            && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
-               UHCRHPS(port) |= 0x200;
-               return 0;
-       }
-        
-       return -1;
-}
-
 extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
@@ -130,11 +103,17 @@ static void pxa27x_start_hc(struct platform_device *dev)
                   Polarity Low to active low. Supply power to USB ports. */
                UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
                        ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+               pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
        }
 
        UHCHR &= ~UHCHR_SSE;
 
        UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
+
+       /* Clear any OTG Pin Hold */
+       if (PSSR & PSSR_OTGPH)
+               PSSR |= PSSR_OTGPH;
 }
 
 static void pxa27x_stop_hc(struct platform_device *dev)
@@ -198,17 +177,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
        pxa27x_start_hc(dev);
 
        /* Select Power Management Mode */
-       pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );
-
-       /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
-       if (pxa27x_ohci_set_port_power(1) < 0)
-               printk(KERN_ERR "Setting port 1 power failed.\n");
-
-       if (pxa27x_ohci_clear_port_power(2) < 0)
-               printk(KERN_ERR "Setting port 2 power failed.\n");
-
-       if (pxa27x_ohci_clear_port_power(3) < 0)
-               printk(KERN_ERR "Setting port 3 power failed.\n");
+       pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
 
        ohci_hcd_init(hcd_to_ohci(hcd));
 
@@ -258,6 +227,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
 
        ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
 
+       /* The value of NDP in roothub_a is incorrect on this hardware */
+       ohci->num_ports = 3;
+
        if ((ret = ohci_init(ohci)) < 0)
                return ret;
 
index 71cdd2262860d129fc1776179b561f3f0ff5dcb4..8a9b9d9209e9276213a51fbc717d5c7aea0de85c 100644 (file)
@@ -383,6 +383,7 @@ struct ohci_hcd {
        /*
         * driver state
         */
+       int                     num_ports;
        int                     load [NUM_INTS];
        u32                     hc_control;     /* copy of hc control reg */
        unsigned long           next_statechange;       /* suspend/resume */
index 0d5d2545bf07ba151a40e617e52583a2a096f62b..0c024898cbea0dcdea54c7c80a24740aac79d277 100644 (file)
@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
-static inline void restart_timer(struct uhci_hcd *uhci)
-{
-       mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
-}
-
-#include "uhci-hub.c"
 #include "uhci-debug.c"
 #include "uhci-q.c"
+#include "uhci-hub.c"
 
 /*
  * Make sure the controller is completely inactive, unable to
@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
 {
        reset_hc(uhci);
        uhci->hc_inaccessible = 1;
-       del_timer(&uhci->stall_timer);
 }
 
 /*
@@ -287,8 +281,11 @@ __acquires(uhci->lock)
        /* Enable resume-detect interrupts if they work.
         * Then enter Global Suspend mode, still configured.
         */
-       int_enable = (resume_detect_interrupts_are_broken(uhci) ?
-                       0 : USBINTR_RESUME);
+       uhci->working_RD = 1;
+       int_enable = USBINTR_RESUME;
+       if (resume_detect_interrupts_are_broken(uhci)) {
+               uhci->working_RD = int_enable = 0;
+       }
        outw(int_enable, uhci->io_addr + USBINTR);
        outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
        mb();
@@ -315,7 +312,6 @@ __acquires(uhci->lock)
 
        uhci->rh_state = new_state;
        uhci->is_stopped = UHCI_IS_STOPPED;
-       del_timer(&uhci->stall_timer);
        uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
        uhci_scan_schedule(uhci, NULL);
@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
        mb();
        uhci->rh_state = UHCI_RH_RUNNING;
        uhci_to_hcd(uhci)->poll_rh = 1;
-       restart_timer(uhci);
 }
 
 static void wakeup_rh(struct uhci_hcd *uhci)
@@ -374,20 +369,6 @@ __acquires(uhci->lock)
        mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
-static void stall_callback(unsigned long _uhci)
-{
-       struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
-       unsigned long flags;
-
-       spin_lock_irqsave(&uhci->lock, flags);
-       uhci_scan_schedule(uhci, NULL);
-       check_fsbr(uhci);
-
-       if (!uhci->is_stopped)
-               restart_timer(uhci);
-       spin_unlock_irqrestore(&uhci->lock, flags);
-}
-
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
                                        "host controller halted, "
                                        "very bad!\n");
                                hc_died(uhci);
-                               spin_unlock_irqrestore(&uhci->lock, flags);
-                               return IRQ_HANDLED;
+
+                               /* Force a callback in case there are
+                                * pending unlinks */
+                               mod_timer(&hcd->rh_timer, jiffies);
                        }
                        spin_unlock_irqrestore(&uhci->lock, flags);
                }
@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 
        if (status & USBSTS_RD)
                usb_hcd_poll_rh_status(hcd);
-
-       spin_lock_irqsave(&uhci->lock, flags);
-       uhci_scan_schedule(uhci, regs);
-       spin_unlock_irqrestore(&uhci->lock, flags);
+       else {
+               spin_lock_irqsave(&uhci->lock, flags);
+               uhci_scan_schedule(uhci, regs);
+               spin_unlock_irqrestore(&uhci->lock, flags);
+       }
 
        return IRQ_HANDLED;
 }
@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
 
        init_waitqueue_head(&uhci->waitqh);
 
-       init_timer(&uhci->stall_timer);
-       uhci->stall_timer.function = stall_callback;
-       uhci->stall_timer.data = (unsigned long) uhci;
-
        uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
                        &dma_handle, 0);
        if (!uhci->fl) {
@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
        spin_lock_irq(&uhci->lock);
-       reset_hc(uhci);
+       if (!uhci->hc_inaccessible)
+               reset_hc(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
 
-       del_timer_sync(&uhci->stall_timer);
        release_uhci(uhci);
 }
 
@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
         */
        pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
        uhci->hc_inaccessible = 1;
+       hcd->poll_rh = 0;
 
        /* FIXME: Enable non-PME# remote wakeup? */
 
 done:
        spin_unlock_irq(&uhci->lock);
-       if (rc == 0)
-               del_timer_sync(&hcd->rh_timer);
        return rc;
 }
 
@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
 
        spin_unlock_irq(&uhci->lock);
 
-       if (hcd->poll_rh)
+       if (!uhci->working_RD) {
+               /* Suspended root hub needs to be polled */
+               hcd->poll_rh = 1;
                usb_hcd_poll_rh_status(hcd);
+       }
        return 0;
 }
 #endif
index bf9c5f9b508b9eb4e8d8eef7fbab0a94454eb158..282f40b75881a98e3e77e45051d52c4cf3237791 100644 (file)
@@ -345,9 +345,6 @@ enum uhci_rh_state {
 
 /*
  * This describes the full uhci information.
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs.
  */
 struct uhci_hcd {
 
@@ -360,8 +357,6 @@ struct uhci_hcd {
        struct dma_pool *qh_pool;
        struct dma_pool *td_pool;
 
-       struct usb_bus *bus;
-
        struct uhci_td *term_td;        /* Terminating TD, see UHCI bug */
        struct uhci_qh *skelqh[UHCI_NUM_SKELQH];        /* Skeleton QH's */
 
@@ -380,6 +375,8 @@ struct uhci_hcd {
        unsigned int scan_in_progress:1;        /* Schedule scan is running */
        unsigned int need_rescan:1;             /* Redo the schedule scan */
        unsigned int hc_inaccessible:1;         /* HC is suspended or dead */
+       unsigned int working_RD:1;              /* Suspended root hub doesn't
+                                                  need to be polled */
 
        /* Support for port suspend/resume/reset */
        unsigned long port_c_suspend;           /* Bit-arrays of ports */
@@ -405,9 +402,7 @@ struct uhci_hcd {
        /* List of URB's awaiting completion callback */
        struct list_head complete_list;         /* P: uhci->lock */
 
-       int rh_numports;
-
-       struct timer_list stall_timer;
+       int rh_numports;                        /* Number of root-hub ports */
 
        wait_queue_head_t waitqh;               /* endpoint_disable waiters */
 };
index 4eace2b19ddb830602b339059e7a953633a73d39..a71e48a668050874481a69ac89cd080a300cde3a 100644 (file)
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        unsigned long flags;
-       int status;
+       int status = 0;
 
        spin_lock_irqsave(&uhci->lock, flags);
-       if (uhci->hc_inaccessible) {
-               status = 0;
-               goto done;
-       }
 
+       uhci_scan_schedule(uhci, NULL);
+       if (uhci->hc_inaccessible)
+               goto done;
+       check_fsbr(uhci);
        uhci_check_ports(uhci);
+
        status = get_hub_status_data(uhci, buf);
 
        switch (uhci->rh_state) {
index bbb36cd6ed6106587b5d20ef827c038f837ab444..ea0d168a8c676a520b9309227db4b1b8960bc8a5 100644 (file)
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
 static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
 {
        if (uhci->is_stopped)
-               mod_timer(&uhci->stall_timer, jiffies);
+               mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
        uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
 }
 
index 482c4be521f55424a68efe4cc328e93cd595c1cd..1e53934907c089b0067d13142e4c4356ee9ff3cc 100644 (file)
@@ -286,3 +286,23 @@ config USB_KEYSPAN_REMOTE
 
          To compile this driver as a module, choose M here: the module will
          be called keyspan_remote.
+
+config USB_APPLETOUCH
+       tristate "Apple USB Touchpad support"
+       depends on USB && INPUT
+       ---help---
+         Say Y here if you want to use an Apple USB Touchpad.
+
+         These are the touchpads that can be found on post-February 2005
+         Apple Powerbooks (prior models have a Synaptics touchpad connected
+         to the ADB bus).
+
+         This driver provides a basic mouse driver but can be interfaced
+         with the synaptics X11 driver to provide acceleration and
+         scrolling in X11.
+
+         For further information, see
+         <file:Documentation/input/appletouch.txt>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called appletouch.
index 43b2f999edfeb448bccb7bf5f73962b1e3ad66da..5e03b93f29f66a8dd42278f3c1941bee5d0c2e96 100644 (file)
@@ -41,3 +41,4 @@ obj-$(CONFIG_USB_WACOM)               += wacom.o
 obj-$(CONFIG_USB_ACECAD)       += acecad.o
 obj-$(CONFIG_USB_YEALINK)      += yealink.o
 obj-$(CONFIG_USB_XPAD)         += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH)   += appletouch.o
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644 (file)
index 0000000..e03c1c5
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
+ * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ *
+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
+ *
+ * This program is free software; 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/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/usb_input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID                0x05AC
+
+#define ATP_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 = 0x03,                                \
+       .bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+       { ATP_DEVICE(0x020E) },
+       { ATP_DEVICE(0x020F) },
+       { ATP_DEVICE(0x030A) },
+       { ATP_DEVICE(0x030B) },
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/* size of a USB urb transfer */
+#define ATP_DATASIZE   81
+
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) sensors.
+ */
+#define ATP_XSENSORS   26
+#define ATP_YSENSORS   16
+
+/* amount of fuzz this touchpad generates */
+#define ATP_FUZZ       16
+
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE   300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ *     0 <= x <  960 on 12" and 15" Powerbooks
+ *     0 <= x < 1600 on 17" Powerbooks
+ *     0 <= y <  646
+ */
+#define ATP_XFACT      64
+#define ATP_YFACT      43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD   5
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+       struct usb_device *     udev;           /* usb device */
+       struct urb *            urb;            /* usb request block */
+       signed char *           data;           /* transferred data */
+       int                     open;           /* non-zero if opened */
+       struct input_dev        input;          /* input dev */
+       int                     valid;          /* are the sensors valid ? */
+       int                     x_old;          /* last reported x/y, */
+       int                     y_old;          /* used for smoothing */
+                                               /* current value of the sensors */
+       signed char             xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+                                               /* last value of the sensors */
+       signed char             xy_old[ATP_XSENSORS + ATP_YSENSORS];
+                                               /* accumulated sensors */
+       int                     xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+};
+
+#define dbg_dump(msg, tab) \
+       if (debug > 1) {                                                \
+               int i;                                                  \
+               printk("appletouch: %s %lld", msg, (long long)jiffies); \
+               for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)       \
+                       printk(" %02x", tab[i]);                        \
+               printk("\n");                                           \
+       }
+
+#define dprintk(format, a...)                                          \
+       do {                                                            \
+               if (debug) printk(format, ##a);                         \
+       } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+                            int *z, int *fingers)
+{
+       int i;
+       /* values to calculate mean */
+       int pcum = 0, psum = 0;
+
+       *fingers = 0;
+
+       for (i = 0; i < nb_sensors; i++) {
+               if (xy_sensors[i] < ATP_THRESHOLD)
+                       continue;
+               if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+                       (*fingers)++;
+               pcum += xy_sensors[i] * i;
+               psum += xy_sensors[i];
+       }
+
+       if (psum > 0) {
+               *z = psum;
+               return pcum * fact / psum;
+       }
+
+       return 0;
+}
+
+static inline void atp_report_fingers(struct input_dev *input, int fingers)
+{
+       input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
+       input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
+       input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+       int x, y, x_z, y_z, x_f, y_f;
+       int retval, i;
+       struct atp *dev = urb->context;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       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;
+       }
+
+       /* drop incomplete datasets */
+       if (dev->urb->actual_length != ATP_DATASIZE) {
+               dprintk("appletouch: incomplete data package.\n");
+               goto exit;
+       }
+
+       /* reorder the sensors values */
+       for (i = 0; i < 8; i++) {
+               /* X values */
+               dev->xy_cur[i     ] = dev->data[5 * i +  2];
+               dev->xy_cur[i +  8] = dev->data[5 * i +  4];
+               dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+               if (i < 2)
+                       dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+               /* Y values */
+               dev->xy_cur[i + 26] = dev->data[5 * i +  1];
+               dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+       }
+
+       dbg_dump("sample", dev->xy_cur);
+
+       if (!dev->valid) {
+               /* first sample */
+               dev->valid = 1;
+               dev->x_old = dev->y_old = -1;
+               memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+               /* 17" Powerbooks have 10 extra X sensors */
+               for (i = 16; i < ATP_XSENSORS; i++)
+                       if (dev->xy_cur[i]) {
+                               printk("appletouch: 17\" model detected.\n");
+                               input_set_abs_params(&dev->input, ABS_X, 0,
+                                                    (ATP_XSENSORS - 1) *
+                                                    ATP_XFACT - 1,
+                                                    ATP_FUZZ, 0);
+                               break;
+                       }
+
+               goto exit;
+       }
+
+       for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+               /* accumulate the change */
+               signed char change = dev->xy_old[i] - dev->xy_cur[i];
+               dev->xy_acc[i] -= change;
+
+               /* prevent down drifting */
+               if (dev->xy_acc[i] < 0)
+                       dev->xy_acc[i] = 0;
+       }
+
+       memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+       dbg_dump("accumulator", dev->xy_acc);
+
+       x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+                             ATP_XFACT, &x_z, &x_f);
+       y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+                             ATP_YFACT, &y_z, &y_f);
+
+       if (x && y) {
+               if (dev->x_old != -1) {
+                       x = (dev->x_old * 3 + x) >> 2;
+                       y = (dev->y_old * 3 + y) >> 2;
+                       dev->x_old = x;
+                       dev->y_old = y;
+
+                       if (debug > 1)
+                               printk("appletouch: X: %3d Y: %3d "
+                                      "Xz: %3d Yz: %3d\n",
+                                      x, y, x_z, y_z);
+
+                       input_report_key(&dev->input, BTN_TOUCH, 1);
+                       input_report_abs(&dev->input, ABS_X, x);
+                       input_report_abs(&dev->input, ABS_Y, y);
+                       input_report_abs(&dev->input, ABS_PRESSURE,
+                                        min(ATP_PRESSURE, x_z + y_z));
+                       atp_report_fingers(&dev->input, max(x_f, y_f));
+               }
+               dev->x_old = x;
+               dev->y_old = y;
+       }
+       else if (!x && !y) {
+
+               dev->x_old = dev->y_old = -1;
+               input_report_key(&dev->input, BTN_TOUCH, 0);
+               input_report_abs(&dev->input, ABS_PRESSURE, 0);
+               atp_report_fingers(&dev->input, 0);
+
+               /* reset the accumulator on release */
+               memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+       }
+
+       input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+
+       input_sync(&dev->input);
+
+exit:
+       retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+       if (retval) {
+               err("%s - usb_submit_urb failed with result %d",
+                   __FUNCTION__, retval);
+       }
+}
+
+static int atp_open(struct input_dev *input)
+{
+       struct atp *dev = input->private;
+
+       if (usb_submit_urb(dev->urb, GFP_ATOMIC))
+               return -EIO;
+
+       dev->open = 1;
+       return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+       struct atp *dev = input->private;
+
+       usb_kill_urb(dev->urb);
+       dev->open = 0;
+}
+
+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+       struct atp *dev = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int int_in_endpointAddr = 0;
+       int i, retval = -ENOMEM;
+
+       /* allocate memory for our device state and initialize it */
+       dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
+       if (dev == NULL) {
+               err("Out of memory");
+               goto err_kmalloc;
+       }
+       memset(dev, 0, sizeof(struct atp));
+
+       dev->udev = interface_to_usbdev(iface);
+
+       /* 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) {
+               retval = -EIO;
+               err("Could not find int-in endpoint");
+               goto err_endpoint;
+       }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(iface, dev);
+
+       dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->urb) {
+               retval = -ENOMEM;
+               goto err_usballoc;
+       }
+       dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+                                    &dev->urb->transfer_dma);
+       if (!dev->data) {
+               retval = -ENOMEM;
+               goto err_usbbufalloc;
+       }
+       usb_fill_int_urb(dev->urb, dev->udev,
+                        usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+                        dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+
+       init_input_dev(&dev->input);
+       dev->input.name = "appletouch";
+       dev->input.dev = &iface->dev;
+       dev->input.private = dev;
+       dev->input.open = atp_open;
+       dev->input.close = atp_close;
+
+       usb_to_input_id(dev->udev, &dev->input.id);
+
+       set_bit(EV_ABS, dev->input.evbit);
+
+       /*
+        * 12" and 15" Powerbooks only have 16 x sensors,
+        * 17" models are detected later.
+        */
+       input_set_abs_params(&dev->input, ABS_X, 0,
+                            (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+       input_set_abs_params(&dev->input, ABS_Y, 0,
+                            (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+       input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+
+       set_bit(EV_KEY, dev->input.evbit);
+       set_bit(BTN_TOUCH, dev->input.keybit);
+       set_bit(BTN_TOOL_FINGER, dev->input.keybit);
+       set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
+       set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
+       set_bit(BTN_LEFT, dev->input.keybit);
+
+       input_register_device(&dev->input);
+
+       printk(KERN_INFO "input: appletouch connected\n");
+
+       return 0;
+
+err_usbbufalloc:
+       usb_free_urb(dev->urb);
+err_usballoc:
+       usb_set_intfdata(iface, NULL);
+err_endpoint:
+       kfree(dev);
+err_kmalloc:
+       return retval;
+}
+
+static void atp_disconnect(struct usb_interface *iface)
+{
+       struct atp *dev = usb_get_intfdata(iface);
+
+       usb_set_intfdata(iface, NULL);
+       if (dev) {
+               usb_kill_urb(dev->urb);
+               input_unregister_device(&dev->input);
+               usb_free_urb(dev->urb);
+               usb_buffer_free(dev->udev, ATP_DATASIZE,
+                               dev->data, dev->urb->transfer_dma);
+               kfree(dev);
+       }
+       printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+static int atp_suspend(struct usb_interface *iface, pm_message_t message)
+{
+       struct atp *dev = usb_get_intfdata(iface);
+       usb_kill_urb(dev->urb);
+       dev->valid = 0;
+       return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+       struct atp *dev = usb_get_intfdata(iface);
+       if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+               return -EIO;
+
+       return 0;
+}
+
+static struct usb_driver atp_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "appletouch",
+       .probe          = atp_probe,
+       .disconnect     = atp_disconnect,
+       .suspend        = atp_suspend,
+       .resume         = atp_resume,
+       .id_table       = atp_table,
+};
+
+static int __init atp_init(void)
+{
+       return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+       usb_deregister(&atp_driver);
+}
+
+module_init(atp_init);
+module_exit(atp_exit);
index e108e0a36b743fd88c191a7e96c8339dbe39f451..a99865c689c57535b2d1215f1c6df8c4e3a3d81b 100644 (file)
@@ -1446,7 +1446,6 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_APPLE            0x05ac
 #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
-#define USB_DEVICE_ID_APPLE_BLUETOOTH  0x1000
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1465,7 +1464,6 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_BLUETOOTH, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
index 3957e144caf7343e2af800653a822d51617c2d08..7603cbe0865d1268811c717dcaadb0eb7224ce09 100644 (file)
@@ -4,11 +4,43 @@ config USB_SISUSBVGA
        depends on USB && USB_EHCI_HCD
         ---help---
          Say Y here if you intend to attach a USB2VGA dongle based on a
-         Net2280 and a SiS315 chip. 
-         
-         Note that this device requires a USB 2.0 host controller. It will not 
+         Net2280 and a SiS315 chip.
+
+         Note that this device requires a USB 2.0 host controller. It will not
          work with USB 1.x controllers.
 
-         To compile this driver as a module, choose M here: the module will be
-         called sisusb.  If unsure, say N.
+         To compile this driver as a module, choose M here; the module will be
+         called sisusbvga. If unsure, say N.
+
+config USB_SISUSBVGA_CON
+       bool "Text console and mode switching support" if USB_SISUSBVGA
+       depends on VT
+       select FONT_8x16
+       ---help---
+         Say Y here if you want a VGA text console via the USB dongle or
+         want to support userland applications that utilize the driver's
+         display mode switching capabilities.
+
+         Note that this console supports VGA/EGA text mode only.
+
+         By default, the console part of the driver will not kick in when
+         the driver is initialized. If you want the driver to take over
+         one or more of the consoles, you need to specify the number of
+         the first and last consoles (starting at 1) as driver parameters.
+
+         For example, if the driver is compiled as a module:
+
+            modprobe sisusbvga first=1 last=5
+
+         If you use hotplug, add this to your modutils config files with
+         the "options" keyword, such as eg.
+
+            options sisusbvga first=1 last=5
+
+         If the driver is compiled into the kernel image, the parameters
+         must be given in the kernel command like, such as
+
+            sisusbvga.first=1 sisusbvga.last=5
+
+
 
index 76f1643ceaf8e96bd634d4ca577d8fd73e3818ab..7f934cfc906c4f503fa7c36a75006ad74cc8deb4 100644 (file)
@@ -2,5 +2,7 @@
 # Makefile for the sisusb driver (if driver is inside kernel tree).
 #
 
-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
+
+sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
 
index d63ce6c030f39d442d98bb16e04b6569ca19457e..39db3155723a567ee21e777d455904305c1f1497 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
  *
+ * Main part
+ *
  * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, this code is licensed under the
 #include <linux/kref.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
 
 #include "sisusb.h"
 
+#ifdef INCL_SISUSB_CON
+#include <linux/font.h>
+#endif
+
 #define SISUSB_DONTSYNC
 
 /* Forward declarations / clean-up routines */
 
+#ifdef INCL_SISUSB_CON
+int    sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+int    sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+int    sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
+int    sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
+int    sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
+int    sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
+int    sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
+
+int    sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+int    sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+int    sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+int    sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+int    sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+                       u32 dest, int length, size_t *bytes_written);
+
+int    sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int  SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern int  SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern void sisusb_init_concode(void);
+extern int  sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+
+extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+
+extern int  sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+               u8 *arg, int cmapsz, int ch512, int dorecalc,
+               struct vc_data *c, int fh, int uplock);
+
+static int sisusb_first_vc = 0;
+static int sisusb_last_vc = 0;
+module_param_named(first, sisusb_first_vc, int, 0);
+module_param_named(last, sisusb_last_vc, int, 0);
+MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
+MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
+#endif
+
 static struct usb_driver sisusb_driver;
 
-static DECLARE_MUTEX(disconnect_sem);
+DECLARE_MUTEX(disconnect_sem);
 
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
 
 /* The following routines assume being used to transfer byte, word,
  * long etc.
- * This means that they assume "data" in machine endianness format.
+ * This means that
+ *   - the write routines expect "data" in machine endianness format.
+ *     The data will be converted to leXX in sisusb_xxx_packet.
+ *   - the read routines can expect read data in machine-endianess.
  */
 
 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
                                if (get_user(swap16, (u16 __user *)userbuffer))
                                        return -EFAULT;
                        } else
-                               swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+                               swap16 = *((u16 *)kernbuffer);
 
                        ret = sisusb_write_memio_word(sisusb,
                                                        SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
                        if (userbuffer) {
                                if (copy_from_user(&buf, userbuffer, 3))
                                        return -EFAULT;
-
+#ifdef __BIG_ENDIAN
                                swap32 = (buf[0] << 16) |
                                         (buf[1] <<  8) |
                                         buf[2];
+#else
+                               swap32 = (buf[2] << 16) |
+                                        (buf[1] <<  8) |
+                                        buf[0];
+#endif
                        } else
+#ifdef __BIG_ENDIAN
                                swap32 = (kernbuffer[0] << 16) |
                                         (kernbuffer[1] <<  8) |
                                         kernbuffer[2];
+#else
+                               swap32 = (kernbuffer[2] << 16) |
+                                        (kernbuffer[1] <<  8) |
+                                        kernbuffer[0];
+#endif
 
                        ret = sisusb_write_memio_24bit(sisusb,
                                                        SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
                                if (get_user(swap32, (u32 __user *)userbuffer))
                                        return -EFAULT;
                        } else
-                               swap32 = (kernbuffer[0] << 24) |
-                                        (kernbuffer[1] << 16) |
-                                        (kernbuffer[2] <<  8) |
-                                        kernbuffer[3];
+                               swap32 = *((u32 *)kernbuffer);
 
                        ret = sisusb_write_memio_long(sisusb,
                                                        SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
        return ret ? -EIO : 0;
 }
 
+/* Remember: Read data in packet is in machine-endianess! So for
+ * byte, word, 24bit, long no endian correction is necessary.
+ */
+
 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
                                                        u32 addr, u8 *data)
 {
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
                                                (u16 __user *)userbuffer))
                                                return -EFAULT;
                                } else {
-                                       kernbuffer[0] = swap16 >> 8;
-                                       kernbuffer[1] = swap16 & 0xff;
+                                       *((u16 *)kernbuffer) = swap16;
                                }
                        }
                        return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
                                                                addr, &swap32);
                        if (!ret) {
                                (*bytes_read) += 3;
+#ifdef __BIG_ENDIAN
                                buf[0] = (swap32 >> 16) & 0xff;
                                buf[1] = (swap32 >> 8) & 0xff;
                                buf[2] = swap32 & 0xff;
+#else
+                               buf[2] = (swap32 >> 16) & 0xff;
+                               buf[1] = (swap32 >> 8) & 0xff;
+                               buf[0] = swap32 & 0xff;
+#endif
                                if (userbuffer) {
                                        if (copy_to_user(userbuffer, &buf[0], 3))
                                                return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
 
                                        userbuffer += 4;
                                } else {
-                                       kernbuffer[0] = (swap32 >> 24) & 0xff;
-                                       kernbuffer[1] = (swap32 >> 16) & 0xff;
-                                       kernbuffer[2] = (swap32 >> 8) & 0xff;
-                                       kernbuffer[3] = swap32 & 0xff;
+                                       *((u32 *)kernbuffer) = swap32;
                                        kernbuffer += 4;
                                }
                                addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
 
 /* High level: Gfx (indexed) register access */
 
-static int
+#ifdef INCL_SISUSB_CON
+int
+sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
+{
+       return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+
+int
+sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
+{
+       return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+#endif
+
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
 {
        int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
        return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
 {
        int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
        return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
                                                        u8 myand, u8 myor)
 {
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
        return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
 {
        return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
 {
        return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
 }
 
+/* Write/read video ram */
+
+#ifdef INCL_SISUSB_CON
+int
+sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
+{
+       return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
+{
+       return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
+{
+       return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
+{
+       return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+                       u32 dest, int length, size_t *bytes_written)
+{
+       return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
+}
+
+#ifdef SISUSBENDIANTEST
+int
+sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
+                       u32 src, int length, size_t *bytes_written)
+{
+       return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
+}
+#endif
+#endif
+
+#ifdef SISUSBENDIANTEST
+static void
+sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
+{
+    static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+    char destbuffer[10];
+    size_t dummy;
+    int i,j;
+
+    sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
+
+    for(i = 1; i <= 7; i++) {
+        printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
+       sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
+       for(j = 0; j < i; j++) {
+            printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
+       }
+    }
+}
+#endif
+
 /* access pci config registers (reg numbers 0, 4, 8, etc) */
 
 static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
        return ret;
 }
 
+
+#ifdef INCL_SISUSB_CON
+
+/* Set up default text mode:
+   - Set text mode (0x03)
+   - Upload default font
+   - Upload user font (if available)
+*/
+
+int
+sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
+{
+       int ret = 0, slot = sisusb->font_slot, i;
+       struct font_desc *myfont;
+       u8 *tempbuf;
+       u16 *tempbufb;
+       size_t written;
+       static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+       static char bootlogo[] = "(o_ //\\ V_/_";
+
+       /* sisusb->lock is down */
+
+       if (!sisusb->SiS_Pr)
+               return 1;
+
+       sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+       sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+       /* Set mode 0x03 */
+       SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
+
+       if (!(myfont = find_font("VGA8x16")))
+               return 1;
+
+       if (!(tempbuf = vmalloc(8192)))
+               return 1;
+
+       for (i = 0; i < 256; i++)
+               memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
+
+       /* Upload default font */
+       ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
+
+       vfree(tempbuf);
+
+       /* Upload user font (and reset current slot) */
+       if (sisusb->font_backup) {
+               ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
+                               8192, sisusb->font_backup_512, 1, NULL,
+                               sisusb->font_backup_height, 0);
+               if (slot != 2)
+                       sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
+                                       NULL, 16, 0);
+       }
+
+       if (init && !sisusb->scrbuf) {
+
+               if ((tempbuf = vmalloc(8192))) {
+
+                       i = 4096;
+                       tempbufb = (u16 *)tempbuf;
+                       while (i--)
+                               *(tempbufb++) = 0x0720;
+
+                       i = 0;
+                       tempbufb = (u16 *)tempbuf;
+                       while (bootlogo[i]) {
+                               *(tempbufb++) = 0x0700 | bootlogo[i++];
+                               if (!(i % 4))
+                                       tempbufb += 76;
+                       }
+
+                       i = 0;
+                       tempbufb = (u16 *)tempbuf + 6;
+                       while (bootstring[i])
+                               *(tempbufb++) = 0x0700 | bootstring[i++];
+
+                       ret |= sisusb_copy_memory(sisusb, tempbuf,
+                               sisusb->vrambase, 8192, &written);
+
+                       vfree(tempbuf);
+
+               }
+
+       } else if (sisusb->scrbuf) {
+
+               ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
+                               sisusb->vrambase, sisusb->scrbuf_size, &written);
+
+       }
+
+       if (sisusb->sisusb_cursor_size_from >= 0 &&
+           sisusb->sisusb_cursor_size_to >= 0) {
+               sisusb_setidxreg(sisusb, SISCR, 0x0a,
+                               sisusb->sisusb_cursor_size_from);
+               sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
+                               sisusb->sisusb_cursor_size_to);
+       } else {
+               sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
+               sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
+               sisusb->sisusb_cursor_size_to = -1;
+       }
+
+       slot = sisusb->sisusb_cursor_loc;
+       if(slot < 0) slot = 0;
+
+       sisusb->sisusb_cursor_loc = -1;
+       sisusb->bad_cursor_pos = 1;
+
+       sisusb_set_cursor(sisusb, slot);
+
+       sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+       sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+
+       sisusb->textmodedestroyed = 0;
+
+       /* sisusb->lock is down */
+
+       return ret;
+}
+
+#endif
+
 /* fops */
 
 static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
                }
        }
 
-       /* increment usage count for the device */
+       /* Increment usage count for our sisusb */
        kref_get(&sisusb->kref);
 
        sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
 
        up(&disconnect_sem);
 
-       printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
-
        return 0;
 }
 
-static void
+void
 sisusb_delete(struct kref *kref)
 {
        struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
        sisusb->sisusb_dev = NULL;
        sisusb_free_buffers(sisusb);
        sisusb_free_urbs(sisusb);
+#ifdef INCL_SISUSB_CON
+       kfree(sisusb->SiS_Pr);
+#endif
        kfree(sisusb);
 }
 
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
 
        up(&disconnect_sem);
 
-       printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
-
        return 0;
 }
 
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
        int     retval, port, length;
        u32     address;
 
+       /* All our commands require the device
+        * to be initialized.
+        */
+       if (!sisusb->devinit)
+               return -ENODEV;
+
        port = y->data3 -
                SISUSB_PCI_PSEUDO_IOPORTBASE +
                SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
                        break;
 
                case SUCMD_CLRSCR:
+                       /* Gfx core must be initialized */
+                       if (!sisusb->gfxinit)
+                               return -ENODEV;
+
                        length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
                        address = y->data3 -
                                SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
                        retval = sisusb_clear_vram(sisusb, address, length);
                        break;
 
+               case SUCMD_HANDLETEXTMODE:
+                       retval = 0;
+#ifdef INCL_SISUSB_CON
+                       /* Gfx core must be initialized, SiS_Pr must exist */
+                       if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+                               return -ENODEV;
+
+                       switch (y->data0) {
+                       case 0:
+                               retval = sisusb_reset_text_mode(sisusb, 0);
+                               break;
+                       case 1:
+                               sisusb->textmodedestroyed = 1;
+                               break;
+                       }
+#endif
+                       break;
+
+#ifdef INCL_SISUSB_CON
+               case SUCMD_SETMODE:
+                       /* Gfx core must be initialized, SiS_Pr must exist */
+                       if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+                               return -ENODEV;
+
+                       retval = 0;
+
+                       sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+                       sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+                       if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
+                               retval = -EINVAL;
+
+                       break;
+
+               case SUCMD_SETVESAMODE:
+                       /* Gfx core must be initialized, SiS_Pr must exist */
+                       if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+                               return -ENODEV;
+
+                       retval = 0;
+
+                       sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+                       sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+                       if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
+                               retval = -EINVAL;
+
+                       break;
+#endif
+
                default:
                        retval = -EINVAL;
        }
 
-       if(retval > 0)
+       if (retval > 0)
                retval = -EIO;
 
        return retval;
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        x.sisusb_vramsize   = sisusb->vramsize;
                        x.sisusb_minor      = sisusb->minor;
                        x.sisusb_fbdevactive= 0;
+#ifdef INCL_SISUSB_CON
+                       x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
+#else
+                       x.sisusb_conactive  = 0;
+#endif
 
                        if (copy_to_user((void __user *)arg, &x, sizeof(x)))
                                retval = -EFAULT;
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
 };
 
 static struct usb_class_driver usb_sisusb_class = {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
        .name =         "usb/sisusbvga%d",
-       .fops =         &usb_sisusb_fops,
        .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+#else
+       .name =         "sisusbvga%d",
+#endif
+       .fops =         &usb_sisusb_fops,
        .minor_base =   SISUSB_MINOR
 };
 
@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
        printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
                                        sisusb->minor, sisusb->numobufs);
 
+#ifdef INCL_SISUSB_CON
+       /* Allocate our SiS_Pr */
+       if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
+               printk(KERN_ERR
+                       "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
+                       sisusb->minor);
+       }
+#endif
+
        /* Do remaining init stuff */
 
        init_waitqueue_head(&sisusb->wait_q);
 
        usb_set_intfdata(intf, sisusb);
 
+       usb_get_dev(sisusb->sisusb_dev);
+
+       sisusb->present = 1;
+
 #ifdef SISUSB_OLD_CONFIG_COMPAT
        {
        int ret;
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
                        sisusb->minor);
        else
                sisusb->ioctl32registered = 1;
-
        }
 #endif
 
-       sisusb->present = 1;
-
        if (dev->speed == USB_SPEED_HIGH) {
-               if (sisusb_init_gfxdevice(sisusb, 1))
+               int initscreen = 1;
+#ifdef INCL_SISUSB_CON
+               if (sisusb_first_vc > 0 &&
+                   sisusb_last_vc > 0 &&
+                   sisusb_first_vc <= sisusb_last_vc &&
+                   sisusb_last_vc <= MAX_NR_CONSOLES)
+                       initscreen = 0;
+#endif
+               if (sisusb_init_gfxdevice(sisusb, initscreen))
                        printk(KERN_ERR
                                "sisusbvga[%d]: Failed to early "
                                "initialize device\n",
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,
 
        sisusb->ready = 1;
 
+#ifdef SISUSBENDIANTEST
+       printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
+       sisusb_testreadwrite(sisusb);
+       printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
+#endif
+
+#ifdef INCL_SISUSB_CON
+       sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
+#endif
+
        return 0;
 
 error_4:
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
        struct sisusb_usb_data *sisusb;
        int minor;
 
-       down(&disconnect_sem);
-
        /* This should *not* happen */
-       if (!(sisusb = usb_get_intfdata(intf))) {
-               up(&disconnect_sem);
+       if (!(sisusb = usb_get_intfdata(intf)))
                return;
-       }
+
+#ifdef INCL_SISUSB_CON
+       sisusb_console_exit(sisusb);
+#endif
+
+       /* The above code doesn't need the disconnect
+        * semaphore to be down; its meaning is to
+        * protect all other routines from the disconnect
+        * case, not the other way round.
+        */
+       down(&disconnect_sem);
 
        down(&sisusb->lock);
 
@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
 {
        int retval;
 
+#ifdef INCL_SISUSB_CON
+       sisusb_init_concode();
+#endif
+
        if (!(retval = usb_register(&sisusb_driver))) {
+
                printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
                        SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
                printk(KERN_INFO
                        "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+
        }
 
        return retval;
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
 module_exit(usb_sisusb_exit);
 
 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
-MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
 MODULE_LICENSE("GPL");
 
index 1306d006a25aba059d6f14cca240ae962df478d8..401ff21d7881c2a0a0c7383b102f1527f6abc77b 100644 (file)
 #endif
 #endif
 
+/* For older kernels, support for text consoles is by default
+ * off. To ensable text console support, change the following:
+ */
+#if 0
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+#define CONFIG_USB_SISUSBVGA_CON
+#endif
+#endif
+
 /* Version Information */
 
 #define SISUSB_VERSION         0
 #define SISUSB_REVISION        0
-#define SISUSB_PATCHLEVEL      7
+#define SISUSB_PATCHLEVEL      8
+
+/* Include console and mode switching code? */
+
+#ifdef CONFIG_USB_SISUSBVGA_CON
+#define INCL_SISUSB_CON                1
+#endif
+
+#ifdef INCL_SISUSB_CON
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include "sisusb_struct.h"
+#endif
 
 /* USB related */
 
-#define SISUSB_MINOR   133             /* FIXME */
+#define SISUSB_MINOR           133     /* official */
 
 /* Size of the sisusb input/output buffers */
 #define SISUSB_IBUF_SIZE  0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
        unsigned char gfxinit;          /* graphics core initialized? */
        unsigned short chipid, chipvendor;
        unsigned short chiprevision;
+#ifdef INCL_SISUSB_CON
+       struct SiS_Private *SiS_Pr;
+       unsigned long scrbuf;
+       unsigned int scrbuf_size;
+       int haveconsole, con_first, con_last;
+       int havethisconsole[MAX_NR_CONSOLES];
+       int textmodedestroyed;
+       unsigned int sisusb_num_columns; /* real number, not vt's idea */
+       int cur_start_addr, con_rolled_over;
+       int sisusb_cursor_loc, bad_cursor_pos;
+       int sisusb_cursor_size_from;
+       int sisusb_cursor_size_to;
+       int current_font_height, current_font_512;
+       int font_backup_size, font_backup_height, font_backup_512;
+       char *font_backup;
+       int font_slot;
+       struct vc_data *sisusb_display_fg;
+       int is_gfx;
+       int con_blanked;
+#endif
 };
 
 #define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {
 
        __u32   sisusb_fbdevactive;     /* != 0 if framebuffer device active */
 
-       __u8    sisusb_reserved[32];    /* for future use */
+       __u32   sisusb_conactive;       /* != 0 if console driver active */
+
+       __u8    sisusb_reserved[28];    /* for future use */
 };
 
 struct sisusb_command {
@@ -261,18 +304,24 @@ struct sisusb_command {
        __u32  data4;           /* for future use */
 };
 
-#define SUCMD_GET      0x01    /* for all: data0 = index, data3 = port */
-#define SUCMD_SET      0x02    /* data1 = value */
-#define SUCMD_SETOR    0x03    /* data1 = or */
-#define SUCMD_SETAND   0x04    /* data1 = and */
-#define SUCMD_SETANDOR 0x05    /* data1 = and, data2 = or */
-#define SUCMD_SETMASK  0x06    /* data1 = data, data2 = mask */
+#define SUCMD_GET      0x01    /* for all: data0 = index, data3 = port */
+#define SUCMD_SET      0x02    /* data1 = value */
+#define SUCMD_SETOR    0x03    /* data1 = or */
+#define SUCMD_SETAND   0x04    /* data1 = and */
+#define SUCMD_SETANDOR 0x05    /* data1 = and, data2 = or */
+#define SUCMD_SETMASK  0x06    /* data1 = data, data2 = mask */
 
-#define SUCMD_CLRSCR   0x07    /* data0:1:2 = length, data3 = address */
+#define SUCMD_CLRSCR   0x07    /* data0:1:2 = length, data3 = address */
+
+#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
+
+#define SUCMD_SETMODE  0x09    /* Set a display mode (data3 = SiS mode) */
+#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */
 
 #define SISUSB_COMMAND         _IOWR(0xF3,0x3D,struct sisusb_command)
-#define SISUSB_GET_CONFIG_SIZE         _IOR(0xF3,0x3E,__u32)
-#define SISUSB_GET_CONFIG      _IOR(0xF3,0x3F,struct sisusb_info)
+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG      _IOR(0xF3,0x3F,struct sisusb_info)
+
 
 #endif /* SISUSB_H */
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644 (file)
index 0000000..2458446
--- /dev/null
@@ -0,0 +1,1658 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * VGA text mode console part
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED 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 AUTHOR 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Portions based on vgacon.c which are
+ *     Created 28 Sep 1997 by Geert Uytterhoeven
+ *      Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ *      based on code Copyright (C) 1991, 1992  Linus Torvalds
+ *                         1995  Jay Estabrook
+ *
+ * A note on using in_atomic() in here: We can't handle console
+ * calls from non-schedulable context due to our USB-dependend
+ * nature. For now, this driver just ignores any calls if it
+ * detects this state.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/smp_lock.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
+extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
+extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
+extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
+
+extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+                       u32 dest, int length, size_t *bytes_written);
+
+extern void sisusb_delete(struct kref *kref);
+extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+
+#define sisusbcon_writew(val, addr)    (*(addr) = (val))
+#define sisusbcon_readw(addr)          (*(addr))
+#define sisusbcon_memmovew(d, s, c)    memmove(d, s, c)
+#define sisusbcon_memcpyw(d, s, c)     memcpy(d, s, c)
+
+/* vc_data -> sisusb conversion table */
+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
+
+/* Forward declaration */
+static const struct consw sisusb_con;
+
+extern struct semaphore disconnect_sem;
+
+static inline void
+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
+{
+       count /= 2;
+       while (count--)
+               sisusbcon_writew(c, s++);
+}
+
+static inline void
+sisusb_initialize(struct sisusb_usb_data *sisusb)
+{
+       /* Reset cursor and start address */
+       if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
+               return;
+       if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
+               return;
+       if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
+               return;
+       sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
+}
+
+static inline void
+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
+{
+       sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
+
+       sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+       sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+}
+
+void
+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
+{
+       if (sisusb->sisusb_cursor_loc == location)
+               return;
+
+       sisusb->sisusb_cursor_loc = location;
+
+       /* Hardware bug: Text cursor appears twice or not at all
+        * at some positions. Work around it with the cursor skew
+        * bits.
+        */
+
+       if ((location & 0x0007) == 0x0007) {
+               sisusb->bad_cursor_pos = 1;
+               location--;
+               if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
+                       return;
+       } else if (sisusb->bad_cursor_pos) {
+               if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
+                       return;
+               sisusb->bad_cursor_pos = 0;
+       }
+
+       if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
+               return;
+       sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
+}
+
+static inline struct sisusb_usb_data *
+sisusb_get_sisusb(unsigned short console)
+{
+       return mysisusbs[console];
+}
+
+static inline int
+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
+{
+       if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
+               return 0;
+
+       return 1;
+}
+
+static struct sisusb_usb_data *
+sisusb_get_sisusb_lock_and_check(unsigned short console)
+{
+       struct sisusb_usb_data *sisusb;
+
+       /* We can't handle console calls in non-schedulable
+        * context due to our locks and the USB transport.
+        * So we simply ignore them. This should only affect
+        * some calls to printk.
+        */
+       if (in_atomic())
+               return NULL;
+
+       if (!(sisusb = sisusb_get_sisusb(console)))
+               return NULL;
+
+       down(&sisusb->lock);
+
+       if (!sisusb_sisusb_valid(sisusb) ||
+           !sisusb->havethisconsole[console]) {
+               up(&sisusb->lock);
+               return NULL;
+       }
+
+       return sisusb;
+}
+
+static int
+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
+{
+       if (sisusb->is_gfx ||
+           sisusb->textmodedestroyed ||
+           c->vc_mode != KD_TEXT)
+               return 1;
+
+       return 0;
+}
+
+/* con_startup console interface routine */
+static const char *
+sisusbcon_startup(void)
+{
+       return "SISUSBCON";
+}
+
+/* con_init console interface routine */
+static void
+sisusbcon_init(struct vc_data *c, int init)
+{
+       struct sisusb_usb_data *sisusb;
+       int cols, rows;
+
+       /* This is called by take_over_console(),
+        * ie by us/under our control. It is
+        * only called after text mode and fonts
+        * are set up/restored.
+        */
+
+       down(&disconnect_sem);
+
+       if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+               up(&disconnect_sem);
+               return;
+       }
+
+       down(&sisusb->lock);
+
+       if (!sisusb_sisusb_valid(sisusb)) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               return;
+       }
+
+       c->vc_can_do_color = 1;
+
+       c->vc_complement_mask = 0x7700;
+
+       c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
+
+       sisusb->haveconsole = 1;
+
+       sisusb->havethisconsole[c->vc_num] = 1;
+
+       /* We only support 640x400 */
+       c->vc_scan_lines = 400;
+
+       c->vc_font.height = sisusb->current_font_height;
+
+       /* We only support width = 8 */
+       cols = 80;
+       rows = c->vc_scan_lines / c->vc_font.height;
+
+       /* Increment usage count for our sisusb.
+        * Doing so saves us from upping/downing
+        * the disconnect semaphore; we can't
+        * lose our sisusb until this is undone
+        * in con_deinit. For all other console
+        * interface functions, it suffices to
+        * use sisusb->lock and do a quick check
+        * of sisusb for device disconnection.
+        */
+       kref_get(&sisusb->kref);
+
+       if (!*c->vc_uni_pagedir_loc)
+               con_set_default_unimap(c);
+
+       up(&sisusb->lock);
+
+       up(&disconnect_sem);
+
+       if (init) {
+               c->vc_cols = cols;
+               c->vc_rows = rows;
+       } else
+               vc_resize(c, cols, rows);
+}
+
+/* con_deinit console interface routine */
+static void
+sisusbcon_deinit(struct vc_data *c)
+{
+       struct sisusb_usb_data *sisusb;
+       int i;
+
+       /* This is called by take_over_console()
+        * and others, ie not under our control.
+        */
+
+       down(&disconnect_sem);
+
+       if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+               up(&disconnect_sem);
+               return;
+       }
+
+       down(&sisusb->lock);
+
+       /* Clear ourselves in mysisusbs */
+       mysisusbs[c->vc_num] = NULL;
+
+       sisusb->havethisconsole[c->vc_num] = 0;
+
+       /* Free our font buffer if all consoles are gone */
+       if (sisusb->font_backup) {
+               for(i = 0; i < MAX_NR_CONSOLES; i++) {
+                       if (sisusb->havethisconsole[c->vc_num])
+                               break;
+               }
+               if (i == MAX_NR_CONSOLES) {
+                       vfree(sisusb->font_backup);
+                       sisusb->font_backup = NULL;
+               }
+       }
+
+       up(&sisusb->lock);
+
+       /* decrement the usage count on our sisusb */
+       kref_put(&sisusb->kref, sisusb_delete);
+
+       up(&disconnect_sem);
+}
+
+/* interface routine */
+static u8
+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+                           u8 blink, u8 underline, u8 reverse)
+{
+       u8 attr = color;
+
+       if (underline)
+               attr = (attr & 0xf0) | c->vc_ulcolor;
+       else if (intensity == 0)
+               attr = (attr & 0xf0) | c->vc_halfcolor;
+
+       if (reverse)
+               attr = ((attr) & 0x88) |
+                      ((((attr) >> 4) |
+                      ((attr) << 4)) & 0x77);
+
+       if (blink)
+               attr ^= 0x80;
+
+       if (intensity == 2)
+               attr ^= 0x08;
+
+       return attr;
+}
+
+/* Interface routine */
+static void
+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
+{
+       /* Invert a region. This is called with a pointer
+        * to the console's internal screen buffer. So we
+        * simply do the inversion there and rely on
+        * a call to putc(s) to update the real screen.
+        */
+
+       while (count--) {
+               u16 a = sisusbcon_readw(p);
+
+               a = ((a) & 0x88ff)        |
+                   (((a) & 0x7000) >> 4) |
+                   (((a) & 0x0700) << 4);
+
+               sisusbcon_writew(a, p++);
+       }
+}
+
+#define SISUSB_VADDR(x,y) \
+       ((u16 *)c->vc_origin + \
+       (y) * sisusb->sisusb_num_columns + \
+       (x))
+
+#define SISUSB_HADDR(x,y) \
+       ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
+       (y) * sisusb->sisusb_num_columns + \
+       (x))
+
+/* Interface routine */
+static void
+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
+{
+       struct sisusb_usb_data *sisusb;
+       ssize_t written;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       /* Don't need to put the character into buffer ourselves,
+        * because the vt does this BEFORE calling us.
+        */
+#if 0
+       sisusbcon_writew(ch, SISUSB_VADDR(x, y));
+#endif
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+
+       sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+                               (u32)SISUSB_HADDR(x, y), 2, &written);
+
+       up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
+                        int count, int y, int x)
+{
+       struct sisusb_usb_data *sisusb;
+       ssize_t written;
+       u16 *dest;
+       int i;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       /* Need to put the characters into the buffer ourselves,
+        * because the vt does this AFTER calling us.
+        */
+
+       dest = SISUSB_VADDR(x, y);
+
+       for (i = count; i > 0; i--)
+               sisusbcon_writew(sisusbcon_readw(s++), dest++);
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+       sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+                               (u32)SISUSB_HADDR(x, y), count * 2, &written);
+
+       up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
+{
+       struct sisusb_usb_data *sisusb;
+       u16 eattr = c->vc_video_erase_char;
+       ssize_t written;
+       int i, length, cols;
+       u16 *dest;
+
+       if (width <= 0 || height <= 0)
+               return;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       /* Need to clear buffer ourselves, because the vt does
+        * this AFTER calling us.
+        */
+
+       dest = SISUSB_VADDR(x, y);
+
+       cols = sisusb->sisusb_num_columns;
+
+       if (width > cols)
+               width = cols;
+
+       if (x == 0 && width >= c->vc_cols) {
+
+               sisusbcon_memsetw(dest, eattr, height * cols * 2);
+
+       } else {
+
+               for (i = height; i > 0; i--, dest += cols)
+                       sisusbcon_memsetw(dest, eattr, width * 2);
+
+       }
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+       length = ((height * cols) - x - (cols - width - x)) * 2;
+
+
+       sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
+                               (u32)SISUSB_HADDR(x, y), length, &written);
+
+       up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_bmove(struct vc_data *c, int sy, int sx,
+                        int dy, int dx, int height, int width)
+{
+       struct sisusb_usb_data *sisusb;
+       ssize_t written;
+       int cols, length;
+#if 0
+       u16 *src, *dest;
+       int i;
+#endif
+
+       if (width <= 0 || height <= 0)
+               return;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       cols = sisusb->sisusb_num_columns;
+
+       /* Don't need to move data outselves, because
+        * vt does this BEFORE calling us.
+        * This is only used by vt's insert/deletechar.
+        */
+#if 0
+       if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
+
+               sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
+                                       height * width * 2);
+
+       } else if (dy < sy || (dy == sy && dx < sx)) {
+
+               src  = SISUSB_VADDR(sx, sy);
+               dest = SISUSB_VADDR(dx, dy);
+
+               for (i = height; i > 0; i--) {
+                       sisusbcon_memmovew(dest, src, width * 2);
+                       src  += cols;
+                       dest += cols;
+               }
+
+       } else {
+
+               src  = SISUSB_VADDR(sx, sy + height - 1);
+               dest = SISUSB_VADDR(dx, dy + height - 1);
+
+               for (i = height; i > 0; i--) {
+                       sisusbcon_memmovew(dest, src, width * 2);
+                       src  -= cols;
+                       dest -= cols;
+               }
+
+       }
+#endif
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+       length = ((height * cols) - dx - (cols - width - dx)) * 2;
+
+
+       sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
+                               (u32)SISUSB_HADDR(dx, dy), length, &written);
+
+       up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_switch(struct vc_data *c)
+{
+       struct sisusb_usb_data *sisusb;
+       ssize_t written;
+       int length;
+
+       /* Returnvalue 0 means we have fully restored screen,
+        *      and vt doesn't need to call do_update_region().
+        * Returnvalue != 0 naturally means the opposite.
+        */
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return 0;
+
+       /* sisusb->lock is down */
+
+       /* Don't write to screen if in gfx mode */
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       /* That really should not happen. It would mean we are
+        * being called while the vc is using its private buffer
+        * as origin.
+        */
+       if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
+               up(&sisusb->lock);
+               printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
+               return 0;
+       }
+
+       /* Check that we don't copy too much */
+       length = min((int)c->vc_screenbuf_size,
+                       (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+       /* Restore the screen contents */
+       sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
+                                                               length);
+
+       sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
+                               (u32)SISUSB_HADDR(0, 0),
+                               length, &written);
+
+       up(&sisusb->lock);
+
+       return 0;
+}
+
+/* interface routine */
+static void
+sisusbcon_save_screen(struct vc_data *c)
+{
+       struct sisusb_usb_data *sisusb;
+       int length;
+
+       /* Save the current screen contents to vc's private
+        * buffer.
+        */
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+       /* Check that we don't copy too much */
+       length = min((int)c->vc_screenbuf_size,
+                       (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+       /* Save the screen contents to vc's private buffer */
+       sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
+                                                               length);
+
+       up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
+{
+       struct sisusb_usb_data *sisusb;
+       int i, j;
+
+       /* Return value not used by vt */
+
+       if (!CON_IS_VISIBLE(c))
+               return -EINVAL;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return -EINVAL;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return -EINVAL;
+       }
+
+       for (i = j = 0; i < 16; i++) {
+               if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
+                       break;
+               if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+                       break;
+               if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+                       break;
+               if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+                       break;
+       }
+
+       up(&sisusb->lock);
+
+       return 0;
+}
+
+/* interface routine */
+static int
+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
+{
+       struct sisusb_usb_data *sisusb;
+       u8 sr1, cr17, pmreg, cr63;
+       ssize_t written;
+       int ret = 0;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return 0;
+
+       /* sisusb->lock is down */
+
+       if (mode_switch)
+               sisusb->is_gfx = blank ? 1 : 0;
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       switch (blank) {
+
+       case 1:         /* Normal blanking: Clear screen */
+       case -1:
+               sisusbcon_memsetw((u16 *)c->vc_origin,
+                               c->vc_video_erase_char,
+                               c->vc_screenbuf_size);
+               sisusb_copy_memory(sisusb,
+                               (unsigned char *)c->vc_origin,
+                               (u32)(sisusb->vrambase +
+                                       (c->vc_origin - sisusb->scrbuf)),
+                               c->vc_screenbuf_size, &written);
+               sisusb->con_blanked = 1;
+               ret = 1;
+               break;
+
+       default:        /* VESA blanking */
+               switch (blank) {
+               case 0: /* Unblank */
+                       sr1   = 0x00;
+                       cr17  = 0x80;
+                       pmreg = 0x00;
+                       cr63  = 0x00;
+                       ret = 1;
+                       sisusb->con_blanked = 0;
+                       break;
+               case VESA_VSYNC_SUSPEND + 1:
+                       sr1   = 0x20;
+                       cr17  = 0x80;
+                       pmreg = 0x80;
+                       cr63  = 0x40;
+                       break;
+               case VESA_HSYNC_SUSPEND + 1:
+                       sr1   = 0x20;
+                       cr17  = 0x80;
+                       pmreg = 0x40;
+                       cr63  = 0x40;
+                       break;
+               case VESA_POWERDOWN + 1:
+                       sr1   = 0x20;
+                       cr17  = 0x00;
+                       pmreg = 0xc0;
+                       cr63  = 0x40;
+                       break;
+               default:
+                       up(&sisusb->lock);
+                       return -EINVAL;
+               }
+
+               sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
+               sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
+               sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
+               sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
+
+       }
+
+       up(&sisusb->lock);
+
+       return ret;
+}
+
+/* interface routine */
+static int
+sisusbcon_scrolldelta(struct vc_data *c, int lines)
+{
+       struct sisusb_usb_data *sisusb;
+       int margin = c->vc_size_row * 4;
+       int ul, we, p, st;
+
+       /* The return value does not seem to be used */
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return 0;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       if (!lines)             /* Turn scrollback off */
+               c->vc_visible_origin = c->vc_origin;
+       else {
+
+               if (sisusb->con_rolled_over >
+                               (c->vc_scr_end - sisusb->scrbuf) + margin) {
+
+                       ul = c->vc_scr_end - sisusb->scrbuf;
+                       we = sisusb->con_rolled_over + c->vc_size_row;
+
+               } else {
+
+                       ul = 0;
+                       we = sisusb->scrbuf_size;
+
+               }
+
+               p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
+                               lines * c->vc_size_row;
+
+               st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
+
+               if (st < 2 * margin)
+                       margin = 0;
+
+               if (p < margin)
+                       p = 0;
+
+               if (p > st - margin)
+                       p = st;
+
+               c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
+       }
+
+       sisusbcon_set_start_address(sisusb, c);
+
+       up(&sisusb->lock);
+
+       return 1;
+}
+
+/* Interface routine */
+static void
+sisusbcon_cursor(struct vc_data *c, int mode)
+{
+       struct sisusb_usb_data *sisusb;
+       int from, to, baseline;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return;
+       }
+
+       if (c->vc_origin != c->vc_visible_origin) {
+               c->vc_visible_origin = c->vc_origin;
+               sisusbcon_set_start_address(sisusb, c);
+       }
+
+       if (mode == CM_ERASE) {
+               sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
+               sisusb->sisusb_cursor_size_to = -1;
+               up(&sisusb->lock);
+               return;
+       }
+
+       sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
+
+       baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
+
+       switch (c->vc_cursor_type & 0x0f) {
+               case CUR_BLOCK:         from = 1;
+                                       to   = c->vc_font.height;
+                                       break;
+               case CUR_TWO_THIRDS:    from = c->vc_font.height / 3;
+                                       to   = baseline;
+                                       break;
+               case CUR_LOWER_HALF:    from = c->vc_font.height / 2;
+                                       to   = baseline;
+                                       break;
+               case CUR_LOWER_THIRD:   from = (c->vc_font.height * 2) / 3;
+                                       to   = baseline;
+                                       break;
+               case CUR_NONE:          from = 31;
+                                       to = 30;
+                                       break;
+               default:
+               case CUR_UNDERLINE:     from = baseline - 1;
+                                       to   = baseline;
+                                       break;
+       }
+
+       if (sisusb->sisusb_cursor_size_from != from ||
+           sisusb->sisusb_cursor_size_to != to) {
+
+               sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
+               sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
+
+               sisusb->sisusb_cursor_size_from = from;
+               sisusb->sisusb_cursor_size_to   = to;
+       }
+
+       up(&sisusb->lock);
+}
+
+static int
+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
+                                       int t, int b, int dir, int lines)
+{
+       int cols = sisusb->sisusb_num_columns;
+       int length = ((b - t) * cols) * 2;
+       u16 eattr = c->vc_video_erase_char;
+       ssize_t written;
+
+       /* sisusb->lock is down */
+
+       /* Scroll an area which does not match the
+        * visible screen's dimensions. This needs
+        * to be done separately, as it does not
+        * use hardware panning.
+        */
+
+       switch (dir) {
+
+               case SM_UP:
+                       sisusbcon_memmovew(SISUSB_VADDR(0, t),
+                                          SISUSB_VADDR(0, t + lines),
+                                          (b - t - lines) * cols * 2);
+                       sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
+                                         lines * cols * 2);
+                       break;
+
+               case SM_DOWN:
+                       sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
+                                          SISUSB_VADDR(0, t),
+                                          (b - t - lines) * cols * 2);
+                       sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+                                         lines * cols * 2);
+                       break;
+       }
+
+       sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
+                               (u32)SISUSB_HADDR(0, t), length, &written);
+
+       up(&sisusb->lock);
+
+       return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+       struct sisusb_usb_data *sisusb;
+       u16 eattr = c->vc_video_erase_char;
+       ssize_t written;
+       int copyall = 0;
+       unsigned long oldorigin;
+       unsigned int delta = lines * c->vc_size_row;
+       u32 originoffset;
+
+       /* Returning != 0 means we have done the scrolling successfully.
+        * Returning 0 makes vt do the scrolling on its own.
+        * Note that con_scroll is only called if the console is
+        * visible. In that case, the origin should be our buffer,
+        * not the vt's private one.
+        */
+
+       if (!lines)
+               return 1;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return 0;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb)) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       /* Special case */
+       if (t || b != c->vc_rows)
+               return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
+
+       if (c->vc_origin != c->vc_visible_origin) {
+               c->vc_visible_origin = c->vc_origin;
+               sisusbcon_set_start_address(sisusb, c);
+       }
+
+       /* limit amount to maximum realistic size */
+       if (lines > c->vc_rows)
+               lines = c->vc_rows;
+
+       oldorigin = c->vc_origin;
+
+       switch (dir) {
+
+       case SM_UP:
+
+               if (c->vc_scr_end + delta >=
+                               sisusb->scrbuf + sisusb->scrbuf_size) {
+                       sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+                                         (u16 *)(oldorigin + delta),
+                                         c->vc_screenbuf_size - delta);
+                       c->vc_origin = sisusb->scrbuf;
+                       sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
+                       copyall = 1;
+               } else
+                       c->vc_origin += delta;
+
+               sisusbcon_memsetw(
+                       (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
+                                       eattr, delta);
+
+               break;
+
+       case SM_DOWN:
+
+               if (oldorigin - delta < sisusb->scrbuf) {
+                       sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
+                                                       sisusb->scrbuf_size -
+                                                       c->vc_screenbuf_size +
+                                                       delta),
+                                          (u16 *)oldorigin,
+                                          c->vc_screenbuf_size - delta);
+                       c->vc_origin = sisusb->scrbuf +
+                                       sisusb->scrbuf_size -
+                                       c->vc_screenbuf_size;
+                       sisusb->con_rolled_over = 0;
+                       copyall = 1;
+               } else
+                       c->vc_origin -= delta;
+
+               c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+
+               scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
+
+               break;
+       }
+
+       originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
+
+       if (copyall)
+               sisusb_copy_memory(sisusb,
+                       (char *)c->vc_origin,
+                       (u32)(sisusb->vrambase + originoffset),
+                       c->vc_screenbuf_size, &written);
+       else if (dir == SM_UP)
+               sisusb_copy_memory(sisusb,
+                       (char *)c->vc_origin + c->vc_screenbuf_size - delta,
+                       (u32)sisusb->vrambase + originoffset +
+                                       c->vc_screenbuf_size - delta,
+                       delta, &written);
+       else
+               sisusb_copy_memory(sisusb,
+                       (char *)c->vc_origin,
+                       (u32)(sisusb->vrambase + originoffset),
+                       delta, &written);
+
+       c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+       c->vc_visible_origin = c->vc_origin;
+
+       sisusbcon_set_start_address(sisusb, c);
+
+       c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
+
+       up(&sisusb->lock);
+
+       return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_set_origin(struct vc_data *c)
+{
+       struct sisusb_usb_data *sisusb;
+
+       /* Returning != 0 means we were successful.
+        * Returning 0 will vt make to use its own
+        *      screenbuffer as the origin.
+        */
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return 0;
+
+       /* sisusb->lock is down */
+
+       if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
+
+       sisusbcon_set_start_address(sisusb, c);
+
+       sisusb->con_rolled_over = 0;
+
+       up(&sisusb->lock);
+
+       return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
+{
+       struct sisusb_usb_data *sisusb;
+       int fh;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return -ENODEV;
+
+       fh = sisusb->current_font_height;
+
+       up(&sisusb->lock);
+
+       /* We are quite unflexible as regards resizing. The vt code
+        * handles sizes where the line length isn't equal the pitch
+        * quite badly. As regards the rows, our panning tricks only
+        * work well if the number of rows equals the visible number
+        * of rows.
+        */
+
+       if (newcols != 80 || c->vc_scan_lines / fh != newrows)
+               return -EINVAL;
+
+       return 0;
+}
+
+int
+sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+                       u8 *arg, int cmapsz, int ch512, int dorecalc,
+                       struct vc_data *c, int fh, int uplock)
+{
+       int font_select = 0x00, i, err = 0;
+       u32 offset = 0;
+       u8 dummy;
+
+       /* sisusb->lock is down */
+
+       /*
+        * The default font is kept in slot 0.
+        * A user font is loaded in slot 2 (256 ch)
+        * or 2+3 (512 ch).
+        */
+
+       if ((slot != 0 && slot != 2) || !fh) {
+               if (uplock)
+                       up(&sisusb->lock);
+               return -EINVAL;
+       }
+
+       if (set)
+               sisusb->font_slot = slot;
+
+       /* Default font is always 256 */
+       if (slot == 0)
+               ch512 = 0;
+       else
+               offset = 4 * cmapsz;
+
+       font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
+
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
+
+       if (err)
+               goto font_op_error;
+
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
+
+       if (err)
+               goto font_op_error;
+
+       if (arg) {
+               if (set)
+                       for (i = 0; i < cmapsz; i++) {
+                               err |= sisusb_writeb(sisusb,
+                                       sisusb->vrambase + offset + i,
+                                       arg[i]);
+                               if (err)
+                                       break;
+                       }
+               else
+                       for (i = 0; i < cmapsz; i++) {
+                               err |= sisusb_readb(sisusb,
+                                       sisusb->vrambase + offset + i,
+                                       &arg[i]);
+                               if (err)
+                                       break;
+                       }
+
+               /*
+                * In 512-character mode, the character map is not contiguous if
+                * we want to remain EGA compatible -- which we do
+                */
+
+               if (ch512) {
+                       if (set)
+                               for (i = 0; i < cmapsz; i++) {
+                                       err |= sisusb_writeb(sisusb,
+                                               sisusb->vrambase + offset +
+                                                       (2 * cmapsz) + i,
+                                               arg[cmapsz + i]);
+                                       if (err)
+                                               break;
+                               }
+                       else
+                               for (i = 0; i < cmapsz; i++) {
+                                       err |= sisusb_readb(sisusb,
+                                               sisusb->vrambase + offset +
+                                                       (2 * cmapsz) + i,
+                                               &arg[cmapsz + i]);
+                                       if (err)
+                                               break;
+                               }
+               }
+       }
+
+       if (err)
+               goto font_op_error;
+
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
+       if (set)
+               sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
+       err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
+
+       if (err)
+               goto font_op_error;
+
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
+       err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
+
+       if (err)
+               goto font_op_error;
+
+       if ((set) && (ch512 != sisusb->current_font_512)) {
+
+               /* Font is shared among all our consoles.
+                * And so is the hi_font_mask.
+                */
+               for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                       struct vc_data *c = vc_cons[i].d;
+                       if (c && c->vc_sw == &sisusb_con)
+                               c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+               }
+
+               sisusb->current_font_512 = ch512;
+
+               /* color plane enable register:
+                       256-char: enable intensity bit
+                       512-char: disable intensity bit */
+               sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+               sisusb_setreg(sisusb, SISAR, 0x12);
+               sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
+
+               sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+               sisusb_setreg(sisusb, SISAR, 0x20);
+               sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+       }
+
+       if (dorecalc) {
+
+               /*
+                * Adjust the screen to fit a font of a certain height
+                */
+
+               unsigned char ovr, vde, fsr;
+               int rows = 0, maxscan = 0;
+
+               if (c) {
+
+                       /* Number of video rows */
+                       rows = c->vc_scan_lines / fh;
+                       /* Scan lines to actually display-1 */
+                       maxscan = rows * fh - 1;
+
+                       /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
+                               rows, maxscan, fh, c->vc_scan_lines);*/
+
+                       sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
+                       vde = maxscan & 0xff;
+                       ovr = (ovr & 0xbd) |
+                             ((maxscan & 0x100) >> 7) |
+                             ((maxscan & 0x200) >> 3);
+                       sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
+                       sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
+
+               }
+
+               sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
+               fsr = (fsr & 0xe0) | (fh - 1);
+               sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
+               sisusb->current_font_height = fh;
+
+               sisusb->sisusb_cursor_size_from = -1;
+               sisusb->sisusb_cursor_size_to   = -1;
+
+       }
+
+       if (uplock)
+               up(&sisusb->lock);
+
+       if (dorecalc && c) {
+               int i, rows = c->vc_scan_lines / fh;
+
+               /* Now adjust our consoles' size */
+
+               for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                       struct vc_data *vc = vc_cons[i].d;
+
+                       if (vc && vc->vc_sw == &sisusb_con) {
+                               if (CON_IS_VISIBLE(vc)) {
+                                       vc->vc_sw->con_cursor(vc, CM_DRAW);
+                               }
+                               vc->vc_font.height = fh;
+                               vc_resize(vc, 0, rows);
+                       }
+               }
+       }
+
+       return 0;
+
+font_op_error:
+       if (uplock)
+               up(&sisusb->lock);
+
+       return -EIO;
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_set(struct vc_data *c, struct console_font *font,
+                                                       unsigned flags)
+{
+       struct sisusb_usb_data *sisusb;
+       unsigned charcount = font->charcount;
+
+       if (font->width != 8 || (charcount != 256 && charcount != 512))
+               return -EINVAL;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return -ENODEV;
+
+       /* sisusb->lock is down */
+
+       /* Save the user-provided font into a buffer. This
+        * is used for restoring text mode after quitting
+        * from X and for the con_getfont routine.
+        */
+       if (sisusb->font_backup) {
+               if (sisusb->font_backup_size < charcount) {
+                       vfree(sisusb->font_backup);
+                       sisusb->font_backup = NULL;
+               }
+       }
+
+       if (!sisusb->font_backup)
+               sisusb->font_backup = vmalloc(charcount * 32);
+
+       if (sisusb->font_backup) {
+               memcpy(sisusb->font_backup, font->data, charcount * 32);
+               sisusb->font_backup_size = charcount;
+               sisusb->font_backup_height = font->height;
+               sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
+       }
+
+       /* do_font_op ups sisusb->lock */
+
+       return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
+                       8192, (charcount == 512),
+                       (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
+                       c, font->height, 1);
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_get(struct vc_data *c, struct console_font *font)
+{
+       struct sisusb_usb_data *sisusb;
+
+       if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+               return -ENODEV;
+
+       /* sisusb->lock is down */
+
+       font->width = 8;
+       font->height = c->vc_font.height;
+       font->charcount = 256;
+
+       if (!font->data) {
+               up(&sisusb->lock);
+               return 0;
+       }
+
+       if (!sisusb->font_backup) {
+               up(&sisusb->lock);
+               return -ENODEV;
+       }
+
+       /* Copy 256 chars only, like vgacon */
+       memcpy(font->data, sisusb->font_backup, 256 * 32);
+
+       up(&sisusb->lock);
+
+       return 0;
+}
+
+/*
+ *  The console `switch' structure for the sisusb console
+ */
+
+static const struct consw sisusb_con = {
+       .owner =                THIS_MODULE,
+       .con_startup =          sisusbcon_startup,
+       .con_init =             sisusbcon_init,
+       .con_deinit =           sisusbcon_deinit,
+       .con_clear =            sisusbcon_clear,
+       .con_putc =             sisusbcon_putc,
+       .con_putcs =            sisusbcon_putcs,
+       .con_cursor =           sisusbcon_cursor,
+       .con_scroll =           sisusbcon_scroll,
+       .con_bmove =            sisusbcon_bmove,
+       .con_switch =           sisusbcon_switch,
+       .con_blank =            sisusbcon_blank,
+       .con_font_set =         sisusbcon_font_set,
+       .con_font_get =         sisusbcon_font_get,
+       .con_set_palette =      sisusbcon_set_palette,
+       .con_scrolldelta =      sisusbcon_scrolldelta,
+       .con_build_attr =       sisusbcon_build_attr,
+       .con_invert_region =    sisusbcon_invert_region,
+       .con_set_origin =       sisusbcon_set_origin,
+       .con_save_screen =      sisusbcon_save_screen,
+       .con_resize =           sisusbcon_resize,
+};
+
+/* Our very own dummy console driver */
+
+static const char *sisusbdummycon_startup(void)
+{
+    return "SISUSBVGADUMMY";
+}
+
+static void sisusbdummycon_init(struct vc_data *vc, int init)
+{
+    vc->vc_can_do_color = 1;
+    if (init) {
+       vc->vc_cols = 80;
+       vc->vc_rows = 25;
+    } else
+       vc_resize(vc, 80, 25);
+}
+
+static int sisusbdummycon_dummy(void)
+{
+    return 0;
+}
+
+#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
+
+const struct consw sisusb_dummy_con = {
+       .owner =                THIS_MODULE,
+       .con_startup =          sisusbdummycon_startup,
+       .con_init =             sisusbdummycon_init,
+       .con_deinit =           SISUSBCONDUMMY,
+       .con_clear =            SISUSBCONDUMMY,
+       .con_putc =             SISUSBCONDUMMY,
+       .con_putcs =            SISUSBCONDUMMY,
+       .con_cursor =           SISUSBCONDUMMY,
+       .con_scroll =           SISUSBCONDUMMY,
+       .con_bmove =            SISUSBCONDUMMY,
+       .con_switch =           SISUSBCONDUMMY,
+       .con_blank =            SISUSBCONDUMMY,
+       .con_font_set =         SISUSBCONDUMMY,
+       .con_font_get =         SISUSBCONDUMMY,
+       .con_font_default =     SISUSBCONDUMMY,
+       .con_font_copy =        SISUSBCONDUMMY,
+       .con_set_palette =      SISUSBCONDUMMY,
+       .con_scrolldelta =      SISUSBCONDUMMY,
+};
+
+int
+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+{
+       int i, ret, minor = sisusb->minor;
+
+       down(&disconnect_sem);
+
+       down(&sisusb->lock);
+
+       /* Erm.. that should not happen */
+       if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               return 1;
+       }
+
+       sisusb->con_first = first;
+       sisusb->con_last  = last;
+
+       if (first > last ||
+           first > MAX_NR_CONSOLES ||
+           last > MAX_NR_CONSOLES) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               return 1;
+       }
+
+       /* If gfxcore not initialized or no consoles given, quit graciously */
+       if (!sisusb->gfxinit || first < 1 || last < 1) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               return 0;
+       }
+
+       sisusb->sisusb_cursor_loc       = -1;
+       sisusb->sisusb_cursor_size_from = -1;
+       sisusb->sisusb_cursor_size_to   = -1;
+
+       /* Set up text mode (and upload  default font) */
+       if (sisusb_reset_text_mode(sisusb, 1)) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               printk(KERN_ERR
+                       "sisusbvga[%d]: Failed to set up text mode\n",
+                       minor);
+               return 1;
+       }
+
+       /* Initialize some gfx registers */
+       sisusb_initialize(sisusb);
+
+       for (i = first - 1; i <= last - 1; i++) {
+               /* Save sisusb for our interface routines */
+               mysisusbs[i] = sisusb;
+       }
+
+       /* Initial console setup */
+       sisusb->sisusb_num_columns = 80;
+
+       /* Use a 32K buffer (matches b8000-bffff area) */
+       sisusb->scrbuf_size = 32 * 1024;
+
+       /* Allocate screen buffer */
+       if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+               up(&sisusb->lock);
+               up(&disconnect_sem);
+               printk(KERN_ERR
+                       "sisusbvga[%d]: Failed to allocate screen buffer\n",
+                       minor);
+               return 1;
+       }
+
+       up(&sisusb->lock);
+       up(&disconnect_sem);
+
+       /* Now grab the desired console(s) */
+       ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
+
+       if (!ret)
+               sisusb->haveconsole = 1;
+       else {
+               for (i = first - 1; i <= last - 1; i++)
+                       mysisusbs[i] = NULL;
+       }
+
+       return ret;
+}
+
+void
+sisusb_console_exit(struct sisusb_usb_data *sisusb)
+{
+       int i;
+
+       /* This is called if the device is disconnected
+        * and while disconnect and lock semaphores
+        * are up. This should be save because we
+        * can't lose our sisusb any other way but by
+        * disconnection (and hence, the disconnect
+        * sema is for protecting all other access
+        * functions from disconnection, not the
+        * other way round).
+        */
+
+       /* Now what do we do in case of disconnection:
+        * One alternative would be to simply call
+        * give_up_console(). Nah, not a good idea.
+        * give_up_console() is obviously buggy as it
+        * only discards the consw pointer from the
+        * driver_map, but doesn't adapt vc->vc_sw
+        * of the affected consoles. Hence, the next
+        * call to any of the console functions will
+        * eventually take a trip to oops county.
+        * Also, give_up_console for some reason
+        * doesn't decrement our module refcount.
+        * Instead, we switch our consoles to a private
+        * dummy console. This, of course, keeps our
+        * refcount up as well, but it works perfectly.
+        */
+
+       if (sisusb->haveconsole) {
+               for (i = 0; i < MAX_NR_CONSOLES; i++)
+                       if (sisusb->havethisconsole[i])
+                               take_over_console(&sisusb_dummy_con, i, i, 0);
+                               /* At this point, con_deinit for all our
+                                * consoles is executed by take_over_console().
+                                */
+               sisusb->haveconsole = 0;
+       }
+
+       vfree((void *)sisusb->scrbuf);
+       sisusb->scrbuf = 0;
+
+       vfree(sisusb->font_backup);
+       sisusb->font_backup = NULL;
+}
+
+void __init sisusb_init_concode(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_NR_CONSOLES; i++)
+               mysisusbs[i] = NULL;
+}
+
+#endif /* INCL_CON */
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644 (file)
index 0000000..f28bc24
--- /dev/null
@@ -0,0 +1,1047 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Display mode initializing code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Author:     Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+
+#include "sisusb_init.h"
+
+/*********************************************/
+/*         POINTER INITIALIZATION            */
+/*********************************************/
+
+static void
+SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
+{
+       SiS_Pr->SiS_ModeResInfo   = SiSUSB_ModeResInfo;
+       SiS_Pr->SiS_StandTable    = SiSUSB_StandTable;
+
+       SiS_Pr->SiS_SModeIDTable  = SiSUSB_SModeIDTable;
+       SiS_Pr->SiS_EModeIDTable  = SiSUSB_EModeIDTable;
+       SiS_Pr->SiS_RefIndex      = SiSUSB_RefIndex;
+       SiS_Pr->SiS_CRT1Table     = SiSUSB_CRT1Table;
+
+       SiS_Pr->SiS_VCLKData      = SiSUSB_VCLKData;
+}
+
+/*********************************************/
+/*            HELPER: Get ModeID             */
+/*********************************************/
+
+unsigned short
+SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
+{
+       unsigned short ModeIndex = 0;
+
+       switch (HDisplay)
+       {
+               case 320:
+                       if (VDisplay == 200)
+                               ModeIndex = ModeIndex_320x200[Depth];
+                       else if (VDisplay == 240)
+                               ModeIndex = ModeIndex_320x240[Depth];
+                       break;
+               case 400:
+                       if (VDisplay == 300)
+                               ModeIndex = ModeIndex_400x300[Depth];
+                       break;
+               case 512:
+                       if (VDisplay == 384)
+                               ModeIndex = ModeIndex_512x384[Depth];
+                       break;
+               case 640:
+                       if (VDisplay == 480)
+                               ModeIndex = ModeIndex_640x480[Depth];
+                       else if (VDisplay == 400)
+                               ModeIndex = ModeIndex_640x400[Depth];
+                       break;
+               case 720:
+                       if (VDisplay == 480)
+                               ModeIndex = ModeIndex_720x480[Depth];
+                       else if (VDisplay == 576)
+                               ModeIndex = ModeIndex_720x576[Depth];
+                       break;
+               case 768:
+                       if (VDisplay == 576)
+                               ModeIndex = ModeIndex_768x576[Depth];
+                       break;
+               case 800:
+                       if (VDisplay == 600)
+                               ModeIndex = ModeIndex_800x600[Depth];
+                       else if (VDisplay == 480)
+                               ModeIndex = ModeIndex_800x480[Depth];
+                       break;
+               case 848:
+                       if (VDisplay == 480)
+                               ModeIndex = ModeIndex_848x480[Depth];
+                       break;
+               case 856:
+                       if (VDisplay == 480)
+                               ModeIndex = ModeIndex_856x480[Depth];
+                       break;
+               case 960:
+                       if (VDisplay == 540)
+                               ModeIndex = ModeIndex_960x540[Depth];
+                       else if (VDisplay == 600)
+                               ModeIndex = ModeIndex_960x600[Depth];
+                       break;
+               case 1024:
+                       if (VDisplay == 576)
+                               ModeIndex = ModeIndex_1024x576[Depth];
+                       else if (VDisplay == 768)
+                               ModeIndex = ModeIndex_1024x768[Depth];
+                       break;
+               case 1152:
+                       if (VDisplay == 864)
+                               ModeIndex = ModeIndex_1152x864[Depth];
+                       break;
+               case 1280:
+                       switch (VDisplay) {
+                               case 720:
+                                       ModeIndex = ModeIndex_1280x720[Depth];
+                                       break;
+                               case 768:
+                                       ModeIndex = ModeIndex_1280x768[Depth];
+                                       break;
+                               case 1024:
+                                       ModeIndex = ModeIndex_1280x1024[Depth];
+                                       break;
+                       }
+       }
+
+       return ModeIndex;
+}
+
+/*********************************************/
+/*          HELPER: SetReg, GetReg           */
+/*********************************************/
+
+static void
+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+                       unsigned short index, unsigned short data)
+{
+       sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
+}
+
+static void
+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
+                                               unsigned short data)
+{
+       sisusb_setreg(SiS_Pr->sisusb, port, data);
+}
+
+static unsigned char
+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+                                               unsigned short index)
+{
+       u8 data;
+
+       sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
+
+       return data;
+}
+
+static unsigned char
+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
+{
+       u8 data;
+
+       sisusb_getreg(SiS_Pr->sisusb, port, &data);
+
+       return data;
+}
+
+static void
+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
+                       unsigned short index, unsigned short DataAND,
+                                               unsigned short DataOR)
+{
+       sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
+}
+
+static void
+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
+                       unsigned short index, unsigned short DataAND)
+{
+       sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
+}
+
+static void
+SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
+                       unsigned short index, unsigned short DataOR)
+{
+       sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
+}
+
+/*********************************************/
+/*      HELPER: DisplayOn, DisplayOff        */
+/*********************************************/
+
+static void
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
+}
+
+/*********************************************/
+/*        HELPER: Init Port Addresses        */
+/*********************************************/
+
+void
+SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
+{
+       SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+       SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+       SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+       SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+       SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+       SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+       SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+       SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+       SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+       SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+       SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+       SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+       SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+       SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+       SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+}
+
+/*********************************************/
+/*             HELPER: GetSysFlags           */
+/*********************************************/
+
+static void
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+       SiS_Pr->SiS_MyCR63 = 0x63;
+}
+
+/*********************************************/
+/*         HELPER: Init PCI & Engines        */
+/*********************************************/
+
+static void
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
+       /*  - Enable 2D (0x40)
+        *  - Enable 3D (0x02)
+        *  - Enable 3D vertex command fetch (0x10)
+        *  - Enable 3D command parser (0x08)
+        *  - Enable 3D G/L transformation engine (0x80)
+        */
+       SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
+}
+
+/*********************************************/
+/*        HELPER: SET SEGMENT REGISTERS      */
+/*********************************************/
+
+static void
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+       unsigned short temp;
+
+       value &= 0x00ff;
+       temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
+       temp |= (value >> 4);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+       temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
+       temp |= (value & 0x0f);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+       unsigned short temp;
+
+       value &= 0x00ff;
+       temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
+       temp |= (value & 0xf0);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+       temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
+       temp |= (value << 4);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+       SiS_SetSegRegLower(SiS_Pr, value);
+       SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+       SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+       unsigned short temp = value >> 8;
+
+       temp &= 0x07;
+       temp |= (temp << 4);
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
+       SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+       SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+       SiS_ResetSegmentReg(SiS_Pr);
+       SiS_ResetSegmentRegOver(SiS_Pr);
+}
+
+/*********************************************/
+/*           HELPER: SearchModeID            */
+/*********************************************/
+
+static int
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+                                               unsigned short *ModeIdIndex)
+{
+       if ((*ModeNo) <= 0x13) {
+
+               if ((*ModeNo) != 0x03)
+                       return 0;
+
+               (*ModeIdIndex) = 0;
+
+       } else {
+
+               for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
+
+                       if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
+                               break;
+
+                       if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+                               return 0;
+               }
+
+       }
+
+       return 1;
+}
+
+/*********************************************/
+/*            HELPER: ENABLE CRT1            */
+/*********************************************/
+
+static void
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+       /* Enable CRT1 gating */
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
+}
+
+/*********************************************/
+/*           HELPER: GetColorDepth           */
+/*********************************************/
+
+static unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex)
+{
+       static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
+       unsigned short modeflag;
+       short index;
+
+       if (ModeNo <= 0x13) {
+               modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+       } else {
+               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+       }
+
+       index = (modeflag & ModeTypeMask) - ModeEGA;
+       if (index < 0) index = 0;
+       return ColorDepth[index];
+}
+
+/*********************************************/
+/*             HELPER: GetOffset             */
+/*********************************************/
+
+static unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short rrti)
+{
+       unsigned short xres, temp, colordepth, infoflag;
+
+       infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+       xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
+
+       colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+       temp = xres / 16;
+
+       if (infoflag & InterlaceMode)
+               temp <<= 1;
+
+       temp *= colordepth;
+
+       if (xres % 16)
+               temp += (colordepth >> 1);
+
+       return temp;
+}
+
+/*********************************************/
+/*                   SEQ                     */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+       unsigned char SRdata;
+       int i;
+
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
+
+       SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
+
+       for(i = 2; i <= 4; i++) {
+               SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
+       }
+}
+
+/*********************************************/
+/*                  MISC                     */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+       unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
+}
+
+/*********************************************/
+/*                  CRTC                     */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+       unsigned char CRTCdata;
+       unsigned short i;
+
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+       for(i = 0; i <= 0x18; i++) {
+               CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
+       }
+}
+
+/*********************************************/
+/*                   ATT                     */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+       unsigned char ARdata;
+       unsigned short i;
+
+       for(i = 0; i <= 0x13; i++) {
+               ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+               SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+               SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
+               SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
+       }
+       SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
+
+       SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
+       SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/*                   GRC                     */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+       unsigned char GRdata;
+       unsigned short i;
+
+       for(i = 0; i <= 0x08; i++) {
+               GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
+       }
+
+       if (SiS_Pr->SiS_ModeType > ModeVGA) {
+               /* 256 color disable */
+               SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
+       }
+}
+
+/*********************************************/
+/*          CLEAR EXTENDED REGISTERS         */
+/*********************************************/
+
+static void
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+       int i;
+
+       for(i = 0x0A; i <= 0x0E; i++) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
+       }
+
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
+}
+
+/*********************************************/
+/*              Get rate index               */
+/*********************************************/
+
+static unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                                       unsigned short ModeIdIndex)
+{
+       unsigned short rrti, i, index, temp;
+
+       if (ModeNo <= 0x13)
+               return 0xFFFF;
+
+       index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
+       if (index > 0) index--;
+
+       rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+       ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
+
+       i = 0;
+       do {
+               if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
+                       break;
+
+               temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
+               if (temp < SiS_Pr->SiS_ModeType)
+                       break;
+
+               i++;
+               index--;
+       } while(index != 0xFFFF);
+
+       i--;
+
+       return (rrti + i);
+}
+
+/*********************************************/
+/*                  SYNC                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
+{
+       unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
+       sync &= 0xC0;
+       sync |= 0x2f;
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
+}
+
+/*********************************************/
+/*                  CRTC/2                   */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex, unsigned short rrti)
+{
+       unsigned char  index;
+       unsigned short temp, i, j, modeflag;
+
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+       modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+       index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
+
+       for(i = 0,j = 0; i <= 7; i++, j++) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+                               SiS_Pr->SiS_CRT1Table[index].CR[i]);
+       }
+       for(j = 0x10; i <= 10; i++, j++) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+                               SiS_Pr->SiS_CRT1Table[index].CR[i]);
+       }
+       for(j = 0x15; i <= 12; i++, j++) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+                               SiS_Pr->SiS_CRT1Table[index].CR[i]);
+       }
+       for(j = 0x0A; i <= 15; i++, j++) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
+                               SiS_Pr->SiS_CRT1Table[index].CR[i]);
+       }
+
+       temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+       SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
+
+       temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+       if (modeflag & DoubleScanMode)  temp |= 0x80;
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
+
+       if (SiS_Pr->SiS_ModeType > ModeVGA)
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
+}
+
+/*********************************************/
+/*               OFFSET & PITCH              */
+/*********************************************/
+/*  (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex, unsigned short rrti)
+{
+       unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+       unsigned short infoflag =  SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+       unsigned short temp;
+
+       temp = (du >> 8) & 0x0f;
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
+
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
+
+       if (infoflag & InterlaceMode) du >>= 1;
+
+       du <<= 5;
+       temp = (du >> 8) & 0xff;
+       if (du & 0xff) temp++;
+       temp++;
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
+}
+
+/*********************************************/
+/*                  VCLK                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                                               unsigned short rrti)
+{
+       unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+       unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+       unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+       SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
+       SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
+       SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
+}
+
+/*********************************************/
+/*                  FIFO                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                                                       unsigned short mi)
+{
+       unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+       /* disable auto-threshold */
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
+
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
+
+       if (ModeNo <= 0x13)
+               return;
+
+       if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
+               SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
+       }
+}
+
+/*********************************************/
+/*              MODE REGISTERS               */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                                                       unsigned short rrti)
+{
+       unsigned short data = 0, VCLK = 0, index = 0;
+
+       if (ModeNo > 0x13) {
+               index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+               VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+       }
+
+       if (VCLK >= 166) data |= 0x0c;
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
+
+       if (VCLK >= 166)
+               SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
+
+       /* DAC speed */
+       data = 0x03;
+       if (VCLK >= 260)
+               data = 0x00;
+       else if (VCLK >= 160)
+               data = 0x01;
+       else if (VCLK >= 135)
+               data = 0x02;
+
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex, unsigned short rrti)
+{
+       unsigned short data, infoflag = 0, modeflag;
+
+       if (ModeNo <= 0x13)
+               modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+       else {
+               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+               infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+       }
+
+       /* Disable DPMS */
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
+
+       data = 0;
+       if (ModeNo > 0x13) {
+               if (SiS_Pr->SiS_ModeType > ModeEGA) {
+                       data |= 0x02;
+                       data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+               }
+               if (infoflag & InterlaceMode) data |= 0x20;
+       }
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
+
+       data = 0;
+       if (infoflag & InterlaceMode) {
+               /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+               unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
+                       ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
+               unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
+                       ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
+               data = hrs - (hto >> 1) + 3;
+       }
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
+
+       if (modeflag & HalfDCLK)
+               SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
+
+       data = 0;
+       if (modeflag & LineCompareOff)
+               data = 0x08;
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
+
+       if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
+               SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
+
+       SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
+
+       data = 0x60;
+       if (SiS_Pr->SiS_ModeType != ModeText) {
+               data ^= 0x60;
+               if (SiS_Pr->SiS_ModeType != ModeEGA)
+                       data ^= 0xA0;
+       }
+       SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
+
+       SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
+
+       if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
+       else
+               SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
+}
+
+/*********************************************/
+/*                 LOAD DAC                  */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
+               unsigned short shiftflag, unsigned short dl, unsigned short ah,
+               unsigned short al, unsigned short dh)
+{
+       unsigned short d1, d2, d3;
+
+       switch (dl) {
+               case  0:
+                       d1 = dh; d2 = ah; d3 = al;
+                       break;
+               case  1:
+                       d1 = ah; d2 = al; d3 = dh;
+                       break;
+               default:
+                       d1 = al; d2 = dh; d3 = ah;
+       }
+       SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
+       SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
+       SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
+}
+
+static void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
+{
+       unsigned short data, data2, time, i, j, k, m, n, o;
+       unsigned short si, di, bx, sf;
+       unsigned long DACAddr, DACData;
+       const unsigned char *table = NULL;
+
+       if (ModeNo < 0x13)
+               data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
+       else
+               data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+       data &= DACInfoFlag;
+
+       j = time = 64;
+       if (data == 0x00)
+               table = SiS_MDA_DAC;
+       else if (data == 0x08)
+               table = SiS_CGA_DAC;
+       else if (data == 0x10)
+               table = SiS_EGA_DAC;
+       else {
+               j = 16;
+               time = 256;
+               table = SiS_VGA_DAC;
+       }
+
+       DACAddr = SiS_Pr->SiS_P3c8;
+       DACData = SiS_Pr->SiS_P3c9;
+       sf = 0;
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+       SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
+
+       for(i = 0; i < j; i++) {
+               data = table[i];
+               for(k = 0; k < 3; k++) {
+                       data2 = 0;
+                       if (data & 0x01) data2 += 0x2A;
+                       if (data & 0x02) data2 += 0x15;
+                       SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
+                       data >>= 2;
+               }
+       }
+
+       if (time == 256) {
+               for(i = 16; i < 32; i++) {
+                       data = table[i] << sf;
+                       for(k = 0; k < 3; k++)
+                               SiS_SetRegByte(SiS_Pr, DACData, data);
+               }
+               si = 32;
+               for(m = 0; m < 9; m++) {
+                       di = si;
+                       bx = si + 4;
+                       for(n = 0; n < 3; n++) {
+                               for(o = 0; o < 5; o++) {
+                                       SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+                                               table[di], table[bx], table[si]);
+                                       si++;
+                               }
+                               si -= 2;
+                               for(o = 0; o < 3; o++) {
+                                       SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+                                               table[di], table[si], table[bx]);
+                                       si--;
+                               }
+                       }
+               si += 5;
+               }
+       }
+}
+
+/*********************************************/
+/*         SET CRT1 REGISTER GROUP           */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                                       unsigned short ModeIdIndex)
+{
+       unsigned short StandTableIndex, rrti;
+
+       SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+       if (ModeNo <= 0x13)
+               StandTableIndex = 0;
+       else
+               StandTableIndex = 1;
+
+       SiS_ResetSegmentRegisters(SiS_Pr);
+       SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+       SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+       SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+       SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+       SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+       SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+
+       rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+       if (rrti != 0xFFFF) {
+               SiS_SetCRT1Sync(SiS_Pr, rrti);
+               SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+               SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+               SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
+       }
+
+       SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+
+       SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+
+       SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+       SiS_DisplayOn(SiS_Pr);
+}
+
+/*********************************************/
+/*                 SiSSetMode()              */
+/*********************************************/
+
+int
+SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+       unsigned short ModeIdIndex;
+       unsigned long  BaseAddr = SiS_Pr->IOAddress;
+
+       SiSUSB_InitPtr(SiS_Pr);
+       SiSUSBRegInit(SiS_Pr, BaseAddr);
+       SiS_GetSysFlags(SiS_Pr);
+
+       if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
+               return 0;
+
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
+
+       SiSInitPCIetc(SiS_Pr);
+
+       ModeNo &= 0x7f;
+
+       SiS_Pr->SiS_ModeType =
+               SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
+
+       SiS_Pr->SiS_SetFlag = LowModeTests;
+
+       /* Set mode on CRT1 */
+       SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+
+       SiS_HandleCRT1(SiS_Pr);
+
+       SiS_DisplayOn(SiS_Pr);
+       SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+       /* Store mode number */
+       SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
+
+       return 1;
+}
+
+int
+SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
+{
+       unsigned short ModeNo = 0;
+       int i;
+
+       SiSUSB_InitPtr(SiS_Pr);
+
+       if (VModeNo == 0x03) {
+
+               ModeNo = 0x03;
+
+       } else {
+
+               i = 0;
+               do {
+
+                       if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
+                               ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
+                               break;
+                       }
+
+               } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
+
+       }
+
+       if (!ModeNo)
+               return 0;
+
+       return SiSUSBSetMode(SiS_Pr, ModeNo);
+}
+
+#endif /* INCL_SISUSB_CON */
+
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644 (file)
index 0000000..5b11577
--- /dev/null
@@ -0,0 +1,830 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; 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 named License,
+ * * or 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Author:     Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_INIT_H_
+#define _SISUSB_INIT_H_
+
+/* SiS_ModeType */
+#define ModeText               0x00
+#define ModeCGA                        0x01
+#define ModeEGA                        0x02
+#define ModeVGA                        0x03
+#define Mode15Bpp              0x04
+#define Mode16Bpp              0x05
+#define Mode24Bpp              0x06
+#define Mode32Bpp              0x07
+
+#define ModeTypeMask           0x07
+#define IsTextMode             0x07
+
+#define DACInfoFlag            0x0018
+#define MemoryInfoFlag         0x01E0
+#define MemorySizeShift                5
+
+/* modeflag */
+#define Charx8Dot              0x0200
+#define LineCompareOff         0x0400
+#define CRT2Mode               0x0800
+#define HalfDCLK               0x1000
+#define NoSupportSimuTV                0x2000
+#define NoSupportLCDScale      0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode         0x8000
+
+/* Infoflag */
+#define SupportTV              0x0008
+#define SupportTV1024          0x0800
+#define SupportCHTV            0x0800
+#define Support64048060Hz      0x0800  /* Special for 640x480 LCD */
+#define SupportHiVision                0x0010
+#define SupportYPbPr750p       0x1000
+#define SupportLCD             0x0020
+#define SupportRAMDAC2         0x0040  /* All           (<= 100Mhz) */
+#define SupportRAMDAC2_135     0x0100  /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162     0x0200  /* B, C          (<= 162Mhz) */
+#define SupportRAMDAC2_202     0x0400  /* C             (<= 202Mhz) */
+#define InterlaceMode          0x0080
+#define SyncPP                 0x0000
+#define SyncPN                 0x4000
+#define SyncNP                 0x8000
+#define SyncNN                 0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2                0x0001
+#define LowModeTests           0x0002
+#define LCDVESATiming          0x0008
+#define EnableLVDSDDA          0x0010
+#define SetDispDevSwitchFlag   0x0020
+#define CheckWinDos            0x0040
+#define SetDOSMode             0x0080
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200         0
+#define SIS_RI_320x240         1
+#define SIS_RI_320x400         2
+#define SIS_RI_400x300         3
+#define SIS_RI_512x384         4
+#define SIS_RI_640x400         5
+#define SIS_RI_640x480         6
+#define SIS_RI_800x600         7
+#define SIS_RI_1024x768                8
+#define SIS_RI_1280x1024       9
+#define SIS_RI_1600x1200       10
+#define SIS_RI_1920x1440       11
+#define SIS_RI_2048x1536       12
+#define SIS_RI_720x480         13
+#define SIS_RI_720x576         14
+#define SIS_RI_1280x960                15
+#define SIS_RI_800x480         16
+#define SIS_RI_1024x576                17
+#define SIS_RI_1280x720                18
+#define SIS_RI_856x480         19
+#define SIS_RI_1280x768                20
+#define SIS_RI_1400x1050       21
+#define SIS_RI_1152x864                22  /* Up to here SiS conforming */
+#define SIS_RI_848x480         23
+#define SIS_RI_1360x768                24
+#define SIS_RI_1024x600                25
+#define SIS_RI_1152x768                26
+#define SIS_RI_768x576         27
+#define SIS_RI_1360x1024       28
+#define SIS_RI_1680x1050       29
+#define SIS_RI_1280x800                30
+#define SIS_RI_1920x1080       31
+#define SIS_RI_960x540         32
+#define SIS_RI_960x600         33
+
+#define SIS_VIDEO_CAPTURE      0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK     0x02 - 0x30
+#define SIS_CRT2_PORT_04       0x04 - 0x30
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[]   = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[]   = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_400x300[]   = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[]   = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[]   = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[]   = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[]   = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[]   = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[]   = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[]   = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[]   = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[]   = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[]   = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[]   = {0x1d, 0x1e, 0x00, 0x1f};
+static const unsigned short ModeIndex_960x600[]   = {0x20, 0x21, 0x00, 0x22};
+static const unsigned short ModeIndex_1024x768[]  = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[]  = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1152x864[]  = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_1280x720[]  = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x768[]  = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+
+static const unsigned char SiS_MDA_DAC[] =
+{
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+        0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+        0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+        0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+        0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+        0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+        0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] =
+{
+       0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+       0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+       0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+       0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+       0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+       0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+       0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+       0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+       0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+       0x0B,0x0C,0x0D,0x0F,0x10
+};
+
+static const struct SiS_St SiSUSB_SModeIDTable[] =
+{
+       {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+       {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
+{
+       { 640,400},
+       { 640,350},
+       { 720,400},
+       { 720,350},
+       { 640,480}
+};
+
+static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
+{
+       {  320, 200, 8, 8},   /* 0x00 */
+       {  320, 240, 8, 8},   /* 0x01 */
+       {  320, 400, 8, 8},   /* 0x02 */
+       {  400, 300, 8, 8},   /* 0x03 */
+       {  512, 384, 8, 8},   /* 0x04 */
+       {  640, 400, 8,16},   /* 0x05 */
+       {  640, 480, 8,16},   /* 0x06 */
+       {  800, 600, 8,16},   /* 0x07 */
+       { 1024, 768, 8,16},   /* 0x08 */
+       { 1280,1024, 8,16},   /* 0x09 */
+       { 1600,1200, 8,16},   /* 0x0a */
+       { 1920,1440, 8,16},   /* 0x0b */
+       { 2048,1536, 8,16},   /* 0x0c */
+       {  720, 480, 8,16},   /* 0x0d */
+       {  720, 576, 8,16},   /* 0x0e */
+       { 1280, 960, 8,16},   /* 0x0f */
+       {  800, 480, 8,16},   /* 0x10 */
+       { 1024, 576, 8,16},   /* 0x11 */
+       { 1280, 720, 8,16},   /* 0x12 */
+       {  856, 480, 8,16},   /* 0x13 */
+       { 1280, 768, 8,16},   /* 0x14 */
+       { 1400,1050, 8,16},   /* 0x15 */
+       { 1152, 864, 8,16},   /* 0x16 */
+       {  848, 480, 8,16},   /* 0x17 */
+       { 1360, 768, 8,16},   /* 0x18 */
+       { 1024, 600, 8,16},   /* 0x19 */
+       { 1152, 768, 8,16},   /* 0x1a */
+       {  768, 576, 8,16},   /* 0x1b */
+       { 1360,1024, 8,16},   /* 0x1c */
+       { 1680,1050, 8,16},   /* 0x1d */
+       { 1280, 800, 8,16},   /* 0x1e */
+       { 1920,1080, 8,16},   /* 0x1f */
+       {  960, 540, 8,16},   /* 0x20 */
+       {  960, 600, 8,16}    /* 0x21 */
+};
+
+static const struct SiS_StandTable SiSUSB_StandTable[] =
+{
+       /* MD_3_400 - mode 0x03 - 400 */
+       {
+               0x50,0x18,0x10,0x1000,
+               { 0x00,0x03,0x00,0x02 },
+               0x67,
+               { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+                 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+                 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+                 0xff },
+               { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+                 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+                 0x0c,0x00,0x0f,0x08 },
+               { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
+       },
+       /* Generic for VGA and higher */
+       {
+               0x00,0x00,0x00,0x0000,
+               { 0x01,0x0f,0x00,0x0e },
+               0x23,
+               { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+                 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+                 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+                 0xff },
+               { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+                 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+                 0x01,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
+       }
+};
+
+static const struct SiS_Ext SiSUSB_EModeIDTable[] =
+{
+       {0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+       {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+       {0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+       {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+       {0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+       {0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+       {0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+       {0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+       {0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+       {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+       {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
+       {0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
+       {0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+       {0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+       {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+       {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
+       {0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8  */
+       {0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8  */
+       {0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8  */
+       {0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
+       {0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
+       {0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
+       {0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8  */
+       {0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
+       {0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
+       {0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+       {0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+       {0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+       {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+       {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
+       {0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
+       {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
+       {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
+       {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
+       {0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
+       {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
+       {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
+       {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
+       {0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
+       {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
+       {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
+       {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
+       {0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
+       {0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1},
+       {0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1},
+       {0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
+       {0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1},
+       {0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1},
+       {0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
+       {0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
+       {0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
+       {0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
+       {0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1},
+       {0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1},
+       {0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
+       {0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1},
+       {0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1},
+       {0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
+       {0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1},
+       {0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1},
+       {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
+       {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+       {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+       {0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const struct SiS_Ext2 SiSUSB_RefIndex[] =
+{
+       {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
+       {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
+       {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
+       {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
+       {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
+       {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
+       {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
+       {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
+       {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
+       {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
+       {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
+       {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
+       {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
+       {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
+       {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
+       {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
+       {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
+       {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
+       {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
+       {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
+       {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
+       {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
+       {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
+       {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
+       {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
+       {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
+       {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
+       {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
+       {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
+       {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
+       {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
+       {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
+       {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
+       {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
+       {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
+       {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
+       {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
+       {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
+       {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
+       {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
+       {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi  */
+       {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz   */
+       {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi  */
+       {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz   */
+       {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz   */
+       {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
+       {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
+       {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
+       {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
+       {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
+       {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
+       {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz  */
+       {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz  */
+       {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz  */
+       {0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
+   0x00}}, /* 0x0 */
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}, /* 0x1 */
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+   0x01}}, /* 0x2 */
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+   0x01}}, /* 0x3 */
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+   0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
+   0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+   0x00}}, /* 0x6 */
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+   0x00}}, /* 0x7 */
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+   0x00}}, /* 0x8 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+   0x61}}, /* 0x9 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
+   0x61}}, /* 0xa */
+ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
+   0x61}}, /* 0xb */
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
+   0x00}}, /* 0xc */
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+   0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+   0x01}}, /* 0xd */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+   0x01}}, /* 0xe */
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+   0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+   0x01}}, /* 0xf */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+   0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+   0x01}}, /* 0x10 */
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+   0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+   0x01}}, /* 0x11 */
+ {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
+   0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
+   0x61}}, /* 0x12 */
+ {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
+   0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
+   0x61}}, /* 0x13 */
+ {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
+   0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
+   0x61}}, /* 0x14 */
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+   0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+   0x00}}, /* 0x15 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}}, /* 0x16 */
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}}, /* 0x17 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+   0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+   0x01}}, /* 0x18 */
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+   0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+   0x01}}, /* 0x19 */
+ {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
+   0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
+   0x62}}, /* 0x1a */
+ {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
+   0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
+   0x62}}, /* 0x1b */
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+   0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+   0x00}}, /* 0x1c */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}}, /* 0x1d */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}}, /* 0x1e */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+   0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+   0x01}}, /* 0x1f */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x20 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x21 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x22 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x23 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x24 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x25 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x26 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x27 */
+ {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
+   0x63}}, /* 0x28 */
+ {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
+   0x63}}, /* 0x29 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2a */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2b */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2c */
+ {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
+   0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
+   0x44}}, /* 0x2d */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
+   0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
+   0x44}}, /* 0x2e */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
+   0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
+   0x44}}, /* 0x2f */
+ {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
+   0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
+   0x44}}, /* 0x30 */
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+   0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+   0x00}}, /* 0x31 */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
+   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+   0x01}}, /* 0x32 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+   0x01}}, /* 0x33 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+   0x01}}, /* 0x34 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+   0x01}}, /* 0x35 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+   0x01}}, /* 0x36 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
+   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+   0x01}}, /* 0x37 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x38 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x39 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+   0x01}}, /* 0x3a */
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
+   0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+   0x01}}, /* 0x3b */
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+   0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}}, /* 0x3d */
+ {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
+   0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
+   0x00}}, /* 0x3e */
+ {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
+   0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
+   0x00}}, /* 0x3f */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+   0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+   0x01}},  /* 0x40 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}},  /* 0x41 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
+   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+   0x01}},  /* 0x42 */
+ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
+   0x00}},  /* 0x43 */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
+   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+   0x01}},  /* 0x44 */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x45 */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
+   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+   0x00}},  /* 0x46 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x47 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
+   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+   0x00}},  /* 0x48 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
+   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+   0x01}},  /* 0x49 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
+   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+   0x01}},  /* 0x4a */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
+   0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
+   0x00}},  /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
+   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+   0x01}},  /* 0x4c */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}},  /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
+   0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+   0x61}},  /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
+   0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+   0x41}},  /* 0x52 */
+ {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
+   0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
+   0x01}},  /* 0x53 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
+   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+   0x41}}   /* 0x54 */
+};
+
+static struct SiS_VCLKData SiSUSB_VCLKData[] =
+{
+       { 0x1b,0xe1, 25}, /* 0x00 */
+       { 0x4e,0xe4, 28}, /* 0x01 */
+       { 0x57,0xe4, 31}, /* 0x02 */
+       { 0xc3,0xc8, 36}, /* 0x03 */
+       { 0x42,0xe2, 40}, /* 0x04 */
+       { 0xfe,0xcd, 43}, /* 0x05 */
+       { 0x5d,0xc4, 44}, /* 0x06 */
+       { 0x52,0xe2, 49}, /* 0x07 */
+       { 0x53,0xe2, 50}, /* 0x08 */
+       { 0x74,0x67, 52}, /* 0x09 */
+       { 0x6d,0x66, 56}, /* 0x0a */
+       { 0x5a,0x64, 65}, /* 0x0b */
+       { 0x46,0x44, 67}, /* 0x0c */
+       { 0xb1,0x46, 68}, /* 0x0d */
+       { 0xd3,0x4a, 72}, /* 0x0e */
+       { 0x29,0x61, 75}, /* 0x0f */
+       { 0x6e,0x46, 76}, /* 0x10 */
+       { 0x2b,0x61, 78}, /* 0x11 */
+       { 0x31,0x42, 79}, /* 0x12 */
+       { 0xab,0x44, 83}, /* 0x13 */
+       { 0x46,0x25, 84}, /* 0x14 */
+       { 0x78,0x29, 86}, /* 0x15 */
+       { 0x62,0x44, 94}, /* 0x16 */
+       { 0x2b,0x41,104}, /* 0x17 */
+       { 0x3a,0x23,105}, /* 0x18 */
+       { 0x70,0x44,108}, /* 0x19 */
+       { 0x3c,0x23,109}, /* 0x1a */
+       { 0x5e,0x43,113}, /* 0x1b */
+       { 0xbc,0x44,116}, /* 0x1c */
+       { 0xe0,0x46,132}, /* 0x1d */
+       { 0x54,0x42,135}, /* 0x1e */
+       { 0xea,0x2a,139}, /* 0x1f */
+       { 0x41,0x22,157}, /* 0x20 */
+       { 0x70,0x24,162}, /* 0x21 */
+       { 0x30,0x21,175}, /* 0x22 */
+       { 0x4e,0x22,189}, /* 0x23 */
+       { 0xde,0x26,194}, /* 0x24 */
+       { 0x62,0x06,202}, /* 0x25 */
+       { 0x3f,0x03,229}, /* 0x26 */
+       { 0xb8,0x06,234}, /* 0x27 */
+       { 0x34,0x02,253}, /* 0x28 */
+       { 0x58,0x04,255}, /* 0x29 */
+       { 0x24,0x01,265}, /* 0x2a */
+       { 0x9b,0x02,267}, /* 0x2b */
+       { 0x70,0x05,270}, /* 0x2c */
+       { 0x25,0x01,272}, /* 0x2d */
+       { 0x9c,0x02,277}, /* 0x2e */
+       { 0x27,0x01,286}, /* 0x2f */
+       { 0x3c,0x02,291}, /* 0x30 */
+       { 0xef,0x0a,292}, /* 0x31 */
+       { 0xf6,0x0a,310}, /* 0x32 */
+       { 0x95,0x01,315}, /* 0x33 */
+       { 0xf0,0x09,324}, /* 0x34 */
+       { 0xfe,0x0a,331}, /* 0x35 */
+       { 0xf3,0x09,332}, /* 0x36 */
+       { 0xea,0x08,340}, /* 0x37 */
+       { 0xe8,0x07,376}, /* 0x38 */
+       { 0xde,0x06,389}, /* 0x39 */
+       { 0x52,0x2a, 54}, /* 0x3a 301 TV */
+       { 0x52,0x6a, 27}, /* 0x3b 301 TV */
+       { 0x62,0x24, 70}, /* 0x3c 301 TV */
+       { 0x62,0x64, 70}, /* 0x3d 301 TV */
+       { 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+       { 0x20,0x26, 33}, /* 0x3f 301 TV */
+       { 0x31,0xc2, 39}, /* 0x40 */
+       { 0x60,0x36, 30}, /* 0x41 Chrontel */
+       { 0x40,0x4a, 28}, /* 0x42 Chrontel */
+       { 0x9f,0x46, 44}, /* 0x43 Chrontel */
+       { 0x97,0x2c, 26}, /* 0x44 */
+       { 0x44,0xe4, 25}, /* 0x45 Chrontel */
+       { 0x7e,0x32, 47}, /* 0x46 Chrontel */
+       { 0x8a,0x24, 31}, /* 0x47 Chrontel */
+       { 0x97,0x2c, 26}, /* 0x48 Chrontel */
+       { 0xce,0x3c, 39}, /* 0x49 */
+       { 0x52,0x4a, 36}, /* 0x4a Chrontel */
+       { 0x34,0x61, 95}, /* 0x4b */
+       { 0x78,0x27,108}, /* 0x4c - was 102 */
+       { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+       { 0x41,0x4e, 21}, /* 0x4e */
+       { 0xa1,0x4a, 29}, /* 0x4f Chrontel */
+       { 0x19,0x42, 42}, /* 0x50 */
+       { 0x54,0x46, 58}, /* 0x51 Chrontel */
+       { 0x25,0x42, 61}, /* 0x52 */
+       { 0x44,0x44, 66}, /* 0x53 Chrontel */
+       { 0x3a,0x62, 70}, /* 0x54 Chrontel */
+       { 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+       { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+       { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+       { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+       { 0x52,0x07,149}, /* 0x59 1280x960-85 */
+       { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+       { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+       { 0x45,0x25, 83}, /* 0x5c 1280x800  */
+       { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+       { 0x70,0x24,162}, /* 0x5e 1600x1200 */
+       { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+       { 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+       { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+       {    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+       { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+       { 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+       { 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+       { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+       { 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+       { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+       { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+       { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+       { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+       { 0x45,0x25, 83}, /* 0x6c 1280x800 */
+       { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+       { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+       { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+       { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+       { 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
+};
+
+void           SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
+unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
+int            SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+int            SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern int     sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+extern int     sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+extern int     sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+                                       u8 index, u8 data);
+extern int     sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+                                       u8 index, u8 *data);
+extern int     sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+                                       u8 idx, u8 myand, u8 myor);
+extern int     sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+                                       u8 index, u8 myor);
+extern int     sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+                                       u8 idx, u8 myand);
+
+#endif
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644 (file)
index 0000000..94edd47
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; 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 named License,
+ * * or 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Author:     Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_STRUCT_H_
+#define _SISUSB_STRUCT_H_
+
+struct SiS_St {
+       unsigned char   St_ModeID;
+       unsigned short  St_ModeFlag;
+       unsigned char   St_StTableIndex;
+       unsigned char   St_CRT2CRTC;
+       unsigned char   St_ResInfo;
+       unsigned char   VB_StTVFlickerIndex;
+       unsigned char   VB_StTVEdgeIndex;
+       unsigned char   VB_StTVYFilterIndex;
+       unsigned char   St_PDC;
+};
+
+struct SiS_StandTable
+{
+       unsigned char   CRT_COLS;
+       unsigned char   ROWS;
+       unsigned char   CHAR_HEIGHT;
+       unsigned short  CRT_LEN;
+       unsigned char   SR[4];
+       unsigned char   MISC;
+       unsigned char   CRTC[0x19];
+       unsigned char   ATTR[0x14];
+       unsigned char   GRC[9];
+};
+
+struct SiS_StResInfo_S {
+       unsigned short  HTotal;
+       unsigned short  VTotal;
+};
+
+struct SiS_Ext
+{
+       unsigned char   Ext_ModeID;
+       unsigned short  Ext_ModeFlag;
+       unsigned short  Ext_VESAID;
+       unsigned char   Ext_RESINFO;
+       unsigned char   VB_ExtTVFlickerIndex;
+       unsigned char   VB_ExtTVEdgeIndex;
+       unsigned char   VB_ExtTVYFilterIndex;
+       unsigned char   VB_ExtTVYFilterIndexROM661;
+       unsigned char   REFindex;
+       char            ROMMODEIDX661;
+};
+
+struct SiS_Ext2
+{
+       unsigned short  Ext_InfoFlag;
+       unsigned char   Ext_CRT1CRTC;
+       unsigned char   Ext_CRTVCLK;
+       unsigned char   Ext_CRT2CRTC;
+       unsigned char   Ext_CRT2CRTC_NS;
+       unsigned char   ModeID;
+       unsigned short  XRes;
+       unsigned short  YRes;
+       unsigned char   Ext_PDC;
+       unsigned char   Ext_FakeCRT2CRTC;
+       unsigned char   Ext_FakeCRT2Clk;
+};
+
+struct SiS_CRT1Table
+{
+       unsigned char   CR[17];
+};
+
+struct SiS_VCLKData
+{
+       unsigned char   SR2B,SR2C;
+       unsigned short  CLOCK;
+};
+
+struct SiS_ModeResInfo
+{
+       unsigned short  HTotal;
+       unsigned short  VTotal;
+       unsigned char   XChar;
+       unsigned char   YChar;
+};
+
+struct SiS_Private
+{
+       void *sisusb;
+
+       unsigned long IOAddress;
+
+       unsigned long SiS_P3c4;
+       unsigned long SiS_P3d4;
+       unsigned long SiS_P3c0;
+       unsigned long SiS_P3ce;
+       unsigned long SiS_P3c2;
+       unsigned long SiS_P3ca;
+       unsigned long SiS_P3c6;
+       unsigned long SiS_P3c7;
+       unsigned long SiS_P3c8;
+       unsigned long SiS_P3c9;
+       unsigned long SiS_P3cb;
+       unsigned long SiS_P3cc;
+       unsigned long SiS_P3cd;
+       unsigned long SiS_P3da;
+       unsigned long SiS_Part1Port;
+
+       unsigned char   SiS_MyCR63;
+       unsigned short  SiS_CRT1Mode;
+       unsigned short  SiS_ModeType;
+       unsigned short  SiS_SetFlag;
+
+       const struct SiS_StandTable     *SiS_StandTable;
+       const struct SiS_St             *SiS_SModeIDTable;
+       const struct SiS_Ext            *SiS_EModeIDTable;
+       const struct SiS_Ext2           *SiS_RefIndex;
+       const struct SiS_CRT1Table      *SiS_CRT1Table;
+       struct SiS_VCLKData             *SiS_VCLKData;
+       const struct SiS_ModeResInfo    *SiS_ModeResInfo;
+};
+
+#endif
+
index faa74436de52cdf539a14f53c5e950d7e1c06834..03fb70ef2eb3ec14e60c5f32188a24d78d5295b4 100644 (file)
@@ -3,8 +3,8 @@
 /*
  *     uss720.c  --  USS720 USB Parport Cable.
  *
- *     Copyright (C) 1999
- *         Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *     Copyright (C) 1999, 2005
+ *         Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
  *  Based on parport_pc.c
  *
  *  History:
- *   0.1  04.08.99  Created
- *   0.2  07.08.99  Some fixes mainly suggested by Tim Waugh
- *                 Interrupt handling currently disabled because
- *                 usb_request_irq crashes somewhere within ohci.c
- *                 for no apparent reason (that is for me, anyway)
- *                 ECP currently untested
- *   0.3  10.08.99  fixing merge errors
- *   0.4  13.08.99  Added Vendor/Product ID of Brad Hard's cable
- *   0.5  20.09.99  usb_control_msg wrapper used
- *        Nov01.00  usb_device_table support by Adam J. Richter
- *        08.04.01  Identify version on module load.  gb
+ *   0.1  04.08.1999  Created
+ *   0.2  07.08.1999  Some fixes mainly suggested by Tim Waugh
+ *                   Interrupt handling currently disabled because
+ *                   usb_request_irq crashes somewhere within ohci.c
+ *                   for no apparent reason (that is for me, anyway)
+ *                   ECP currently untested
+ *   0.3  10.08.1999  fixing merge errors
+ *   0.4  13.08.1999  Added Vendor/Product ID of Brad Hard's cable
+ *   0.5  20.09.1999  usb_control_msg wrapper used
+ *        Nov01.2000  usb_device_table support by Adam J. Richter
+ *        08.04.2001  Identify version on module load.  gb
+ *   0.6  02.09.2005  Fix "scheduling in interrupt" problem by making save/restore
+ *                    context asynchronous
  *
  */
 
 /*****************************************************************************/
 
+#define DEBUG
+
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <linux/parport.h>
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.5"
-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_VERSION "v0.6"
+#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
 #define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
 
 /* --------------------------------------------------------------------- */
 
 struct parport_uss720_private {
        struct usb_device *usbdev;
-       void *irqhandle;
-       unsigned int irqpipe;
-       unsigned char reg[7];  /* USB registers */
+       struct parport *pp;
+       struct kref ref_count;
+       __u8 reg[7];  /* USB registers */
+       struct list_head asynclist;
+       spinlock_t asynclock;
+};
+
+struct uss720_async_request {
+       struct parport_uss720_private *priv;
+       struct kref ref_count;
+       struct list_head asynclist;
+       struct completion compl;
+       struct urb *urb;
+       struct usb_ctrlrequest dr;
+       __u8 reg[7];
 };
 
 /* --------------------------------------------------------------------- */
 
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+static void destroy_priv(struct kref *kref)
 {
-       struct parport_uss720_private *priv = pp->private_data;
-       struct usb_device *usbdev = priv->usbdev;
-       static const unsigned char regindex[9] = {
-               4, 0, 1, 5, 5, 0, 2, 3, 6
-       };
-       int ret;
+       struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
 
-       if (!usbdev)
-               return -1;
-       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
-       if (ret != 7) {
-               printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
-                      (unsigned int)reg, ret);
-               ret = -1;
-       } else {
+       usb_put_dev(priv->usbdev);
+       kfree(priv);
+       dbg("destroying priv datastructure");
+}
+
+static void destroy_async(struct kref *kref)
+{
+       struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
+       struct parport_uss720_private *priv = rq->priv;
+       unsigned long flags;
+
+       if (likely(rq->urb))
+               usb_free_urb(rq->urb);
+       spin_lock_irqsave(&priv->asynclock, flags);
+       list_del_init(&rq->asynclist);
+       spin_unlock_irqrestore(&priv->asynclock, flags);
+       kfree(rq);
+       kref_put(&priv->ref_count, destroy_priv);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+       struct uss720_async_request *rq;
+       struct parport *pp;
+       struct parport_uss720_private *priv;
+
+       rq = urb->context;
+       priv = rq->priv;
+       pp = priv->pp;
+       if (urb->status) {
+               err("async_complete: urb error %d", urb->status);
+       } else if (rq->dr.bRequest == 3) {
+               memcpy(priv->reg, rq->reg, sizeof(priv->reg));
 #if 0
-               printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
-                      (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
-                      (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
-                      (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
+               dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
+                   (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
+                   (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
+                   (unsigned int)priv->reg[6]);
 #endif
                /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
-               if (priv->reg[2] & priv->reg[1] & 0x10)
+               if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
                        parport_generic_irq(0, pp, NULL);
-               ret = 0;
        }
-       if (val)
-               *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
-       return ret;
+       complete(&rq->compl);
+       kref_put(&rq->ref_count, destroy_async);
 }
 
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
+                                                        __u8 request, __u8 requesttype, __u16 value, __u16 index,
+                                                        unsigned int mem_flags)
 {
-       struct parport_uss720_private *priv = pp->private_data;
-       struct usb_device *usbdev = priv->usbdev;
+       struct usb_device *usbdev;
+       struct uss720_async_request *rq;
+       unsigned long flags;
        int ret;
 
+       if (!priv)
+               return NULL;
+       usbdev = priv->usbdev;
        if (!usbdev)
-               return -1;
-       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
-       if (ret) {
-               printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
-                      (unsigned int)reg, (unsigned int)val, ret);
-       } else {
-#if 0
-               printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 
-                      (unsigned int)reg, (unsigned int)val);
-#endif
+               return NULL;
+       rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
+       if (!rq) {
+               err("submit_async_request out of memory");
+               return NULL;
+       }
+       kref_init(&rq->ref_count);
+       INIT_LIST_HEAD(&rq->asynclist);
+       init_completion(&rq->compl);
+       kref_get(&priv->ref_count);
+       rq->priv = priv;
+       rq->urb = usb_alloc_urb(0, mem_flags);
+       if (!rq->urb) {
+               kref_put(&rq->ref_count, destroy_async);
+               err("submit_async_request out of memory");
+               return NULL;
+       }
+       rq->dr.bRequestType = requesttype;
+       rq->dr.bRequest = request;
+       rq->dr.wValue = cpu_to_le16(value);
+       rq->dr.wIndex = cpu_to_le16(index);
+       rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
+       usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
+                            (unsigned char *)&rq->dr,
+                            (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
+       /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
+       spin_lock_irqsave(&priv->asynclock, flags);
+       list_add_tail(&rq->asynclist, &priv->asynclist);
+       spin_unlock_irqrestore(&priv->asynclock, flags);
+       ret = usb_submit_urb(rq->urb, mem_flags);
+       if (!ret) {
+               kref_get(&rq->ref_count);
+               return rq;
        }
+       kref_put(&rq->ref_count, destroy_async);
+       err("submit_async_request submit_urb failed with %d", ret);
+       return NULL;
+}
+
+static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
+{
+       struct uss720_async_request *rq;
+       unsigned long flags;
+       unsigned int ret = 0;
+
+       spin_lock_irqsave(&priv->asynclock, flags);
+       list_for_each_entry(rq, &priv->asynclist, asynclist) {
+               usb_unlink_urb(rq->urb);
+               ret++;
+       }
+       spin_unlock_irqrestore(&priv->asynclock, flags);
        return ret;
 }
 
 /* --------------------------------------------------------------------- */
 
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+{
+       struct parport_uss720_private *priv;
+       struct uss720_async_request *rq;
+       static const unsigned char regindex[9] = {
+               4, 0, 1, 5, 5, 0, 2, 3, 6
+       };
+       int ret;
+
+       if (!pp)
+               return -EIO;
+       priv = pp->private_data;
+       rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
+       if (!rq) {
+               err("get_1284_register(%u) failed", (unsigned int)reg);
+               return -EIO;
+       }
+       if (!val) {
+               kref_put(&rq->ref_count, destroy_async);
+               return 0;
+       }
+       if (wait_for_completion_timeout(&rq->compl, HZ)) {
+               ret = rq->urb->status;
+               *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
+               if (ret)
+                       warn("get_1284_register: usb error %d", ret);
+               kref_put(&rq->ref_count, destroy_async);
+               return ret;
+       }
+       warn("get_1284_register timeout");
+       kill_all_async_requests_priv(priv);
+       return -EIO;
+}
+
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
+{
+       struct parport_uss720_private *priv;
+       struct uss720_async_request *rq;
+
+       if (!pp)
+               return -EIO;
+       priv = pp->private_data;
+       rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
+       if (!rq) {
+               err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
+               return -EIO;
+       }
+       kref_put(&rq->ref_count, destroy_async);
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
 /* ECR modes */
 #define ECR_SPP 00
 #define ECR_PS2 01
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
 {
        struct parport_uss720_private *priv = pp->private_data;
        int mode;
+       __u8 reg;
 
-       if (get_1284_register(pp, 6, NULL))
+       if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
                return -EIO;
        /* Bits <7:5> contain the mode. */
        mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
                case ECR_ECP: /* ECP Parallel Port mode */
                        /* Poll slowly. */
                        for (;;) {
-                               if (get_1284_register(pp, 6, NULL))
+                               if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
                                        return -EIO;
                                if (priv->reg[2] & 0x01)
                                        break;
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
                }
        }
        /* Set the mode. */
-       if (set_1284_register(pp, 6, m << 5))
+       if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
+               return -EIO;
+       if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
                return -EIO;
        return 0;
 }
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
 {
        unsigned char stat;
 
-       if (get_1284_register(pp, 1, &stat))
+       if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
                return 1;
        return stat & 1;
 }
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
 
 static void parport_uss720_write_data(struct parport *pp, unsigned char d)
 {
-       set_1284_register(pp, 0, d);
+       set_1284_register(pp, 0, d, GFP_KERNEL);
 }
 
 static unsigned char parport_uss720_read_data(struct parport *pp)
 {
        unsigned char ret;
 
-       if (get_1284_register(pp, 0, &ret))
+       if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
                return 0;
        return ret;
 }
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
        struct parport_uss720_private *priv = pp->private_data; 
 
        d = (d & 0xf) | (priv->reg[1] & 0xf0);
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return;
        priv->reg[1] = d;
 }
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
        mask &= 0x0f;
        val &= 0x0f;
        d = (priv->reg[1] & (~mask)) ^ val;
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return 0;
        priv->reg[1] = d;
        return d & 0xf;
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
 {
        unsigned char ret;
 
-       if (get_1284_register(pp, 1, &ret))
+       if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
                return 0;
        return ret & 0xf8;
 }
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
        unsigned char d;
 
        d = priv->reg[1] & ~0x10;
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return;
        priv->reg[1] = d;
 }
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
        unsigned char d;
 
        d = priv->reg[1] | 0x10;
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return;
        priv->reg[1] = d;
 }
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
        unsigned char d;
 
        d = priv->reg[1] & ~0x20;
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return;
        priv->reg[1] = d;
 }
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
        unsigned char d;
 
        d = priv->reg[1] | 0x20;
-       if (set_1284_register(pp, 2, d))
+       if (set_1284_register(pp, 2, d, GFP_KERNEL))
                return;
        priv->reg[1] = d;
 }
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
 {
        struct parport_uss720_private *priv = pp->private_data; 
 
-       if (get_1284_register(pp, 2, NULL))
+#if 0
+       if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
                return;
+#endif
        s->u.pc.ctr = priv->reg[1];
        s->u.pc.ecr = priv->reg[2];
 }
 
 static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
 {
-       set_1284_register(pp, 2, s->u.pc.ctr);
-       set_1284_register(pp, 6, s->u.pc.ecr);
-       get_1284_register(pp, 2, NULL);
+       struct parport_uss720_private *priv = pp->private_data;
+
+       set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
+       set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
+       get_1284_register(pp, 2, NULL, GFP_ATOMIC);
+       priv->reg[1] = s->u.pc.ctr;
+       priv->reg[2] = s->u.pc.ecr;
 }
 
 static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
        if (change_mode(pp, ECR_EPP))
                return 0;
        for (; got < length; got++) {
-               if (get_1284_register(pp, 4, (char *)buf))
+               if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
                        break;
                buf++;
                if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
        if (change_mode(pp, ECR_EPP))
                return 0;
        for (; written < length; written++) {
-               if (set_1284_register(pp, 4, (char *)buf))
+               if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
                        break;
                ((char*)buf)++;
-               if (get_1284_register(pp, 1, NULL))
+               if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
                        break;
                if (priv->reg[0] & 0x01) {
                        clear_epp_timeout(pp);
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
        if (change_mode(pp, ECR_EPP))
                return 0;
        for (; got < length; got++) {
-               if (get_1284_register(pp, 3, (char *)buf))
+               if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
                        break;
                buf++;
                if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
        if (change_mode(pp, ECR_EPP))
                return 0;
        for (; written < length; written++) {
-               if (set_1284_register(pp, 3, *(char *)buf))
+               if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
                        break;
                buf++;
-               if (get_1284_register(pp, 1, NULL))
+               if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
                        break;
                if (priv->reg[0] & 0x01) {
                        clear_epp_timeout(pp);
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
        if (change_mode(pp, ECR_ECP))
                return 0;
        for (; written < len; written++) {
-               if (set_1284_register(pp, 5, *(char *)buffer))
+               if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
                        break;
                buffer++;
        }
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
 static int uss720_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
 {
-       struct usb_device *usbdev = interface_to_usbdev(intf);
+       struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
        struct usb_host_interface *interface;
        struct usb_host_endpoint *endpoint;
        struct parport_uss720_private *priv;
        struct parport *pp;
+       unsigned char reg;
        int i;
 
-       printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
-              le16_to_cpu(usbdev->descriptor.idVendor),
-              le16_to_cpu(usbdev->descriptor.idProduct));
+       dbg("probe: vendor id 0x%x, device id 0x%x\n",
+           le16_to_cpu(usbdev->descriptor.idVendor),
+           le16_to_cpu(usbdev->descriptor.idProduct));
 
        /* our known interfaces have 3 alternate settings */
-       if (intf->num_altsetting != 3)
+       if (intf->num_altsetting != 3) {
+               usb_put_dev(usbdev);
                return -ENODEV;
-
+       }
        i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
-       printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+       dbg("set inteface result %d", i);
 
        interface = intf->cur_altsetting;
 
        /*
         * Allocate parport interface 
         */
-       printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
-
-       if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+       if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+               usb_put_dev(usbdev);
                return -ENOMEM;
+       }
+       priv->pp = NULL;
+       priv->usbdev = usbdev;
+       kref_init(&priv->ref_count);
+       spin_lock_init(&priv->asynclock);
+       INIT_LIST_HEAD(&priv->asynclist);
        if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
-               printk(KERN_WARNING "usb-uss720: could not register parport\n");
+               warn("could not register parport");
                goto probe_abort;
        }
 
+       priv->pp = pp;
        pp->private_data = priv;
-       priv->usbdev = usbdev;
        pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
 
        /* set the USS720 control register to manual mode, no ECP compression, enable all ints */
-       set_1284_register(pp, 7, 0x00);
-       set_1284_register(pp, 6, 0x30);  /* PS/2 mode */
-       set_1284_register(pp, 2, 0x0c);
+       set_1284_register(pp, 7, 0x00, GFP_KERNEL);
+       set_1284_register(pp, 6, 0x30, GFP_KERNEL);  /* PS/2 mode */
+       set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
        /* debugging */
-       get_1284_register(pp, 0, NULL);
-       printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
-              priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+       get_1284_register(pp, 0, &reg, GFP_KERNEL);
+       dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
+           priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
 
        endpoint = &interface->endpoint[2];
-       printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
-#if 0
-       priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
-       i = usb_request_irq(usbdev, priv->irqpipe,
-                                 uss720_irq, endpoint->bInterval,
-                                 pp, &priv->irqhandle);
-       if (i) {
-               printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
-               goto probe_abort_port;
-       }
-#endif
+       dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
        parport_announce_port(pp);
 
-       usb_set_intfdata (intf, pp);
+       usb_set_intfdata(intf, pp);
        return 0;
 
-#if 0
-probe_abort_port:
-       parport_put_port(pp);
-#endif
 probe_abort:
-       kfree(priv);
+       kill_all_async_requests_priv(priv);
+       kref_put(&priv->ref_count, destroy_priv);
        return -ENODEV;
 }
 
 static void uss720_disconnect(struct usb_interface *intf)
 {
-       struct parport *pp = usb_get_intfdata (intf);
+       struct parport *pp = usb_get_intfdata(intf);
        struct parport_uss720_private *priv;
+       struct usb_device *usbdev;
 
-       usb_set_intfdata (intf, NULL);
+       dbg("disconnect");
+       usb_set_intfdata(intf, NULL);
        if (pp) {
                priv = pp->private_data;
-               parport_remove_port(pp);
-#if 0
-               usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
+               usbdev = priv->usbdev;
                priv->usbdev = NULL;
+               priv->pp = NULL;
+               dbg("parport_remove_port");
+               parport_remove_port(pp);
                parport_put_port(pp);
-               kfree(priv);
+               kill_all_async_requests_priv(priv);
+               kref_put(&priv->ref_count, destroy_priv);
        }
+       dbg("disconnect done");
 }
 
 /* table of cables that work through this driver */
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static int __init uss720_init(void)
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
                goto out;
 
        info(DRIVER_VERSION ":" DRIVER_DESC);
+       info("NOTE: this is a special purpose driver to allow nonstandard");
+       info("protocols (eg. bitbang) over USS720 usb to parallel cables");
+       info("If you just want to connect to a printer, use usblp instead");
 out:
        return retval;
 }
index 417464dea9f6457948a3caba9f82a4170c81e30a..17d0190ef64ecce708999654a8e278c96d6a3558 100644 (file)
@@ -79,7 +79,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
                return '-';
 
        if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
-               return 'D';
+               return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
        if (urb->setup_packet == NULL)
                return 'Z';     /* '0' would be not as pretty. */
 
index 4ace9964fc6bd36a22c0a82da2fc432be4eef5f7..97c78c21e8d1db5a865092d05fbc93df93b959f6 100644 (file)
@@ -32,7 +32,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.04"
+#define DRIVER_VERSION "v0.05"
 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
 
 /*
@@ -54,8 +54,11 @@ static void cp2101_shutdown(struct usb_serial*);
 static int debug;
 
 static struct usb_device_id id_table [] = {
+       { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+       { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+       { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { } /* Terminating Entry */
 };
index 05c44ae3ed32adce07adbfb0a3d05edfdc5c1979..9ee1aaff2fcdc759a8f0fa28864eb58a5719ddf6 100644 (file)
@@ -610,8 +610,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
                timeout = max((HZ*2560)/bps,HZ/10);
        else
                timeout = 2*HZ;
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(timeout);
+       schedule_timeout_interruptible(timeout);
 
        dbg("%s - stopping urbs", __FUNCTION__);
        usb_kill_urb (port->interrupt_in_urb);
index 0a6e8b474b1ff46db9efd8b423dd9ad36b215c18..4e434cb10bb12de49efedf44838aaad248bad2b8 100644 (file)
@@ -914,7 +914,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
        unsigned interfaces;
 
        /* Assume it is not the original SIO device for now. */
-       priv->baud_base = 48000000 / 16;
+       priv->baud_base = 48000000 / 2;
        priv->write_offset = 0;
 
        version = le16_to_cpu(udev->descriptor.bcdDevice);
index 461474176cfbc8aae66081e1dc1c3b3117c83c37..3cf245bdda54d0a877989e5850886562d877c2d9 100644 (file)
@@ -95,6 +95,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
        { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
+       { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
        { }                                     /* Terminating entry */
 };
 
@@ -652,8 +653,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
                timeout = max((HZ*2560)/bps,HZ/10);
        else
                timeout = 2*HZ;
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(timeout);
+       schedule_timeout_interruptible(timeout);
 
        /* shutdown our urbs */
        dbg("%s - shutting down urbs", __FUNCTION__);
index b734c4003c5af6cf725d009f979e408641a6f8cf..7be9644f5a03e763c4f56e2308c341d9a78eaff2 100644 (file)
@@ -58,3 +58,7 @@
 
 #define SYNTECH_VENDOR_ID      0x0745
 #define SYNTECH_PRODUCT_ID     0x0001
+
+/* Nokia CA-42 Cable */
+#define NOKIA_CA42_VENDOR_ID   0x078b
+#define NOKIA_CA42_PRODUCT_ID  0x1234
index d34dc9f417f0267f40d1927e3c7f0f8d8d481193..4837524eada7170049c78f61fdff0eab29fddd0a 100644 (file)
@@ -227,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
  ***********************************************************************/
 
 /* Command timeout and abort */
-/* This is always called with scsi_lock(host) held */
 static int command_abort(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
 
        US_DEBUGP("%s called\n", __FUNCTION__);
 
+       /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+        * bits are protected by the host lock. */
+       scsi_lock(us_to_host(us));
+
        /* Is this command still active? */
        if (us->srb != srb) {
+               scsi_unlock(us_to_host(us));
                US_DEBUGP ("-- nothing to abort\n");
                return FAILED;
        }
 
        /* Set the TIMED_OUT bit.  Also set the ABORTING bit, but only if
         * a device reset isn't already in progress (to avoid interfering
-        * with the reset).  To prevent races with auto-reset, we must
-        * stop any ongoing USB transfers while still holding the host
-        * lock. */
+        * with the reset).  Note that we must retain the host lock while
+        * calling usb_stor_stop_transport(); otherwise it might interfere
+        * with an auto-reset that begins as soon as we release the lock. */
        set_bit(US_FLIDX_TIMED_OUT, &us->flags);
        if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
                set_bit(US_FLIDX_ABORTING, &us->flags);
                usb_stor_stop_transport(us);
        }
+       scsi_unlock(us_to_host(us));
 
        /* Wait for the aborted command to finish */
        wait_for_completion(&us->notify);
-
-       /* Reacquire the lock and allow USB transfers to resume */
-       clear_bit(US_FLIDX_ABORTING, &us->flags);
-       clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
        return SUCCESS;
 }
 
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
-/* This is always called with scsi_lock(host) held */
 static int device_reset(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
@@ -279,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
 }
 
 /* Simulate a SCSI bus reset by resetting the device's USB port. */
-/* This is always called with scsi_lock(host) held */
 static int bus_reset(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
@@ -291,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
        result = usb_stor_port_reset(us);
        up(&(us->dev_semaphore));
 
-       /* lock the host for the return */
        return result < 0 ? FAILED : SUCCESS;
 }
 
index ad0cfd7a782f2e8c5418d04c6e3f13563e9993f7..b79dad1b598c04365c9727d6b283e94e0cb881b7 100644 (file)
@@ -86,6 +86,16 @@ UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
+ * for USB floppies that need the SINGLE_LUN enforcement.
+ */
+UNUSUAL_DEV(  0x0409, 0x0040, 0x0000, 0x9999,
+               "NEC",
+               "NEC USB UF000x",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
+
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
  * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
  * always fails and confuses drive.
@@ -96,6 +106,13 @@ UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_INQUIRY ),
 
+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
+UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+               "SMSC",
+               "FDC GOLD-2.30",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
+
 #ifdef CONFIG_USB_STORAGE_DPCM
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
                "Microtech",
@@ -103,6 +120,24 @@ UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
                US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
 #endif
 
+/*
+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
+ * The key does not actually break, but it returns zero sense which
+ * makes our SCSI stack to print confusing messages.
+ */
+UNUSUAL_DEV(  0x0457, 0x0150, 0x0100, 0x0100,
+               "USBest Technology",    /* sold by Transcend */
+               "USB Mass Storage Device",
+               US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV(  0x0451, 0x5416, 0x0100, 0x0100,
+               "Neuros Audio",
+               "USB 2.0 HD 2.5",
+               US_SC_DEVICE, US_PR_BULK, NULL,
+               US_FL_NEED_OVERRIDE ),
+
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
                "Kyocera",
index cb4c770baf32a52be5d5ced2f0a3db946c43c359..f9a9bfa1aef5be8d0181ea2ddc64d844e6c85d61 100644 (file)
@@ -392,11 +392,16 @@ SkipForAbort:
                /* If an abort request was received we need to signal that
                 * the abort has finished.  The proper test for this is
                 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
-                * a timeout/abort request might be received after all the
-                * USB processing was complete. */
-               if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))
+                * the timeout might have occurred after the command had
+                * already completed with a different result code. */
+               if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
                        complete(&(us->notify));
 
+                       /* Allow USB transfers to resume */
+                       clear_bit(US_FLIDX_ABORTING, &us->flags);
+                       clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+               }
+
                /* finished working on this command */
                us->srb = NULL;
                scsi_unlock(host);
index 5fe182d6e4ab44bc09dc605b5980da37a915e67f..eb83a7874c71508798bac35e4205f1770edac560 100644 (file)
@@ -137,7 +137,7 @@ config FONT_8x8
 
 config FONT_8x16
        bool "VGA 8x16 font" if FONTS
-       depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
+       depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
        default y if !SPARC32 && !SPARC64 && !FONTS
        help
          This is the "high resolution" font for the VGA frame buffer (the one
index b562f6bb9d316d64addc4acc4934e83257bda83f..42c7b8dcd22073397da5f89bdf94ddc62dc71204 100644 (file)
@@ -33,6 +33,10 @@ endif
 
 obj-$(CONFIG_FB_STI)              += sticore.o font.o
 
+ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
+obj-$(CONFIG_USB_SISUSBVGA)           += font.o
+endif
+
 # Targets that kbuild needs to know about
 targets := promcon_tbl.c
 
index 7018ffffcbc4e391f8dbc8076a072ed59f865f82..0dbc9ddb6766e78eba0b1b58f5e5eb0c57d0051b 100644 (file)
@@ -95,18 +95,18 @@ static struct pci_driver i810fb_driver = {
 static char *mode_option __devinitdata = NULL;
 static int vram       __devinitdata = 4;
 static int bpp        __devinitdata = 8;
-static int mtrr       __devinitdata = 0;
-static int accel      __devinitdata = 0;
-static int hsync1     __devinitdata = 0;
-static int hsync2     __devinitdata = 0;
-static int vsync1     __devinitdata = 0;
-static int vsync2     __devinitdata = 0;
-static int xres       __devinitdata = 640;
-static int yres       __devinitdata = 480;
-static int vyres      __devinitdata = 0;
-static int sync       __devinitdata = 0;
-static int ext_vga    __devinitdata = 0;
-static int dcolor     __devinitdata = 0;
+static int mtrr       __devinitdata;
+static int accel      __devinitdata;
+static int hsync1     __devinitdata;
+static int hsync2     __devinitdata;
+static int vsync1     __devinitdata;
+static int vsync2     __devinitdata;
+static int xres       __devinitdata;
+static int yres       __devinitdata;
+static int vyres      __devinitdata;
+static int sync       __devinitdata;
+static int extvga     __devinitdata;
+static int dcolor     __devinitdata;
 
 /*------------------------------------------------------------*/
 
@@ -950,7 +950,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                             struct fb_info *info)
 {
        struct i810fb_par *par = (struct i810fb_par *) info->par;
-       int line_length, vidmem, mode_valid = 0;
+       int line_length, vidmem, mode_valid = 0, retval = 0;
        u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
        /*
         *  Memory limit
@@ -1026,10 +1026,11 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                        printk("i810fb: invalid video mode%s\n",
                               default_sync ? "" : ". Specifying "
                               "vsyncN/hsyncN parameters may help");
+                       retval = -EINVAL;
                }
        }
 
-       return 0;
+       return retval;
 }      
 
 /**
@@ -1724,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
        if (bpp < 8)
                bpp = 8;
        
+       par->i810fb_ops = i810fb_ops;
+
+       if (xres)
+               info->var.xres = xres;
+       else
+               info->var.xres = 640;
+
+       if (yres)
+               info->var.yres = yres;
+       else
+               info->var.yres = 480;
+
        if (!vyres) 
-               vyres = (vram << 20)/(xres*bpp >> 3);
+               vyres = (vram << 20)/(info->var.xres*bpp >> 3);
 
-       par->i810fb_ops = i810fb_ops;
-       info->var.xres = xres;
-       info->var.yres = yres;
        info->var.yres_virtual = vyres;
        info->var.bits_per_pixel = bpp;
 
@@ -1756,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
        i810_init_cursor(par);
 
        /* mvo: enable external vga-connector (for laptops) */
-       if (ext_vga) {
+       if (extvga) {
                i810_writel(HVSYNC, mmio, 0);
                i810_writel(PWR_CLKC, mmio, 3);
        }
@@ -1830,7 +1840,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
 {
        struct fb_videomode mode;
        struct fb_var_screeninfo var;
-       struct fb_monspecs *specs = NULL;
+       struct fb_monspecs *specs = &info->monspecs;
        int found = 0;
 #ifdef CONFIG_FB_I810_I2C
        int i;
@@ -1853,16 +1863,24 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
        if (!err)
                printk("i810fb_init_pci: DDC probe successful\n");
 
-       fb_edid_to_monspecs(par->edid, &info->monspecs);
+       fb_edid_to_monspecs(par->edid, specs);
 
-       if (info->monspecs.modedb == NULL)
+       if (specs->modedb == NULL)
                printk("i810fb_init_pci: Unable to get Mode Database\n");
 
-       specs = &info->monspecs;
        fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
                                 &info->modelist);
        if (specs->modedb != NULL) {
-               if (specs->misc & FB_MISC_1ST_DETAIL) {
+               if (xres && yres) {
+                       struct fb_videomode *m;
+
+                       if ((m = fb_find_best_mode(&var, &info->modelist))) {
+                               mode = *m;
+                               found  = 1;
+                       }
+               }
+
+               if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
                        for (i = 0; i < specs->modedb_len; i++) {
                                if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
                                        mode = specs->modedb[i];
@@ -1903,8 +1921,8 @@ static int __devinit i810fb_setup(char *options)
                        mtrr = 1;
                else if (!strncmp(this_opt, "accel", 5))
                        accel = 1;
-               else if (!strncmp(this_opt, "ext_vga", 7))
-                       ext_vga = 1;
+               else if (!strncmp(this_opt, "extvga", 6))
+                       extvga = 1;
                else if (!strncmp(this_opt, "sync", 4))
                        sync = 1;
                else if (!strncmp(this_opt, "vram:", 5))
@@ -2133,8 +2151,8 @@ module_param(accel, bool, 0);
 MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
 module_param(mtrr, bool, 0);
 MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
 module_param(sync, bool, 0);
 MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
                 " (default = 0)");
index b7c24b34d270db1129009b374d52710a012c0287..279e0e0363d6afb7e7326da42381d6c36c5e37f4 100644 (file)
 #include <linux/delay.h>
 #ifdef CONFIG_W1_F23_CRC
 #include <linux/crc16.h>
+
+#define CRC16_INIT             0
+#define CRC16_VALID            0xb001
+
 #endif
 
 #include "w1.h"
@@ -214,7 +218,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
 #ifdef CONFIG_W1_F23_CRC
        /* can only write full blocks in cached mode */
        if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
-               dev_err(&sl->dev, "invalid offset/count off=%d cnt=%d\n",
+               dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
                        (int)off, count);
                return -EINVAL;
        }
index e4fd6134244dd0f93290c3653ab56a3e4b4e1d12..49eafbdb15c145e1884945e8aae5e1a74d0e3ed0 100644 (file)
@@ -34,9 +34,6 @@ ToDo/Notes:
          journals with two different restart pages.  We sanity check both and
          either use the only sane one or the more recent one of the two in the
          case that both are valid.
-       - Modify fs/ntfs/malloc.h::ntfs_malloc_nofs() to do the kmalloc() based
-         allocations with __GFP_HIGHMEM, analogous to how the vmalloc() based
-         allocations are done.
        - Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
          ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
          hence cannot fail.
@@ -90,7 +87,11 @@ ToDo/Notes:
          in the first buffer head instead of a driver global spin lock to
          improve scalability.
        - Minor fix to error handling and error message display in
-         fs/ntfs/aops.c::ntfs_prepare_nonresident_write(). 
+         fs/ntfs/aops.c::ntfs_prepare_nonresident_write().
+       - Change the mount options {u,f,d}mask to always parse the number as
+         an octal number to conform to how chmod(1) works, too.  Thanks to
+         Giuseppe Bilotta and Horst von Brand for pointing out the errors of
+         my ways.
 
 2.1.23 - Implement extension of resident files and make writing safe as well as
         many bug fixes, cleanups, and enhancements...
index 9994e019a3cfa958216899ffeae4ebbca3c4db54..3288bcc2c4aa162190316277f9c6aefa4f128216 100644 (file)
@@ -45,7 +45,7 @@ static inline void *__ntfs_malloc(unsigned long size,
        if (likely(size <= PAGE_SIZE)) {
                BUG_ON(!size);
                /* kmalloc() has per-CPU caches so is faster for now. */
-               return kmalloc(PAGE_SIZE, gfp_mask);
+               return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM);
                /* return (void *)__get_free_page(gfp_mask); */
        }
        if (likely(size >> PAGE_SHIFT < num_physpages))
index b2b392961268fdefebc7b054d6149ceed78d57c9..453d0d51ea4bc4d9b731e48345db0e45bb034b24 100644 (file)
@@ -126,6 +126,14 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
                if (*v)                                                 \
                        goto needs_val;                                 \
        }
+#define NTFS_GETOPT_OCTAL(option, variable)                            \
+       if (!strcmp(p, option)) {                                       \
+               if (!v || !*v)                                          \
+                       goto needs_arg;                                 \
+               variable = simple_strtoul(ov = v, &v, 8);               \
+               if (*v)                                                 \
+                       goto needs_val;                                 \
+       }
 #define NTFS_GETOPT_BOOL(option, variable)                             \
        if (!strcmp(p, option)) {                                       \
                BOOL val;                                               \
@@ -157,9 +165,9 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
                        *v++ = 0;
                NTFS_GETOPT("uid", uid)
                else NTFS_GETOPT("gid", gid)
-               else NTFS_GETOPT("umask", fmask = dmask)
-               else NTFS_GETOPT("fmask", fmask)
-               else NTFS_GETOPT("dmask", dmask)
+               else NTFS_GETOPT_OCTAL("umask", fmask = dmask)
+               else NTFS_GETOPT_OCTAL("fmask", fmask)
+               else NTFS_GETOPT_OCTAL("dmask", dmask)
                else NTFS_GETOPT("mft_zone_multiplier", mft_zone_multiplier)
                else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE)
                else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files)
index faff403e1061562f77e6c7a13f7c46d6775bb257..7d0298347ee7df599088ca5cbb6a4f0c8ee2947b 100644 (file)
  * and page free order so much..
  */
 #ifdef CONFIG_SMP
-  #define FREE_PTE_NR  506
+  #ifdef ARCH_FREE_PTR_NR
+    #define FREE_PTR_NR   ARCH_FREE_PTR_NR
+  #else
+    #define FREE_PTE_NR        506
+  #endif
   #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
 #else
   #define FREE_PTE_NR  1
index 6a1b1882285c004a1c5f80b109c046fe483c8bee..8c454aa58ac6b157441ad2a77f9211e4a30f882e 100644 (file)
@@ -130,6 +130,8 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+extern int disable_timer_pin_1;
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
diff --git a/include/asm-i386/numa.h b/include/asm-i386/numa.h
new file mode 100644 (file)
index 0000000..96fcb15
--- /dev/null
@@ -0,0 +1,3 @@
+
+int pxm_to_nid(int pxm);
+
index 2461b731781ebc182fd7b70c534b6dd87bb15e76..0ec27c9e8e45ba696be1a06a81df49d27d222729 100644 (file)
@@ -60,7 +60,7 @@ static inline int node_to_first_cpu(int node)
        return first_cpu(mask);
 }
 
-#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_node(bus) ((long) (bus)->sysdata)
 #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
 
 /* sched_domains SD_NODE_INIT for NUMAQ machines */
index a7cb377745bf01968d49984ade8d57fcd27369dd..fbaf90a3968c1f7c4f5bd11b818a604c625e8923 100644 (file)
@@ -332,7 +332,7 @@ type name(type1 arg1) \
 long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1))); \
+       : "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -342,7 +342,7 @@ type name(type1 arg1,type2 arg2) \
 long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
+       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -353,7 +353,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-                 "d" ((long)(arg3))); \
+                 "d" ((long)(arg3)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -364,7 +364,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4))); \
+         "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
 __syscall_return(type,__res); \
 } 
 
@@ -376,7 +376,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
+         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -389,7 +389,7 @@ __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; p
        : "=a" (__res) \
        : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
          "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
-         "0" ((long)(arg6))); \
+         "0" ((long)(arg6)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
index f95e32b4042545025f7b557e8984bcb2021facb8..c42f88a9b9f986d25b3f859d38b9f3794ff17378 100644 (file)
@@ -259,7 +259,7 @@ static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
 #define find_first_bit(addr, size) \
         find_next_bit((addr), (size), 0)
 
-static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (const void * addr, int size, int offset)
 {
        unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
        unsigned long result = offset & ~31UL;
index 92cf102c2534c0445ed581e74d451bce311ef104..294ec7583ac9149696314aaece0256746e595b18 100644 (file)
@@ -25,7 +25,8 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  * better 64-bit) boundary
  */
 
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+       int len, int sum);
 
 
 /*
@@ -35,8 +36,8 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
  * better 64-bit) boundary
  */
 
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
-                                               int len, int sum, int *csum_err);
+extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+       unsigned char *dst, int len, int sum, int *csum_err);
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)  \
        csum_partial_copy((src), (dst), (len), (sum))
index d280d013da032c0e3992b98a5b01c2267791441e..e7878d0f7d7a57d94003a0c9788fc858cbec88e9 100644 (file)
 /*
  *     SDRAM configuration registers.
  */
-#ifdef CONFIG_M5271EVB
+#ifdef CONFIG_M5271
 #define        MCFSIM_DCR              0x40            /* SDRAM control */
 #define        MCFSIM_DACR0            0x48            /* SDRAM base address 0 */
 #define        MCFSIM_DMR0             0x4c            /* SDRAM address mask 0 */
 #define        MCFSIM_DACR1            0x50            /* SDRAM base address 1 */
 #define        MCFSIM_DMR1             0x54            /* SDRAM address mask 1 */
-#else
+#endif
+#ifdef CONFIG_M5275
 #define        MCFSIM_DMR              0x40            /* SDRAM mode */
 #define        MCFSIM_DCR              0x44            /* SDRAM control */
 #define        MCFSIM_DCFG1            0x48            /* SDRAM configuration 1 */
 #define        MCFSIM_DMR1             0x5c            /* SDRAM address mask 1 */
 #endif
 
+/*
+ *     GPIO pins setups to enable the UARTs.
+ */
+#ifdef CONFIG_M5271
+#define MCF_GPIO_PAR_UART      0x100048        /* PAR UART address */
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x0ff0
+#define UART2_ENABLE_MASK      0x3000
+#endif
+#ifdef CONFIG_M5275
+#define MCF_GPIO_PAR_UART      0x10007c        /* PAR UART address */
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x00f0
+#define UART2_ENABLE_MASK      0x3f00 
+#endif
+
 /****************************************************************************/
 #endif /* m527xsim_h */
index 371993a206acdc751d2727f435d88bade432963d..610774a17f70d86a00524fb1c1e88f99f9d484af 100644 (file)
 #define        MCFSIM_DACR1            0x50            /* SDRAM base address 1 */
 #define        MCFSIM_DMR1             0x54            /* SDRAM address mask 1 */
 
+/*
+ *     Derek Cheung - 6 Feb 2005
+ *             add I2C and QSPI register definition using Freescale's MCF5282
+ */
+/* set Port AS pin for I2C or UART */
+#define MCF5282_GPIO_PASPAR     (volatile u16 *) (MCF_IPSBAR + 0x00100056)
+
+/* Interrupt Mask Register Register Low */ 
+#define MCF5282_INTC0_IMRL      (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
+/* Interrupt Control Register 7 */
+#define MCF5282_INTC0_ICR17     (volatile u8 *) (MCF_IPSBAR + 0x0C51)
+
+
+
+/*********************************************************************
+*
+* Inter-IC (I2C) Module
+*
+*********************************************************************/
+/* Read/Write access macros for general use */
+#define MCF5282_I2C_I2ADR       (volatile u8 *) (MCF_IPSBAR + 0x0300) // Address 
+#define MCF5282_I2C_I2FDR       (volatile u8 *) (MCF_IPSBAR + 0x0304) // Freq Divider
+#define MCF5282_I2C_I2CR        (volatile u8 *) (MCF_IPSBAR + 0x0308) // Control
+#define MCF5282_I2C_I2SR        (volatile u8 *) (MCF_IPSBAR + 0x030C) // Status
+#define MCF5282_I2C_I2DR        (volatile u8 *) (MCF_IPSBAR + 0x0310) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF5282_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
+
+#define MCF5282_I2C_I2FDR_IC(x)                         (((x)&0x3F))
+
+#define MCF5282_I2C_I2CR_IEN    (0x80) // I2C enable
+#define MCF5282_I2C_I2CR_IIEN   (0x40)  // interrupt enable
+#define MCF5282_I2C_I2CR_MSTA   (0x20)  // master/slave mode
+#define MCF5282_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
+#define MCF5282_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
+#define MCF5282_I2C_I2CR_RSTA   (0x04)  // repeat start
+
+#define MCF5282_I2C_I2SR_ICF    (0x80)  // data transfer bit
+#define MCF5282_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
+#define MCF5282_I2C_I2SR_IBB    (0x20)  // I2C bus busy
+#define MCF5282_I2C_I2SR_IAL    (0x10)  // aribitration lost
+#define MCF5282_I2C_I2SR_SRW    (0x04)  // slave read/write
+#define MCF5282_I2C_I2SR_IIF    (0x02)  // I2C interrupt
+#define MCF5282_I2C_I2SR_RXAK   (0x01)  // received acknowledge
+
+
+
+/*********************************************************************
+*
+* Queued Serial Peripheral Interface (QSPI) Module
+*
+*********************************************************************/
+/* Derek - 21 Feb 2005 */
+/* change to the format used in I2C */
+/* Read/Write access macros for general use */
+#define MCF5282_QSPI_QMR        MCF_IPSBAR + 0x0340
+#define MCF5282_QSPI_QDLYR      MCF_IPSBAR + 0x0344
+#define MCF5282_QSPI_QWR        MCF_IPSBAR + 0x0348
+#define MCF5282_QSPI_QIR        MCF_IPSBAR + 0x034C
+#define MCF5282_QSPI_QAR        MCF_IPSBAR + 0x0350
+#define MCF5282_QSPI_QDR        MCF_IPSBAR + 0x0354
+#define MCF5282_QSPI_QCR        MCF_IPSBAR + 0x0354
+
+/* Bit level definitions and macros */
+#define MCF5282_QSPI_QMR_MSTR                           (0x8000)
+#define MCF5282_QSPI_QMR_DOHIE                          (0x4000)
+#define MCF5282_QSPI_QMR_BITS_16                        (0x0000)
+#define MCF5282_QSPI_QMR_BITS_8                         (0x2000)
+#define MCF5282_QSPI_QMR_BITS_9                         (0x2400)
+#define MCF5282_QSPI_QMR_BITS_10                        (0x2800)
+#define MCF5282_QSPI_QMR_BITS_11                        (0x2C00)
+#define MCF5282_QSPI_QMR_BITS_12                        (0x3000)
+#define MCF5282_QSPI_QMR_BITS_13                        (0x3400)
+#define MCF5282_QSPI_QMR_BITS_14                        (0x3800)
+#define MCF5282_QSPI_QMR_BITS_15                        (0x3C00)
+#define MCF5282_QSPI_QMR_CPOL                           (0x0200)
+#define MCF5282_QSPI_QMR_CPHA                           (0x0100)
+#define MCF5282_QSPI_QMR_BAUD(x)                        (((x)&0x00FF))
+
+#define MCF5282_QSPI_QDLYR_SPE                          (0x80)
+#define MCF5282_QSPI_QDLYR_QCD(x)                       (((x)&0x007F)<<8)
+#define MCF5282_QSPI_QDLYR_DTL(x)                       (((x)&0x00FF))
+
+#define MCF5282_QSPI_QWR_HALT                           (0x8000)
+#define MCF5282_QSPI_QWR_WREN                           (0x4000)
+#define MCF5282_QSPI_QWR_WRTO                           (0x2000)
+#define MCF5282_QSPI_QWR_CSIV                           (0x1000)
+#define MCF5282_QSPI_QWR_ENDQP(x)                       (((x)&0x000F)<<8)
+#define MCF5282_QSPI_QWR_CPTQP(x)                       (((x)&0x000F)<<4)
+#define MCF5282_QSPI_QWR_NEWQP(x)                       (((x)&0x000F))
+
+#define MCF5282_QSPI_QIR_WCEFB                          (0x8000)
+#define MCF5282_QSPI_QIR_ABRTB                          (0x4000)
+#define MCF5282_QSPI_QIR_ABRTL                          (0x1000)
+#define MCF5282_QSPI_QIR_WCEFE                          (0x0800)
+#define MCF5282_QSPI_QIR_ABRTE                          (0x0400)
+#define MCF5282_QSPI_QIR_SPIFE                          (0x0100)
+#define MCF5282_QSPI_QIR_WCEF                           (0x0008)
+#define MCF5282_QSPI_QIR_ABRT                           (0x0004)
+#define MCF5282_QSPI_QIR_SPIF                           (0x0001)
+
+#define MCF5282_QSPI_QAR_ADDR(x)                        (((x)&0x003F))
+
+#define MCF5282_QSPI_QDR_COMMAND(x)                     (((x)&0xFF00))
+#define MCF5282_QSPI_QCR_DATA(x)                        (((x)&0x00FF)<<8)
+#define MCF5282_QSPI_QCR_CONT                           (0x8000)
+#define MCF5282_QSPI_QCR_BITSE                          (0x4000)
+#define MCF5282_QSPI_QCR_DT                             (0x2000)
+#define MCF5282_QSPI_QCR_DSCK                           (0x1000)
+#define MCF5282_QSPI_QCR_CS                             (((x)&0x000F)<<8)
+
 /****************************************************************************/
 #endif /* m528xsim_h */
index bdd8c53ef34ce171ca6117a5c99f6f6948316e77..b17cd920977f592c7a05f5fdae337039fb784a66 100644 (file)
@@ -33,7 +33,7 @@
 .endm
 #endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
 
-#if defined(CONFIG_M527x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
 /*
  *     New version 2 cores have a configurable split cache arrangement.
  *     For now I am just enabling instruction cache - but ultimately I
        movec   %d0,%CACR               /* enable cache */
        nop
 .endm
-#endif /* CONFIG_M527x */
+#endif /* CONFIG_M523x || CONFIG_M527x */
 
 #if defined(CONFIG_M528x)
-/*
- *     Cache is totally broken on early 5282 silicon. So far now we
- *     disable its cache all together.
- */
 .macro CACHE_ENABLE
-       movel   #0x01000000,%d0
-       movec   %d0,%CACR               /* invalidate cache */
        nop
-       movel   #0x0000c000,%d0         /* set SDRAM cached only */
-       movec   %d0,%ACR0
-       movel   #0x00000000,%d0         /* no other regions cached */
-       movec   %d0,%ACR1
-       movel   #0x00000000,%d0         /* configure cache */
-       movec   %d0,%CACR               /* enable cache */
+       movel   #0x01000000, %d0
+       movec   %d0, %CACR              /* Invalidate cache */
+       nop
+       movel   #0x0000c020, %d0        /* Set SDRAM cached only */
+       movec   %d0, %ACR0
+       movel   #0xff00c000, %d0        /* Cache Flash also */
+       movec   %d0, %ACR1
+       movel   #0x80000200, %d0        /* Setup cache mask */
+       movec   %d0, %CACR              /* Enable cache */
        nop
 .endm
 #endif /* CONFIG_M528x */
index 350c6090b5c1ed5f3959ad5eae8d4b06b7bc283c..b93f8ba8a248e6269a0d8385217dc6f50893cb3a 100644 (file)
@@ -21,7 +21,7 @@
 #define        MCFDMA_BASE1            0x240           /* Base address of DMA 1 */
 #elif defined(CONFIG_M5272)
 #define        MCFDMA_BASE0            0x0e0           /* Base address of DMA 0 */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /* These are relative to the IPSBAR, not MBAR */
 #define        MCFDMA_BASE0            0x100           /* Base address of DMA 0 */
 #define        MCFDMA_BASE1            0x140           /* Base address of DMA 1 */
index 538ea8ef509b99f4d2ec3350d64e12bd27450332..12f1bce037be7f57c422b26246b692838b4fbc9d 100644 (file)
 
 #include <asm-generic/siginfo.h>
 
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRANCH    (__SI_FAULT|3)  /* process taken branch trap */
+#define TRAP_HWBKPT    (__SI_FAULT|4)  /* hardware breakpoint or watchpoint */
+#undef NSIGTRAP
+#define NSIGTRAP       4
+
 #endif /* _ASM_POWERPC_SIGINFO_H */
index 9d4e4ea530c3a7c2c5dd34b0d01d6824914a08f3..7043c164b5375d98a9ae8794b1b77db89653b3ab 100644 (file)
@@ -142,4 +142,11 @@ do {                                                                             \
 #define PTRACE_GETEVRREGS      20
 #define PTRACE_SETEVRREGS      21
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG    25
+#define PTRACE_SET_DEBUGREG    26
+
 #endif
index 4f668a4baff01b13427e59be038280075c7e835c..ab7c3cf24888cd6c6fb2f3663cd835f95d088f7b 100644 (file)
 #define H_PP1                  (1UL<<(63-62))
 #define H_PP2                  (1UL<<(63-63))
 
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR     (1UL<<(63-61))
+#define H_DABRX_KERNEL         (1UL<<(63-62))
+#define H_DABRX_USER           (1UL<<(63-63))
+
 /* pSeries hypervisor opcodes */
 #define H_REMOVE               0x04
 #define H_ENTER                        0x08
 #define H_VIO_SIGNAL           0x104
 #define H_SEND_CRQ             0x108
 #define H_COPY_RDMA             0x110
+#define H_SET_XDABR            0x134
 #define H_STUFF_TCE            0x138
 #define H_PUT_TCE_INDIRECT     0x13C
 #define H_VTERM_PARTNER_INFO   0x150
index 9a1ef4427ed2dfa0b2923f99ef2f8c4098cf4011..8027160ec96d005966b3afd54edac45fecfa5512 100644 (file)
@@ -88,6 +88,7 @@ struct machdep_calls {
 
        /* PCI stuff */
        void            (*pcibios_fixup)(void);
+       int             (*pci_probe_mode)(struct pci_bus *);
 
        void            (*restart)(char *cmd);
        void            (*power_off)(void);
@@ -173,10 +174,6 @@ extern sys_ctrler_t sys_ctrler;
 void ppc64_boot_msg(unsigned int src, const char *msg);
 /* Print a termination message (print only -- does not stop the kernel) */
 void ppc64_terminate_msg(unsigned int src, const char *msg);
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg);
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg);
 
 static inline void log_error(char *buf, unsigned int err_type, int fatal)
 {
index 6b4a5b1f695e916cf72b38f29ec44f8ed1e132ec..d8991389ab3960c598fbd030c7dc6e0385f40b90 100644 (file)
@@ -119,5 +119,10 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
        return PCI_DN(busdn)->phb;
 }
 
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE      1       /* Instantiate from device tree */
+
 #endif
 #endif /* __KERNEL__ */
index f4a5fb7d67c7ccd24a0aa82c06672e8f54461565..72dd2449ee76224f6f9f1748e5ef69c81b4843bd 100644 (file)
@@ -107,5 +107,14 @@ static inline long plpar_put_term_char(unsigned long termno,
                                  lbuf[1]);
 }
 
+static inline long plpar_set_xdabr(unsigned long address, unsigned long flags)
+{
+       return plpar_hcall_norets(H_SET_XDABR, address, flags);
+}
+
+static inline long plpar_set_dabr(unsigned long val)
+{
+       return plpar_hcall_norets(H_SET_DABR, val);
+}
 
 #endif /* _PPC64_PLPAR_WRAPPERS_H */
index 8bd7aa959385d01d33c530526609e7302cf97921..4146189006e32cac1d8d11d618e8f02498bfe1ce 100644 (file)
@@ -433,6 +433,7 @@ struct thread_struct {
        unsigned long   start_tb;       /* Start purr when proc switched in */
        unsigned long   accum_tb;       /* Total accumilated purr for process */
        unsigned long   vdso_base;      /* base of the vDSO library */
+       unsigned long   dabr;           /* Data address breakpoint register */
 #ifdef CONFIG_ALTIVEC
        /* Complete AltiVec register set */
        vector128       vr[32] __attribute((aligned(16)));
index af03547f9c7edf4151afbbb3f29d5bbd89fddba6..b1babb7296733632baeaa2ea60a21e0399bc60e0 100644 (file)
 
 #ifndef _PPC64_PTRACE_COMMON_H
 #define _PPC64_PTRACE_COMMON_H
+
+#include <linux/config.h>
+#include <asm/system.h>
+
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
@@ -69,4 +73,92 @@ static inline void clear_single_step(struct task_struct *task)
        clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
 }
 
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the
+ * same structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long __user *data,
+                            struct task_struct *task)
+{
+       unsigned long regsize;
+
+       /* copy AltiVec registers VR[0] .. VR[31] */
+       regsize = 32 * sizeof(vector128);
+       if (copy_to_user(data, task->thread.vr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VSCR */
+       regsize = 1 * sizeof(vector128);
+       if (copy_to_user(data, &task->thread.vscr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VRSAVE */
+       if (put_user(task->thread.vrsave, (u32 __user *)data))
+               return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task,
+                            unsigned long __user *data)
+{
+       unsigned long regsize;
+
+       /* copy AltiVec registers VR[0] .. VR[31] */
+       regsize = 32 * sizeof(vector128);
+       if (copy_from_user(task->thread.vr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VSCR */
+       regsize = 1 * sizeof(vector128);
+       if (copy_from_user(&task->thread.vscr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VRSAVE */
+       if (get_user(task->thread.vrsave, (u32 __user *)data))
+               return -EFAULT;
+
+       return 0;
+}
+#endif
+
+static inline int ptrace_set_debugreg(struct task_struct *task,
+                                     unsigned long addr, unsigned long data)
+{
+       /* We only support one DABR and no IABRS at the moment */
+       if (addr > 0)
+               return -EINVAL;
+
+       /* The bottom 3 bits are flags */
+       if ((data & ~0x7UL) >= TASK_SIZE)
+               return -EIO;
+
+       /* Ensure translation is on */
+       if (data && !(data & DABR_TRANSLATION))
+               return -EIO;
+
+       task->thread.dabr = data;
+       return 0;
+}
+
 #endif /* _PPC64_PTRACE_COMMON_H */
index c96aad28fc081fc721d8c66fbca460864f1ea7b5..3a55377f1fd30fe2781c7cd817f2ca283f832265 100644 (file)
  */
 
 #ifndef __ASSEMBLY__
-#define PPC_REG unsigned long
+
 struct pt_regs {
-       PPC_REG gpr[32];
-       PPC_REG nip;
-       PPC_REG msr;
-       PPC_REG orig_gpr3;      /* Used for restarting system calls */
-       PPC_REG ctr;
-       PPC_REG link;
-       PPC_REG xer;
-       PPC_REG ccr;
-       PPC_REG softe;          /* Soft enabled/disabled */
-       PPC_REG trap;           /* Reason for being here */
-       PPC_REG dar;            /* Fault registers */
-       PPC_REG dsisr;
-       PPC_REG result;         /* Result of a system call */
+       unsigned long gpr[32];
+       unsigned long nip;
+       unsigned long msr;
+       unsigned long orig_gpr3; /* Used for restarting system calls */
+       unsigned long ctr;
+       unsigned long link;
+       unsigned long xer;
+       unsigned long ccr;
+       unsigned long softe;    /* Soft enabled/disabled */
+       unsigned long trap;     /* Reason for being here */
+       unsigned long dar;      /* Fault registers */
+       unsigned long dsisr;
+       unsigned long result;   /* Result of a system call */
 };
 
-#define PPC_REG_32 unsigned int
 struct pt_regs32 {
-       PPC_REG_32 gpr[32];
-       PPC_REG_32 nip;
-       PPC_REG_32 msr;
-       PPC_REG_32 orig_gpr3;   /* Used for restarting system calls */
-       PPC_REG_32 ctr;
-       PPC_REG_32 link;
-       PPC_REG_32 xer;
-       PPC_REG_32 ccr;
-       PPC_REG_32 mq;          /* 601 only (not used at present) */
-                               /* Used on APUS to hold IPL value. */
-       PPC_REG_32 trap;                /* Reason for being here */
-       PPC_REG_32 dar;         /* Fault registers */
-       PPC_REG_32 dsisr;
-       PPC_REG_32 result;      /* Result of a system call */
+       unsigned int gpr[32];
+       unsigned int nip;
+       unsigned int msr;
+       unsigned int orig_gpr3; /* Used for restarting system calls */
+       unsigned int ctr;
+       unsigned int link;
+       unsigned int xer;
+       unsigned int ccr;
+       unsigned int mq;        /* 601 only (not used at present) */
+       unsigned int trap;      /* Reason for being here */
+       unsigned int dar;       /* Fault registers */
+       unsigned int dsisr;
+       unsigned int result;    /* Result of a system call */
 };
 
+#ifdef __KERNEL__
+
 #define instruction_pointer(regs) ((regs)->nip)
+
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
 
-#endif /* __ASSEMBLY__ */
-
-#define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
-
-/* Size of dummy stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE     128
-#define __SIGNAL_FRAMESIZE32   64
-
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
@@ -89,6 +82,16 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define TRAP(regs)             ((regs)->trap & ~0xF)
 #define CHECK_FULL_REGS(regs)  BUG_ON(regs->trap & 1)
 
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
+
+/* Size of dummy stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE     128
+#define __SIGNAL_FRAMESIZE32   64
+
 /*
  * Offsets used by 'ptrace' system call interface.
  */
@@ -135,17 +138,21 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PT_XER 37
 #define PT_CCR 38
 #define PT_SOFTE 39
+#define PT_TRAP        40
+#define PT_DAR 41
+#define PT_DSISR 42
 #define PT_RESULT 43
 
 #define PT_FPR0        48
 
-/* Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will have
- * visibility to the asm-ppc/ptrace.h header instead of this one.
+/*
+ * Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will
+ * have visibility to the asm-ppc/ptrace.h header instead of this one.
  */
-#define PT_FPSCR (PT_FPR0 + 32)          /* each FP reg occupies 1 slot in 64-bit space */
+#define PT_FPSCR (PT_FPR0 + 32)        /* each FP reg occupies 1 slot in 64-bit space */
 
 #ifdef __KERNEL__
-#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)          /* each FP reg occupies 2 32-bit userspace slots */
+#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)        /* each FP reg occupies 2 32-bit userspace slots */
 #endif
 
 #define PT_VR0 82      /* each Vector reg occupies 2 slots in 64-bit */
@@ -173,17 +180,34 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PTRACE_GETVRREGS       18
 #define PTRACE_SETVRREGS       19
 
-/* Additional PTRACE requests implemented on PowerPC. */
-#define PPC_PTRACE_GETREGS           0x99  /* Get GPRs 0 - 31 */
-#define PPC_PTRACE_SETREGS           0x98  /* Set GPRs 0 - 31 */
-#define PPC_PTRACE_GETFPREGS       0x97  /* Get FPRs 0 - 31 */
-#define PPC_PTRACE_SETFPREGS       0x96  /* Set FPRs 0 - 31 */
-#define PPC_PTRACE_PEEKTEXT_3264  0x95  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKDATA_3264  0x94  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKETEXT_3264  0x93  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEDATA_3264  0x92  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKUSR_3264   0x91  /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEUSR_3264   0x90  /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */
+/*
+ * While we dont have 64bit book E processors, we need to reserve the
+ * relevant ptrace calls for 32bit compatibility.
+ */
+#if 0
+#define PTRACE_GETEVRREGS       20
+#define PTRACE_SETEVRREGS       21
+#endif
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG    25
+#define PTRACE_SET_DEBUGREG    26
+
+/* Additional PTRACE requests implemented on PowerPC. */
+#define PPC_PTRACE_GETREGS     0x99    /* Get GPRs 0 - 31 */
+#define PPC_PTRACE_SETREGS     0x98    /* Set GPRs 0 - 31 */
+#define PPC_PTRACE_GETFPREGS   0x97    /* Get FPRs 0 - 31 */
+#define PPC_PTRACE_SETFPREGS   0x96    /* Set FPRs 0 - 31 */
+
+/* Calls to trace a 64bit program from a 32bit program */
+#define PPC_PTRACE_PEEKTEXT_3264 0x95
+#define PPC_PTRACE_PEEKDATA_3264 0x94
+#define PPC_PTRACE_POKETEXT_3264 0x93
+#define PPC_PTRACE_POKEDATA_3264 0x92
+#define PPC_PTRACE_PEEKUSR_3264  0x91
+#define PPC_PTRACE_POKEUSR_3264  0x90
 
 #endif /* _PPC64_PTRACE_H */
index c0396428cc3c0c908bb723c111adff2a1d44ebac..375015c62f2071083b0114040404719fccc58818 100644 (file)
@@ -101,6 +101,9 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
+extern int set_dabr(unsigned long dabr);
+extern void _exception(int signr, struct pt_regs *regs, int code,
+                      unsigned long addr);
 extern int fix_alignment(struct pt_regs *regs);
 extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
                           int sig);
index 16ec82e16b21aa18e400e269f386b3d52b3d9ee0..6c5d5ca8383a2abf4e2bd437bdb4ea865a6ec1e5 100644 (file)
@@ -109,9 +109,10 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+extern int disable_timer_pin_1;
+
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#define esr_disable 0
 extern unsigned boot_cpu_id;
 
 #endif /* __ASM_APIC_H */
index 9388062c4f6e52fd409ef099395ca55be862c21d..fb1c99ac669fda16727616a5172aac3c44de2c51 100644 (file)
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
 #define MAX_IO_APICS 128
+#define MAX_LOCAL_APIC 256
 
 /*
  * All x86-64 systems are xAPIC compatible.
index eed785667289fa34b0e287ba7240db98ab9866d3..80ac1fe966ac13ec3be908b2ec94bfaccefb40cc 100644 (file)
@@ -9,10 +9,8 @@
  */
 struct bug_frame {
        unsigned char ud2[2];
-       unsigned char mov;
-       /* should use 32bit offset instead, but the assembler doesn't 
-          like it */
-       char *filename;
+       unsigned char push;
+       signed int filename;
        unsigned char ret;
        unsigned short line;
 } __attribute__((packed));
@@ -25,8 +23,8 @@ struct bug_frame {
    The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
 #define BUG()                                                          \
        asm volatile(                                                   \
-       "ud2 ; .byte 0xa3 ; .quad %c1 ; .byte 0xc2 ; .short %c0" ::     \
-                    "i"(__LINE__), "i" (__stringify(__FILE__)))
+       "ud2 ; pushq $%c1 ; ret $%c0" ::                                \
+                    "i"(__LINE__), "i" (__FILE__))
 void out_of_line_bug(void);
 #else
 static inline void out_of_line_bug(void) { }
index 0bc12655fa5be49e1feada576d01ba3a297b881c..fc2c5a6c262a20356c1fc1dc5e475fa84d97189c 100644 (file)
        .if \skipr11
        .else
        movq (%rsp),%r11
+       CFI_RESTORE r11
        .endif
        .if \skipr8910
        .else
        movq 1*8(%rsp),%r10
+       CFI_RESTORE r10
        movq 2*8(%rsp),%r9
+       CFI_RESTORE r9
        movq 3*8(%rsp),%r8
+       CFI_RESTORE r8
        .endif
        .if \skiprax
        .else
        movq 4*8(%rsp),%rax
+       CFI_RESTORE rax
        .endif
        .if \skiprcx
        .else
        movq 5*8(%rsp),%rcx
+       CFI_RESTORE rcx
        .endif
        .if \skiprdx
        .else
        movq 6*8(%rsp),%rdx
+       CFI_RESTORE rdx
        .endif
        movq 7*8(%rsp),%rsi
+       CFI_RESTORE rsi
        movq 8*8(%rsp),%rdi
+       CFI_RESTORE rdi
        .if ARG_SKIP+\addskip > 0
        addq $ARG_SKIP+\addskip,%rsp
        CFI_ADJUST_CFA_OFFSET   -(ARG_SKIP+\addskip)
 
        .macro RESTORE_REST
        movq (%rsp),%r15
+       CFI_RESTORE r15
        movq 1*8(%rsp),%r14
+       CFI_RESTORE r14
        movq 2*8(%rsp),%r13
+       CFI_RESTORE r13
        movq 3*8(%rsp),%r12
+       CFI_RESTORE r12
        movq 4*8(%rsp),%rbp
+       CFI_RESTORE rbp
        movq 5*8(%rsp),%rbx
+       CFI_RESTORE rbx
        addq $REST_SKIP,%rsp
        CFI_ADJUST_CFA_OFFSET   -(REST_SKIP)
        .endm
        .macro icebp
        .byte 0xf1
        .endm
-
-#ifdef CONFIG_FRAME_POINTER
-#define ENTER enter
-#define LEAVE leave
-#else
-#define ENTER
-#define LEAVE
-#endif
index c89b58bebee24619f9ae2b5ad903b752f5e1ec12..594e610f4a1e7d66aff1a12aa3666e7af8e9dd0a 100644 (file)
@@ -191,7 +191,7 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 /*
  * load one particular LDT into the current CPU
  */
-extern inline void load_LDT_nolock (mm_context_t *pc, int cpu)
+static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
 {
        int count = pc->size;
 
index a416dc31634a207fa4ff3330810ef20dce2829c9..e784fdc524f1ac7be2dce7930995cccab58dc0f6 100644 (file)
@@ -85,6 +85,11 @@ static inline void dma_sync_single_for_device(struct device *hwdev,
        flush_write_buffers();
 }
 
+#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir)       \
+        dma_sync_single_for_cpu(dev, dma_handle, size, dir)
+#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir)    \
+        dma_sync_single_for_device(dev, dma_handle, size, dir)
+
 static inline void dma_sync_sg_for_cpu(struct device *hwdev,
                                       struct scatterlist *sg,
                                       int nelems, int direction)
index afd4212e860bd4e93409c16d38f0184c47c292f4..582757fc03655423d12d96b7baf43d986e6fe031 100644 (file)
 #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
 
 #else
 
 #define CFI_ADJUST_CFA_OFFSET  #
 #define CFI_OFFSET     #
 #define CFI_REL_OFFSET #
+#define CFI_REGISTER   #
+#define CFI_RESTORE    #
+#define CFI_REMEMBER_STATE     #
+#define CFI_RESTORE_STATE      #
 
 #endif
 
index cf8b16cbe8db65e40ce5a84e6e18c8decdcba931..a582cfcf2231a631564bac9aeda0a4422d8f0ca6 100644 (file)
@@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void);
  * directly without translation, we catch the bug with a NULL-deference
  * kernel oops. Illegal ranges of incoming indices are caught too.
  */
-extern inline unsigned long fix_to_virt(const unsigned int idx)
+static inline unsigned long fix_to_virt(const unsigned int idx)
 {
        /*
         * this branch gets completely eliminated after inlining,
index 27c381fa1c9d0e15eb0ff5e60c901a24336bd714..8661b476fb404f74e14d4ed7342e92575c37c50d 100644 (file)
@@ -9,11 +9,12 @@
 
 #define __ARCH_IRQ_STAT 1
 
-/* Generate a lvalue for a pda member. Should fix softirq.c instead to use
-   special access macros. This would generate better code. */ 
-#define __IRQ_STAT(cpu,member) (read_pda(me)->member)
+#define local_softirq_pending() read_pda(__softirq_pending)
 
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#define __ARCH_SET_SOFTIRQ_PENDING 1
+
+#define set_softirq_pending(x) write_pda(__softirq_pending, (x))
+#define or_softirq_pending(x)  or_pda(__softirq_pending, (x))
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
index 2b5cb2865d21de2b835da29788c5b5456e5f2670..dc97668ea0f9d3bc76ffa960fdfc50e596745847 100644 (file)
@@ -26,6 +26,7 @@
 struct hw_interrupt_type;
 #endif
 
+#define NMI_VECTOR             0x02
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
@@ -50,14 +51,15 @@ struct hw_interrupt_type;
  */
 #define SPURIOUS_APIC_VECTOR   0xff
 #define ERROR_APIC_VECTOR      0xfe
-#define INVALIDATE_TLB_VECTOR  0xfd
-#define RESCHEDULE_VECTOR      0xfc
-#define TASK_MIGRATION_VECTOR  0xfb
-#define CALL_FUNCTION_VECTOR   0xfa
-#define KDB_VECTOR     0xf9
-
-#define THERMAL_APIC_VECTOR    0xf0
-
+#define RESCHEDULE_VECTOR      0xfd
+#define CALL_FUNCTION_VECTOR   0xfc
+#define KDB_VECTOR             0xfb    /* reserved for KDB */
+#define THERMAL_APIC_VECTOR    0xfa
+/* 0xf9 free */
+#define INVALIDATE_TLB_VECTOR_END      0xf8
+#define INVALIDATE_TLB_VECTOR_START    0xf0    /* f0-f8 used for TLB flush */
+
+#define NUM_INVALIDATE_TLB_VECTORS     8
 
 /*
  * Local APIC timer IRQ vector is on a different priority level,
index 37fc3f149a5a6a2cf54cf194303d3975d32e85b9..52ff269fe05473ff255d8ced8c87f80a274e57b9 100644 (file)
@@ -48,7 +48,7 @@
  * Talk about misusing macros..
  */
 #define __OUT1(s,x) \
-extern inline void out##s(unsigned x value, unsigned short port) {
+static inline void out##s(unsigned x value, unsigned short port) {
 
 #define __OUT2(s,s1,s2) \
 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
@@ -58,7 +58,7 @@ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
 __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
 
 #define __IN1(s) \
-extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
 
 #define __IN2(s,s1,s2) \
 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
@@ -68,12 +68,12 @@ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
 __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
 
 #define __INS(s) \
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; ins" #s \
 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
 #define __OUTS(s) \
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; outs" #s \
 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
@@ -110,12 +110,12 @@ __OUTS(l)
  * Change virtual addresses to physical addresses and vv.
  * These are pretty trivial
  */
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
 {
        return __pa(address);
 }
 
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
 {
        return __va(address);
 }
@@ -130,7 +130,7 @@ extern inline void * phys_to_virt(unsigned long address)
 
 extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
 {
        return __ioremap(offset, size, 0);
 }
index 5e166b9d3bdeb766cb406eaeea764ef9402fb47d..022e9d340ad759cbc763458ed5df2cc186f2eafe 100644 (file)
 
 static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
 {
-       unsigned int icr =  APIC_DM_FIXED | shortcut | vector | dest;
-       if (vector == KDB_VECTOR)
-               icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
+       unsigned int icr = shortcut | dest;
+
+       switch (vector) {
+       default:
+               icr |= APIC_DM_FIXED | vector;
+               break;
+       case NMI_VECTOR:
+               /*
+                * Setup KDB IPI to be delivered as an NMI
+                */
+       case KDB_VECTOR:
+               icr |= APIC_DM_NMI;
+               break;
+       }
        return icr;
 }
 
@@ -66,7 +77,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write_around(APIC_ICR, cfg);
+       apic_write(APIC_ICR, cfg);
 }
 
 
@@ -92,7 +103,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
                 * prepare target chip field
                 */
                cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
-               apic_write_around(APIC_ICR2, cfg);
+               apic_write(APIC_ICR2, cfg);
 
                /*
                 * program the ICR
@@ -102,7 +113,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
                /*
                 * Send the IPI. The write to APIC_ICR fires this off.
                 */
-               apic_write_around(APIC_ICR, cfg);
+               apic_write(APIC_ICR, cfg);
        }
        local_irq_restore(flags);
 }
index b90341994d80f6e78d18f685cca99e15baea8e37..f604e84c53039e784e10605b3b3e428af9d91deb 100644 (file)
@@ -46,7 +46,7 @@ extern void die(const char *,struct pt_regs *,long);
 extern void __die(const char *,struct pt_regs *,long);
 extern void show_registers(struct pt_regs *regs);
 extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
 
 #endif
index c954f15c1a755f850c60b7e0f0c05a17b1feb2b8..3e72c41727c53af2f7ea75666aab6da56be79a5f 100644 (file)
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
                :"m" (v->counter));
 }
 
-static __inline__ void local_add(unsigned long i, local_t *v)
+static __inline__ void local_add(unsigned int i, local_t *v)
 {
        __asm__ __volatile__(
                "addl %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned long i, local_t *v)
                :"ir" (i), "m" (v->counter));
 }
 
-static __inline__ void local_sub(unsigned long i, local_t *v)
+static __inline__ void local_sub(unsigned int i, local_t *v)
 {
        __asm__ __volatile__(
                "subl %1,%0"
index 768413751b34288c0eb6b1ae5b56f4c5eecb3d13..b40c661f111e32b58f2c07bdd081a89fa4aa4b40 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <asm/smp.h>
 
-#define NODEMAPSIZE 0xff
+#define NODEMAPSIZE 0xfff
 
 /* Simple perfect hash to map physical addresses to node numbers */
 extern int memnode_shift; 
@@ -54,7 +54,7 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
 
 #define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \
                        ({ u8 nid__ = pfn_to_nid(pfn); \
-                          nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
+                          nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); }))
 #endif
 
 #define local_mapnr(kvaddr) \
index ba15279a79d02f826e2c8d79f58d14d50671bfdf..4d727f3f5550bb2eadba0a20829bbf96ff970050 100644 (file)
 #define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32) 
 
 /* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__;                                              \
-       asm volatile("2: wrmsr ; xorl %0,%0\n"                                          \
-                    "1:\n\t"                                                           \
-                    ".section .fixup,\"ax\"\n\t"                                       \
-                    "3:  movl %4,%0 ; jmp 1b\n\t"                                      \
-                    ".previous\n\t"                                                    \
-                    ".section __ex_table,\"a\"\n"                                      \
-                    "   .align 8\n\t"                                                  \
-                    "   .quad  2b,3b\n\t"                                              \
-                    ".previous"                                                        \
-                    : "=a" (ret__)                                                     \
-                    : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
+#define wrmsr_safe(msr,a,b) ({ int ret__;                      \
+       asm volatile("2: wrmsr ; xorl %0,%0\n"                  \
+                    "1:\n\t"                                   \
+                    ".section .fixup,\"ax\"\n\t"               \
+                    "3:  movl %4,%0 ; jmp 1b\n\t"              \
+                    ".previous\n\t"                            \
+                    ".section __ex_table,\"a\"\n"              \
+                    "   .align 8\n\t"                          \
+                    "   .quad  2b,3b\n\t"                      \
+                    ".previous"                                \
+                    : "=a" (ret__)                             \
+                    : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
        ret__; })
 
 #define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
 
+#define rdmsr_safe(msr,a,b) \
+       ({ int ret__;                                           \
+         asm volatile ("1:       rdmsr\n"                      \
+                      "2:\n"                                   \
+                      ".section .fixup,\"ax\"\n"               \
+                      "3:       movl %4,%0\n"                  \
+                      " jmp 2b\n"                              \
+                      ".previous\n"                            \
+                      ".section __ex_table,\"a\"\n"            \
+                      " .align 8\n"                            \
+                      " .quad 1b,3b\n"                         \
+                      ".previous":"=&bDS" (ret__), "=a"(a), "=d"(b)\
+                      :"c"(msr), "i"(-EIO), "0"(0));           \
+         ret__; })             
+
 #define rdtsc(low,high) \
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
 
@@ -64,7 +79,7 @@
                          : "=a" (low), "=d" (high) \
                          : "c" (counter))
 
-extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
                         unsigned int *ecx, unsigned int *edx)
 {
        __asm__("cpuid"
@@ -90,7 +105,7 @@ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
 /*
  * CPUID functions returning a single datum
  */
-extern inline unsigned int cpuid_eax(unsigned int op)
+static inline unsigned int cpuid_eax(unsigned int op)
 {
        unsigned int eax;
 
@@ -100,7 +115,7 @@ extern inline unsigned int cpuid_eax(unsigned int op)
                : "bx", "cx", "dx");
        return eax;
 }
-extern inline unsigned int cpuid_ebx(unsigned int op)
+static inline unsigned int cpuid_ebx(unsigned int op)
 {
        unsigned int eax, ebx;
 
@@ -110,7 +125,7 @@ extern inline unsigned int cpuid_ebx(unsigned int op)
                : "cx", "dx" );
        return ebx;
 }
-extern inline unsigned int cpuid_ecx(unsigned int op)
+static inline unsigned int cpuid_ecx(unsigned int op)
 {
        unsigned int eax, ecx;
 
@@ -120,7 +135,7 @@ extern inline unsigned int cpuid_ecx(unsigned int op)
                : "bx", "dx" );
        return ecx;
 }
-extern inline unsigned int cpuid_edx(unsigned int op)
+static inline unsigned int cpuid_edx(unsigned int op)
 {
        unsigned int eax, edx;
 
index 5c363a1482e43ecada598942d124b87d64a0041a..bcf55c3f7f7f35e0f162c504c5f6030578a857f8 100644 (file)
@@ -9,6 +9,7 @@ struct node {
 };
 
 extern int compute_hash_shift(struct node *nodes, int numnodes);
+extern int pxm_to_node(int nid);
 
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
@@ -16,6 +17,8 @@ extern void numa_add_cpu(int cpu);
 extern void numa_init_array(void);
 extern int numa_off;
 
+extern unsigned char apicid_to_node[256];
+
 #define NUMA_NO_NODE 0xff
 
 #endif
index 135ffaa0393b4d8aa5559241d0f512fb61251742..e5ab4d231f2ce2d837dea8476e7a024f5436060a 100644 (file)
@@ -32,6 +32,8 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+extern unsigned long end_pfn;
+
 void clear_page(void *);
 void copy_page(void *, void *);
 
@@ -111,7 +113,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)       (mem_map + (pfn))
 #define page_to_pfn(page)      ((unsigned long)((page) - mem_map))
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+#define pfn_valid(pfn)         ((pfn) < end_pfn)
 #endif
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
index eeb3088a1c9e3d2fbbff1140b94fad85c69777f9..5a82a6762c2183411c5af255c8c32f2140a0e8c0 100644 (file)
@@ -50,10 +50,10 @@ extern int iommu_setup(char *opt);
  * address space.  The networking and block device layers use
  * this boolean for bounce buffer decisions
  *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
+ * On x86-64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an hard or soft IOMMU is available.
  */
-#define PCI_DMA_BUS_IS_PHYS    (no_iommu ? 1 : 0)
+#define PCI_DMA_BUS_IS_PHYS 0
 
 /*
  * x86-64 always supports DAC, but sometimes it is useful to force
index 36b766cfc4d5630992c14e374d3a550fab7a54eb..bbf89aa8a1afe67a7178b5ada67c3e7368e71484 100644 (file)
 struct x8664_pda {
        struct task_struct *pcurrent;   /* Current process */
        unsigned long data_offset;      /* Per cpu data offset from linker address */
-       struct x8664_pda *me;       /* Pointer to itself */  
        unsigned long kernelstack;  /* top of kernel stack for current */ 
        unsigned long oldrsp;       /* user rsp for system call */
-       unsigned long irqrsp;       /* Old rsp for interrupts. */ 
         int irqcount;              /* Irq nesting counter. Starts with -1 */   
        int cpunumber;              /* Logical CPU number */
        char *irqstackptr;      /* top of irqstack */
@@ -22,7 +20,7 @@ struct x8664_pda {
        struct mm_struct *active_mm;
        int mmu_state;     
        unsigned apic_timer_irqs;
-} ____cacheline_aligned;
+} ____cacheline_aligned_in_smp;
 
 
 #define IRQSTACK_ORDER 2
@@ -42,13 +40,14 @@ extern void __bad_pda_field(void);
 #define pda_offset(field) offsetof(struct x8664_pda, field)
 
 #define pda_to_op(op,field,val) do { \
+       typedef typeof_field(struct x8664_pda, field) T__; \
        switch (sizeof_field(struct x8664_pda, field)) {                \
 case 2: \
-asm volatile(op "w %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 4: \
-asm volatile(op "l %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 8: \
-asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
        default: __bad_pda_field();                                     \
        } \
        } while (0)
@@ -58,7 +57,7 @@ asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); bre
  * Unfortunately removing them causes all hell to break lose currently.
  */
 #define pda_from_op(op,field) ({ \
-       typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \
+       typeof_field(struct x8664_pda, field) ret__; \
        switch (sizeof_field(struct x8664_pda, field)) {                \
 case 2: \
 asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
@@ -75,6 +74,7 @@ asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); b
 #define write_pda(field,val) pda_to_op("mov",field,val)
 #define add_pda(field,val) pda_to_op("add",field,val)
 #define sub_pda(field,val) pda_to_op("sub",field,val)
+#define or_pda(field,val) pda_to_op("or",field,val)
 
 #endif
 
index deadd146978b189c002b81feaa305cdd5da3b8da..08cad2482bcbc56e88ac82cbfb82b0f1ff3f97bb 100644 (file)
@@ -18,12 +18,12 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
        set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
 }
 
-extern __inline__ pmd_t *get_pmd(void)
+static inline pmd_t *get_pmd(void)
 {
        return (pmd_t *)get_zeroed_page(GFP_KERNEL);
 }
 
-extern __inline__ void pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
 {
        BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
        free_page((unsigned long)pmd);
@@ -86,13 +86,13 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
 /* Should really implement gc for free page table pages. This could be
    done with a reference count in struct page. */
 
-extern __inline__ void pte_free_kernel(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
 {
        BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
        free_page((unsigned long)pte); 
 }
 
-extern inline void pte_free(struct page *pte)
+static inline void pte_free(struct page *pte)
 {
        __free_page(pte);
 } 
index 5e0f2fdab0d35885f75f1177d54d18b4117808ec..1dc110ba82d63e80781f514b79cacb0711ee6d25 100644 (file)
@@ -85,7 +85,7 @@ static inline void set_pud(pud_t *dst, pud_t val)
        pud_val(*dst) = pud_val(val);
 }
 
-extern inline void pud_clear (pud_t *pud)
+static inline void pud_clear (pud_t *pud)
 {
        set_pud(pud, __pud(0));
 }
@@ -95,7 +95,7 @@ static inline void set_pgd(pgd_t *dst, pgd_t val)
        pgd_val(*dst) = pgd_val(val); 
 } 
 
-extern inline void pgd_clear (pgd_t * pgd)
+static inline void pgd_clear (pgd_t * pgd)
 {
        set_pgd(pgd, __pgd(0));
 }
@@ -375,7 +375,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 }
  
 /* Change flags of a PTE */
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
        pte_val(pte) &= _PAGE_CHG_MASK;
        pte_val(pte) |= pgprot_val(newprot);
index a8321999448f840e256d142a3cf2a62cd62db120..03837d34fba0ccdb4caab752902f1bc943755876 100644 (file)
@@ -254,7 +254,13 @@ struct thread_struct {
        u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
 
-#define INIT_THREAD  {}
+#define INIT_THREAD  { \
+       .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+#define INIT_TSS  { \
+       .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
@@ -375,13 +381,13 @@ struct extended_sigtable {
 #define ASM_NOP_MAX 8
 
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-extern inline void rep_nop(void)
+static inline void rep_nop(void)
 {
        __asm__ __volatile__("rep;nop": : :"memory");
 }
 
 /* Stop speculative execution */
-extern inline void sync_core(void)
+static inline void sync_core(void)
 { 
        int tmp;
        asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
index f7574196424e1c4e266b1b0d7e9bbd4f5a48f2a3..dbb37b0adb43df3f2ea20d62bc4e398c9bd469be 100644 (file)
@@ -74,9 +74,6 @@ extern void acpi_reserve_bootmem(void);
 
 extern void swap_low_mappings(void);
 
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
 extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
@@ -93,8 +90,6 @@ extern int unhandled_signal(struct task_struct *tsk, int sig);
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
 
-extern unsigned long max_mapnr;
-extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
 
 extern int exception_trace;
index fe9b96d94815f688091d6c1318e1905d8c995ac8..f8d55798535ac4ccf06e1fc46cbc624a6b68cd76 100644 (file)
@@ -143,23 +143,23 @@ typedef struct sigaltstack {
 #undef __HAVE_ARCH_SIG_BITOPS
 #if 0
 
-extern __inline__ void sigaddset(sigset_t *set, int _sig)
+static inline void sigaddset(sigset_t *set, int _sig)
 {
        __asm__("btsq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ void sigdelset(sigset_t *set, int _sig)
+static inline void sigdelset(sigset_t *set, int _sig)
 {
        __asm__("btrq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ int __const_sigismember(sigset_t *set, int _sig)
+static inline int __const_sigismember(sigset_t *set, int _sig)
 {
        unsigned long sig = _sig - 1;
        return 1 & (set->sig[sig / _NSIG_BPW] >> (sig & ~(_NSIG_BPW-1)));
 }
 
-extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
+static inline int __gen_sigismember(sigset_t *set, int _sig)
 {
        int ret;
        __asm__("btq %2,%1\n\tsbbq %0,%0"
@@ -172,7 +172,7 @@ extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
         __const_sigismember((set),(sig)) :     \
         __gen_sigismember((set),(sig)))
 
-extern __inline__ int sigfindinword(unsigned long word)
+static inline int sigfindinword(unsigned long word)
 {
        __asm__("bsfq %1,%0" : "=r"(word) : "rm"(word) : "cc");
        return word;
index de8b57b2b62b934c8bfe6cf3b0fa6fd87b8204f8..24e32611f0bf3d93bc0a41f15fa3678d3006f598 100644 (file)
@@ -72,7 +72,7 @@ static inline int num_booting_cpus(void)
 
 #define raw_smp_processor_id() read_pda(cpunumber)
 
-extern __inline int hard_smp_processor_id(void)
+static inline int hard_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
        return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
index 8606e170a7dc825c40d10d4101a2c721ff20f536..85348e02ad2e1f847580d21e7e8acd878f83fc4f 100644 (file)
@@ -188,7 +188,7 @@ static inline void write_cr4(unsigned long val)
 
 #define __xg(x) ((volatile long *)(x))
 
-extern inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
 {
        *ptr = val;
 }
@@ -253,19 +253,19 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
        case 2:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 4:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 8:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        }
index 24ecf6a637cb47ce9a5097ad1d7f9fecf1f2b26e..f971f45d6d78b63479fa7cf48e9fb4b9efd11833 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASMx8664_TIMEX_H
 #define _ASMx8664_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/8253pit.h>
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
index 505b0cf906ded2658ff91da72b9d51e54e80adcc..4a9c20ea9b105d9523bb712e0b9a30d93aa30047 100644 (file)
@@ -109,6 +109,10 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
 #define TLBSTATE_OK    1
 #define TLBSTATE_LAZY  2
 
+/* Roughly an IPI every 20MB with 4k pages for freeing page table
+   ranges. Cost is about 42k of memory for each CPU. */
+#define ARCH_FREE_PTE_NR 5350  
+
 #endif
 
 #define flush_tlb_kernel_range(start, end) flush_tlb_all()
index c1bc3fad482ed4a4388412ff300a0395f86178a1..1c603cd7e4d096389d7cf92f11b79afcc338b288 100644 (file)
@@ -13,7 +13,6 @@
 extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
-extern unsigned char pci_bus_to_node[];
 extern cpumask_t     node_to_cpumask[];
 
 #ifdef CONFIG_ACPI_NUMA
@@ -26,7 +25,7 @@ extern int __node_distance(int, int);
 #define parent_node(node)              (node)
 #define node_to_first_cpu(node)        (__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)          (node_to_cpumask[node])
-#define pcibus_to_node(bus)            pci_bus_to_node[(bus)->number]
+#define pcibus_to_node(bus)            ((long)(bus->sysdata))  
 #define pcibus_to_cpumask(bus)         node_to_cpumask(pcibus_to_node(bus));
 
 /* sched_domains SD_NODE_INIT for x86_64 machines */
index 2872da23fc7ea5990feb03c110278e012aea7d15..438a3f52f839fa8161fc5c1ac8f2ec7b8f00ec89 100644 (file)
@@ -29,7 +29,6 @@ enum vsyscall_num {
 
 struct vxtime_data {
        long hpet_address;      /* HPET base address */
-       unsigned long hz;       /* HPET clocks / sec */
        int last;
        unsigned long last_tsc;
        long quot;
diff --git a/include/linux/connector.h b/include/linux/connector.h
new file mode 100644 (file)
index 0000000..96de263
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *     connector.h
+ * 
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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
+ */
+
+#ifndef __CONNECTOR_H
+#define __CONNECTOR_H
+
+#include <asm/types.h>
+
+#define CN_IDX_CONNECTOR               0xffffffff
+#define CN_VAL_CONNECTOR               0xffffffff
+
+#define CN_NETLINK_USERS               1
+
+/*
+ * Maximum connector's message size.
+ */
+#define CONNECTOR_MAX_MSG_SIZE         1024
+
+/*
+ * idx and val are unique identifiers which 
+ * are used for message routing and 
+ * must be registered in connector.h for in-kernel usage.
+ */
+
+struct cb_id {
+       __u32 idx;
+       __u32 val;
+};
+
+struct cn_msg {
+       struct cb_id id;
+
+       __u32 seq;
+       __u32 ack;
+
+       __u16 len;              /* Length of the following data */
+       __u16 flags;
+       __u8 data[0];
+};
+
+/*
+ * Notify structure - requests notification about
+ * registering/unregistering idx/val in range [first, first+range].
+ */
+struct cn_notify_req {
+       __u32 first;
+       __u32 range;
+};
+
+/*
+ * Main notification control message
+ * *_notify_num        - number of appropriate cn_notify_req structures after 
+ *                             this struct.
+ * group               - notification receiver's idx.
+ * len                         - total length of the attached data.
+ */
+struct cn_ctl_msg {
+       __u32 idx_notify_num;
+       __u32 val_notify_num;
+       __u32 group;
+       __u32 len;
+       __u8 data[0];
+};
+
+#ifdef __KERNEL__
+
+#include <asm/atomic.h>
+
+#include <linux/list.h>
+#include <linux/workqueue.h>
+
+#include <net/sock.h>
+
+#define CN_CBQ_NAMELEN         32
+
+struct cn_queue_dev {
+       atomic_t refcnt;
+       unsigned char name[CN_CBQ_NAMELEN];
+
+       struct workqueue_struct *cn_queue;
+
+       struct list_head queue_list;
+       spinlock_t queue_lock;
+
+       int netlink_groups;
+       struct sock *nls;
+};
+
+struct cn_callback {
+       unsigned char name[CN_CBQ_NAMELEN];
+
+       struct cb_id id;
+       void (*callback) (void *);
+       void *priv;
+};
+
+struct cn_callback_entry {
+       struct list_head callback_entry;
+       struct cn_callback *cb;
+       struct work_struct work;
+       struct cn_queue_dev *pdev;
+
+       void (*destruct_data) (void *);
+       void *ddata;
+
+       int seq, group;
+       struct sock *nls;
+};
+
+struct cn_ctl_entry {
+       struct list_head notify_entry;
+       struct cn_ctl_msg *msg;
+};
+
+struct cn_dev {
+       struct cb_id id;
+
+       u32 seq, groups;
+       struct sock *nls;
+       void (*input) (struct sock * sk, int len);
+
+       struct cn_queue_dev *cbdev;
+};
+
+int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
+void cn_del_callback(struct cb_id *);
+int cn_netlink_send(struct cn_msg *, u32, int);
+
+int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb);
+void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
+
+struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
+void cn_queue_free_dev(struct cn_queue_dev *dev);
+
+int cn_cb_equal(struct cb_id *, struct cb_id *);
+
+extern int cn_already_initialized;
+
+#endif                         /* __KERNEL__ */
+#endif                         /* __CONNECTOR_H */
index bdedf825b04a5b7dc824b2dc8f7982a4f9bd704b..9443c084f8811d79bbd7904ff14f95fe2ecee42c 100644 (file)
@@ -1,22 +1,11 @@
 /*
  *     crc16.h - CRC-16 routine
  *
- * Implements the standard CRC-16, as used with 1-wire devices:
+ * Implements the standard CRC-16:
  *   Width 16
  *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
  *   Init  0
  *
- * For 1-wire devices, the CRC is stored inverted, LSB-first
- *
- * Example buffer with the CRC attached:
- *   31 32 33 34 35 36 37 38 39 C2 44
- *
- * The CRC over a buffer with the CRC attached is 0xB001.
- * So, if (crc16(0, buf, size) == 0xB001) then the buffer is valid.
- *
- * Refer to "Application Note 937: Book of iButton Standards" for details.
- * http://www.maxim-ic.com/appnotes.cfm/appnote_number/937
- *
  * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
  *
  * This source code is licensed under the GNU General Public License,
@@ -28,9 +17,6 @@
 
 #include <linux/types.h>
 
-#define CRC16_INIT             0
-#define CRC16_VALID            0xb001
-
 extern u16 const crc16_table[256];
 
 extern u16 crc16(u16 crc, const u8 *buffer, size_t len);
index c30175e8dec67fa39f7a7fb1bf753f4fa40d0dda..a415f1d93e9a4f6c6c647dd851bc19be7ef3035b 100644 (file)
@@ -70,7 +70,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name,
 
 static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
 static inline char * dmi_get_system_info(int field) { return NULL; }
-static struct dmi_device * dmi_find_device(int type, const char *name,
+static inline struct dmi_device * dmi_find_device(int type, const char *name,
        struct dmi_device *from) { return NULL; }
 
 #endif
index d99e7aeb7d338a9fde859840ab4aff555f20e488..0a90205184b0b4511776604fd0b37a6fc0cf6bc1 100644 (file)
@@ -57,6 +57,11 @@ extern void disable_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
 #endif
 
+#ifndef __ARCH_SET_SOFTIRQ_PENDING
+#define set_softirq_pending(x) (local_softirq_pending() = (x))
+#define or_softirq_pending(x)  (local_softirq_pending() |= (x))
+#endif
+
 /*
  * Temporary defines for UP kernels, until all code gets fixed.
  */
@@ -123,7 +128,7 @@ struct softirq_action
 asmlinkage void do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
 extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 extern void FASTCALL(raise_softirq(unsigned int nr));
 
index 1675186689361370861897bd7b12a1003c9e5af3..7bbd25970c9ebfb4a5a73ef1b555082e748e6752 100644 (file)
@@ -15,6 +15,7 @@
 #define NETLINK_ISCSI          8       /* Open-iSCSI */
 #define NETLINK_AUDIT          9       /* auditing */
 #define NETLINK_FIB_LOOKUP     10      
+#define NETLINK_CONNECTOR      11
 #define NETLINK_NETFILTER      12      /* netfilter subsystem */
 #define NETLINK_IP6_FW         13
 #define NETLINK_DNRTMSG                14      /* DECnet routing messages */
index ed3bb19d13372c56aeac9ddac804162844378812..38c8654aaa96b66d327a09aa2b2cf9effb49674d 100644 (file)
@@ -785,7 +785,6 @@ struct task_struct {
        short il_next;
 #endif
 #ifdef CONFIG_CPUSETS
-       short cpuset_sem_nest_depth;
        struct cpuset *cpuset;
        nodemask_t mems_allowed;
        int cpuset_mems_generation;
index 532a6c5c24e9cc105b30accf34f4a6e792967988..3a29a9f9b451d7f3b0e6135ff7d4fcc0fa886027 100644 (file)
@@ -544,7 +544,8 @@ enum {
        NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8,
        NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9,
        NET_NETROM_ROUTING_CONTROL=10,
-       NET_NETROM_LINK_FAILS_COUNT=11
+       NET_NETROM_LINK_FAILS_COUNT=11,
+       NET_NETROM_RESET=12
 };
 
 /* /proc/sys/net/ax25 */
index fb57c221746827a06a1f7153ad794728771b1c89..9facf733800ccb99a7fb59e2be87b9a7846ada57 100644 (file)
@@ -32,7 +32,6 @@
 #define _LINUX_USBDEVICE_FS_H
 
 #include <linux/types.h>
-#include <linux/compat.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -125,6 +124,7 @@ struct usbdevfs_hub_portinfo {
 };
 
 #ifdef CONFIG_COMPAT
+#include <linux/compat.h>
 struct usbdevfs_urb32 {
        unsigned char type;
        unsigned char endpoint;
index 227d3378decd8cf86d8467652f6e9ebc9e3daec5..9dbcd9e51c00a33d1502824929468ce6a9e594c2 100644 (file)
 
 /* AX.25 Protocol IDs */
 #define AX25_P_ROSE                    0x01
-#define AX25_P_IP                      0xCC
-#define AX25_P_ARP                     0xCD
-#define AX25_P_TEXT                    0xF0
-#define AX25_P_NETROM                  0xCF
-#define        AX25_P_SEGMENT                  0x08
+#define AX25_P_VJCOMP                  0x06    /* Compressed TCP/IP packet   */
+                                               /* Van Jacobsen (RFC 1144)    */
+#define AX25_P_VJUNCOMP                        0x07    /* Uncompressed TCP/IP packet */
+                                               /* Van Jacobsen (RFC 1144)    */
+#define        AX25_P_SEGMENT                  0x08    /* Segmentation fragment      */
+#define AX25_P_TEXNET                  0xc3    /* TEXTNET datagram protocol  */
+#define AX25_P_LQ                      0xc4    /* Link Quality Protocol      */
+#define AX25_P_ATALK                   0xca    /* Appletalk                  */
+#define AX25_P_ATALK_ARP               0xcb    /* Appletalk ARP              */
+#define AX25_P_IP                      0xcc    /* ARPA Internet Protocol     */
+#define AX25_P_ARP                     0xcd    /* ARPA Adress Resolution     */
+#define AX25_P_FLEXNET                 0xce    /* FlexNet                    */
+#define AX25_P_NETROM                  0xcf    /* NET/ROM                    */
+#define AX25_P_TEXT                    0xF0    /* No layer 3 protocol impl.  */
 
 /* AX.25 Segment control values */
 #define        AX25_SEG_REM                    0x7F
 /* Define Link State constants. */
 
 enum { 
-       AX25_STATE_0,
-       AX25_STATE_1,
-       AX25_STATE_2,
-       AX25_STATE_3,
-       AX25_STATE_4
+       AX25_STATE_0,                   /* Listening */
+       AX25_STATE_1,                   /* SABM sent */
+       AX25_STATE_2,                   /* DISC sent */
+       AX25_STATE_3,                   /* Established */
+       AX25_STATE_4                    /* Recovery */
 };
 
 #define AX25_MODULUS           8       /*  Standard AX.25 modulus */
@@ -319,7 +328,7 @@ extern int  ax25_rx_iframe(ax25_cb *, struct sk_buff *);
 extern int  ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
 
 /* ax25_ip.c */
-extern int  ax25_encapsulate(struct sk_buff *, struct net_device *, unsigned short, void *, void *, unsigned int);
+extern int  ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short, void *, void *, unsigned int);
 extern int  ax25_rebuild_header(struct sk_buff *);
 
 /* ax25_out.c */
index 45f2c7616d8b8566e690aedbdecb66db9ccea9d3..a6bf6e0f606aed23ac8a8b4a2583bc5d7d6a8d19 100644 (file)
@@ -6,6 +6,7 @@
 
 #ifndef _NETROM_H
 #define _NETROM_H 
+
 #include <linux/netrom.h>
 #include <linux/list.h>
 #include <net/sock.h>
@@ -22,6 +23,7 @@
 #define        NR_DISCACK                      0x04
 #define        NR_INFO                         0x05
 #define        NR_INFOACK                      0x06
+#define        NR_RESET                        0x07
 
 #define        NR_CHOKE_FLAG                   0x80
 #define        NR_NAK_FLAG                     0x40
@@ -51,11 +53,16 @@ enum {
 #define        NR_DEFAULT_TTL                  16              /* Default Time To Live - 16 */
 #define        NR_DEFAULT_ROUTING              1               /* Is routing enabled ? */
 #define        NR_DEFAULT_FAILS                2               /* Link fails until route fails */
+#define        NR_DEFAULT_RESET                0               /* Sent / accept reset cmds? */
 
 #define NR_MODULUS                     256
 #define NR_MAX_WINDOW_SIZE             127                     /* Maximum Window Allowable - 127 */
 #define        NR_MAX_PACKET_SIZE              236                     /* Maximum Packet Length - 236 */
 
+struct nr_private {
+       struct net_device_stats stats;
+};
+
 struct nr_sock {
        struct sock             sock;
        ax25_address            user_addr, source_addr, dest_addr;
@@ -176,6 +183,8 @@ extern int  sysctl_netrom_transport_requested_window_size;
 extern int  sysctl_netrom_transport_no_activity_timeout;
 extern int  sysctl_netrom_routing_control;
 extern int  sysctl_netrom_link_fails_count;
+extern int  sysctl_netrom_reset_circuit;
+
 extern int  nr_rx_frame(struct sk_buff *, struct net_device *);
 extern void nr_destroy_socket(struct sock *);
 
@@ -218,7 +227,28 @@ extern void nr_requeue_frames(struct sock *);
 extern int  nr_validate_nr(struct sock *, unsigned short);
 extern int  nr_in_rx_window(struct sock *, unsigned short);
 extern void nr_write_internal(struct sock *, int);
-extern void nr_transmit_refusal(struct sk_buff *, int);
+
+extern void __nr_transmit_reply(struct sk_buff *skb, int mine,
+       unsigned char cmdflags);
+
+/*
+ * This routine is called when a Connect Acknowledge with the Choke Flag
+ * set is needed to refuse a connection.
+ */
+#define nr_transmit_refusal(skb, mine)                                 \
+do {                                                                   \
+       __nr_transmit_reply((skb), (mine), NR_CONNACK | NR_CHOKE_FLAG); \
+} while (0)
+
+/*
+ * This routine is called when we don't have a circuit matching an incoming
+ * NET/ROM packet.  This is an G8PZT Xrouter extension.
+ */
+#define nr_transmit_reset(skb, mine)                                   \
+do {                                                                   \
+       __nr_transmit_reply((skb), (mine), NR_RESET);                   \
+} while (0)
+
 extern void nr_disconnect(struct sock *, int);
 
 /* nr_timer.c */
index 407b5f0a8c8eeed2aea648b08748771dd284b3d7..79866bc6b3a154d06c4b42daa3daec60aa96ebd9 100644 (file)
@@ -180,6 +180,8 @@ static struct super_block *cpuset_sb = NULL;
  */
 
 static DECLARE_MUTEX(cpuset_sem);
+static struct task_struct *cpuset_sem_owner;
+static int cpuset_sem_depth;
 
 /*
  * The global cpuset semaphore cpuset_sem can be needed by the
@@ -200,16 +202,19 @@ static DECLARE_MUTEX(cpuset_sem);
 
 static inline void cpuset_down(struct semaphore *psem)
 {
-       if (current->cpuset_sem_nest_depth == 0)
+       if (cpuset_sem_owner != current) {
                down(psem);
-       current->cpuset_sem_nest_depth++;
+               cpuset_sem_owner = current;
+       }
+       cpuset_sem_depth++;
 }
 
 static inline void cpuset_up(struct semaphore *psem)
 {
-       current->cpuset_sem_nest_depth--;
-       if (current->cpuset_sem_nest_depth == 0)
+       if (--cpuset_sem_depth == 0) {
+               cpuset_sem_owner = NULL;
                up(psem);
+       }
 }
 
 /*
index e9ff04a9b56df3e424dff87eec851196f72c0d4c..81b3a96ed2d09a79f7937503a88c3ced4c959953 100644 (file)
@@ -3576,32 +3576,6 @@ task_t *idle_task(int cpu)
        return cpu_rq(cpu)->idle;
 }
 
-/**
- * curr_task - return the current task for a given cpu.
- * @cpu: the processor in question.
- */
-task_t *curr_task(int cpu)
-{
-       return cpu_curr(cpu);
-}
-
-/**
- * set_curr_task - set the current task for a given cpu.
- * @cpu: the processor in question.
- * @p: the task pointer to set.
- *
- * Description: This function must only be used when non-maskable interrupts
- * are serviced on a separate stack.  It allows the architecture to switch the
- * notion of the current task on a cpu in a non-blocking manner.  This function
- * must be called with interrupts disabled, the caller must save the original
- * value of the current task (see curr_task() above) and restore that value
- * before reenabling interrupts.
- */
-void set_curr_task(int cpu, task_t *p)
-{
-       cpu_curr(cpu) = p;
-}
-
 /**
  * find_process_by_pid - find a process with a matching PID value.
  * @pid: the pid in question.
@@ -5628,3 +5602,47 @@ void normalize_rt_tasks(void)
 }
 
 #endif /* CONFIG_MAGIC_SYSRQ */
+
+#ifdef CONFIG_IA64
+/*
+ * These functions are only useful for the IA64 MCA handling.
+ *
+ * They can only be called when the whole system has been
+ * stopped - every CPU needs to be quiescent, and no scheduling
+ * activity can take place. Using them for anything else would
+ * be a serious bug, and as a result, they aren't even visible
+ * under any other configuration.
+ */
+
+/**
+ * curr_task - return the current task for a given cpu.
+ * @cpu: the processor in question.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+task_t *curr_task(int cpu)
+{
+       return cpu_curr(cpu);
+}
+
+/**
+ * set_curr_task - set the current task for a given cpu.
+ * @cpu: the processor in question.
+ * @p: the task pointer to set.
+ *
+ * Description: This function must only be used when non-maskable interrupts
+ * are serviced on a separate stack.  It allows the architecture to switch the
+ * notion of the current task on a cpu in a non-blocking manner.  This function
+ * must be called with all CPU's synchronized, and interrupts disabled, the
+ * and caller must save the original value of the current task (see
+ * curr_task() above) and restore that value before reenabling interrupts and
+ * re-starting the system.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+void set_curr_task(int cpu, task_t *p)
+{
+       cpu_curr(cpu) = p;
+}
+
+#endif
index b4ab6af1dea8513147c19694a8eff8a4353c69e0..f766b2fc48be8cd54cc254c91660ec414603a2c5 100644 (file)
@@ -84,7 +84,7 @@ asmlinkage void __do_softirq(void)
        cpu = smp_processor_id();
 restart:
        /* Reset the pending bitmask before enabling irqs */
-       local_softirq_pending() = 0;
+       set_softirq_pending(0);
 
        local_irq_enable();
 
index 3754c9a8f5c8e1e3fccebf2d0f282fd5eda6bcb4..016e89a44ac8defe6c753bd73d6bc74aa4e48e0f 100644 (file)
@@ -170,11 +170,11 @@ config DEBUG_FS
 
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
-       depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
        default y if DEBUG_INFO && UML
        help
          If you say Y here the resulting kernel image will be slightly larger
-         and slower, but it will give very useful debugging information.
-         If you don't debug the kernel, you can say N, but we may not be able
-         to solve problems without frame pointers.
+         and slower, but it might give very useful debugging information
+         on some architectures or you use external debuggers.
+         If you don't debug the kernel, you can say N.
 
index c1330cc197835ae66bffaa2baacc032ace0020b4..8ec4e4c2a179f5fc1a8d7ddb648dad0d9f69cdbb 100644 (file)
@@ -61,9 +61,17 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
 {
        bootmem_data_t *bdata = pgdat->bdata;
        unsigned long mapsize = ((end - start)+7)/8;
-
-       pgdat->pgdat_next = pgdat_list;
-       pgdat_list = pgdat;
+       static struct pglist_data *pgdat_last;
+
+       pgdat->pgdat_next = NULL;
+       /* Add new nodes last so that bootmem always starts
+          searching in the first nodes, not the last ones */
+       if (pgdat_last)
+               pgdat_last->pgdat_next = pgdat;
+       else {
+               pgdat_list = pgdat;     
+               pgdat_last = pgdat;
+       }
 
        mapsize = ALIGN(mapsize, sizeof(long));
        bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
index fd4e8df0f02df979bb2a2de5a891e35f82754a7d..064d70442895a05f9dbba0db0ecdcf72cf044e60 100644 (file)
@@ -57,6 +57,11 @@ DECLARE_RWSEM(nommu_vma_sem);
 struct vm_operations_struct generic_file_vm_ops = {
 };
 
+EXPORT_SYMBOL(vmalloc);
+EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_32);
+
 /*
  * Handle all mappings that got truncated by a "truncate()"
  * system call.
@@ -142,6 +147,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        return(i);
 }
 
+EXPORT_SYMBOL(get_user_pages);
+
 DEFINE_RWLOCK(vmlist_lock);
 struct vm_struct *vmlist;
 
@@ -852,7 +859,7 @@ unsigned long do_mmap_pgoff(struct file *file,
  error_getting_vma:
        up_write(&nommu_vma_sem);
        kfree(vml);
-       printk("Allocation of vml for %lu byte allocation from process %d failed\n",
+       printk("Allocation of vma for %lu byte allocation from process %d failed\n",
               len, current->pid);
        show_free_areas();
        return -ENOMEM;
@@ -909,7 +916,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 
        for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
                if ((*parent)->vma->vm_start == addr &&
-                   (*parent)->vma->vm_end == end)
+                   ((len == 0) || ((*parent)->vma->vm_end == end)))
                        goto found;
 
        printk("munmap of non-mmaped memory by process %d (%s): %p\n",
@@ -1054,7 +1061,8 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
                unsigned long to, unsigned long size, pgprot_t prot)
 {
-       return -EPERM;
+       vma->vm_start = vma->vm_pgoff << PAGE_SHIFT;
+       return 0;
 }
 
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -1073,9 +1081,10 @@ void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 
 void update_mem_hiwater(struct task_struct *tsk)
 {
-       unsigned long rss = get_mm_counter(tsk->mm, rss);
+       unsigned long rss;
 
        if (likely(tsk->mm)) {
+               rss = get_mm_counter(tsk->mm, rss);
                if (tsk->mm->hiwater_rss < rss)
                        tsk->mm->hiwater_rss = rss;
                if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
index ed705ddad56be0e9bb6b69580b681b1e5c91f6d0..8e37e71e34ff1929aef5a8b8efb2ef362dec6b54 100644 (file)
@@ -1695,16 +1695,12 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                /* These two are safe on a single CPU system as only user tasks fiddle here */
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
-               res = put_user(amount, (int __user *)argp);
+               res = put_user(amount, (int __user *) argp);
                break;
        }
 
        case SIOCGSTAMP:
-               if (sk != NULL) {
-                       res = sock_get_timestamp(sk, argp);
-                       break;
-               }
-               res = -EINVAL;
+               res = sock_get_timestamp(sk, argp);
                break;
 
        case SIOCAX25ADDUID:    /* Add a uid to the uid/call map table */
@@ -1951,24 +1947,24 @@ static struct net_proto_family ax25_family_ops = {
 };
 
 static struct proto_ops ax25_proto_ops = {
-       .family =       PF_AX25,
-       .owner =        THIS_MODULE,
-       .release =      ax25_release,
-       .bind =         ax25_bind,
-       .connect =      ax25_connect,
-       .socketpair =   sock_no_socketpair,
-       .accept =       ax25_accept,
-       .getname =      ax25_getname,
-       .poll =         datagram_poll,
-       .ioctl =        ax25_ioctl,
-       .listen =       ax25_listen,
-       .shutdown =     ax25_shutdown,
-       .setsockopt =   ax25_setsockopt,
-       .getsockopt =   ax25_getsockopt,
-       .sendmsg =      ax25_sendmsg,
-       .recvmsg =      ax25_recvmsg,
-       .mmap =         sock_no_mmap,
-       .sendpage =     sock_no_sendpage,
+       .family         = PF_AX25,
+       .owner          = THIS_MODULE,
+       .release        = ax25_release,
+       .bind           = ax25_bind,
+       .connect        = ax25_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = ax25_accept,
+       .getname        = ax25_getname,
+       .poll           = datagram_poll,
+       .ioctl          = ax25_ioctl,
+       .listen         = ax25_listen,
+       .shutdown       = ax25_shutdown,
+       .setsockopt     = ax25_setsockopt,
+       .getsockopt     = ax25_getsockopt,
+       .sendmsg        = ax25_sendmsg,
+       .recvmsg        = ax25_recvmsg,
+       .mmap           = sock_no_mmap,
+       .sendpage       = sock_no_sendpage,
 };
 
 /*
@@ -1984,7 +1980,7 @@ static struct notifier_block ax25_dev_notifier = {
        .notifier_call =ax25_device_event,
 };
 
-EXPORT_SYMBOL(ax25_encapsulate);
+EXPORT_SYMBOL(ax25_hard_header);
 EXPORT_SYMBOL(ax25_rebuild_header);
 EXPORT_SYMBOL(ax25_findbyuid);
 EXPORT_SYMBOL(ax25_find_cb);
index bba0173e2d6500a44954871389fc5e35396dffa2..d643dac3eccc6981b8d56b1a9c1ba20fa3b5bcf4 100644 (file)
@@ -47,7 +47,7 @@
 
 #ifdef CONFIG_INET
 
-int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
 {
        unsigned char *buff;
 
@@ -88,7 +88,7 @@ int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short
                *buff++ = AX25_P_ARP;
                break;
        default:
-               printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%2.2x\n", type);
+               printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
                *buff++ = 0;
                break;
        }
@@ -209,7 +209,7 @@ put:
 
 #else  /* INET */
 
-int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
 {
        return -AX25_HEADER_LEN;
 }
index b3ad49fa7d787ad7d8a01feb7a1a62f3faaa0bd9..ef430b1e8e42acc87af3d12fb4c95544c8996570 100644 (file)
@@ -1452,8 +1452,7 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
                thread_lock();
                t->control |= T_REMDEV;
                thread_unlock();
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(HZ/8);  /* Propagate thread->control  */
+               schedule_timeout_interruptible(msecs_to_jiffies(125));  /* Propagate thread->control  */
                ret = count;
                 sprintf(pg_result, "OK: rem_device_all");
                goto out;
@@ -1716,10 +1715,9 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
        printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
        while (now < spin_until_us) {
                /* TODO: optimise sleeping behavior */
-               if (spin_until_us - now > (1000000/HZ)+1) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(1);
-               } else if (spin_until_us - now > 100) {
+               if (spin_until_us - now > jiffies_to_usecs(1)+1)
+                       schedule_timeout_interruptible(1);
+               else if (spin_until_us - now > 100) {
                        do_softirq();
                        if (!pkt_dev->running)
                                return;
@@ -2449,8 +2447,7 @@ static void pktgen_run_all_threads(void)
        }
        thread_unlock();
 
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ/8);  /* Propagate thread->control  */
+       schedule_timeout_interruptible(msecs_to_jiffies(125));  /* Propagate thread->control  */
                        
        pktgen_wait_all_threads_run();
 }
index e05f4f955eeee8d0bd68eae5ccfab3bc674bec8b..38aa84986118564379043c462b19e832f8342933 100644 (file)
@@ -1095,6 +1095,10 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 {
        const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 
+       /* Listen socks doesn't have a private CCID block */
+       if (sk->sk_state == DCCP_LISTEN)
+               return;
+
        BUG_ON(hcrx == NULL);
 
        info->tcpi_ca_state     = hcrx->ccid3hcrx_state;
@@ -1106,6 +1110,10 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
 {
        const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
+       /* Listen socks doesn't have a private CCID block */
+       if (sk->sk_state == DCCP_LISTEN)
+               return;
+
        BUG_ON(hctx == NULL);
 
        info->tcpi_rto = hctx->ccid3hctx_t_rto;
index 953129d392d21cc97f551f93c519b491cb0190cc..e8674baaa8d99034ee0d56a7fdbdfc66d205abf6 100644 (file)
@@ -1103,10 +1103,8 @@ static int __init ic_dynamic(void)
 #endif
 
                jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
-               while (time_before(jiffies, jiff) && !ic_got_reply) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               while (time_before(jiffies, jiff) && !ic_got_reply)
+                       schedule_timeout_uninterruptible(1);
 #ifdef IPCONFIG_DHCP
                /* DHCP isn't done until we get a DHCPACK. */
                if ((ic_got_reply & IC_BOOTP)
index 5d1e61168eb72d77c18f9fa278fa8a92516577f0..6f20b4206e08a56bc3b79902b9fededeac826cd9 100644 (file)
@@ -567,10 +567,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
        self->tty = NULL;
 
        if (self->blocked_open) {
-               if (self->close_delay) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(self->close_delay);
-               }
+               if (self->close_delay)
+                       schedule_timeout_interruptible(self->close_delay);
                wake_up_interruptible(&self->open_wait);
        }
 
@@ -863,8 +861,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
        spin_lock_irqsave(&self->spinlock, flags);
        while (self->tx_skb && self->tx_skb->len) {
                spin_unlock_irqrestore(&self->spinlock, flags);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(poll_time);
+               schedule_timeout_interruptible(poll_time);
                spin_lock_irqsave(&self->spinlock, flags);
                if (signal_pending(current))
                        break;
index f4578c759ffcc3350ebbd708c7f0a2ffef52c587..e5d82d711cae2ea36e1e36e652fdeebd0b5db591 100644 (file)
@@ -56,6 +56,7 @@ int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW;
 int sysctl_netrom_transport_no_activity_timeout   = NR_DEFAULT_IDLE;
 int sysctl_netrom_routing_control                 = NR_DEFAULT_ROUTING;
 int sysctl_netrom_link_fails_count                = NR_DEFAULT_FAILS;
+int sysctl_netrom_reset_circuit                   = NR_DEFAULT_RESET;
 
 static unsigned short circuit = 0x101;
 
@@ -908,17 +909,17 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
        if (frametype != NR_CONNREQ) {
                /*
                 * Here it would be nice to be able to send a reset but
-                * NET/ROM doesn't have one. The following hack would
-                * have been a way to extend the protocol but apparently
-                * it kills BPQ boxes... :-(
+                * NET/ROM doesn't have one.  We've tried to extend the protocol
+                * by sending NR_CONNACK | NR_CHOKE_FLAGS replies but that
+                * apparently kills BPQ boxes... :-(
+                * So now we try to follow the established behaviour of
+                * G8PZT's Xrouter which is sending packets with command type 7
+                * as an extension of the protocol.
                 */
-#if 0
-               /*
-                * Never reply to a CONNACK/CHOKE.
-                */
-               if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG)
-                       nr_transmit_refusal(skb, 1);
-#endif
+               if (sysctl_netrom_reset_circuit &&
+                   (frametype != NR_RESET || flags != 0))
+                       nr_transmit_reset(skb, 1);
+
                return 0;
        }
 
@@ -1187,9 +1188,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        }
 
        case SIOCGSTAMP:
-               ret = -EINVAL;
-               if (sk != NULL)
-                       ret = sock_get_timestamp(sk, argp);
+               ret = sock_get_timestamp(sk, argp);
                release_sock(sk);
                return ret;
 
@@ -1393,8 +1392,7 @@ static int __init nr_proto_init(void)
                struct net_device *dev;
 
                sprintf(name, "nr%d", i);
-               dev = alloc_netdev(sizeof(struct net_device_stats), name,
-                                         nr_setup);
+               dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup);
                if (!dev) {
                        printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
                        goto fail;
index 263da4c26494cb2cf875d22b75ca773be770c8b8..4e66eef9a03479f0ead803fabdfb3d1f73e0b18f 100644 (file)
@@ -47,7 +47,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
        struct net_device_stats *stats = netdev_priv(dev);
 
        if (!netif_running(dev)) {
-               stats->rx_errors++;
+               stats->rx_dropped++;
                return 0;
        }
 
@@ -71,15 +71,10 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
 
 static int nr_rebuild_header(struct sk_buff *skb)
 {
-       struct net_device *dev = skb->dev;
-       struct net_device_stats *stats = netdev_priv(dev);
-       struct sk_buff *skbn;
        unsigned char *bp = skb->data;
-       int len;
 
-       if (arp_find(bp + 7, skb)) {
+       if (arp_find(bp + 7, skb))
                return 1;
-       }
 
        bp[6] &= ~AX25_CBIT;
        bp[6] &= ~AX25_EBIT;
@@ -90,27 +85,7 @@ static int nr_rebuild_header(struct sk_buff *skb)
        bp[6] |= AX25_EBIT;
        bp[6] |= AX25_SSSID_SPARE;
 
-       if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-               kfree_skb(skb);
-               return 1;
-       }
-
-       if (skb->sk != NULL)
-               skb_set_owner_w(skbn, skb->sk);
-
-       kfree_skb(skb);
-
-       len = skbn->len;
-
-       if (!nr_route_frame(skbn, NULL)) {
-               kfree_skb(skbn);
-               stats->tx_errors++;
-       }
-
-       stats->tx_packets++;
-       stats->tx_bytes += len;
-
-       return 1;
+       return 0;
 }
 
 #else
@@ -185,15 +160,27 @@ static int nr_close(struct net_device *dev)
 
 static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct net_device_stats *stats = netdev_priv(dev);
-       dev_kfree_skb(skb);
-       stats->tx_errors++;
+       struct nr_private *nr = netdev_priv(dev);
+       struct net_device_stats *stats = &nr->stats;
+       unsigned int len = skb->len;
+
+       if (!nr_route_frame(skb, NULL)) {
+               kfree_skb(skb);
+               stats->tx_errors++;
+               return 0;
+       }
+
+       stats->tx_packets++;
+       stats->tx_bytes += len;
+
        return 0;
 }
 
 static struct net_device_stats *nr_get_stats(struct net_device *dev)
 {
-       return netdev_priv(dev);
+       struct nr_private *nr = netdev_priv(dev);
+
+       return &nr->stats;
 }
 
 void nr_setup(struct net_device *dev)
@@ -208,12 +195,11 @@ void nr_setup(struct net_device *dev)
        dev->hard_header_len    = NR_NETWORK_LEN + NR_TRANSPORT_LEN;
        dev->addr_len           = AX25_ADDR_LEN;
        dev->type               = ARPHRD_NETROM;
-       dev->tx_queue_len       = 40;
        dev->rebuild_header     = nr_rebuild_header;
        dev->set_mac_address    = nr_set_mac_address;
 
        /* New-style flags. */
-       dev->flags              = 0;
+       dev->flags              = IFF_NOARP;
 
        dev->get_stats          = nr_get_stats;
 }
index 64b81a7969077c706353e76309a67698380f2095..004e8599b8fe595f5b72c92b0b51bb203b99a44d 100644 (file)
@@ -98,6 +98,11 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
                nr_disconnect(sk, ECONNREFUSED);
                break;
 
+       case NR_RESET:
+               if (sysctl_netrom_reset_circuit);
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+
        default:
                break;
        }
@@ -124,6 +129,11 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
                nr_disconnect(sk, 0);
                break;
 
+       case NR_RESET:
+               if (sysctl_netrom_reset_circuit);
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+
        default:
                break;
        }
@@ -254,6 +264,11 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
                }
                break;
 
+       case NR_RESET:
+               if (sysctl_netrom_reset_circuit);
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+
        default:
                break;
        }
index 587bed2674bfb4dcb09e40f13ae0d33b8342e053..bcb9946b4f5628f59276cfed1082c33135d95119 100644 (file)
@@ -210,10 +210,9 @@ void nr_write_internal(struct sock *sk, int frametype)
 }
 
 /*
- * This routine is called when a Connect Acknowledge with the Choke Flag
- * set is needed to refuse a connection.
+ * This routine is called to send an error reply.
  */
-void nr_transmit_refusal(struct sk_buff *skb, int mine)
+void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags)
 {
        struct sk_buff *skbn;
        unsigned char *dptr;
@@ -254,7 +253,7 @@ void nr_transmit_refusal(struct sk_buff *skb, int mine)
                *dptr++ = 0;
        }
 
-       *dptr++ = NR_CONNACK | NR_CHOKE_FLAG;
+       *dptr++ = cmdflags;
        *dptr++ = 0;
 
        if (!nr_route_frame(skbn, NULL))
index c9ed50382ea7bb067766173207bafbade894f984..6bb8dda849dc71d1de1bd13ca8942eb6d607316f 100644 (file)
@@ -30,6 +30,7 @@ static int min_idle[]    = {0 * HZ};
 static int max_idle[]    = {65535 * HZ};
 static int min_route[]   = {0}, max_route[]   = {1};
 static int min_fails[]   = {1}, max_fails[]   = {10};
+static int min_reset[]   = {0}, max_reset[]   = {1};
 
 static struct ctl_table_header *nr_table_header;
 
@@ -155,6 +156,17 @@ static ctl_table nr_table[] = {
                .extra1         = &min_fails,
                .extra2         = &max_fails
        },
+        {
+               .ctl_name       = NET_NETROM_RESET,
+               .procname       = "reset",
+               .data           = &sysctl_netrom_reset_circuit,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &min_reset,
+               .extra2         = &max_reset
+       },
        { .ctl_name = 0 }
 };
 
index 3077878ed4f09fdc1a9a1bcf0b1303084f098641..5acb1680524ab5a3ae381b2a741fabd0219f8bc1 100644 (file)
@@ -1243,7 +1243,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
                if (amount < 0)
                        amount = 0;
-               return put_user(amount, (unsigned int __user *)argp);
+               return put_user(amount, (unsigned int __user *) argp);
        }
 
        case TIOCINQ: {
@@ -1252,13 +1252,11 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                /* These two are safe on a single CPU system as only user tasks fiddle here */
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
-               return put_user(amount, (unsigned int __user *)argp);
+               return put_user(amount, (unsigned int __user *) argp);
        }
 
        case SIOCGSTAMP:
-               if (sk != NULL) 
-                       return sock_get_timestamp(sk, (struct timeval __user *)argp);
-               return -EINVAL;
+               return sock_get_timestamp(sk, (struct timeval __user *) argp);
 
        case SIOCGIFADDR:
        case SIOCSIFADDR:
index a8ed9a1d09f9efe2dee89d08893bad4d892bd836..d297af737d1023a41c88f028a8628d91e52bc3eb 100644 (file)
@@ -149,6 +149,6 @@ void rose_setup(struct net_device *dev)
        dev->set_mac_address    = rose_set_mac_address;
 
        /* New-style flags. */
-       dev->flags              = 0;
+       dev->flags              = IFF_NOARP;
        dev->get_stats = rose_get_stats;
 }
index 05fe2e735538e15999a5b018f19b5c8474573dc7..51885b5f744e938eaa71ffcb8617759469a68f7b 100644 (file)
@@ -1170,8 +1170,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
        while (rqstp->rq_arghi < pages) {
                struct page *p = alloc_page(GFP_KERNEL);
                if (!p) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(HZ/2);
+                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
                        continue;
                }
                rqstp->rq_argpages[rqstp->rq_arghi++] = p;