summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2002-07-26 01:39:38 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-07-26 01:39:38 -0700
commita8a4e4a9b2fa28ebf48ef9c34f461de95256a020 (patch)
tree10fec7baa36bd0ae83e599ef2897be7e325be593
parent025f143cddaaf9827fca546eba574fea6e0f514a (diff)
parentd243f1a8e0dcb20c1728919dce5f6e8b3e4136dc (diff)
Merge bk://lsm.bkbits.net/linus-2.5
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
-rw-r--r--Documentation/serial/driver2
-rw-r--r--arch/alpha/config.in4
-rw-r--r--arch/arm/config.in4
-rw-r--r--arch/i386/config.in42
-rw-r--r--arch/i386/kernel/apic.c18
-rw-r--r--arch/i386/kernel/apm.c39
-rw-r--r--arch/i386/kernel/cpu/common.c32
-rw-r--r--arch/i386/kernel/entry.S2
-rw-r--r--arch/i386/kernel/head.S44
-rw-r--r--arch/i386/kernel/i386_ksyms.c1
-rw-r--r--arch/i386/kernel/mtrr.c6
-rw-r--r--arch/i386/kernel/nmi.c2
-rw-r--r--arch/i386/kernel/process.c66
-rw-r--r--arch/i386/kernel/smp.c3
-rw-r--r--arch/i386/kernel/smpboot.c141
-rw-r--r--arch/i386/kernel/suspend.c11
-rw-r--r--arch/i386/kernel/trampoline.S7
-rw-r--r--arch/i386/kernel/traps.c38
-rw-r--r--arch/i386/mm/Makefile2
-rw-r--r--arch/i386/mm/fault.c4
-rw-r--r--arch/i386/mm/init.c532
-rw-r--r--arch/i386/mm/pgtable.c188
-rw-r--r--arch/ia64/config.in4
-rw-r--r--arch/m68k/config.in8
-rw-r--r--arch/mips/config.in4
-rw-r--r--arch/mips64/config.in4
-rw-r--r--arch/ppc/kernel/open_pic.c2
-rw-r--r--arch/ppc/kernel/smp.c172
-rw-r--r--arch/ppc/platforms/chrp_smp.c84
-rw-r--r--arch/ppc/platforms/gemini_setup.c2
-rw-r--r--arch/ppc/platforms/iSeries_smp.c7
-rw-r--r--arch/ppc/platforms/pmac_smp.c4
-rw-r--r--arch/ppc/platforms/pplus_setup.c2
-rw-r--r--arch/ppc/platforms/prep_setup.c2
-rw-r--r--arch/ppc64/config.in4
-rw-r--r--arch/sh/config.in4
-rw-r--r--arch/sparc/config.in4
-rw-r--r--arch/sparc64/config.in4
-rw-r--r--arch/x86_64/config.in4
-rw-r--r--drivers/acpi/ac.c16
-rw-r--r--drivers/acpi/battery.c16
-rw-r--r--drivers/acpi/bus.c10
-rw-r--r--drivers/acpi/button.c16
-rw-r--r--drivers/acpi/debugger/dbcmds.c5
-rw-r--r--drivers/acpi/debugger/dbfileio.c16
-rw-r--r--drivers/acpi/debugger/dbxface.c6
-rw-r--r--drivers/acpi/dispatcher/dsobject.c394
-rw-r--r--drivers/acpi/dispatcher/dsutils.c83
-rw-r--r--drivers/acpi/dispatcher/dswload.c20
-rw-r--r--drivers/acpi/dispatcher/dswstate.c6
-rw-r--r--drivers/acpi/ec.c36
-rw-r--r--drivers/acpi/executer/excreate.c4
-rw-r--r--drivers/acpi/executer/exdump.c6
-rw-r--r--drivers/acpi/executer/exoparg1.c24
-rw-r--r--drivers/acpi/executer/exutils.c61
-rw-r--r--drivers/acpi/fan.c16
-rw-r--r--drivers/acpi/include/acconfig.h13
-rw-r--r--drivers/acpi/include/acdebug.h48
-rw-r--r--drivers/acpi/include/acdisasm.h362
-rw-r--r--drivers/acpi/include/acglobal.h14
-rw-r--r--drivers/acpi/include/aclocal.h30
-rw-r--r--drivers/acpi/include/acmacros.h15
-rw-r--r--drivers/acpi/include/acnamesp.h4
-rw-r--r--drivers/acpi/include/acpiosxf.h8
-rw-r--r--drivers/acpi/include/acutils.h5
-rw-r--r--drivers/acpi/include/amlcode.h11
-rw-r--r--drivers/acpi/include/amlresrc.h37
-rw-r--r--drivers/acpi/include/platform/acenv.h17
-rw-r--r--drivers/acpi/namespace/nsdump.c89
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c124
-rw-r--r--drivers/acpi/namespace/nsload.c110
-rw-r--r--drivers/acpi/namespace/nsxfeval.c719
-rw-r--r--drivers/acpi/namespace/nsxfobj.c765
-rw-r--r--drivers/acpi/parser/psargs.c38
-rw-r--r--drivers/acpi/parser/psopcode.c4
-rw-r--r--drivers/acpi/parser/psparse.c4
-rw-r--r--drivers/acpi/parser/psutils.c6
-rw-r--r--drivers/acpi/pci_irq.c2
-rw-r--r--drivers/acpi/pci_link.c16
-rw-r--r--drivers/acpi/pci_root.c16
-rw-r--r--drivers/acpi/power.c16
-rw-r--r--drivers/acpi/processor.c16
-rw-r--r--drivers/acpi/resources/rsio.c23
-rw-r--r--drivers/acpi/resources/rsirq.c19
-rw-r--r--drivers/acpi/system.c36
-rw-r--r--drivers/acpi/tables.c10
-rw-r--r--drivers/acpi/tables/tbrsdt.c8
-rw-r--r--drivers/acpi/thermal.c16
-rw-r--r--drivers/acpi/utilities/utglobal.c58
-rw-r--r--drivers/base/fs.c6
-rw-r--r--drivers/block/DAC960.c2
-rw-r--r--drivers/block/ll_rw_blk.c52
-rw-r--r--drivers/char/serial_21285.c497
-rw-r--r--drivers/char/serial_amba.c2014
-rw-r--r--drivers/char/tty_io.c1
-rw-r--r--drivers/ide/Config.help10
-rw-r--r--drivers/ide/Config.in65
-rw-r--r--drivers/ide/Makefile4
-rw-r--r--drivers/ide/aec62xx.c5
-rw-r--r--drivers/ide/ali14xx.c5
-rw-r--r--drivers/ide/alim15x3.c34
-rw-r--r--drivers/ide/amd74xx.c5
-rw-r--r--drivers/ide/ata-timing.c5
-rw-r--r--drivers/ide/cmd640.c60
-rw-r--r--drivers/ide/cmd64x.c34
-rw-r--r--drivers/ide/cs5530.c14
-rw-r--r--drivers/ide/cy82c693.c13
-rw-r--r--drivers/ide/dtc2278.c6
-rw-r--r--drivers/ide/hpt34x.c4
-rw-r--r--drivers/ide/hpt366.c5
-rw-r--r--drivers/ide/hptraid.c4
-rw-r--r--drivers/ide/ht6560b.c20
-rw-r--r--drivers/ide/icside.c2
-rw-r--r--drivers/ide/ide-cd.c4
-rw-r--r--drivers/ide/ide-cd.h26
-rw-r--r--drivers/ide/ide-disk.c3
-rw-r--r--drivers/ide/ide-floppy.c4
-rw-r--r--drivers/ide/ide-m8xx.c9
-rw-r--r--drivers/ide/ide-pci.c3
-rw-r--r--drivers/ide/ide-pmac.c28
-rw-r--r--drivers/ide/ide-tape.c6
-rw-r--r--drivers/ide/ide.c398
-rw-r--r--drivers/ide/ioctl.c16
-rw-r--r--drivers/ide/it8172.c5
-rw-r--r--drivers/ide/main.c6
-rw-r--r--drivers/ide/ns87415.c2
-rw-r--r--drivers/ide/opti621.c16
-rw-r--r--drivers/ide/pcidma.c5
-rw-r--r--drivers/ide/pdc202xx.c14
-rw-r--r--drivers/ide/pdc4030.c4
-rw-r--r--drivers/ide/pdcraid.c4
-rw-r--r--drivers/ide/piix.c5
-rw-r--r--drivers/ide/probe.c11
-rw-r--r--drivers/ide/qd65xx.c47
-rw-r--r--drivers/ide/qd65xx.h4
-rw-r--r--drivers/ide/quirks.c7
-rw-r--r--drivers/ide/serverworks.c4
-rw-r--r--drivers/ide/sis5513.c34
-rw-r--r--drivers/ide/sl82c105.c10
-rw-r--r--drivers/ide/tcq.c1
-rw-r--r--drivers/ide/timing.h (renamed from drivers/ide/ata-timing.h)14
-rw-r--r--drivers/ide/trm290.c2
-rw-r--r--drivers/ide/umc8672.c18
-rw-r--r--drivers/ide/via82cxxx.c5
-rw-r--r--drivers/parport/parport_pc.c2
-rw-r--r--drivers/parport/share.c14
-rw-r--r--drivers/scsi/scsi_lib.c51
-rw-r--r--drivers/serial/21285.c88
-rw-r--r--drivers/serial/8250.c64
-rw-r--r--drivers/serial/8250_pci.c8
-rw-r--r--drivers/serial/amba.c108
-rw-r--r--drivers/serial/anakin.c118
-rw-r--r--drivers/serial/clps711x.c80
-rw-r--r--drivers/serial/core.c7
-rw-r--r--drivers/serial/sa1100.c60
-rw-r--r--drivers/serial/uart00.c74
-rw-r--r--drivers/usb/Config.help13
-rw-r--r--drivers/usb/class/Config.help4
-rw-r--r--drivers/usb/class/audio.c4
-rw-r--r--drivers/usb/core/usb.c4
-rw-r--r--drivers/usb/host/Config.help3
-rw-r--r--drivers/usb/host/ehci-hcd.c128
-rw-r--r--drivers/usb/host/ehci-q.c8
-rw-r--r--drivers/usb/host/ehci-sched.c43
-rw-r--r--drivers/usb/host/ohci-dbg.c13
-rw-r--r--drivers/usb/host/ohci-hcd.c144
-rw-r--r--drivers/usb/host/ohci-hub.c10
-rw-r--r--drivers/usb/host/ohci-q.c449
-rw-r--r--drivers/usb/host/ohci.h21
-rw-r--r--drivers/usb/image/scanner.h7
-rw-r--r--drivers/usb/input/Config.help23
-rw-r--r--drivers/usb/input/Config.in3
-rw-r--r--drivers/usb/input/Makefile5
-rw-r--r--drivers/usb/input/fixp-arith.h8
-rw-r--r--drivers/usb/input/hid-core.c8
-rw-r--r--drivers/usb/input/hid-ff.c16
-rw-r--r--drivers/usb/input/hid-lg3dff.c444
-rw-r--r--drivers/usb/input/hid-lgff.c493
-rw-r--r--drivers/usb/input/wacom.c14
-rw-r--r--drivers/usb/misc/Config.help2
-rw-r--r--drivers/usb/misc/emi26.c8
-rw-r--r--drivers/usb/net/pegasus.c4
-rw-r--r--drivers/usb/net/usbnet.c12
-rw-r--r--drivers/usb/serial/Config.help10
-rw-r--r--drivers/usb/serial/Config.in1
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/digi_acceleport.c4
-rw-r--r--drivers/usb/serial/io_fw_down3.h799
-rw-r--r--drivers/usb/serial/io_ti.c2684
-rw-r--r--drivers/usb/serial/io_ti.h180
-rw-r--r--drivers/usb/serial/io_usbvend.h113
-rw-r--r--drivers/usb/serial/usbserial.c7
-rw-r--r--drivers/usb/storage/Config.help13
-rw-r--r--drivers/usb/storage/Config.in10
-rw-r--r--drivers/usb/storage/usb.c72
-rw-r--r--fs/driverfs/inode.c111
-rw-r--r--fs/nfs/dir.c95
-rw-r--r--fs/nfs/inode.c30
-rw-r--r--fs/nfs/nfs3proc.c17
-rw-r--r--fs/partitions/msdos.c1
-rw-r--r--include/asm-generic/sections.h11
-rw-r--r--include/asm-i386/apic.h3
-rw-r--r--include/asm-i386/desc.h109
-rw-r--r--include/asm-i386/mmu_context.h12
-rw-r--r--include/asm-i386/pgtable-3level.h2
-rw-r--r--include/asm-i386/processor.h9
-rw-r--r--include/asm-i386/sections.h7
-rw-r--r--include/asm-i386/smp.h15
-rw-r--r--include/asm-ppc/machdep.h8
-rw-r--r--include/asm-ppc/smp.h6
-rw-r--r--include/asm-s390/hdreg.h13
-rw-r--r--include/asm-s390/ide.h27
-rw-r--r--include/asm-s390x/hdreg.h13
-rw-r--r--include/linux/blkdev.h31
-rw-r--r--include/linux/hdreg.h488
-rw-r--r--include/linux/ide.h61
-rw-r--r--include/linux/nbd.h2
-rw-r--r--include/linux/nfs_fs.h12
-rw-r--r--include/linux/nfs_xdr.h2
-rw-r--r--include/linux/notifier.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/smp.h23
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/sunrpc/xprt.h11
-rw-r--r--init/main.c61
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/cpu.c54
-rw-r--r--kernel/sched.c58
-rw-r--r--kernel/softirq.c37
-rw-r--r--net/sunrpc/clnt.c14
-rw-r--r--net/sunrpc/sunrpc_syms.c1
-rw-r--r--net/sunrpc/xprt.c67
-rw-r--r--scripts/Makefile2
233 files changed, 9141 insertions, 7215 deletions
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 105e702b9b41..637c89effb5b 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -120,7 +120,7 @@ hardware.
TTY stop to the driver (equiv to rs_stop).
Locking: port->lock taken.
- Interrupts: caller dependent.
+ Interrupts: locally disabled.
This call must not sleep
start_tx(port,tty_start)
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index 9e19e9d5b667..ee9ac56c4701 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -283,9 +283,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 79afb5c85fd1..8779afbc706f 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -529,9 +529,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/i386/config.in b/arch/i386/config.in
index d1c238813604..de59f559ee7b 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -298,18 +298,10 @@ source drivers/pnp/Config.in
source drivers/block/Config.in
-source drivers/md/Config.in
-
-if [ "$CONFIG_NET" = "y" ]; then
- source net/Config.in
-fi
-
-source drivers/telephony/Config.in
-
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL device support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL device support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
@@ -319,15 +311,32 @@ fi
endmenu
mainmenu_option next_comment
-comment 'SCSI support'
+comment 'SCSI device support'
-tristate 'SCSI support' CONFIG_SCSI
+tristate 'SCSI device support' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
source drivers/scsi/Config.in
fi
endmenu
+mainmenu_option next_comment
+comment 'Old non-SCSI/ATAPI CD-ROM drives'
+
+bool 'Support non-SCSI/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+ source drivers/cdrom/Config.in
+fi
+endmenu
+
+source drivers/md/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+fi
+
+source drivers/telephony/Config.in
+
source drivers/message/fusion/Config.in
source drivers/ieee1394/Config.in
@@ -354,15 +363,6 @@ source net/irda/Config.in
source drivers/isdn/Config.in
-mainmenu_option next_comment
-comment 'Old CD-ROM drivers (not SCSI, not IDE)'
-
-bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
-if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
- source drivers/cdrom/Config.in
-fi
-endmenu
-
#
# input before char - char/joystick depends on it. As does USB.
#
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index d1abf23f0133..a864800e1f3c 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -796,9 +796,9 @@ void __setup_APIC_LVTT(unsigned int clocks)
apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
-void setup_APIC_timer(void * data)
+static void setup_APIC_timer(unsigned int clocks)
{
- unsigned int clocks = (unsigned int) data, slice, t0, t1;
+ unsigned int slice, t0, t1;
unsigned long flags;
int delta;
@@ -924,7 +924,7 @@ static unsigned int calibration_result;
int dont_use_local_apic_timer __initdata = 0;
-void __init setup_APIC_clocks (void)
+void __init setup_boot_APIC_clock(void)
{
/* Disabled by DMI scan or kernel option? */
if (dont_use_local_apic_timer)
@@ -939,12 +939,16 @@ void __init setup_APIC_clocks (void)
/*
* Now set up the timer for real.
*/
- setup_APIC_timer((void *)calibration_result);
+ setup_APIC_timer(calibration_result);
local_irq_enable();
+}
- /* and update all other cpus */
- smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
+void __init setup_secondary_APIC_clock(void)
+{
+ local_irq_disable(); /* FIXME: Do we need this? --RR */
+ setup_APIC_timer(calibration_result);
+ local_irq_enable();
}
void __init disable_APIC_timer(void)
@@ -1177,7 +1181,7 @@ int __init APIC_init_uniprocessor (void)
if (!skip_ioapic_setup && nr_ioapics)
setup_IO_APIC();
#endif
- setup_APIC_clocks();
+ setup_boot_APIC_clock();
return 0;
}
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 1dfd424a2eb9..61f644279efd 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1589,7 +1589,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
p = buf;
- if ((num_online_cpus() == 1) &&
+ if ((num_possible_cpus() == 1) &&
!(error = apm_get_power_status(&bx, &cx, &dx))) {
ac_line_status = (bx >> 8) & 0xff;
battery_status = bx & 0xff;
@@ -1720,7 +1720,7 @@ static int apm(void *unused)
}
}
- if (debug && (num_online_cpus() == 1)) {
+ if (debug && (num_possible_cpus() == 1)) {
error = apm_get_power_status(&bx, &cx, &dx);
if (error)
printk(KERN_INFO "apm: power status not available\n");
@@ -1764,7 +1764,7 @@ static int apm(void *unused)
pm_power_off = apm_power_off;
register_sysrq_key('o', &sysrq_poweroff_op);
- if (num_online_cpus() == 1) {
+ if (num_possible_cpus() == 1) {
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
console_blank_hook = apm_console_blank;
#endif
@@ -1907,9 +1907,7 @@ static int __init apm_init(void)
printk(KERN_NOTICE "apm: disabled on user request.\n");
return -ENODEV;
}
- /* FIXME: When boot code changes, this will need to be
- deactivated when/if a CPU comes up --RR */
- if ((num_online_cpus() > 1) && !power_off) {
+ if ((num_possible_cpus() > 1) && !power_off) {
printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
return -ENODEV;
}
@@ -1924,35 +1922,38 @@ static int __init apm_init(void)
* that extends up to the end of page zero (that we have reserved).
* This is for buggy BIOS's that refer to (real mode) segment 0x40
* even though they are called in protected mode.
+ *
+ * NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's
+ * enough to modify CPU#0's GDT.
*/
- set_base(gdt[APM_40 >> 3],
+ set_base(cpu_gdt_table[0][APM_40 >> 3],
__va((unsigned long)0x40 << 4));
- _set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
+ _set_limit((char *)&cpu_gdt_table[0][APM_40 >> 3], 4095 - (0x40 << 4));
apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
- set_base(gdt[APM_CS >> 3],
+ set_base(cpu_gdt_table[0][APM_CS >> 3],
__va((unsigned long)apm_info.bios.cseg << 4));
- set_base(gdt[APM_CS_16 >> 3],
+ set_base(cpu_gdt_table[0][APM_CS_16 >> 3],
__va((unsigned long)apm_info.bios.cseg_16 << 4));
- set_base(gdt[APM_DS >> 3],
+ set_base(cpu_gdt_table[0][APM_DS >> 3],
__va((unsigned long)apm_info.bios.dseg << 4));
#ifndef APM_RELAX_SEGMENTS
if (apm_info.bios.version == 0x100) {
#endif
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
- _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
+ _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3], 64 * 1024 - 1);
/* For some unknown machine. */
- _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
+ _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3], 64 * 1024 - 1);
/* For the DEC Hinote Ultra CT475 (and others?) */
- _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
+ _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3], 64 * 1024 - 1);
#ifndef APM_RELAX_SEGMENTS
} else {
- _set_limit((char *)&gdt[APM_CS >> 3],
+ _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3],
(apm_info.bios.cseg_len - 1) & 0xffff);
- _set_limit((char *)&gdt[APM_CS_16 >> 3],
+ _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3],
(apm_info.bios.cseg_16_len - 1) & 0xffff);
- _set_limit((char *)&gdt[APM_DS >> 3],
+ _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3],
(apm_info.bios.dseg_len - 1) & 0xffff);
}
#endif
@@ -1963,9 +1964,7 @@ static int __init apm_init(void)
kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
- /* FIXME: When boot code changes, this will need to be
- deactivated when/if a CPU comes up --RR */
- if (num_online_cpus() > 1) {
+ if (num_possible_cpus() > 1) {
printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe (power off active).\n");
return 0;
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 8a8305d024f3..22fa9139694b 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -421,14 +421,14 @@ void __init early_cpu_init(void)
*/
void __init cpu_init (void)
{
- int nr = smp_processor_id();
- struct tss_struct * t = &init_tss[nr];
+ int cpu = smp_processor_id();
+ struct tss_struct * t = init_tss + cpu;
- if (test_and_set_bit(nr, &cpu_initialized)) {
- printk(KERN_WARNING "CPU#%d already initialized!\n", nr);
+ if (test_and_set_bit(cpu, &cpu_initialized)) {
+ printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
for (;;) local_irq_enable();
}
- printk(KERN_INFO "Initializing CPU#%d\n", nr);
+ printk(KERN_INFO "Initializing CPU#%d\n", cpu);
if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
@@ -441,7 +441,17 @@ void __init cpu_init (void)
}
#endif
- __asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
+ /*
+ * Initialize the per-CPU GDT with the boot GDT,
+ * and set up the GDT descriptor:
+ */
+ if (cpu) {
+ memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
+ cpu_gdt_descr[cpu].size = GDT_SIZE;
+ cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
+ }
+
+ __asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu]));
__asm__ __volatile__("lidt %0": "=m" (idt_descr));
/*
@@ -450,18 +460,18 @@ void __init cpu_init (void)
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
/*
- * set up and load the per-CPU TSS and LDT
+ * Set up and load the per-CPU TSS and LDT
*/
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
if(current->mm)
BUG();
- enter_lazy_tlb(&init_mm, current, nr);
+ enter_lazy_tlb(&init_mm, current, cpu);
t->esp0 = current->thread.esp0;
- set_tss_desc(nr,t);
- gdt_table[__TSS(nr)].b &= 0xfffffdff;
- load_TR(nr);
+ set_tss_desc(cpu,t);
+ cpu_gdt_table[cpu][TSS_ENTRY].b &= 0xfffffdff;
+ load_TR_desc();
load_LDT(&init_mm.context);
/* Clear %fs and %gs. */
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index f10564893337..be79bd27a039 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -417,7 +417,6 @@ ENTRY(simd_coprocessor_error)
ENTRY(device_not_available)
pushl $-1 # mark this as an int
SAVE_ALL
- GET_THREAD_INFO(%ebx)
movl %cr0, %eax
testl $0x4, %eax # EM (math emulation bit)
jne device_not_available_emulate
@@ -753,6 +752,7 @@ ENTRY(sys_call_table)
.long sys_futex /* 240 */
.long sys_sched_setaffinity
.long sys_sched_getaffinity
+ .long sys_set_thread_area
.rept NR_syscalls-(.-sys_call_table)/4
.long sys_ni_syscall
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 94ec417ebbef..3d2c11f0e592 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -231,7 +231,7 @@ is386: movl $2,%ecx # set MP
call check_x87
incb ready
- lgdt gdt_descr
+ lgdt cpu_gdt_descr
lidt idt_descr
ljmp $(__KERNEL_CS),$1f
1: movl $(__KERNEL_DS),%eax # reload all the segment registers
@@ -338,29 +338,28 @@ ignore_int:
iret
/*
- * The interrupt descriptor table has room for 256 idt's,
- * the global descriptor table is dependent on the number
- * of tasks we can have..
+ * The IDT and GDT 'descriptors' are a strange 48-bit object
+ * only used by the lidt and lgdt instructions. They are not
+ * like usual segment descriptors - they consist of a 16-bit
+ * segment size, and 32-bit linear address value:
*/
-#define IDT_ENTRIES 256
-#define GDT_ENTRIES (__TSS(NR_CPUS))
-
-.globl idt
-.globl gdt
+.globl idt_descr
+.globl cpu_gdt_descr
ALIGN
- .word 0
+ .word 0 # 32-bit align idt_desc.address
idt_descr:
.word IDT_ENTRIES*8-1 # idt contains 256 entries
-idt:
.long idt_table
- .word 0
-gdt_descr:
+# boot GDT descriptor (later on used by CPU#0):
+
+cpu_gdt_descr:
.word GDT_ENTRIES*8-1
-gdt:
- .long gdt_table
+ .long cpu_gdt_table
+
+ .fill NR_CPUS-1,6,0 # space for the other GDT descriptors
/*
* This is initialized to create an identity-mapping at 0-8M (for bootup
@@ -418,15 +417,15 @@ ALIGN
* NOTE! Make sure the gdt descriptor in head.S matches this if you
* change anything.
*/
-ENTRY(gdt_table)
+ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x0000000000000000 /* not used */
+ .quad 0x0000000000000000 /* TLS descriptor */
.quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
- .quad 0x0000000000000000 /* not used */
- .quad 0x0000000000000000 /* not used */
+ .quad 0x0000000000000000 /* TSS descriptor */
+ .quad 0x0000000000000000 /* LDT descriptor */
/*
* The APM segments have byte granularity and their bases
* and limits are set at run time.
@@ -444,5 +443,8 @@ ENTRY(gdt_table)
.quad 0x0000000000000000 /* 0x88 not used */
.quad 0x0000000000000000 /* 0x90 not used */
.quad 0x0000000000000000 /* 0x98 not used */
- /* Per CPU segments */
- .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */
+
+#if CONFIG_SMP
+ .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */
+#endif
+
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 04bbafb264ec..2b6ba73e1fd9 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -74,7 +74,6 @@ EXPORT_SYMBOL(pm_idle);
EXPORT_SYMBOL(pm_power_off);
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(apm_info);
-EXPORT_SYMBOL(gdt);
#ifdef CONFIG_DEBUG_IOVIRT
EXPORT_SYMBOL(__io_virt_debug);
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 05eb8e9d7e66..c17e01b48bab 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -1055,7 +1055,7 @@ static void set_mtrr_smp (unsigned int reg, unsigned long base,
wait_barrier_cache_disable = TRUE;
wait_barrier_execute = TRUE;
wait_barrier_cache_enable = TRUE;
- atomic_set (&undone_count, num_online_cpus() - 1);
+ atomic_set (&undone_count, num_booting_cpus() - 1);
/* Start the ball rolling on other CPUs */
if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
panic ("mtrr: timed out waiting for other CPUs\n");
@@ -1064,14 +1064,14 @@ static void set_mtrr_smp (unsigned int reg, unsigned long base,
/* Wait for all other CPUs to flush and disable their caches */
while (atomic_read (&undone_count) > 0) { rep_nop(); barrier(); }
/* Set up for completion wait and then release other CPUs to change MTRRs*/
- atomic_set (&undone_count, num_online_cpus() - 1);
+ atomic_set (&undone_count, num_booting_cpus() - 1);
wait_barrier_cache_disable = FALSE;
set_mtrr_cache_disable (&ctxt);
/* Wait for all other CPUs to flush and disable their caches */
while (atomic_read (&undone_count) > 0) { rep_nop(); barrier(); }
/* Set up for completion wait and then release other CPUs to change MTRRs*/
- atomic_set (&undone_count, num_online_cpus() - 1);
+ atomic_set (&undone_count, num_booting_cpus() - 1);
wait_barrier_execute = FALSE;
(*set_mtrr_up) (reg, base, size, type, FALSE);
/* Now wait for other CPUs to complete the function */
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2963a6f34a66..26302608eb13 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -82,6 +82,8 @@ int __init check_nmi_watchdog (void)
local_irq_enable();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
+ /* FIXME: Only boot CPU is online at this stage. Check CPUs
+ as they come up. */
for (cpu = 0; cpu < NR_CPUS; cpu++) {
if (!cpu_online(cpu))
continue;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 1a7a569827d6..43673f006c10 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -662,7 +662,8 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
- struct tss_struct *tss = init_tss + smp_processor_id();
+ int cpu = smp_processor_id();
+ struct tss_struct *tss = init_tss + cpu;
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
@@ -689,6 +690,14 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
}
/*
+ * Load the per-thread Thread-Local Storage descriptor.
+ *
+ * NOTE: it's faster to do the two stores unconditionally
+ * than to branch away.
+ */
+ load_TLS_desc(next, cpu);
+
+ /*
* Now maybe reload the debug registers
*/
if (unlikely(next->debugreg[7])) {
@@ -818,3 +827,58 @@ unsigned long get_wchan(struct task_struct *p)
}
#undef last_sched
#undef first_sched
+
+/*
+ * Set the Thread-Local Storage area:
+ */
+asmlinkage int sys_set_thread_area(unsigned int base, unsigned int limit, unsigned int flags)
+{
+ struct thread_struct *t = &current->thread;
+ int limit_in_pages = 0, writable = 0;
+ int cpu;
+
+ /* do not allow unused flags */
+ if (flags & ~TLS_FLAGS_MASK)
+ return -EINVAL;
+
+ /* check limit */
+ if (limit & 0xfff00000)
+ return -EINVAL;
+
+ /*
+ * Clear the TLS?
+ */
+ if (flags & TLS_FLAG_CLEAR) {
+ cpu = get_cpu();
+ t->tls_base = t->tls_limit = t->tls_flags = 0;
+ t->tls_desc.a = t->tls_desc.b = 0;
+ load_TLS_desc(t, cpu);
+ put_cpu();
+ return 0;
+ }
+
+ if (flags & TLS_FLAG_LIMIT_IN_PAGES)
+ limit_in_pages = 1;
+ if (flags & TLS_FLAG_WRITABLE)
+ writable = 1;
+
+ /*
+ * We must not get preempted while modifying the TLS.
+ */
+ cpu = get_cpu();
+ t->tls_base = base;
+ t->tls_limit = limit;
+ t->tls_flags = flags;
+
+ t->tls_desc.a = ((base & 0x0000ffff) << 16) | (limit & 0x0ffff);
+
+ t->tls_desc.b = (base & 0xff000000) | ((base & 0x00ff0000) >> 16) |
+ (limit & 0xf0000) | (writable << 9) | (1 << 15) |
+ (1 << 22) | (limit_in_pages << 23) | 0x7000;
+
+ load_TLS_desc(t, cpu);
+ put_cpu();
+
+ return TLS_ENTRY*8 + 3;
+}
+
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 8c903feb9bb4..19000818cf2b 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -646,7 +646,10 @@ asmlinkage void smp_call_function_interrupt(void)
/*
* At this point the info structure may be out of scope unless wait==1
*/
+ irq_enter();
(*func)(info);
+ irq_exit();
+
if (wait) {
mb();
atomic_inc(&call_data->finished);
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index cdd964721ab4..5a4f1a257d97 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -31,7 +31,7 @@
* Maciej W. Rozycki : Bits for genuine 82489DX APICs
* Martin J. Bligh : Added support for multi-quad systems
* Dave Jones : Report invalid combinations of Athlon CPUs.
- */
+* Rusty Russell : Hacked into shape for new "hotplug" boot process. */
#include <linux/config.h>
#include <linux/init.h>
@@ -53,9 +53,6 @@
/* Set if we find a B stepping CPU */
static int __initdata smp_b_stepping;
-/* Setup configured maximum number of CPUs to activate */
-static int __initdata max_cpus = NR_CPUS;
-
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
int __initdata phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
@@ -64,7 +61,8 @@ int __initdata phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
unsigned long cpu_online_map;
static volatile unsigned long cpu_callin_map;
-static volatile unsigned long cpu_callout_map;
+volatile unsigned long cpu_callout_map;
+static unsigned long smp_commenced_mask;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
@@ -73,33 +71,6 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
int smp_threads_ready;
/*
- * Setup routine for controlling SMP activation
- *
- * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
- * activation entirely (the MPS table probe still happens, though).
- *
- * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- * greater than 0, limits the maximum number of CPUs activated in
- * SMP mode to <NUM>.
- */
-
-static int __init nosmp(char *str)
-{
- max_cpus = 0;
- return 1;
-}
-
-__setup("nosmp", nosmp);
-
-static int __init maxcpus(char *str)
-{
- get_option(&str, &max_cpus);
- return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
-/*
* Trampoline 80x86 program as an array.
*/
@@ -139,7 +110,7 @@ void __init smp_alloc_memory(void)
* a given CPU
*/
-void __init smp_store_cpu_info(int id)
+static void __init smp_store_cpu_info(int id)
{
struct cpuinfo_x86 *c = cpu_data + id;
@@ -193,29 +164,6 @@ valid_k7:
}
/*
- * Architecture specific routine called by the kernel just before init is
- * fired off. This allows the BP to have everything in order [we hope].
- * At the end of this all the APs will hit the system scheduling and off
- * we go. Each AP will load the system gdt's and jump through the kernel
- * init into idle(). At this point the scheduler will one day take over
- * and give them jobs to do. smp_callin is a standard routine
- * we use to track CPUs as they power up.
- */
-
-static atomic_t smp_commenced = ATOMIC_INIT(0);
-
-void __init smp_commence(void)
-{
- /*
- * Lets the callins below out of their loop.
- */
- Dprintk("Setting commenced=1, go go go\n");
-
- wmb();
- atomic_set(&smp_commenced,1);
-}
-
-/*
* TSC synchronization.
*
* We first check wether all CPUs have their TSC's synchronized,
@@ -268,7 +216,7 @@ static void __init synchronize_tsc_bp (void)
unsigned long one_usec;
int buggy = 0;
- printk("checking TSC synchronization across CPUs: ");
+ printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus());
one_usec = ((1<<30)/fast_gettimeoffset_quotient)*(1<<2);
@@ -289,7 +237,7 @@ static void __init synchronize_tsc_bp (void)
/*
* all APs synchronize but they loop on '== num_cpus'
*/
- while (atomic_read(&tsc_count_start) != num_online_cpus()-1)
+ while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
mb();
atomic_set(&tsc_count_stop, 0);
wmb();
@@ -308,7 +256,7 @@ static void __init synchronize_tsc_bp (void)
/*
* Wait for all APs to leave the synchronization point:
*/
- while (atomic_read(&tsc_count_stop) != num_online_cpus()-1)
+ while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
mb();
atomic_set(&tsc_count_start, 0);
wmb();
@@ -317,16 +265,16 @@ static void __init synchronize_tsc_bp (void)
sum = 0;
for (i = 0; i < NR_CPUS; i++) {
- if (cpu_online(i)) {
+ if (test_bit(i, &cpu_callout_map)) {
t0 = tsc_values[i];
sum += t0;
}
}
- avg = div64(sum, num_online_cpus());
+ avg = div64(sum, num_booting_cpus());
sum = 0;
for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i))
+ if (!test_bit(i, &cpu_callout_map))
continue;
delta = tsc_values[i] - avg;
if (delta < 0)
@@ -359,7 +307,7 @@ static void __init synchronize_tsc_ap (void)
int i;
/*
- * num_online_cpus is not necessarily known at the time
+ * Not every cpu is online at the time
* this gets called, so we first wait for the BP to
* finish SMP initialization:
*/
@@ -367,7 +315,7 @@ static void __init synchronize_tsc_ap (void)
for (i = 0; i < NR_LOOPS; i++) {
atomic_inc(&tsc_count_start);
- while (atomic_read(&tsc_count_start) != num_online_cpus())
+ while (atomic_read(&tsc_count_start) != num_booting_cpus())
mb();
rdtscll(tsc_values[smp_processor_id()]);
@@ -375,7 +323,7 @@ static void __init synchronize_tsc_ap (void)
write_tsc(0, 0);
atomic_inc(&tsc_count_stop);
- while (atomic_read(&tsc_count_stop) != num_online_cpus()) mb();
+ while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb();
}
}
#undef NR_LOOPS
@@ -403,7 +351,7 @@ void __init smp_callin(void)
*/
phys_id = GET_APIC_ID(apic_read(APIC_ID));
cpuid = smp_processor_id();
- if (test_and_set_bit(cpuid, &cpu_online_map)) {
+ if (test_bit(cpuid, &cpu_callin_map)) {
printk("huh, phys CPU#%d, CPU#%d already present??\n",
phys_id, cpuid);
BUG();
@@ -501,15 +449,17 @@ int __init start_secondary(void *unused)
*/
cpu_init();
smp_callin();
- while (!atomic_read(&smp_commenced))
+ while (!test_bit(smp_processor_id(), &smp_commenced_mask))
rep_nop();
+ setup_secondary_APIC_clock();
enable_APIC_timer();
/*
* low-memory mappings have been cleared, flush them from
* the local TLBs too.
*/
local_flush_tlb();
-
+ set_bit(smp_processor_id(), &cpu_online_map);
+ wmb();
return cpu_idle();
}
@@ -943,7 +893,6 @@ static void __init do_boot_cpu (int apicid)
unmap_cpu_to_boot_apicid(cpu, apicid);
clear_bit(cpu, &cpu_callout_map); /* was set here (do_boot_cpu()) */
clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
- clear_bit(cpu, &cpu_online_map); /* was set in smp_callin() */
cpucount--;
}
@@ -1015,7 +964,7 @@ void *xquad_portio;
int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
-void __init smp_boot_cpus(void)
+static void __init smp_boot_cpus(unsigned int max_cpus)
{
int apicid, cpu, bit;
@@ -1057,6 +1006,7 @@ void __init smp_boot_cpus(void)
* We have the boot CPU online for sure.
*/
set_bit(0, &cpu_online_map);
+ set_bit(0, &cpu_callout_map);
boot_cpu_logical_apicid = logical_smp_processor_id();
map_cpu_to_boot_apicid(0, boot_cpu_apicid);
@@ -1072,11 +1022,11 @@ void __init smp_boot_cpus(void)
#ifndef CONFIG_VISWS
io_apic_irqs = 0;
#endif
- cpu_online_map = phys_cpu_present_map = 1;
+ phys_cpu_present_map = 1;
if (APIC_init_uniprocessor())
printk(KERN_NOTICE "Local APIC not detected."
" Using dummy APIC emulation.\n");
- goto smp_done;
+ return;
}
/*
@@ -1101,8 +1051,8 @@ void __init smp_boot_cpus(void)
#ifndef CONFIG_VISWS
io_apic_irqs = 0;
#endif
- cpu_online_map = phys_cpu_present_map = 1;
- goto smp_done;
+ phys_cpu_present_map = 1;
+ return;
}
verify_local_APIC();
@@ -1116,8 +1066,8 @@ void __init smp_boot_cpus(void)
#ifndef CONFIG_VISWS
io_apic_irqs = 0;
#endif
- cpu_online_map = phys_cpu_present_map = 1;
- goto smp_done;
+ phys_cpu_present_map = 1;
+ return;
}
connect_bsp_APIC();
@@ -1189,7 +1139,7 @@ void __init smp_boot_cpus(void)
} else {
unsigned long bogosum = 0;
for (cpu = 0; cpu < NR_CPUS; cpu++)
- if (cpu_online_map & (1<<cpu))
+ if (cpu_callout_map & (1<<cpu))
bogosum += cpu_data[cpu].loops_per_jiffy;
printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
cpucount+1,
@@ -1212,10 +1162,10 @@ void __init smp_boot_cpus(void)
for (cpu = 0; cpu < NR_CPUS; cpu++) {
int i;
- if (!cpu_online(cpu)) continue;
+ if (!test_bit(cpu, &cpu_callout_map)) continue;
for (i = 0; i < NR_CPUS; i++) {
- if (i == cpu || !cpu_online(i))
+ if (i == cpu || !test_bit(i, &cpu_callout_map))
continue;
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_sibling_map[cpu] = i;
@@ -1239,17 +1189,40 @@ void __init smp_boot_cpus(void)
setup_IO_APIC();
#endif
- /*
- * Set up all local APIC timers in the system:
- */
- setup_APIC_clocks();
+ setup_boot_APIC_clock();
/*
* Synchronize the TSC with the AP
*/
if (cpu_has_tsc && cpucount)
synchronize_tsc_bp();
+}
+
+/* These are wrappers to interface to the new boot process. Someone
+ who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ smp_boot_cpus(max_cpus);
+}
-smp_done:
+int __devinit __cpu_up(unsigned int cpu)
+{
+ /* This only works at boot for x86. See "rewrite" above. */
+ if (test_bit(cpu, &smp_commenced_mask))
+ return -ENOSYS;
+
+ /* In case one didn't come up */
+ if (!test_bit(cpu, &cpu_callin_map))
+ return -EIO;
+
+ /* Unleash the CPU! */
+ set_bit(cpu, &smp_commenced_mask);
+ while (!test_bit(cpu, &cpu_online_map))
+ mb();
+ return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
zap_low_mappings();
}
diff --git a/arch/i386/kernel/suspend.c b/arch/i386/kernel/suspend.c
index 402fe803e6dd..0481326d7038 100644
--- a/arch/i386/kernel/suspend.c
+++ b/arch/i386/kernel/suspend.c
@@ -203,14 +203,13 @@ acpi_sleep_done:
void fix_processor_context(void)
{
- int nr = smp_processor_id();
- struct tss_struct * t = &init_tss[nr];
+ int cpu = smp_processor_id();
+ struct tss_struct * t = init_tss + cpu;
- set_tss_desc(nr,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy tsc or some similar stupidity. */
- gdt_table[__TSS(nr)].b &= 0xfffffdff;
-
- load_TR(nr); /* This does ltr */
+ set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy tsc or some similar stupidity. */
+ cpu_gdt_table[cpu][TSS_ENTRY].b &= 0xfffffdff;
+ load_TR_desc(); /* This does ltr */
load_LDT(&current->mm->context); /* This does lldt */
/*
diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S
index d978a210ea95..991248f54256 100644
--- a/arch/i386/kernel/trampoline.S
+++ b/arch/i386/kernel/trampoline.S
@@ -63,9 +63,14 @@ idt_48:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L
+#
+# NOTE: here we actually use CPU#0's GDT - but that is OK, we reload
+# the proper GDT shortly after booting up the secondary CPUs.
+#
+
gdt_48:
.word 0x0800 # gdt limit = 2048, 256 GDT entries
- .long gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU)
+ .long cpu_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU)
.globl trampoline_end
trampoline_end:
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 6ab2d98ca508..4338f4c60fa9 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -784,11 +784,10 @@ void __init trap_init_f00f_bug(void)
__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
/*
- * "idt" is magic - it overlaps the idt_descr
- * variable so that updating idt will automatically
- * update the idt descriptor..
+ * Update the IDT descriptor and reload the IDT so that
+ * it uses the read-only mapped virtual address.
*/
- idt = (struct desc_struct *) fix_to_virt(FIX_F00F_IDT);
+ idt_descr.address = fix_to_virt(FIX_F00F_IDT);
__asm__ __volatile__("lidt %0": "=m" (idt_descr));
}
#endif
@@ -833,37 +832,6 @@ static void __init set_call_gate(void *a, void *addr)
_set_gate(a,12,3,addr);
}
-#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
- *((gate_addr)+1) = ((base) & 0xff000000) | \
- (((base) & 0x00ff0000)>>16) | \
- ((limit) & 0xf0000) | \
- ((dpl)<<13) | \
- (0x00408000) | \
- ((type)<<8); \
- *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
- ((limit) & 0x0ffff); }
-
-#define _set_tssldt_desc(n,addr,limit,type) \
-__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
- "movw %%ax,2(%2)\n\t" \
- "rorl $16,%%eax\n\t" \
- "movb %%al,4(%2)\n\t" \
- "movb %4,5(%2)\n\t" \
- "movb $0,6(%2)\n\t" \
- "movb %%ah,7(%2)\n\t" \
- "rorl $16,%%eax" \
- : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
-
-void set_tss_desc(unsigned int n, void *addr)
-{
- _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
-}
-
-void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
-{
- _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
-}
-
#ifdef CONFIG_X86_VISWS_APIC
/*
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index 67df8b6f6594..f8c5d36ff1b5 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -9,7 +9,7 @@
O_TARGET := mm.o
-obj-y := init.o fault.o ioremap.o extable.o pageattr.o
+obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o
export-objs := pageattr.o
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 8c4328690ebe..cd4083d09658 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -24,6 +24,7 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/hardirq.h>
+#include <asm/desc.h>
extern void die(const char *,struct pt_regs *,long);
@@ -129,7 +130,6 @@ void bust_spinlocks(int yes)
}
asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
-extern unsigned long idt;
/*
* This routine handles page faults. It determines the address,
@@ -293,7 +293,7 @@ bad_area:
if (boot_cpu_data.f00f_bug) {
unsigned long nr;
- nr = (address - idt) >> 3;
+ nr = (address - idt_descr.address) >> 3;
if (nr == 6) {
do_invalid_op(regs, 0);
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index ce90cf20bc9c..23b997cd5d5e 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -38,15 +38,146 @@
#include <asm/apic.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
+#include <asm/sections.h>
mmu_gather_t mmu_gathers[NR_CPUS];
unsigned long highstart_pfn, highend_pfn;
/*
- * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
- * physical space so we can cache the place of the first one and move
- * around without checking the pgd every time.
+ * Creates a middle page table and puts a pointer to it in the
+ * given global directory entry. This only returns the gd entry
+ * in non-PAE compilation mode, since the middle layer is folded.
*/
+static pmd_t * __init one_md_table_init(pgd_t *pgd)
+{
+ pmd_t *pmd_table;
+
+#if CONFIG_X86_PAE
+ pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pgd(pgd, __pgd(__pa(md_table) | _PAGE_PRESENT));
+ if (pmd_table != pmd_offset(pgd, 0))
+ BUG();
+#else
+ pmd_table = pmd_offset(pgd, 0);
+#endif
+
+ return pmd_table;
+}
+
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static pte_t * __init one_page_table_init(pmd_t *pmd)
+{
+ pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE));
+ if (page_table != pte_offset_kernel(pmd, 0))
+ BUG();
+
+ return page_table;
+}
+
+/*
+ * This function initializes a certain range of kernel virtual memory
+ * with new bootmem page tables, everywhere page tables are missing in
+ * the given range.
+ */
+
+/*
+ * NOTE: The pagetables are allocated contiguous on the physical space
+ * so we can cache the place of the first one and move around without
+ * checking the pgd every time.
+ */
+static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ int pgd_ofs, pmd_ofs;
+ unsigned long vaddr;
+
+ vaddr = start;
+ pgd_ofs = __pgd_offset(vaddr);
+ pmd_ofs = __pmd_offset(vaddr);
+ pgd = pgd_base + pgd_ofs;
+
+ for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) {
+ if (pgd_none(*pgd))
+ one_md_table_init(pgd);
+
+ pmd = pmd_offset(pgd, vaddr);
+ for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) {
+ if (pmd_none(*pmd))
+ one_page_table_init(pmd);
+
+ vaddr += PMD_SIZE;
+ }
+ pmd_ofs = 0;
+ }
+}
+
+/*
+ * This maps the physical memory to kernel virtual address space, a total
+ * of max_low_pfn pages, by creating page tables starting from address
+ * PAGE_OFFSET.
+ */
+static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+{
+ unsigned long pfn;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int pgd_ofs, pmd_ofs, pte_ofs;
+
+ pgd_ofs = __pgd_offset(PAGE_OFFSET);
+ pgd = pgd_base + pgd_ofs;
+ pfn = 0;
+
+ for (; pgd_ofs < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_ofs++) {
+ pmd = one_md_table_init(pgd);
+ for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) {
+ /* Map with big pages if possible, otherwise create normal page tables. */
+ if (cpu_has_pse) {
+ set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
+ pfn += PTRS_PER_PTE;
+ } else {
+ pte = one_page_table_init(pmd);
+
+ for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++)
+ set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
+ }
+ }
+ }
+}
+
+static inline int page_kills_ppro(unsigned long pagenr)
+{
+ if (pagenr >= 0x70000 && pagenr <= 0x7003F)
+ return 1;
+ return 0;
+}
+
+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;
+}
#if CONFIG_HIGHMEM
pte_t *kmap_pte;
@@ -65,186 +196,88 @@ void __init kmap_init(void)
kmap_prot = PAGE_KERNEL;
}
-#endif /* CONFIG_HIGHMEM */
-void show_mem(void)
-{
- int i, total = 0, reserved = 0;
- int shared = 0, cached = 0;
- int highmem = 0;
-
- printk("Mem-info:\n");
- show_free_areas();
- printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
- i = max_mapnr;
- while (i-- > 0) {
- total++;
- if (PageHighMem(mem_map+i))
- highmem++;
- if (PageReserved(mem_map+i))
- reserved++;
- else if (PageSwapCache(mem_map+i))
- cached++;
- else if (page_count(mem_map+i))
- shared += page_count(mem_map+i) - 1;
- }
- printk("%d pages of RAM\n", total);
- printk("%d pages of HIGHMEM\n",highmem);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
-}
-
-/* References to section boundaries */
-
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
-static inline void set_pte_phys (unsigned long vaddr,
- unsigned long phys, pgprot_t flags)
+void __init permanent_kmaps_init(pgd_t *pgd_base)
{
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
+ unsigned long vaddr;
+
+ vaddr = PKMAP_BASE;
+ page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
pgd = swapper_pg_dir + __pgd_offset(vaddr);
- if (pgd_none(*pgd)) {
- printk("PAE BUG #00!\n");
- return;
- }
pmd = pmd_offset(pgd, vaddr);
- if (pmd_none(*pmd)) {
- printk("PAE BUG #01!\n");
- return;
- }
pte = pte_offset_kernel(pmd, vaddr);
- /* <phys,flags> stored as-is, to permit clearing entries */
- set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
-
- /*
- * It's enough to flush this one mapping.
- * (PGE mappings get flushed as well)
- */
- __flush_tlb_one(vaddr);
+ pkmap_page_table = pte;
}
-void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
+void __init set_highmem_pages_init(int bad_ppro)
{
- unsigned long address = __fix_to_virt(idx);
+ int pfn;
+ for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) {
+ struct page *page = mem_map + pfn;
- if (idx >= __end_of_fixed_addresses) {
- printk("Invalid __set_fixmap\n");
- return;
- }
- set_pte_phys(address, phys, flags);
-}
-
-static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
-{
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- int i, j;
- unsigned long vaddr;
-
- vaddr = start;
- i = __pgd_offset(vaddr);
- j = __pmd_offset(vaddr);
- pgd = pgd_base + i;
-
- for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-#if CONFIG_X86_PAE
- if (pgd_none(*pgd)) {
- pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
- if (pmd != pmd_offset(pgd, 0))
- printk("PAE BUG #02!\n");
+ if (!page_is_ram(pfn)) {
+ SetPageReserved(page);
+ continue;
}
- pmd = pmd_offset(pgd, vaddr);
-#else
- pmd = (pmd_t *)pgd;
-#endif
- for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- if (pmd_none(*pmd)) {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
- vaddr += PMD_SIZE;
+ if (bad_ppro && page_kills_ppro(pfn))
+ {
+ SetPageReserved(page);
+ continue;
}
- j = 0;
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ atomic_set(&page->count, 1);
+ __free_page(page);
+ totalhigh_pages++;
}
+ totalram_pages += totalhigh_pages;
}
+#else
+#define kmap_init() do { } while (0)
+#define permanent_kmaps_init(pgd_base) do { } while (0)
+#define set_highmem_pages_init(bad_ppro) do { } while (0)
+#endif /* CONFIG_HIGHMEM */
+
unsigned long __PAGE_KERNEL = _PAGE_KERNEL;
static void __init pagetable_init (void)
{
- unsigned long vaddr, pfn;
- pgd_t *pgd, *pgd_base;
- int i, j, k;
- pmd_t *pmd;
- pte_t *pte, *pte_base;
+ unsigned long vaddr;
+ pgd_t *pgd_base = swapper_pg_dir;
- pgd_base = swapper_pg_dir;
#if CONFIG_X86_PAE
+ int i;
+ /* Init entries of the first-level page table to the zero page */
for (i = 0; i < PTRS_PER_PGD; i++)
set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
#endif
+
+ /* Enable PSE if available */
if (cpu_has_pse) {
set_in_cr4(X86_CR4_PSE);
}
+
+ /* Enable PGE if available */
if (cpu_has_pge) {
set_in_cr4(X86_CR4_PGE);
__PAGE_KERNEL |= _PAGE_GLOBAL;
}
- i = __pgd_offset(PAGE_OFFSET);
- pfn = 0;
- pgd = pgd_base + i;
-
- for (; i < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, i++) {
-#if CONFIG_X86_PAE
- pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pgd(pgd, __pgd(__pa(pmd) | _PAGE_PRESENT));
-#else
- pmd = (pmd_t *) pgd;
-#endif
- for (j = 0; j < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, j++) {
- if (cpu_has_pse) {
- set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
- pfn += PTRS_PER_PTE;
- } else {
- pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-
- for (k = 0; k < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, k++)
- set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
-
- set_pmd(pmd, __pmd(__pa(pte_base) | _KERNPG_TABLE));
- }
- }
- }
+ kernel_physical_mapping_init(pgd_base);
/*
* Fixed mappings, only the page table structure has to be
* created - mappings will be set by set_fixmap():
*/
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
- fixrange_init(vaddr, 0, pgd_base);
+ page_table_range_init(vaddr, 0, pgd_base);
-#if CONFIG_HIGHMEM
- /*
- * Permanent kmaps:
- */
- vaddr = PKMAP_BASE;
- fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
-
- pgd = swapper_pg_dir + __pgd_offset(vaddr);
- pmd = pmd_offset(pgd, vaddr);
- pte = pte_offset_kernel(pmd, vaddr);
- pkmap_page_table = pte;
-#endif
+ permanent_kmaps_init(pgd_base);
#if CONFIG_X86_PAE
/*
@@ -276,6 +309,27 @@ void __init zap_low_mappings (void)
flush_tlb_all();
}
+void __init zone_sizes_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned int max_dma, high, low;
+
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ low = max_low_pfn;
+ high = highend_pfn;
+
+ if (low < max_dma)
+ zones_size[ZONE_DMA] = low;
+ else {
+ zones_size[ZONE_DMA] = max_dma;
+ zones_size[ZONE_NORMAL] = low - max_dma;
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = high - low;
+#endif
+ }
+ free_area_init(zones_size);
+}
+
/*
* paging_init() sets up the page tables - note that the first 8MB are
* already mapped by head.S.
@@ -297,32 +351,10 @@ void __init paging_init(void)
if (cpu_has_pae)
set_in_cr4(X86_CR4_PAE);
#endif
-
__flush_tlb_all();
-#ifdef CONFIG_HIGHMEM
kmap_init();
-#endif
- {
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
- unsigned int max_dma, high, low;
-
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- low = max_low_pfn;
- high = highend_pfn;
-
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = high - low;
-#endif
- }
- free_area_init(zones_size);
- }
- return;
+ zone_sizes_init();
}
/*
@@ -373,35 +405,6 @@ void __init test_wp_bit(void)
printk("Ok.\n");
}
}
-
-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;
-}
-
-static inline int page_kills_ppro(unsigned long pagenr)
-{
- if(pagenr >= 0x70000 && pagenr <= 0x7003F)
- return 1;
- return 0;
-}
void __init mem_init(void)
{
@@ -436,27 +439,9 @@ void __init mem_init(void)
*/
if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
reservedpages++;
-#ifdef CONFIG_HIGHMEM
- for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
- struct page *page = mem_map + tmp;
- if (!page_is_ram(tmp)) {
- SetPageReserved(page);
- continue;
- }
- if (bad_ppro && page_kills_ppro(tmp))
- {
- SetPageReserved(page);
- continue;
- }
- ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
- atomic_set(&page->count, 1);
- __free_page(page);
- totalhigh_pages++;
- }
- totalram_pages += totalhigh_pages;
-#endif
+ set_highmem_pages_init(bad_ppro);
+
codesize = (unsigned long) &_etext - (unsigned long) &_text;
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -487,8 +472,22 @@ void __init mem_init(void)
#ifndef CONFIG_SMP
zap_low_mappings();
#endif
+}
+
+#if CONFIG_X86_PAE
+struct kmem_cache_s *pae_pgd_cachep;
+void __init pgtable_cache_init(void)
+{
+ /*
+ * PAE pgds must be 16-byte aligned:
+ */
+ pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
+ SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
+ if (!pae_pgd_cachep)
+ panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
}
+#endif
/* Put this after the callers, so that it cannot be inlined */
static int do_test_wp_bit(unsigned long vaddr)
@@ -541,110 +540,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
}
#endif
-
-#if defined(CONFIG_X86_PAE)
-static struct kmem_cache_s *pae_pgd_cachep;
-
-void __init pgtable_cache_init(void)
-{
- /*
- * PAE pgds must be 16-byte aligned:
- */
- pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
- SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
- if (!pae_pgd_cachep)
- panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
-}
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
- int i;
- pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
-
- if (pgd) {
- for (i = 0; i < USER_PTRS_PER_PGD; i++) {
- unsigned long pmd = __get_free_page(GFP_KERNEL);
- if (!pmd)
- goto out_oom;
- clear_page(pmd);
- set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
- }
- memcpy(pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- }
- return pgd;
-out_oom:
- for (i--; i >= 0; i--)
- free_page((unsigned long)__va(pgd_val(pgd[i])-1));
- kmem_cache_free(pae_pgd_cachep, pgd);
- return NULL;
-}
-
-void pgd_free(pgd_t *pgd)
-{
- int i;
-
- for (i = 0; i < USER_PTRS_PER_PGD; i++)
- free_page((unsigned long)__va(pgd_val(pgd[i])-1));
- kmem_cache_free(pae_pgd_cachep, pgd);
-}
-
-#else
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
- pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
-
- if (pgd) {
- memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- }
- return pgd;
-}
-
-void pgd_free(pgd_t *pgd)
-{
- free_page((unsigned long)pgd);
-}
-#endif /* CONFIG_X86_PAE */
-
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
- int count = 0;
- pte_t *pte;
-
- do {
- pte = (pte_t *) __get_free_page(GFP_KERNEL);
- if (pte)
- clear_page(pte);
- else {
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
- }
- } while (!pte && (count++ < 10));
- return pte;
-}
-
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- int count = 0;
- struct page *pte;
-
- do {
-#if CONFIG_HIGHPTE
- pte = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
-#else
- pte = alloc_pages(GFP_KERNEL, 0);
-#endif
- if (pte)
- clear_highpage(pte);
- else {
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
- }
- } while (!pte && (count++ < 10));
- return pte;
-}
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
new file mode 100644
index 000000000000..72769eb878eb
--- /dev/null
+++ b/arch/i386/mm/pgtable.c
@@ -0,0 +1,188 @@
+/*
+ * linux/arch/i386/mm/pgtable.c
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/fixmap.h>
+#include <asm/e820.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+void show_mem(void)
+{
+ int i, total = 0, reserved = 0;
+ int shared = 0, cached = 0;
+ int highmem = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageHighMem(mem_map+i))
+ highmem++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (page_count(mem_map+i))
+ shared += page_count(mem_map+i) - 1;
+ }
+ printk("%d pages of RAM\n", total);
+ printk("%d pages of HIGHMEM\n",highmem);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+}
+
+/*
+ * Associate a virtual page frame with a given physical page frame
+ * and protection flags for that frame.
+ */
+static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ if (pgd_none(*pgd)) {
+ BUG();
+ return;
+ }
+ pmd = pmd_offset(pgd, vaddr);
+ if (pmd_none(*pmd)) {
+ BUG();
+ return;
+ }
+ pte = pte_offset_kernel(pmd, vaddr);
+ /* <pfn,flags> stored as-is, to permit clearing entries */
+ set_pte(pte, pfn_pte(pfn, flags));
+
+ /*
+ * It's enough to flush this one mapping.
+ * (PGE mappings get flushed as well)
+ */
+ __flush_tlb_one(vaddr);
+}
+
+void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
+{
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ BUG();
+ return;
+ }
+ set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ int count = 0;
+ pte_t *pte;
+
+ do {
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
+ if (pte)
+ clear_page(pte);
+ else {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ);
+ }
+ } while (!pte && (count++ < 10));
+ return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ int count = 0;
+ struct page *pte;
+
+ do {
+#if CONFIG_HIGHPTE
+ pte = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+#else
+ pte = alloc_pages(GFP_KERNEL, 0);
+#endif
+ if (pte)
+ clear_highpage(pte);
+ else {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ);
+ }
+ } while (!pte && (count++ < 10));
+ return pte;
+}
+
+#if CONFIG_X86_PAE
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ int i;
+ pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
+
+ if (pgd) {
+ for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+ unsigned long pmd = __get_free_page(GFP_KERNEL);
+ if (!pmd)
+ goto out_oom;
+ clear_page(pmd);
+ set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
+ }
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ }
+ return pgd;
+out_oom:
+ for (i--; i >= 0; i--)
+ free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+ kmem_cache_free(pae_pgd_cachep, pgd);
+ return NULL;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+ int i;
+
+ for (i = 0; i < USER_PTRS_PER_PGD; i++)
+ free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+ kmem_cache_free(pae_pgd_cachep, pgd);
+}
+
+#else
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+ if (pgd) {
+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ }
+ return pgd;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+ free_page((unsigned long)pgd);
+}
+
+#endif /* CONFIG_X86_PAE */
+
diff --git a/arch/ia64/config.in b/arch/ia64/config.in
index 8e1ded185c1a..e8b206238104 100644
--- a/arch/ia64/config.in
+++ b/arch/ia64/config.in
@@ -133,9 +133,9 @@ source drivers/md/Config.in
source drivers/message/fusion/Config.in
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index 47a648512561..8a46861a2ded 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -160,9 +160,9 @@ if [ "$CONFIG_MAC" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL device support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL device support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
@@ -172,9 +172,9 @@ fi
endmenu
mainmenu_option next_comment
-comment 'SCSI support'
+comment 'SCSI device support'
-tristate 'SCSI support' CONFIG_SCSI
+tristate 'SCSI device support' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 9a1ddf0b0614..93d4b4b55f06 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -343,9 +343,9 @@ if [ "$CONFIG_SGI_IP22" != "y" -a \
"$CONFIG_DECSTATION" != "y" ]; then
mainmenu_option next_comment
- comment 'ATA/IDE/MFM/RLL support'
+ comment 'ATA/ATAPI/MFM/RLL support'
- tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+ tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/mips64/config.in b/arch/mips64/config.in
index d5941d8c2716..ca2afb6638ab 100644
--- a/arch/mips64/config.in
+++ b/arch/mips64/config.in
@@ -138,9 +138,9 @@ fi
source drivers/telephony/Config.in
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index 9727f59e8f95..685cbf463769 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -602,7 +602,7 @@ void openpic_request_IPIs(void)
* -- Cort
*/
-void __init do_openpic_setup_cpu(void)
+void __devinit do_openpic_setup_cpu(void)
{
int i;
u32 msk = 1 << smp_hw_index[smp_processor_id()];
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index 5ac73276f493..52150568c47b 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -48,15 +48,17 @@ struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
atomic_t ipi_recv;
atomic_t ipi_sent;
spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
-unsigned int prof_multiplier[NR_CPUS];
-unsigned int prof_counter[NR_CPUS];
-unsigned long cache_decay_ticks;
-static int max_cpus __initdata = NR_CPUS;
-unsigned long cpu_online_map;
+unsigned int prof_multiplier[NR_CPUS] = { [1 ... NR_CPUS-1] = 1 };
+unsigned int prof_counter[NR_CPUS] = { [1 ... NR_CPUS-1] = 1 };
+unsigned long cache_decay_ticks = HZ/100;
+unsigned long cpu_online_map = 1UL;
+unsigned long cpu_possible_map = 1UL;
int smp_hw_index[NR_CPUS];
-static struct smp_ops_t *smp_ops;
struct thread_info *secondary_ti;
+/* SMP operations for this machine */
+static struct smp_ops_t *smp_ops;
+
/* all cpu mappings are 1-1 -- Cort */
volatile unsigned long cpu_callin_map[NR_CPUS];
@@ -70,10 +72,6 @@ void smp_call_function_interrupt(void);
static int __smp_call_function(void (*func) (void *info), void *info,
int wait, int target);
-#ifdef CONFIG_PPC_ISERIES
-extern void smp_iSeries_space_timers( unsigned nr );
-#endif
-
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
* Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
@@ -291,6 +289,7 @@ void smp_call_function_interrupt(void)
atomic_inc(&call_data->finished);
}
+#if 0 /* Old boot code. */
void __init smp_boot_cpus(void)
{
int i, cpu_nr;
@@ -556,3 +555,156 @@ static int __init maxcpus(char *str)
}
__setup("maxcpus=", maxcpus);
+#else /* New boot code */
+/* FIXME: Do this properly for all archs --RR */
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+
+void __devinit
+smp_generic_give_timebase(void)
+{
+ spin_lock(&timebase_lock);
+ do {
+ timebase_upper = get_tbu();
+ timebase_lower = get_tbl();
+ } while (timebase_upper != get_tbu());
+ spin_unlock(&timebase_lock);
+
+ while (timebase_upper || timebase_lower)
+ rmb();
+}
+
+void __devinit
+smp_generic_take_timebase(void)
+{
+ int done = 0;
+
+ while (!done) {
+ spin_lock(&timebase_lock);
+ if (timebase_upper || timebase_lower) {
+ set_tb(timebase_upper, timebase_lower);
+ timebase_upper = 0;
+ timebase_lower = 0;
+ done = 1;
+ }
+ spin_unlock(&timebase_lock);
+ }
+}
+
+static void __devinit smp_store_cpu_info(int id)
+{
+ struct cpuinfo_PPC *c = &cpu_data[id];
+
+ /* assume bogomips are same for everything */
+ c->loops_per_jiffy = loops_per_jiffy;
+ c->pvr = mfspr(PVR);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ int num_cpus;
+
+ /* Fixup boot cpu */
+ smp_store_cpu_info(smp_processor_id());
+ cpu_callin_map[smp_processor_id()] = 1;
+
+ smp_ops = ppc_md.smp_ops;
+ if (smp_ops == NULL) {
+ printk("SMP not supported on this machine.\n");
+ return;
+ }
+
+ /* Probe platform for CPUs: always linear. */
+ num_cpus = smp_ops->probe();
+ cpu_possible_map = (1 << num_cpus)-1;
+
+ if (smp_ops->space_timers)
+ smp_ops->space_timers(num_cpus);
+}
+
+int __init setup_profiling_timer(unsigned int multiplier)
+{
+ return 0;
+}
+
+/* Processor coming up starts here */
+int __devinit start_secondary(void *unused)
+{
+ int cpu;
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ cpu = smp_processor_id();
+ smp_store_cpu_info(cpu);
+ set_dec(tb_ticks_per_jiffy);
+ cpu_callin_map[cpu] = 1;
+
+ printk("CPU %i done callin...\n", cpu);
+ smp_ops->setup_cpu(cpu);
+ printk("CPU %i done setup...\n", cpu);
+ smp_ops->take_timebase();
+ printk("CPU %i done timebase take...\n", cpu);
+
+ return cpu_idle(NULL);
+}
+
+int __cpu_up(unsigned int cpu)
+{
+ struct pt_regs regs;
+ struct task_struct *p;
+ char buf[32];
+ int c;
+
+ /* create a process for the processor */
+ /* only regs.msr is actually used, and 0 is OK for it */
+ memset(&regs, 0, sizeof(struct pt_regs));
+ p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+ if (IS_ERR(p))
+ panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+
+ init_idle(p, cpu);
+ unhash_process(p);
+
+ secondary_ti = p->thread_info;
+ p->thread_info->cpu = cpu;
+
+ /*
+ * There was a cache flush loop here to flush the cache
+ * to memory for the first 8MB of RAM. The cache flush
+ * has been pushed into the kick_cpu function for those
+ * platforms that need it.
+ */
+
+ /* wake up cpu */
+ smp_ops->kick_cpu(cpu);
+
+ /*
+ * wait to see if the cpu made a callin (is actually up).
+ * use this value that I found through experimentation.
+ * -- Cort
+ */
+ for (c = 1000; c && !cpu_callin_map[cpu]; c--)
+ udelay(100);
+
+ if (!cpu_callin_map[cpu]) {
+ sprintf(buf, "didn't find cpu %u", cpu);
+ if (ppc_md.progress) ppc_md.progress(buf, 0x360+cpu);
+ printk("Processor %u is stuck.\n", cpu);
+ return -ENOENT;
+ }
+
+ sprintf(buf, "found cpu %u", cpu);
+ if (ppc_md.progress) ppc_md.progress(buf, 0x350+cpu);
+ printk("Processor %d found.\n", cpu);
+
+ smp_ops->give_timebase();
+ set_bit(cpu, &cpu_online_map);
+ return 0;
+}
+
+void smp_cpus_done(unsigned int max_cpus)
+{
+ smp_ops->setup_cpu(0);
+}
+#endif
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
index 4d28976651fe..80e6584c93d9 100644
--- a/arch/ppc/platforms/chrp_smp.c
+++ b/arch/ppc/platforms/chrp_smp.c
@@ -50,59 +50,61 @@ smp_chrp_probe(void)
return smp_chrp_cpu_nr;
}
-static void __init
+static void __devinit
smp_chrp_kick_cpu(int nr)
{
*(unsigned long *)KERNELBASE = nr;
asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
}
-static void __init
+static void __devinit
smp_chrp_setup_cpu(int cpu_nr)
{
- static atomic_t ready = ATOMIC_INIT(1);
- static volatile int frozen = 0;
-
- /* FIXME: Hotplug cpu breaks all this --RR */
- if (cpu_nr == 0) {
- /* wait for all the others */
- while (atomic_read(&ready) < num_online_cpus())
- barrier();
- atomic_set(&ready, 1);
- /* freeze the timebase */
- call_rtas("freeze-time-base", 0, 1, NULL);
- mb();
- frozen = 1;
- /* XXX assumes this is not a 601 */
- set_tb(0, 0);
- last_jiffy_stamp(0) = 0;
- while (atomic_read(&ready) < num_online_cpus())
- barrier();
- /* thaw the timebase again */
- call_rtas("thaw-time-base", 0, 1, NULL);
- mb();
- frozen = 0;
- smp_tb_synchronized = 1;
- } else {
- atomic_inc(&ready);
- while (!frozen)
- barrier();
- set_tb(0, 0);
- last_jiffy_stamp(0) = 0;
- mb();
- atomic_inc(&ready);
- while (frozen)
- barrier();
- }
-
if (OpenPIC_Addr)
do_openpic_setup_cpu();
}
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+
+void __devinit
+smp_chrp_give_timebase(void)
+{
+ spin_lock(&timebase_lock);
+ call_rtas("freeze-time-base", 0, 1, NULL);
+ timebase_upper = get_tbu();
+ timebase_lower = get_tbl();
+ spin_unlock(&timebase_lock);
+
+ while (timebase_upper || timebase_lower)
+ rmb();
+ call_rtas("thaw-time-base", 0, 1, NULL);
+}
+
+void __devinit
+smp_chrp_take_timebase(void)
+{
+ int done = 0;
+
+ while (!done) {
+ spin_lock(&timebase_lock);
+ if (timebase_upper || timebase_lower) {
+ set_tb(timebase_upper, timebase_lower);
+ timebase_upper = 0;
+ timebase_lower = 0;
+ done = 1;
+ }
+ spin_unlock(&timebase_lock);
+ }
+ printk("CPU %i taken timebase\n", smp_processor_id());
+}
+
/* CHRP with openpic */
struct smp_ops_t chrp_smp_ops __chrpdata = {
- smp_openpic_message_pass,
- smp_chrp_probe,
- smp_chrp_kick_cpu,
- smp_chrp_setup_cpu,
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_chrp_probe,
+ .kick_cpu = smp_chrp_kick_cpu,
+ .setup_cpu = smp_chrp_setup_cpu,
+ .give_timebase = smp_chrp_give_timebase,
+ .take_timebase = smp_chrp_take_timebase,
};
diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
index db86f459abd4..feeee01f669b 100644
--- a/arch/ppc/platforms/gemini_setup.c
+++ b/arch/ppc/platforms/gemini_setup.c
@@ -528,6 +528,8 @@ static struct smp_ops_t gemini_smp_ops = {
smp_gemini_probe,
smp_gemini_kick_cpu,
smp_gemini_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
#endif /* CONFIG_SMP */
diff --git a/arch/ppc/platforms/iSeries_smp.c b/arch/ppc/platforms/iSeries_smp.c
index 055a4f58ce50..1a22a035125e 100644
--- a/arch/ppc/platforms/iSeries_smp.c
+++ b/arch/ppc/platforms/iSeries_smp.c
@@ -117,7 +117,7 @@ static void smp_iSeries_setup_cpu(int nr)
set_dec( xPaca[nr].default_decr );
}
-void smp_iSeries_space_timers( unsigned nr )
+static void smp_iSeries_space_timers(unsigned nr)
{
unsigned offset,i;
@@ -131,6 +131,9 @@ struct smp_ops_t iSeries_smp_ops = {
smp_iSeries_message_pass,
smp_iSeries_probe,
smp_iSeries_kick_cpu,
- smp_iSeries_setup_cpu
+ smp_iSeries_setup_cpu,
+ smp_iSeries_space_timers,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 0ca0e3af9f58..cd5804be4e88 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -612,6 +612,8 @@ struct smp_ops_t psurge_smp_ops __pmacdata = {
smp_psurge_probe,
smp_psurge_kick_cpu,
smp_psurge_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
/* Core99 Macs (dual G4s) */
@@ -620,4 +622,6 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
smp_core99_probe,
smp_core99_kick_cpu,
smp_core99_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
diff --git a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c
index 640c6164fbd0..73d74c2d0e99 100644
--- a/arch/ppc/platforms/pplus_setup.c
+++ b/arch/ppc/platforms/pplus_setup.c
@@ -309,6 +309,8 @@ static struct smp_ops_t pplus_smp_ops = {
smp_pplus_probe,
smp_pplus_kick_cpu,
smp_pplus_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
#endif /* CONFIG_SMP */
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 9ab36cbf3f10..25721ad975b7 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -756,6 +756,8 @@ static struct smp_ops_t prep_smp_ops __prepdata = {
smp_prep_probe,
smp_prep_kick_cpu,
smp_prep_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
#endif /* CONFIG_SMP */
diff --git a/arch/ppc64/config.in b/arch/ppc64/config.in
index 707724082d80..20159b4a0cb0 100644
--- a/arch/ppc64/config.in
+++ b/arch/ppc64/config.in
@@ -92,9 +92,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/sh/config.in b/arch/sh/config.in
index 5a11a5c75237..b7a953e906ba 100644
--- a/arch/sh/config.in
+++ b/arch/sh/config.in
@@ -211,9 +211,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index ff66b25bd60b..6077e0ec37cc 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -104,9 +104,9 @@ fi
if [ "$CONFIG_PCI" = "y" ]; then
mainmenu_option next_comment
- comment 'ATA/IDE/MFM/RLL support'
+ comment 'ATA/ATAPI/MFM/RLL support'
- tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+ tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index 686475eebce0..61d0825243b3 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -105,9 +105,9 @@ if [ "$CONFIG_NET" = "y" ]; then
fi
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL device support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL device support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/arch/x86_64/config.in b/arch/x86_64/config.in
index 98a7141a8ea3..beb522968c8e 100644
--- a/arch/x86_64/config.in
+++ b/arch/x86_64/config.in
@@ -126,9 +126,9 @@ fi
source drivers/telephony/Config.in
mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
+comment 'ATA/ATAPI/MFM/RLL support'
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index c98eefa44766..c9faecf0e450 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -1,5 +1,5 @@
/*
- * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 26 $)
+ * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -47,13 +47,13 @@ int acpi_ac_add (struct acpi_device *device);
int acpi_ac_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_ac_driver = {
- name: ACPI_AC_DRIVER_NAME,
- class: ACPI_AC_CLASS,
- ids: ACPI_AC_HID,
- ops: {
- add: acpi_ac_add,
- remove: acpi_ac_remove,
- },
+ .name = ACPI_AC_DRIVER_NAME,
+ .class = ACPI_AC_CLASS,
+ .ids = ACPI_AC_HID,
+ .ops = {
+ .add = acpi_ac_add,
+ .remove = acpi_ac_remove,
+ },
};
struct acpi_ac {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 6684da84decd..6a096d8c1463 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1,5 +1,5 @@
/*
- * acpi_battery.c - ACPI Battery Driver ($Revision: 36 $)
+ * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -52,13 +52,13 @@ static int acpi_battery_add (struct acpi_device *device);
static int acpi_battery_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_battery_driver = {
- name: ACPI_BATTERY_DRIVER_NAME,
- class: ACPI_BATTERY_CLASS,
- ids: ACPI_BATTERY_HID,
- ops: {
- add: acpi_battery_add,
- remove: acpi_battery_remove,
- },
+ .name = ACPI_BATTERY_DRIVER_NAME,
+ .class = ACPI_BATTERY_CLASS,
+ .ids = ACPI_BATTERY_HID,
+ .ops = {
+ .add = acpi_battery_add,
+ .remove = acpi_battery_remove,
+ },
};
struct acpi_battery_status {
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 900cbe0de6b2..881d02a7c5c7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1,5 +1,5 @@
/*
- * acpi_bus.c - ACPI Bus Driver ($Revision: 79 $)
+ * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
*
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
@@ -97,10 +97,10 @@ static int acpi_device_suspend(struct device *dev, u32 state, u32 stage);
static int acpi_device_resume(struct device *dev, u32 stage);
static struct device_driver acpi_bus_driver = {
- probe: acpi_device_probe,
- remove: acpi_device_remove,
- suspend: acpi_device_suspend,
- resume: acpi_device_resume,
+ .probe = acpi_device_probe,
+ .remove = acpi_device_remove,
+ .suspend = acpi_device_suspend,
+ .resume = acpi_device_resume,
};
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 5beed76b3dd3..cdd6c926ea5c 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -1,5 +1,5 @@
/*
- * acpi_button.c - ACPI Button Driver ($Revision: 29 $)
+ * acpi_button.c - ACPI Button Driver ($Revision: 30 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -47,13 +47,13 @@ int acpi_button_add (struct acpi_device *device);
int acpi_button_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_button_driver = {
- name: ACPI_BUTTON_DRIVER_NAME,
- class: ACPI_BUTTON_CLASS,
- ids: "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
- ops: {
- add: acpi_button_add,
- remove: acpi_button_remove,
- },
+ .name = ACPI_BUTTON_DRIVER_NAME,
+ .class = ACPI_BUTTON_CLASS,
+ .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
+ .ops = {
+ .add = acpi_button_add,
+ .remove = acpi_button_remove,
+ },
};
struct acpi_button {
diff --git a/drivers/acpi/debugger/dbcmds.c b/drivers/acpi/debugger/dbcmds.c
index 0a3a4282cbb3..6cb00097d1d5 100644
--- a/drivers/acpi/debugger/dbcmds.c
+++ b/drivers/acpi/debugger/dbcmds.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: dbcmds - debug commands and output routines
- * $Revision: 84 $
+ * $Revision: 85 $
*
******************************************************************************/
@@ -31,6 +31,7 @@
#include "acevents.h"
#include "acdebug.h"
#include "acresrc.h"
+#include "acdisasm.h"
#ifdef ENABLE_DEBUGGER
@@ -342,7 +343,7 @@ acpi_db_disassemble_aml (
num_statements = ACPI_STRTOUL (statements, NULL, 0);
}
- acpi_db_display_op (NULL, op, num_statements);
+ acpi_dm_disassemble (NULL, op, num_statements);
}
diff --git a/drivers/acpi/debugger/dbfileio.c b/drivers/acpi/debugger/dbfileio.c
index d9c7406c7f0c..a814fc858135 100644
--- a/drivers/acpi/debugger/dbfileio.c
+++ b/drivers/acpi/debugger/dbfileio.c
@@ -2,7 +2,7 @@
*
* Module Name: dbfileio - Debugger file I/O commands. These can't usually
* be used when running the debugger in Ring 0 (Kernel mode)
- * $Revision: 64 $
+ * $Revision: 67 $
*
******************************************************************************/
@@ -30,7 +30,7 @@
#include "acnamesp.h"
#include "actables.h"
-#ifdef ENABLE_DEBUGGER
+#if (defined ENABLE_DEBUGGER || defined ACPI_DISASSEMBLER)
#define _COMPONENT ACPI_DEBUGGER
ACPI_MODULE_NAME ("dbfileio")
@@ -86,6 +86,7 @@ acpi_db_match_argument (
}
+#ifdef ENABLE_DEBUGGER
/*******************************************************************************
*
* FUNCTION: Acpi_db_close_debug_file
@@ -148,6 +149,7 @@ acpi_db_open_debug_file (
#endif
}
+#endif
#ifdef ACPI_APPLICATION
@@ -190,7 +192,7 @@ acpi_db_load_table(
status = acpi_tb_validate_table_header (&table_header);
if ((ACPI_FAILURE (status)) ||
- (table_header.length > 524288)) /* 1/2 Mbyte should be enough */ {
+ (table_header.length > 0x800000)) /* 8 Mbyte should be enough */ {
acpi_os_printf ("Table header is invalid!\n");
return (AE_ERROR);
}
@@ -296,7 +298,7 @@ ae_local_load_table (
}
-#ifndef PARSER_ONLY
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node);
if (ACPI_FAILURE (status)) {
/* Uninstall table and free the buffer */
@@ -330,7 +332,7 @@ acpi_db_get_acpi_table (
/* Get the entire file */
- acpi_os_printf ("Loading Acpi table from file %s\n", filename);
+ fprintf (stderr, "Loading Acpi table from file %s\n", filename);
status = acpi_db_load_table (fp, &acpi_gbl_db_table_ptr, &table_length);
fclose(fp);
@@ -383,8 +385,8 @@ acpi_db_load_acpi_table (
return (status);
}
- acpi_os_printf ("%4.4s at %p successfully installed and loaded\n",
- acpi_gbl_db_table_ptr->signature, acpi_gbl_db_table_ptr);
+ fprintf (stderr, "Acpi table [%4.4s] successfully installed and loaded\n",
+ acpi_gbl_db_table_ptr->signature);
acpi_gbl_acpi_hardware_present = FALSE;
diff --git a/drivers/acpi/debugger/dbxface.c b/drivers/acpi/debugger/dbxface.c
index d0cad6347c5d..50d28c7ac8e4 100644
--- a/drivers/acpi/debugger/dbxface.c
+++ b/drivers/acpi/debugger/dbxface.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: dbxface - AML Debugger external interfaces
- * $Revision: 59 $
+ * $Revision: 61 $
*
******************************************************************************/
@@ -27,6 +27,7 @@
#include "acpi.h"
#include "amlcode.h"
#include "acdebug.h"
+#include "acdisasm.h"
#ifdef ENABLE_DEBUGGER
@@ -164,7 +165,7 @@ acpi_db_single_step (
/* Now we can display it */
- acpi_db_display_op (walk_state, display_op, ACPI_UINT32_MAX);
+ acpi_dm_disassemble (walk_state, display_op, ACPI_UINT32_MAX);
if ((op->common.aml_opcode == AML_IF_OP) ||
(op->common.aml_opcode == AML_WHILE_OP)) {
@@ -351,7 +352,6 @@ acpi_db_initialize (void)
}
if (!acpi_gbl_db_opt_verbose) {
- acpi_gbl_db_disasm_indent = " ";
acpi_gbl_db_opt_disasm = TRUE;
acpi_gbl_db_opt_stats = FALSE;
}
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index a78f428efe25..9923b6650cc4 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: dsobject - Dispatcher object management routines
- * $Revision: 104 $
+ * $Revision: 105 $
*
*****************************************************************************/
@@ -35,6 +35,7 @@
ACPI_MODULE_NAME ("dsobject")
+#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
* FUNCTION: Acpi_ds_init_one_object
@@ -218,199 +219,6 @@ acpi_ds_initialize_objects (
/*****************************************************************************
*
- * FUNCTION: Acpi_ds_init_object_from_op
- *
- * PARAMETERS: Walk_state - Current walk state
- * Op - Parser op used to init the internal object
- * Opcode - AML opcode associated with the object
- * Ret_obj_desc - Namespace object to be initialized
- *
- * RETURN: Status
- *
- * DESCRIPTION: Initialize a namespace object from a parser Op and its
- * associated arguments. The namespace object is a more compact
- * representation of the Op and its arguments.
- *
- ****************************************************************************/
-
-acpi_status
-acpi_ds_init_object_from_op (
- acpi_walk_state *walk_state,
- acpi_parse_object *op,
- u16 opcode,
- acpi_operand_object **ret_obj_desc)
-{
- const acpi_opcode_info *op_info;
- acpi_operand_object *obj_desc;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("Ds_init_object_from_op");
-
-
- obj_desc = *ret_obj_desc;
- op_info = acpi_ps_get_opcode_info (opcode);
- if (op_info->class == AML_CLASS_UNKNOWN) {
- /* Unknown opcode */
-
- return_ACPI_STATUS (AE_TYPE);
- }
-
- /* Perform per-object initialization */
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
- case ACPI_TYPE_BUFFER:
-
- /*
- * Defer evaluation of Buffer Term_arg operand
- */
- obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0];
- obj_desc->buffer.aml_start = op->named.data;
- obj_desc->buffer.aml_length = op->named.length;
- break;
-
-
- case ACPI_TYPE_PACKAGE:
-
- /*
- * Defer evaluation of Package Term_arg operand
- */
- obj_desc->package.node = (acpi_namespace_node *) walk_state->operands[0];
- obj_desc->package.aml_start = op->named.data;
- obj_desc->package.aml_length = op->named.length;
- break;
-
-
- case ACPI_TYPE_INTEGER:
-
- switch (op_info->type) {
- case AML_TYPE_CONSTANT:
- /*
- * Resolve AML Constants here - AND ONLY HERE!
- * All constants are integers.
- * We mark the integer with a flag that indicates that it started life
- * as a constant -- so that stores to constants will perform as expected (noop).
- * (Zero_op is used as a placeholder for optional target operands.)
- */
- obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
-
- switch (opcode) {
- case AML_ZERO_OP:
-
- obj_desc->integer.value = 0;
- break;
-
- case AML_ONE_OP:
-
- obj_desc->integer.value = 1;
- break;
-
- case AML_ONES_OP:
-
- obj_desc->integer.value = ACPI_INTEGER_MAX;
-
- /* Truncate value if we are executing from a 32-bit ACPI table */
-
- acpi_ex_truncate_for32bit_table (obj_desc);
- break;
-
- case AML_REVISION_OP:
-
- obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL;
- break;
-
- default:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
- status = AE_AML_OPERAND_TYPE;
- break;
- }
- break;
-
-
- case AML_TYPE_LITERAL:
-
- obj_desc->integer.value = op->common.value.integer;
- break;
-
-
- default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
- status = AE_AML_OPERAND_TYPE;
- break;
- }
- break;
-
-
- case ACPI_TYPE_STRING:
-
- obj_desc->string.pointer = op->common.value.string;
- obj_desc->string.length = ACPI_STRLEN (op->common.value.string);
-
- /*
- * The string is contained in the ACPI table, don't ever try
- * to delete it
- */
- obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
- break;
-
-
- case ACPI_TYPE_METHOD:
- break;
-
-
- case INTERNAL_TYPE_REFERENCE:
-
- switch (op_info->type) {
- case AML_TYPE_LOCAL_VARIABLE:
-
- /* Split the opcode into a base opcode + offset */
-
- obj_desc->reference.opcode = AML_LOCAL_OP;
- obj_desc->reference.offset = opcode - AML_LOCAL_OP;
- acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset,
- walk_state, (acpi_namespace_node **) &obj_desc->reference.object);
- break;
-
-
- case AML_TYPE_METHOD_ARGUMENT:
-
- /* Split the opcode into a base opcode + offset */
-
- obj_desc->reference.opcode = AML_ARG_OP;
- obj_desc->reference.offset = opcode - AML_ARG_OP;
- break;
-
-
- default: /* Other literals, etc.. */
-
- if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
- /* Node was saved in Op */
-
- obj_desc->reference.node = op->common.node;
- }
-
- obj_desc->reference.opcode = opcode;
- break;
- }
- break;
-
-
- default:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
- ACPI_GET_OBJECT_TYPE (obj_desc)));
-
- status = AE_AML_OPERAND_TYPE;
- break;
- }
-
- return_ACPI_STATUS (status);
-}
-
-
-/*****************************************************************************
- *
* FUNCTION: Acpi_ds_build_internal_object
*
* PARAMETERS: Walk_state - Current walk state
@@ -781,4 +589,202 @@ acpi_ds_create_node (
return_ACPI_STATUS (status);
}
+#endif /* ACPI_NO_METHOD_EXECUTION */
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: Acpi_ds_init_object_from_op
+ *
+ * PARAMETERS: Walk_state - Current walk state
+ * Op - Parser op used to init the internal object
+ * Opcode - AML opcode associated with the object
+ * Ret_obj_desc - Namespace object to be initialized
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize a namespace object from a parser Op and its
+ * associated arguments. The namespace object is a more compact
+ * representation of the Op and its arguments.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_init_object_from_op (
+ acpi_walk_state *walk_state,
+ acpi_parse_object *op,
+ u16 opcode,
+ acpi_operand_object **ret_obj_desc)
+{
+ const acpi_opcode_info *op_info;
+ acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE ("Ds_init_object_from_op");
+
+
+ obj_desc = *ret_obj_desc;
+ op_info = acpi_ps_get_opcode_info (opcode);
+ if (op_info->class == AML_CLASS_UNKNOWN) {
+ /* Unknown opcode */
+
+ return_ACPI_STATUS (AE_TYPE);
+ }
+
+ /* Perform per-object initialization */
+
+ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * Defer evaluation of Buffer Term_arg operand
+ */
+ obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0];
+ obj_desc->buffer.aml_start = op->named.data;
+ obj_desc->buffer.aml_length = op->named.length;
+ break;
+
+
+ case ACPI_TYPE_PACKAGE:
+
+ /*
+ * Defer evaluation of Package Term_arg operand
+ */
+ obj_desc->package.node = (acpi_namespace_node *) walk_state->operands[0];
+ obj_desc->package.aml_start = op->named.data;
+ obj_desc->package.aml_length = op->named.length;
+ break;
+
+
+ case ACPI_TYPE_INTEGER:
+
+ switch (op_info->type) {
+ case AML_TYPE_CONSTANT:
+ /*
+ * Resolve AML Constants here - AND ONLY HERE!
+ * All constants are integers.
+ * We mark the integer with a flag that indicates that it started life
+ * as a constant -- so that stores to constants will perform as expected (noop).
+ * (Zero_op is used as a placeholder for optional target operands.)
+ */
+ obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
+
+ switch (opcode) {
+ case AML_ZERO_OP:
+
+ obj_desc->integer.value = 0;
+ break;
+
+ case AML_ONE_OP:
+
+ obj_desc->integer.value = 1;
+ break;
+
+ case AML_ONES_OP:
+
+ obj_desc->integer.value = ACPI_INTEGER_MAX;
+
+ /* Truncate value if we are executing from a 32-bit ACPI table */
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+ acpi_ex_truncate_for32bit_table (obj_desc);
+#endif
+ break;
+
+ case AML_REVISION_OP:
+
+ obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL;
+ break;
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+ break;
+
+
+ case AML_TYPE_LITERAL:
+
+ obj_desc->integer.value = op->common.value.integer;
+ break;
+
+
+ default:
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ obj_desc->string.pointer = op->common.value.string;
+ obj_desc->string.length = ACPI_STRLEN (op->common.value.string);
+
+ /*
+ * The string is contained in the ACPI table, don't ever try
+ * to delete it
+ */
+ obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
+ break;
+
+
+ case ACPI_TYPE_METHOD:
+ break;
+
+
+ case INTERNAL_TYPE_REFERENCE:
+
+ switch (op_info->type) {
+ case AML_TYPE_LOCAL_VARIABLE:
+
+ /* Split the opcode into a base opcode + offset */
+
+ obj_desc->reference.opcode = AML_LOCAL_OP;
+ obj_desc->reference.offset = opcode - AML_LOCAL_OP;
+#ifndef ACPI_NO_METHOD_EXECUTION
+ acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset,
+ walk_state, (acpi_namespace_node **) &obj_desc->reference.object);
+#endif
+ break;
+
+
+ case AML_TYPE_METHOD_ARGUMENT:
+
+ /* Split the opcode into a base opcode + offset */
+
+ obj_desc->reference.opcode = AML_ARG_OP;
+ obj_desc->reference.offset = opcode - AML_ARG_OP;
+ break;
+
+ default: /* Other literals, etc.. */
+
+ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ /* Node was saved in Op */
+
+ obj_desc->reference.node = op->common.node;
+ }
+
+ obj_desc->reference.opcode = opcode;
+ break;
+ }
+ break;
+
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
+ ACPI_GET_OBJECT_TYPE (obj_desc)));
+
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+
+ return_ACPI_STATUS (status);
+}
+
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 77b50406d3a2..66b6d64bfe6d 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: dsutils - Dispatcher utilities
- * $Revision: 93 $
+ * $Revision: 94 $
*
******************************************************************************/
@@ -35,6 +35,7 @@
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME ("dsutils")
+#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -237,6 +238,47 @@ acpi_ds_delete_result_if_not_used (
/*******************************************************************************
*
+ * FUNCTION: Acpi_ds_resolve_operands
+ *
+ * PARAMETERS: Walk_state - Current walk state with operands on stack
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Resolve all operands to their values. Used to prepare
+ * arguments to a control method invocation (a call from one
+ * method to another.)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_resolve_operands (
+ acpi_walk_state *walk_state)
+{
+ u32 i;
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("Ds_resolve_operands", walk_state);
+
+
+ /*
+ * Attempt to resolve each of the valid operands
+ * Method arguments are passed by value, not by reference
+ */
+ for (i = 0; i < walk_state->num_operands; i++) {
+ status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+ }
+
+ return_ACPI_STATUS (status);
+}
+#endif
+
+
+/*******************************************************************************
+ *
* FUNCTION: Acpi_ds_create_operand
*
* PARAMETERS: Walk_state
@@ -515,42 +557,3 @@ cleanup:
}
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ds_resolve_operands
- *
- * PARAMETERS: Walk_state - Current walk state with operands on stack
- *
- * RETURN: Status
- *
- * DESCRIPTION: Resolve all operands to their values. Used to prepare
- * arguments to a control method invocation (a call from one
- * method to another.)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_resolve_operands (
- acpi_walk_state *walk_state)
-{
- u32 i;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("Ds_resolve_operands", walk_state);
-
-
- /*
- * Attempt to resolve each of the valid operands
- * Method arguments are passed by value, not by reference
- */
- for (i = 0; i < walk_state->num_operands; i++) {
- status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
- if (ACPI_FAILURE (status)) {
- break;
- }
- }
-
- return_ACPI_STATUS (status);
-}
-
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index c73bbcaf6213..3da768ff5856 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: dswload - Dispatcher namespace load callbacks
- * $Revision: 67 $
+ * $Revision: 69 $
*
*****************************************************************************/
@@ -70,9 +70,11 @@ acpi_ds_init_callbacks (
break;
case 3:
+#ifndef ACPI_NO_METHOD_EXECUTION
walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_exec_begin_op;
walk_state->ascending_callback = acpi_ds_exec_end_op;
+#endif
break;
default:
@@ -169,6 +171,11 @@ acpi_ds_load1_begin_op (
op->named.name = node->name.integer;
+#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
+ op->named.path = (u8 *) path;
+#endif
+
+
/*
* Put the Node in the "op" object that the parser uses, so we
* can get it again quickly when this scope is closed
@@ -221,6 +228,7 @@ acpi_ds_load1_end_op (
object_type = walk_state->op_info->object_type;
+#ifndef ACPI_NO_METHOD_EXECUTION
if (walk_state->op_info->flags & AML_FIELD) {
if (walk_state->opcode == AML_FIELD_OP ||
walk_state->opcode == AML_BANK_FIELD_OP ||
@@ -238,6 +246,7 @@ acpi_ds_load1_end_op (
return (status);
}
}
+#endif
if (op->common.aml_opcode == AML_NAME_OP) {
/* For Name opcode, get the object type from the argument */
@@ -430,7 +439,9 @@ acpi_ds_load2_end_op (
acpi_namespace_node *node;
acpi_parse_object *arg;
acpi_namespace_node *new_node;
+#ifndef ACPI_NO_METHOD_EXECUTION
u32 i;
+#endif
ACPI_FUNCTION_NAME ("Ds_load2_end_op");
@@ -478,6 +489,7 @@ acpi_ds_load2_end_op (
}
}
+
/*
* Named operations are as follows:
*
@@ -515,6 +527,8 @@ acpi_ds_load2_end_op (
arg = op->common.value.arg;
switch (walk_state->op_info->type) {
+#ifndef ACPI_NO_METHOD_EXECUTION
+
case AML_TYPE_CREATE_FIELD:
/*
@@ -604,7 +618,7 @@ acpi_ds_load2_end_op (
}
break;
-
+#endif /* ACPI_NO_METHOD_EXECUTION */
case AML_TYPE_NAMED_COMPLEX:
@@ -629,6 +643,7 @@ acpi_ds_load2_end_op (
break;
+#ifndef ACPI_NO_METHOD_EXECUTION
case AML_REGION_OP:
/*
* The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
@@ -656,6 +671,7 @@ acpi_ds_load2_end_op (
status = acpi_ds_create_node (walk_state, node, op);
break;
+#endif /* ACPI_NO_METHOD_EXECUTION */
default:
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 37bb06d5fd9b..c5f83e5704d0 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: dswstate - Dispatcher parse tree walk management routines
- * $Revision: 65 $
+ * $Revision: 67 $
*
*****************************************************************************/
@@ -837,7 +837,7 @@ acpi_ds_create_walk_state (
/* Init the method args/local */
-#ifndef _ACPI_ASL_COMPILER
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
acpi_ds_method_data_init (walk_state);
#endif
@@ -858,7 +858,6 @@ acpi_ds_create_walk_state (
}
-#ifndef _ACPI_ASL_COMPILER
/*******************************************************************************
*
* FUNCTION: Acpi_ds_init_aml_walk
@@ -943,7 +942,6 @@ acpi_ds_init_aml_walk (
status = acpi_ds_init_callbacks (walk_state, pass_number);
return_ACPI_STATUS (status);
}
-#endif
/*******************************************************************************
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3dba2994bd6a..a0fc74029b09 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1,5 +1,5 @@
/*
- * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 35 $)
+ * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -62,15 +62,15 @@ static int acpi_ec_start (struct acpi_device *device);
static int acpi_ec_stop (struct acpi_device *device, int type);
static struct acpi_driver acpi_ec_driver = {
- name: ACPI_EC_DRIVER_NAME,
- class: ACPI_EC_CLASS,
- ids: ACPI_EC_HID,
- ops: {
- add: acpi_ec_add,
- remove: acpi_ec_remove,
- start: acpi_ec_start,
- stop: acpi_ec_stop,
- },
+ .name = ACPI_EC_DRIVER_NAME,
+ .class = ACPI_EC_CLASS,
+ .ids = ACPI_EC_HID,
+ .ops = {
+ .add = acpi_ec_add,
+ .remove = acpi_ec_remove,
+ .start = acpi_ec_start,
+ .stop = acpi_ec_stop,
+ },
};
struct acpi_ec {
@@ -134,7 +134,7 @@ static int
acpi_ec_read (
struct acpi_ec *ec,
u8 address,
- u8 *data)
+ u32 *data)
{
acpi_status status = AE_OK;
int result = 0;
@@ -167,7 +167,7 @@ acpi_ec_read (
goto end;
- acpi_hw_low_level_read(8, (u32*) data, &ec->data_addr, 0);
+ acpi_hw_low_level_read(8, data, &ec->data_addr, 0);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
*data, address));
@@ -237,7 +237,7 @@ end:
static int
acpi_ec_query (
struct acpi_ec *ec,
- u8 *data)
+ u32 *data)
{
int result = 0;
acpi_status status = AE_OK;
@@ -269,7 +269,7 @@ acpi_ec_query (
if (result)
goto end;
- acpi_hw_low_level_read(8, (u32*) data, &ec->data_addr, 0);
+ acpi_hw_low_level_read(8, data, &ec->data_addr, 0);
if (!*data)
result = -ENODATA;
@@ -328,7 +328,7 @@ acpi_ec_gpe_handler (
{
acpi_status status = AE_OK;
struct acpi_ec *ec = (struct acpi_ec *) data;
- u8 value = 0;
+ u32 value = 0;
unsigned long flags = 0;
struct acpi_ec_query_data *query_data = NULL;
@@ -336,7 +336,7 @@ acpi_ec_gpe_handler (
return;
spin_lock_irqsave(&ec->lock, flags);
- acpi_hw_low_level_read(8, (u32*) &value, &ec->command_addr, 0);
+ acpi_hw_low_level_read(8, &value, &ec->command_addr, 0);
spin_unlock_irqrestore(&ec->lock, flags);
/* TBD: Implement asynch events!
@@ -398,6 +398,7 @@ acpi_ec_space_handler (
{
int result = 0;
struct acpi_ec *ec = NULL;
+ u32 temp = 0;
ACPI_FUNCTION_TRACE("acpi_ec_space_handler");
@@ -408,7 +409,8 @@ acpi_ec_space_handler (
switch (function) {
case ACPI_READ:
- result = acpi_ec_read(ec, (u8) address, (u8*) value);
+ result = acpi_ec_read(ec, (u8) address, &temp);
+ *value = (acpi_integer) temp;
break;
case ACPI_WRITE:
result = acpi_ec_write(ec, (u8) address, (u8) *value);
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 7ea92f53a22b..2f9c06242e88 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: excreate - Named object creation
- * $Revision: 92 $
+ * $Revision: 93 $
*
*****************************************************************************/
@@ -36,6 +36,7 @@
ACPI_MODULE_NAME ("excreate")
+#ifndef ACPI_NO_METHOD_EXECUTION
/*****************************************************************************
*
* FUNCTION: Acpi_ex_create_alias
@@ -490,6 +491,7 @@ acpi_ex_create_power_resource (
return_ACPI_STATUS (status);
}
+#endif
/*****************************************************************************
*
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 49c68d410a68..634d2a4385d7 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: exdump - Interpreter debug output routines
- * $Revision: 156 $
+ * $Revision: 157 $
*
*****************************************************************************/
@@ -575,14 +575,14 @@ acpi_ex_dump_object_descriptor (
{
if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer)))
{
- return;
+ return_VOID;
}
}
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND)
{
acpi_os_printf ("Ex_dump_object_descriptor: %p is not a valid ACPI object\n", obj_desc);
- return;
+ return_VOID;
}
/* Common Fields */
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 688e2b80c892..803b00ea38c3 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Module Name: exoparg1 - AML execution - opcodes with 1 argument
- * $Revision: 140 $
+ * $Revision: 141 $
*
*****************************************************************************/
@@ -804,16 +804,7 @@ acpi_ex_opcode_1A_0T_1R (
switch (operand[0]->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
- /* Ensure that the Buffer arguments are evaluated */
-
temp_desc = operand[0]->reference.object;
-#if 0
-
- status = acpi_ds_get_buffer_arguments (temp_desc);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
- }
-#endif
/*
* Create a new object that contains one element of the
@@ -841,14 +832,6 @@ acpi_ex_opcode_1A_0T_1R (
case ACPI_TYPE_PACKAGE:
-#if 0
- /* Ensure that the Package arguments are evaluated */
-
- status = acpi_ds_get_package_arguments (operand[0]->reference.object);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
- }
-#endif
/*
* Return the referenced element of the package. We must add
* another reference to the referenced object, however.
@@ -884,6 +867,11 @@ acpi_ex_opcode_1A_0T_1R (
return_desc = operand[0]->reference.object;
+ if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) == ACPI_DESC_TYPE_NAMED) {
+
+ return_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) return_desc);
+ }
+
/* Add another reference to the object! */
acpi_ut_add_reference (return_desc);
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 11005af6a7a2..6e5b06166f92 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Module Name: exutils - interpreter/scanner utilities
- * $Revision: 100 $
+ * $Revision: 102 $
*
*****************************************************************************/
@@ -52,6 +52,34 @@
/*******************************************************************************
*
+ * FUNCTION: Acpi_ex_validate_object_type
+ *
+ * PARAMETERS: Type Object type to validate
+ *
+ * DESCRIPTION: Determine if a type is a valid ACPI object type
+ *
+ ******************************************************************************/
+
+u8
+acpi_ex_validate_object_type (
+ acpi_object_type type)
+{
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) ||
+ (type > INTERNAL_TYPE_MAX)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+
+/*******************************************************************************
+ *
* FUNCTION: Acpi_ex_enter_interpreter
*
* PARAMETERS: None
@@ -118,33 +146,6 @@ acpi_ex_exit_interpreter (void)
/*******************************************************************************
*
- * FUNCTION: Acpi_ex_validate_object_type
- *
- * PARAMETERS: Type Object type to validate
- *
- * DESCRIPTION: Determine if a type is a valid ACPI object type
- *
- ******************************************************************************/
-
-u8
-acpi_ex_validate_object_type (
- acpi_object_type type)
-{
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) ||
- (type > INTERNAL_TYPE_MAX)) {
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: Acpi_ex_truncate_for32bit_table
*
* PARAMETERS: Obj_desc - Object to be truncated
@@ -263,6 +264,8 @@ acpi_ex_release_global_lock (
ACPI_REPORT_ERROR (("Could not release ACPI Global Lock\n"));
}
}
+
+ return_VOID;
}
@@ -378,4 +381,4 @@ acpi_ex_unsigned_integer_to_string (
}
}
-
+#endif
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 3429bbf111be..3b3c728d3eac 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -1,5 +1,5 @@
/*
- * acpi_fan.c - ACPI Fan Driver ($Revision: 28 $)
+ * acpi_fan.c - ACPI Fan Driver ($Revision: 29 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -47,13 +47,13 @@ int acpi_fan_add (struct acpi_device *device);
int acpi_fan_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
- name: ACPI_FAN_DRIVER_NAME,
- class: ACPI_FAN_CLASS,
- ids: ACPI_FAN_HID,
- ops: {
- add: acpi_fan_add,
- remove: acpi_fan_remove,
- },
+ .name = ACPI_FAN_DRIVER_NAME,
+ .class = ACPI_FAN_CLASS,
+ .ids = ACPI_FAN_HID,
+ .ops = {
+ .add = acpi_fan_add,
+ .remove = acpi_fan_remove,
+ },
};
struct acpi_fan {
diff --git a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h
index 3987706d5ecf..bc88390e874c 100644
--- a/drivers/acpi/include/acconfig.h
+++ b/drivers/acpi/include/acconfig.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acconfig.h - Global configuration constants
- * $Revision: 105 $
+ * $Revision: 107 $
*
*****************************************************************************/
@@ -54,7 +54,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20020702
+#define ACPI_CA_VERSION 0x20020725
/* Version of ACPI supported */
@@ -152,6 +152,15 @@
#define ACPI_MAX_ADDRESS_SPACE 255
+/* Array sizes. Used for range checking also */
+
+#define NUM_ACCESS_TYPES 6
+#define NUM_UPDATE_RULES 3
+#define NUM_LOCK_RULES 2
+#define NUM_MATCH_OPS 6
+#define NUM_OPCODES 256
+#define NUM_FIELD_NAMES 2
+
/* RSDP checksums */
#define ACPI_RSDP_CHECKSUM_LENGTH 20
diff --git a/drivers/acpi/include/acdebug.h b/drivers/acpi/include/acdebug.h
index e76ad4b956fc..f32ebd8fe1bc 100644
--- a/drivers/acpi/include/acdebug.h
+++ b/drivers/acpi/include/acdebug.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acdebug.h - ACPI/AML debugger
- * $Revision: 62 $
+ * $Revision: 63 $
*
*****************************************************************************/
@@ -29,7 +29,6 @@
#define ACPI_DEBUG_BUFFER_SIZE 4196
-
typedef struct command_info
{
NATIVE_CHAR *name; /* Command Name */
@@ -186,47 +185,6 @@ acpi_db_walk_for_specific_objects (
/*
- * dbdisasm - AML disassembler
- */
-
-void
-acpi_db_display_op (
- acpi_walk_state *walk_state,
- acpi_parse_object *origin,
- u32 num_opcodes);
-
-void
-acpi_db_display_namestring (
- NATIVE_CHAR *name);
-
-void
-acpi_db_display_path (
- acpi_parse_object *op);
-
-void
-acpi_db_display_opcode (
- acpi_walk_state *walk_state,
- acpi_parse_object *op);
-
-void
-acpi_db_decode_internal_object (
- acpi_operand_object *obj_desc);
-
-void
-acpi_db_decode_node (
- acpi_namespace_node *node);
-
-u32
-acpi_db_block_type (
- acpi_parse_object *op);
-
-acpi_status
-acpi_ps_display_object_pathname (
- acpi_walk_state *walk_state,
- acpi_parse_object *op);
-
-
-/*
* dbdisply - debug display commands
*/
@@ -282,6 +240,10 @@ void *
acpi_db_get_pointer (
void *target);
+void
+acpi_db_decode_internal_object (
+ acpi_operand_object *obj_desc);
+
/*
* dbexec - debugger control method execution
diff --git a/drivers/acpi/include/acdisasm.h b/drivers/acpi/include/acdisasm.h
new file mode 100644
index 000000000000..6c126d07f728
--- /dev/null
+++ b/drivers/acpi/include/acdisasm.h
@@ -0,0 +1,362 @@
+/******************************************************************************
+ *
+ * Name: acdisasm.h - AML disassembler
+ * $Revision: 2 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2002, R. Byron Moore
+ *
+ * This program is free software; you can redistribute 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 __ACDISASM_H__
+#define __ACDISASM_H__
+
+#include "amlresrc.h"
+
+
+#define BLOCK_NONE 0
+#define BLOCK_PAREN 1
+#define BLOCK_BRACE 2
+#define BLOCK_COMMA_LIST 4
+
+extern const char *acpi_gbl_io_decode[2];
+extern const char *acpi_gbl_word_decode[4];
+extern const char *acpi_gbl_consume_decode[2];
+extern const char *acpi_gbl_min_decode[2];
+extern const char *acpi_gbl_max_decode[2];
+extern const char *acpi_gbl_DECdecode[2];
+extern const char *acpi_gbl_RNGdecode[4];
+extern const char *acpi_gbl_MEMdecode[4];
+extern const char *acpi_gbl_RWdecode[2];
+extern const char *acpi_gbl_irq_decode[2];
+extern const char *acpi_gbl_HEdecode[2];
+extern const char *acpi_gbl_LLdecode[2];
+extern const char *acpi_gbl_SHRdecode[2];
+extern const char *acpi_gbl_TYPdecode[4];
+extern const char *acpi_gbl_BMdecode[2];
+extern const char *acpi_gbl_SIZdecode[4];
+extern const NATIVE_CHAR *acpi_gbl_lock_rule[NUM_LOCK_RULES];
+extern const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES];
+extern const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES];
+extern const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS];
+
+
+typedef struct acpi_op_walk_info
+{
+ u32 level;
+ u32 bit_offset;
+
+} ACPI_OP_WALK_INFO;
+
+typedef
+acpi_status (*ASL_WALK_CALLBACK) (
+ acpi_parse_object *op,
+ u32 level,
+ void *context);
+
+
+/*
+ * dmwalk
+ */
+
+void
+acpi_dm_walk_parse_tree (
+ acpi_parse_object *op,
+ ASL_WALK_CALLBACK descending_callback,
+ ASL_WALK_CALLBACK ascending_callback,
+ void *context);
+
+acpi_status
+acpi_dm_descending_op (
+ acpi_parse_object *op,
+ u32 level,
+ void *context);
+
+acpi_status
+acpi_dm_ascending_op (
+ acpi_parse_object *op,
+ u32 level,
+ void *context);
+
+
+/*
+ * dmopcode
+ */
+
+void
+acpi_dm_validate_name (
+ char *name,
+ acpi_parse_object *op);
+
+u32
+acpi_dm_dump_name (
+ char *name);
+
+void
+acpi_dm_string (
+ char *string);
+
+void
+acpi_dm_unicode (
+ acpi_parse_object *op);
+
+void
+acpi_dm_disassemble (
+ acpi_walk_state *walk_state,
+ acpi_parse_object *origin,
+ u32 num_opcodes);
+
+void
+acpi_dm_namestring (
+ NATIVE_CHAR *name);
+
+void
+acpi_dm_display_path (
+ acpi_parse_object *op);
+
+void
+acpi_dm_disassemble_one_op (
+ acpi_walk_state *walk_state,
+ ACPI_OP_WALK_INFO *info,
+ acpi_parse_object *op);
+
+void
+acpi_dm_decode_internal_object (
+ acpi_operand_object *obj_desc);
+
+void
+acpi_dm_decode_node (
+ acpi_namespace_node *node);
+
+u32
+acpi_dm_block_type (
+ acpi_parse_object *op);
+
+u32
+acpi_dm_list_type (
+ acpi_parse_object *op);
+
+acpi_status
+acpi_ps_display_object_pathname (
+ acpi_walk_state *walk_state,
+ acpi_parse_object *op);
+
+void
+acpi_dm_method_flags (
+ acpi_parse_object *op);
+
+void
+acpi_dm_field_flags (
+ acpi_parse_object *op);
+
+void
+acpi_dm_address_space (
+ u8 space_id);
+
+void
+acpi_dm_region_flags (
+ acpi_parse_object *op);
+
+void
+acpi_dm_match_op (
+ acpi_parse_object *op);
+
+void
+acpi_dm_match_keyword (
+ acpi_parse_object *op);
+
+u8
+acpi_dm_comma_if_list_member (
+ acpi_parse_object *op);
+
+void
+acpi_dm_comma_if_field_member (
+ acpi_parse_object *op);
+
+
+/*
+ * dmbuffer
+ */
+
+void
+acpi_is_eisa_id (
+ acpi_parse_object *op);
+
+void
+acpi_dm_eisa_id (
+ u32 encoded_id);
+
+u8
+acpi_dm_is_unicode_buffer (
+ acpi_parse_object *op);
+
+u8
+acpi_dm_is_string_buffer (
+ acpi_parse_object *op);
+
+
+/*
+ * dmresrc
+ */
+
+void
+acpi_dm_disasm_byte_list (
+ u32 level,
+ u8 *byte_data,
+ u32 byte_count);
+
+void
+acpi_dm_byte_list (
+ ACPI_OP_WALK_INFO *info,
+ acpi_parse_object *op);
+
+void
+acpi_dm_resource_descriptor (
+ ACPI_OP_WALK_INFO *info,
+ u8 *byte_data,
+ u32 byte_count);
+
+u8
+acpi_dm_is_resource_descriptor (
+ acpi_parse_object *op);
+
+void
+acpi_dm_indent (
+ u32 level);
+
+void
+acpi_dm_bit_list (
+ u16 mask);
+
+
+/*
+ * dmresrcl
+ */
+
+void
+acpi_dm_io_flags (
+ u8 flags);
+
+void
+acpi_dm_memory_flags (
+ u8 flags,
+ u8 specific_flags);
+
+void
+acpi_dm_word_descriptor (
+ ASL_WORD_ADDRESS_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_dword_descriptor (
+ ASL_DWORD_ADDRESS_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_qword_descriptor (
+ ASL_QWORD_ADDRESS_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_memory24_descriptor (
+ ASL_MEMORY_24_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_memory32_descriptor (
+ ASL_MEMORY_32_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_fixed_mem32_descriptor (
+ ASL_FIXED_MEMORY_32_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_generic_register_descriptor (
+ ASL_GENERAL_REGISTER_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_interrupt_descriptor (
+ ASL_EXTENDED_XRUPT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_vendor_large_descriptor (
+ ASL_LARGE_VENDOR_DESC *resource,
+ u32 length,
+ u32 level);
+
+
+/*
+ * dmresrcs
+ */
+
+void
+acpi_dm_irq_descriptor (
+ ASL_IRQ_FORMAT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_dma_descriptor (
+ ASL_DMA_FORMAT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_io_descriptor (
+ ASL_IO_PORT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_fixed_io_descriptor (
+ ASL_FIXED_IO_PORT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_start_dependent_descriptor (
+ ASL_START_DEPENDENT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_end_dependent_descriptor (
+ ASL_START_DEPENDENT_DESC *resource,
+ u32 length,
+ u32 level);
+
+void
+acpi_dm_vendor_small_descriptor (
+ ASL_SMALL_VENDOR_DESC *resource,
+ u32 length,
+ u32 level);
+
+
+#endif /* __ACDISASM_H__ */
diff --git a/drivers/acpi/include/acglobal.h b/drivers/acpi/include/acglobal.h
index 1d10c1b4203a..28e9d46ae359 100644
--- a/drivers/acpi/include/acglobal.h
+++ b/drivers/acpi/include/acglobal.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acglobal.h - Declarations for global variables
- * $Revision: 126 $
+ * $Revision: 128 $
*
*****************************************************************************/
@@ -140,8 +140,9 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_present;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_startup_flags;
extern const u8 acpi_gbl_decode_to8bit[8];
-extern const NATIVE_CHAR *acpi_gbl_db_sleep_states[ACPI_NUM_SLEEP_STATES];
+extern const NATIVE_CHAR *acpi_gbl_db_sleep_states[ACPI_NUM_SLEEP_STATES];
extern const acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
+extern const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
/*****************************************************************************
@@ -237,6 +238,12 @@ ACPI_EXTERN ACPI_GPE_INDEX_INFO *acpi_gbl_gpe_number_to_index;
ACPI_EXTERN u8 acpi_gbl_db_output_flags;
+#ifdef ACPI_DISASSEMBLER
+
+ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
+ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
+#endif
+
#ifdef ENABLE_DEBUGGER
@@ -247,9 +254,7 @@ ACPI_EXTERN int optind;
ACPI_EXTERN NATIVE_CHAR *optarg;
ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
-ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
-ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
@@ -261,7 +266,6 @@ ACPI_EXTERN NATIVE_CHAR acpi_gbl_db_debug_filename[40];
ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_buffer;
ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_filename;
-ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_disasm_indent;
ACPI_EXTERN u32 acpi_gbl_db_debug_level;
ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
ACPI_EXTERN acpi_table_header *acpi_gbl_db_table_ptr;
diff --git a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h
index 54eb05fc66c8..f9d6e2f1f031 100644
--- a/drivers/acpi/include/aclocal.h
+++ b/drivers/acpi/include/aclocal.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: aclocal.h - Internal data types used across the ACPI subsystem
- * $Revision: 168 $
+ * $Revision: 173 $
*
*****************************************************************************/
@@ -567,8 +567,8 @@ acpi_status (*ACPI_EXECUTE_OP) (
*/
typedef struct acpi_opcode_info
{
-#ifdef _OPCODE_NAMES
- NATIVE_CHAR *name; /* Opcode name (debug only) */
+#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG)
+ NATIVE_CHAR *name; /* Opcode name (disassembler/debug only) */
#endif
u32 parse_args; /* Grammar/Parse time arguments */
u32 runtime_args; /* Interpret time arguments */
@@ -603,15 +603,23 @@ typedef union acpi_parse_val
u32 aml_offset; /* offset of declaration in AML */\
union acpi_parse_obj *parent; /* parent op */\
union acpi_parse_obj *next; /* next op */\
- ACPI_DEBUG_ONLY_MEMBERS (\
+ ACPI_DISASM_ONLY_MEMBERS (\
+ u8 disasm_flags; /* Used during AML disassembly */\
+ u8 disasm_opcode; /* Subtype used for disassembly */\
NATIVE_CHAR aml_op_name[16]) /* op name (debug only) */\
/* NON-DEBUG members below: */\
acpi_namespace_node *node; /* for use by interpreter */\
acpi_parse_value value; /* Value or args associated with the opcode */\
+#define ACPI_DASM_BUFFER 0x00
+#define ACPI_DASM_RESOURCE 0x01
+#define ACPI_DASM_STRING 0x02
+#define ACPI_DASM_UNICODE 0x03
+#define ACPI_DASM_EISAID 0x04
+#define ACPI_DASM_MATCHOP 0x05
/*
- * generic operation (eg. If, While, Store)
+ * generic operation (for example: If, While, Store)
*/
typedef struct acpi_parseobj_common
{
@@ -626,6 +634,7 @@ typedef struct acpi_parseobj_common
typedef struct acpi_parseobj_named
{
ACPI_PARSE_COMMON
+ u8 *path;
u8 *data; /* AML body or bytelist data */
u32 length; /* AML length */
u32 name; /* 4-byte name or zero if no name */
@@ -653,15 +662,15 @@ typedef struct acpi_parseobj_asl
u32 logical_byte_offset;
u32 end_line;
u32 end_logical_line;
- u16 parse_opcode;
u32 acpi_btype;
u32 aml_length;
u32 aml_subtree_length;
u32 final_aml_length;
u32 final_aml_offset;
+ u16 parse_opcode;
+ u16 compile_flags;
u8 aml_opcode_length;
u8 aml_pkg_len_bytes;
- u16 compile_flags;
u8 extra;
char parse_op_name[12];
@@ -705,6 +714,13 @@ typedef struct acpi_parse_state
#define ACPI_PARSEOP_BYTELIST 0x08
#define ACPI_PARSEOP_IN_CACHE 0x80
+/* Parse object Disasm_flags */
+
+#define ACPI_PARSEOP_IGNORE 0x01
+#define ACPI_PARSEOP_PARAMLIST 0x02
+#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
+#define ACPI_PARSEOP_SPECIAL 0x10
+
/*****************************************************************************
*
diff --git a/drivers/acpi/include/acmacros.h b/drivers/acpi/include/acmacros.h
index f48ac95210bf..57452f9b6cbf 100644
--- a/drivers/acpi/include/acmacros.h
+++ b/drivers/acpi/include/acmacros.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acmacros.h - C macros for the entire subsystem.
- * $Revision: 124 $
+ * $Revision: 126 $
*
*****************************************************************************/
@@ -287,12 +287,18 @@
/*
* Macros for the master AML opcode table
*/
-#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER)
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG)
#define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {name,Pargs,Iargs,flags,obj_type,class,type}
#else
#define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {Pargs,Iargs,flags,obj_type,class,type}
#endif
+#ifdef ACPI_DISASSEMBLER
+#define ACPI_DISASM_ONLY_MEMBERS(a) a;
+#else
+#define ACPI_DISASM_ONLY_MEMBERS(a)
+#endif
+
#define ARG_TYPE_WIDTH 5
#define ARG_1(x) ((u32)(x))
#define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH))
@@ -435,7 +441,6 @@
#define ACPI_DEBUG_DEFINE(a) a;
#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
-#define _OPCODE_NAMES
#define _VERBOSE_STRUCTURES
@@ -515,10 +520,6 @@
#define return_VALUE(s) return(s)
#define return_PTR(s) return(s)
-#ifdef ENABLE_DEBUGGER
-#define _OPCODE_NAMES
-#endif
-
#endif
/*
diff --git a/drivers/acpi/include/acnamesp.h b/drivers/acpi/include/acnamesp.h
index c5a90435c3f7..49c5223e1f27 100644
--- a/drivers/acpi/include/acnamesp.h
+++ b/drivers/acpi/include/acnamesp.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acnamesp.h - Namespace subcomponent prototypes and defines
- * $Revision: 125 $
+ * $Revision: 126 $
*
*****************************************************************************/
@@ -43,7 +43,7 @@
/* Definitions of the predefined namespace names */
#define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */
-#define ACPI_ROOT_NAME (u32) 0x2F202020 /* Root name is "/ " */
+#define ACPI_ROOT_NAME (u32) 0x5F5F5F5C /* Root name is "\___" */
#define ACPI_SYS_BUS_NAME (u32) 0x5F53425F /* Sys bus name is "_SB_" */
#define ACPI_NS_ROOT_PATH "\\"
diff --git a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h
index 56d4037f8b46..b6cac89b91b9 100644
--- a/drivers/acpi/include/acpiosxf.h
+++ b/drivers/acpi/include/acpiosxf.h
@@ -204,7 +204,6 @@ acpi_os_read_port (
void *value,
u32 width);
-
acpi_status
acpi_os_write_port (
ACPI_IO_ADDRESS address,
@@ -222,7 +221,6 @@ acpi_os_read_memory (
void *value,
u32 width);
-
acpi_status
acpi_os_write_memory (
ACPI_PHYSICAL_ADDRESS address,
@@ -241,7 +239,6 @@ acpi_os_read_pci_configuration (
void *value,
u32 width);
-
acpi_status
acpi_os_write_pci_configuration (
acpi_pci_id *pci_id,
@@ -259,7 +256,6 @@ acpi_os_readable (
void *pointer,
u32 length);
-
u8
acpi_os_writable (
void *pointer,
@@ -288,6 +284,10 @@ acpi_os_vprintf (
const NATIVE_CHAR *format,
va_list args);
+void
+acpi_os_redirect_output (
+ void *destination);
+
/*
* Debug input
diff --git a/drivers/acpi/include/acutils.h b/drivers/acpi/include/acutils.h
index 46ea89bafd70..3af0afac24b5 100644
--- a/drivers/acpi/include/acutils.h
+++ b/drivers/acpi/include/acutils.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acutils.h -- prototypes for the common (subsystem-wide) procedures
- * $Revision: 140 $
+ * $Revision: 142 $
*
*****************************************************************************/
@@ -224,6 +224,9 @@ extern const u8 _acpi_ctype[];
#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP))
#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
+#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
+#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
+#define ACPI_IS_ASCII(c) ((c) < 0x80)
#endif /* ACPI_USE_SYSTEM_CLIBRARY */
diff --git a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h
index ddcffdf80897..b5802baca761 100644
--- a/drivers/acpi/include/amlcode.h
+++ b/drivers/acpi/include/amlcode.h
@@ -3,7 +3,7 @@
* Name: amlcode.h - Definitions for AML, as included in "definition blocks"
* Declarations and definitions contained herein are derived
* directly from the ACPI specification.
- * $Revision: 68 $
+ * $Revision: 69 $
*
*****************************************************************************/
@@ -474,13 +474,4 @@ typedef enum
#define METHOD_FLAGS_SYNCH_LEVEL 0xF0
-/* Array sizes. Used for range checking also */
-
-#define NUM_ACCESS_TYPES 6
-#define NUM_UPDATE_RULES 3
-#define NUM_MATCH_OPS 7
-#define NUM_OPCODES 256
-#define NUM_FIELD_NAMES 2
-
-
#endif /* __AMLCODE_H__ */
diff --git a/drivers/acpi/include/amlresrc.h b/drivers/acpi/include/amlresrc.h
index d8aa2befb2c1..a97dbf2f59e4 100644
--- a/drivers/acpi/include/amlresrc.h
+++ b/drivers/acpi/include/amlresrc.h
@@ -1,8 +1,8 @@
/******************************************************************************
*
- * Module Name: aslresource.h - ASL resource descriptors
- * $Revision: 19 $
+ * Module Name: amlresrc.h - AML resource descriptors
+ * $Revision: 20 $
*
*****************************************************************************/
@@ -25,8 +25,8 @@
*/
-#ifndef __ASLRESOURCE_H
-#define __ASLRESOURCE_H
+#ifndef __AMLRESRC_H
+#define __AMLRESRC_H
#define ASL_RESNAME_ADDRESS "_ADR"
@@ -80,11 +80,13 @@ typedef struct asl_resource_node
/*
- * Resource descriptors defined in the ACPI specification
+ * Resource descriptors defined in the ACPI specification.
+ *
+ * Alignment must be BYTE because these descriptors
+ * are used to overlay the AML byte stream.
*/
-
-
#pragma pack(1)
+
typedef struct asl_irq_format_desc
{
u8 descriptor_type;
@@ -94,7 +96,6 @@ typedef struct asl_irq_format_desc
} ASL_IRQ_FORMAT_DESC;
-#pragma pack(1)
typedef struct asl_irq_noflags_desc
{
u8 descriptor_type;
@@ -103,7 +104,6 @@ typedef struct asl_irq_noflags_desc
} ASL_IRQ_NOFLAGS_DESC;
-#pragma pack(1)
typedef struct asl_dma_format_desc
{
u8 descriptor_type;
@@ -113,7 +113,6 @@ typedef struct asl_dma_format_desc
} ASL_DMA_FORMAT_DESC;
-#pragma pack(1)
typedef struct asl_start_dependent_desc
{
u8 descriptor_type;
@@ -122,7 +121,6 @@ typedef struct asl_start_dependent_desc
} ASL_START_DEPENDENT_DESC;
-#pragma pack(1)
typedef struct asl_start_dependent_noprio_desc
{
u8 descriptor_type;
@@ -130,7 +128,6 @@ typedef struct asl_start_dependent_noprio_desc
} ASL_START_DEPENDENT_NOPRIO_DESC;
-#pragma pack(1)
typedef struct asl_end_dependent_desc
{
u8 descriptor_type;
@@ -138,7 +135,6 @@ typedef struct asl_end_dependent_desc
} ASL_END_DEPENDENT_DESC;
-#pragma pack(1)
typedef struct asl_io_port_desc
{
u8 descriptor_type;
@@ -151,7 +147,6 @@ typedef struct asl_io_port_desc
} ASL_IO_PORT_DESC;
-#pragma pack(1)
typedef struct asl_fixed_io_port_desc
{
u8 descriptor_type;
@@ -161,7 +156,6 @@ typedef struct asl_fixed_io_port_desc
} ASL_FIXED_IO_PORT_DESC;
-#pragma pack(1)
typedef struct asl_small_vendor_desc
{
u8 descriptor_type;
@@ -170,7 +164,6 @@ typedef struct asl_small_vendor_desc
} ASL_SMALL_VENDOR_DESC;
-#pragma pack(1)
typedef struct asl_end_tag_desc
{
u8 descriptor_type;
@@ -181,7 +174,6 @@ typedef struct asl_end_tag_desc
/* LARGE descriptors */
-#pragma pack(1)
typedef struct asl_memory_24_desc
{
u8 descriptor_type;
@@ -195,7 +187,6 @@ typedef struct asl_memory_24_desc
} ASL_MEMORY_24_DESC;
-#pragma pack(1)
typedef struct asl_large_vendor_desc
{
u8 descriptor_type;
@@ -205,7 +196,6 @@ typedef struct asl_large_vendor_desc
} ASL_LARGE_VENDOR_DESC;
-#pragma pack(1)
typedef struct asl_memory_32_desc
{
u8 descriptor_type;
@@ -219,7 +209,6 @@ typedef struct asl_memory_32_desc
} ASL_MEMORY_32_DESC;
-#pragma pack(1)
typedef struct asl_fixed_memory_32_desc
{
u8 descriptor_type;
@@ -231,7 +220,6 @@ typedef struct asl_fixed_memory_32_desc
} ASL_FIXED_MEMORY_32_DESC;
-#pragma pack(1)
typedef struct asl_qword_address_desc
{
u8 descriptor_type;
@@ -249,7 +237,6 @@ typedef struct asl_qword_address_desc
} ASL_QWORD_ADDRESS_DESC;
-#pragma pack(1)
typedef struct asl_dword_address_desc
{
u8 descriptor_type;
@@ -267,7 +254,6 @@ typedef struct asl_dword_address_desc
} ASL_DWORD_ADDRESS_DESC;
-#pragma pack(1)
typedef struct asl_word_address_desc
{
u8 descriptor_type;
@@ -285,7 +271,6 @@ typedef struct asl_word_address_desc
} ASL_WORD_ADDRESS_DESC;
-#pragma pack(1)
typedef struct asl_extended_xrupt_desc
{
u8 descriptor_type;
@@ -298,7 +283,6 @@ typedef struct asl_extended_xrupt_desc
} ASL_EXTENDED_XRUPT_DESC;
-#pragma pack(1)
typedef struct asl_general_register_desc
{
u8 descriptor_type;
@@ -311,6 +295,9 @@ typedef struct asl_general_register_desc
} ASL_GENERAL_REGISTER_DESC;
+/* restore default alignment */
+
+#pragma pack()
/* Union of all resource descriptors, sow we can allocate the worst case */
diff --git a/drivers/acpi/include/platform/acenv.h b/drivers/acpi/include/platform/acenv.h
index 1cb3f2939509..47f8f1cb2d3e 100644
--- a/drivers/acpi/include/platform/acenv.h
+++ b/drivers/acpi/include/platform/acenv.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: acenv.h - Generation environment specific items
- * $Revision: 95 $
+ * $Revision: 99 $
*
*****************************************************************************/
@@ -32,11 +32,13 @@
*/
#ifdef _ACPI_DUMP_APP
+#ifndef MSDOS
#define ACPI_DEBUG
+#endif
#define ACPI_APPLICATION
-#define ENABLE_DEBUGGER
+#define ACPI_DISASSEMBLER
+#define ACPI_NO_METHOD_EXECUTION
#define ACPI_USE_SYSTEM_CLIBRARY
-#define PARSER_ONLY
#endif
#ifdef _ACPI_EXEC_APP
@@ -45,13 +47,15 @@
#define ACPI_DEBUG
#define ACPI_APPLICATION
#define ENABLE_DEBUGGER
+#define ACPI_DISASSEMBLER
#define ACPI_USE_SYSTEM_CLIBRARY
#endif
#ifdef _ACPI_ASL_COMPILER
#define ACPI_DEBUG
#define ACPI_APPLICATION
-/* #define ENABLE_DEBUGGER */
+#define ACPI_DISASSEMBLER
+#define ACPI_CONSTANT_EVAL_ONLY
#define ACPI_USE_SYSTEM_CLIBRARY
#endif
@@ -183,7 +187,6 @@
/*
* Use the standard C library headers.
* We want to keep these to a minimum.
- *
*/
#ifdef ACPI_USE_STANDARD_HEADERS
@@ -213,12 +216,16 @@
#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (ACPI_SIZE)(n))
#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (ACPI_SIZE)(n))
#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (ACPI_SIZE)(n))
+
#define ACPI_TOUPPER toupper
#define ACPI_TOLOWER tolower
#define ACPI_IS_XDIGIT isxdigit
#define ACPI_IS_DIGIT isdigit
#define ACPI_IS_SPACE isspace
#define ACPI_IS_UPPER isupper
+#define ACPI_IS_PRINT isprint
+#define ACPI_IS_ALPHA isalpha
+#define ACPI_IS_ASCII isascii
/******************************************************************************
*
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index da59d90b095f..5a6c8c520af4 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: nsdump - table dumping routines for debug
- * $Revision: 136 $
+ * $Revision: 137 $
*
*****************************************************************************/
@@ -619,93 +619,6 @@ acpi_ns_dump_objects (
}
-#ifndef _ACPI_ASL_COMPILER
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ns_dump_one_device
- *
- * PARAMETERS: Handle - Node to be dumped
- * Level - Nesting level of the handle
- * Context - Passed into Walk_namespace
- *
- * DESCRIPTION: Dump a single Node that represents a device
- * This procedure is a User_function called by Acpi_ns_walk_namespace.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_dump_one_device (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
-{
- acpi_device_info info;
- acpi_status status;
- u32 i;
-
-
- ACPI_FUNCTION_NAME ("Ns_dump_one_device");
-
-
- status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
-
- status = acpi_get_object_info (obj_handle, &info);
- if (ACPI_SUCCESS (status)) {
- for (i = 0; i < level; i++) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
- }
-
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
- info.hardware_id,
- ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address),
- info.current_status));
- }
-
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ns_dump_root_devices
- *
- * PARAMETERS: None
- *
- * DESCRIPTION: Dump all objects of type "device"
- *
- ******************************************************************************/
-
-void
-acpi_ns_dump_root_devices (void)
-{
- acpi_handle sys_bus_handle;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("Ns_dump_root_devices");
-
-
- /* Only dump the table if tracing is enabled */
-
- if (!(ACPI_LV_TABLES & acpi_dbg_level)) {
- return;
- }
-
- status = acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
- if (ACPI_FAILURE (status)) {
- return;
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n"));
-
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ns_dump_one_device, NULL, NULL);
-}
-
-#endif
-
/*******************************************************************************
*
* FUNCTION: Acpi_ns_dump_tables
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
new file mode 100644
index 000000000000..0c82ecb93b7d
--- /dev/null
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -0,0 +1,124 @@
+/******************************************************************************
+ *
+ * Module Name: nsdump - table dumping routines for debug
+ * $Revision: 1 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2002, R. Byron Moore
+ *
+ * This program is free software; you can redistribute 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 "acpi.h"
+#include "acnamesp.h"
+#include "acparser.h"
+
+
+#define _COMPONENT ACPI_NAMESPACE
+ ACPI_MODULE_NAME ("nsdumpdv")
+
+
+#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER)
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_dump_one_device
+ *
+ * PARAMETERS: Handle - Node to be dumped
+ * Level - Nesting level of the handle
+ * Context - Passed into Walk_namespace
+ *
+ * DESCRIPTION: Dump a single Node that represents a device
+ * This procedure is a User_function called by Acpi_ns_walk_namespace.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_dump_one_device (
+ acpi_handle obj_handle,
+ u32 level,
+ void *context,
+ void **return_value)
+{
+ acpi_device_info info;
+ acpi_status status;
+ u32 i;
+
+
+ ACPI_FUNCTION_NAME ("Ns_dump_one_device");
+
+
+ status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
+
+ status = acpi_get_object_info (obj_handle, &info);
+ if (ACPI_SUCCESS (status)) {
+ for (i = 0; i < level; i++) {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
+ }
+
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
+ info.hardware_id,
+ ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address),
+ info.current_status));
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_dump_root_devices
+ *
+ * PARAMETERS: None
+ *
+ * DESCRIPTION: Dump all objects of type "device"
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_dump_root_devices (void)
+{
+ acpi_handle sys_bus_handle;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_NAME ("Ns_dump_root_devices");
+
+
+ /* Only dump the table if tracing is enabled */
+
+ if (!(ACPI_LV_TABLES & acpi_dbg_level)) {
+ return;
+ }
+
+ status = acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
+ if (ACPI_FAILURE (status)) {
+ return;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n"));
+
+ status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ns_dump_one_device, NULL, NULL);
+}
+
+#endif
+
+
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index cfbb32ba5779..967ed83b6937 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: nsload - namespace loading/expanding/contracting procedures
- * $Revision: 56 $
+ * $Revision: 57 $
*
*****************************************************************************/
@@ -37,59 +37,7 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_load_namespace
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
- * (DSDT points to either the BIOS or a buffer.)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_load_namespace (
- void)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("Acpi_load_name_space");
-
-
- /* There must be at least a DSDT installed */
-
- if (acpi_gbl_DSDT == NULL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
- }
-
- /*
- * Load the namespace. The DSDT is required,
- * but the SSDT and PSDT tables are optional.
- */
- status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- /* Ignore exceptions from these */
-
- (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
- (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
-
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
- "ACPI Namespace successfully loaded at root %p\n",
- acpi_gbl_root_node));
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ns_one_parse_pass
+ * FUNCTION: Ns_one_complete_parse
*
* PARAMETERS: Pass_number - 1 or 2
* Table_desc - The table to be parsed.
@@ -203,6 +151,7 @@ acpi_ns_parse_table (
return_ACPI_STATUS (status);
}
+#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -421,6 +370,58 @@ unlock_and_exit:
/*******************************************************************************
*
+ * FUNCTION: Acpi_load_namespace
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
+ * (DSDT points to either the BIOS or a buffer.)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_load_namespace (
+ void)
+{
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("Acpi_load_name_space");
+
+
+ /* There must be at least a DSDT installed */
+
+ if (acpi_gbl_DSDT == NULL) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
+ return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ }
+
+ /*
+ * Load the namespace. The DSDT is required,
+ * but the SSDT and PSDT tables are optional.
+ */
+ status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Ignore exceptions from these */
+
+ (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
+ (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
+
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
+ "ACPI Namespace successfully loaded at root %p\n",
+ acpi_gbl_root_node));
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: Acpi_ns_delete_subtree
*
* PARAMETERS: Start_handle - Handle in namespace where search begins
@@ -550,4 +551,5 @@ acpi_ns_unload_namespace (
return_ACPI_STATUS (status);
}
+#endif
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
new file mode 100644
index 000000000000..0eded64d3647
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -0,0 +1,719 @@
+/*******************************************************************************
+ *
+ * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
+ * ACPI Object evaluation interfaces
+ * $Revision: 1 $
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2002, R. Byron Moore
+ *
+ * This program is free software; you can redistribute 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 "acpi.h"
+#include "acnamesp.h"
+
+
+#define _COMPONENT ACPI_NAMESPACE
+ ACPI_MODULE_NAME ("nsxfeval")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_evaluate_object_typed
+ *
+ * PARAMETERS: Handle - Object handle (optional)
+ * *Pathname - Object pathname (optional)
+ * **External_params - List of parameters to pass to method,
+ * terminated by NULL. May be NULL
+ * if no parameters are being passed.
+ * *Return_buffer - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ * Return_type - Expected type of return object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and evaluate the given object, passing the given
+ * parameters if necessary. One of "Handle" or "Pathname" must
+ * be valid (non-null)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_evaluate_object_typed (
+ acpi_handle handle,
+ acpi_string pathname,
+ acpi_object_list *external_params,
+ acpi_buffer *return_buffer,
+ acpi_object_type return_type)
+{
+ acpi_status status;
+ u8 must_free = FALSE;
+
+
+ ACPI_FUNCTION_TRACE ("Acpi_evaluate_object_typed");
+
+
+ /* Return buffer must be valid */
+
+ if (!return_buffer) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
+ must_free = TRUE;
+ }
+
+ /* Evaluate the object */
+
+ status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Type ANY means "don't care" */
+
+ if (return_type == ACPI_TYPE_ANY) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ if (return_buffer->length == 0) {
+ /* Error because caller specifically asked for a return value */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "No return value\n"));
+
+ return_ACPI_STATUS (AE_NULL_OBJECT);
+ }
+
+ /* Examine the object type returned from Evaluate_object */
+
+ if (((acpi_object *) return_buffer->pointer)->type == return_type) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Return object type does not match requested type */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Incorrect return type [%s] requested [%s]\n",
+ acpi_ut_get_type_name (((acpi_object *) return_buffer->pointer)->type),
+ acpi_ut_get_type_name (return_type)));
+
+ if (must_free) {
+ /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
+
+ acpi_os_free (return_buffer->pointer);
+ return_buffer->pointer = NULL;
+ }
+
+ return_buffer->length = 0;
+ return_ACPI_STATUS (AE_TYPE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_evaluate_object
+ *
+ * PARAMETERS: Handle - Object handle (optional)
+ * *Pathname - Object pathname (optional)
+ * **External_params - List of parameters to pass to method,
+ * terminated by NULL. May be NULL
+ * if no parameters are being passed.
+ * *Return_buffer - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and evaluate the given object, passing the given
+ * parameters if necessary. One of "Handle" or "Pathname" must
+ * be valid (non-null)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_evaluate_object (
+ acpi_handle handle,
+ acpi_string pathname,
+ acpi_object_list *external_params,
+ acpi_buffer *return_buffer)
+{
+ acpi_status status;
+ acpi_operand_object **internal_params = NULL;
+ acpi_operand_object *internal_return_obj = NULL;
+ ACPI_SIZE buffer_space_needed;
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE ("Acpi_evaluate_object");
+
+
+ /*
+ * If there are parameters to be passed to the object
+ * (which must be a control method), the external objects
+ * must be converted to internal objects
+ */
+ if (external_params && external_params->count) {
+ /*
+ * Allocate a new parameter block for the internal objects
+ * Add 1 to count to allow for null terminated internal list
+ */
+ internal_params = ACPI_MEM_CALLOCATE (((ACPI_SIZE) external_params->count + 1) *
+ sizeof (void *));
+ if (!internal_params) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /*
+ * Convert each external object in the list to an
+ * internal object
+ */
+ for (i = 0; i < external_params->count; i++) {
+ status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
+ &internal_params[i]);
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_delete_internal_object_list (internal_params);
+ return_ACPI_STATUS (status);
+ }
+ }
+ internal_params[external_params->count] = NULL;
+ }
+
+ /*
+ * Three major cases:
+ * 1) Fully qualified pathname
+ * 2) No handle, not fully qualified pathname (error)
+ * 3) Valid handle
+ */
+ if ((pathname) &&
+ (acpi_ns_valid_root_prefix (pathname[0]))) {
+ /*
+ * The path is fully qualified, just evaluate by name
+ */
+ status = acpi_ns_evaluate_by_name (pathname, internal_params,
+ &internal_return_obj);
+ }
+ else if (!handle) {
+ /*
+ * A handle is optional iff a fully qualified pathname
+ * is specified. Since we've already handled fully
+ * qualified names above, this is an error
+ */
+ if (!pathname) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Both Handle and Pathname are NULL\n"));
+ }
+ else {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Handle is NULL and Pathname is relative\n"));
+ }
+
+ status = AE_BAD_PARAMETER;
+ }
+ else {
+ /*
+ * We get here if we have a handle -- and if we have a
+ * pathname it is relative. The handle will be validated
+ * in the lower procedures
+ */
+ if (!pathname) {
+ /*
+ * The null pathname case means the handle is for
+ * the actual object to be evaluated
+ */
+ status = acpi_ns_evaluate_by_handle (handle, internal_params,
+ &internal_return_obj);
+ }
+ else {
+ /*
+ * Both a Handle and a relative Pathname
+ */
+ status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
+ &internal_return_obj);
+ }
+ }
+
+
+ /*
+ * If we are expecting a return value, and all went well above,
+ * copy the return value to an external object.
+ */
+ if (return_buffer) {
+ if (!internal_return_obj) {
+ return_buffer->length = 0;
+ }
+ else {
+ if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
+ /*
+ * If we received a NS Node as a return object, this means that
+ * the object we are evaluating has nothing interesting to
+ * return (such as a mutex, etc.) We return an error because
+ * these types are essentially unsupported by this interface.
+ * We don't check up front because this makes it easier to add
+ * support for various types at a later date if necessary.
+ */
+ status = AE_TYPE;
+ internal_return_obj = NULL; /* No need to delete a NS Node */
+ return_buffer->length = 0;
+ }
+
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Find out how large a buffer is needed
+ * to contain the returned object
+ */
+ status = acpi_ut_get_object_size (internal_return_obj,
+ &buffer_space_needed);
+ if (ACPI_SUCCESS (status)) {
+ /* Validate/Allocate/Clear caller buffer */
+
+ status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
+ if (ACPI_FAILURE (status)) {
+ /*
+ * Caller's buffer is too small or a new one can't be allocated
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+ "Needed buffer size %X, %s\n",
+ (u32) buffer_space_needed, acpi_format_exception (status)));
+ }
+ else {
+ /*
+ * We have enough space for the object, build it
+ */
+ status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
+ return_buffer);
+ }
+ }
+ }
+ }
+ }
+
+ /* Delete the return and parameter objects */
+
+ if (internal_return_obj) {
+ /*
+ * Delete the internal return object. (Or at least
+ * decrement the reference count by one)
+ */
+ acpi_ut_remove_reference (internal_return_obj);
+ }
+
+ /*
+ * Free the input parameter list (if we created one),
+ */
+ if (internal_params) {
+ /* Free the allocated parameter block */
+
+ acpi_ut_delete_internal_object_list (internal_params);
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_walk_namespace
+ *
+ * PARAMETERS: Type - acpi_object_type to search for
+ * Start_object - Handle in namespace where search begins
+ * Max_depth - Depth to which search is to reach
+ * User_function - Called when an object of "Type" is found
+ * Context - Passed to user function
+ * Return_value - Location where return value of
+ * User_function is put if terminated early
+ *
+ * RETURNS Return value from the User_function if terminated early.
+ * Otherwise, returns NULL.
+ *
+ * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
+ * starting (and ending) at the object specified by Start_handle.
+ * The User_function is called whenever an object that matches
+ * the type parameter is found. If the user function returns
+ * a non-zero value, the search is terminated immediately and this
+ * value is returned to the caller.
+ *
+ * The point of this procedure is to provide a generic namespace
+ * walk routine that can be called from multiple places to
+ * provide multiple services; the User Function can be tailored
+ * to each task, whether it is a print function, a compare
+ * function, etc.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_walk_namespace (
+ acpi_object_type type,
+ acpi_handle start_object,
+ u32 max_depth,
+ acpi_walk_callback user_function,
+ void *context,
+ void **return_value)
+{
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("Acpi_walk_namespace");
+
+
+ /* Parameter validation */
+
+ if ((type > ACPI_TYPE_MAX) ||
+ (!max_depth) ||
+ (!user_function)) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Lock the namespace around the walk.
+ * The namespace will be unlocked/locked around each call
+ * to the user function - since this function
+ * must be allowed to make Acpi calls itself.
+ */
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK,
+ user_function, context, return_value);
+
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_device_callback
+ *
+ * PARAMETERS: Callback from Acpi_get_device
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non-
+ * present devices, or if they specified a HID, it filters based
+ * on that.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_get_device_callback (
+ acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context,
+ void **return_value)
+{
+ acpi_status status;
+ acpi_namespace_node *node;
+ u32 flags;
+ acpi_device_id hid;
+ acpi_device_id cid;
+ acpi_get_devices_info *info;
+
+
+ info = context;
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ node = acpi_ns_map_handle_to_node (obj_handle);
+ status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ if (!node) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Run _STA to determine if device is present
+ */
+ status = acpi_ut_execute_STA (node, &flags);
+ if (ACPI_FAILURE (status)) {
+ return (AE_CTRL_DEPTH);
+ }
+
+ if (!(flags & 0x01)) {
+ /* Don't return at the device or children of the device if not there */
+ return (AE_CTRL_DEPTH);
+ }
+
+ /*
+ * Filter based on device HID & CID
+ */
+ if (info->hid != NULL) {
+ status = acpi_ut_execute_HID (node, &hid);
+ if (status == AE_NOT_FOUND) {
+ return (AE_OK);
+ }
+ else if (ACPI_FAILURE (status)) {
+ return (AE_CTRL_DEPTH);
+ }
+
+ if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) {
+ status = acpi_ut_execute_CID (node, &cid);
+ if (status == AE_NOT_FOUND) {
+ return (AE_OK);
+ }
+ else if (ACPI_FAILURE (status)) {
+ return (AE_CTRL_DEPTH);
+ }
+
+ /* TBD: Handle CID packages */
+
+ if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) {
+ return (AE_OK);
+ }
+ }
+ }
+
+ status = info->user_function (obj_handle, nesting_level, info->context, return_value);
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_get_devices
+ *
+ * PARAMETERS: HID - HID to search for. Can be NULL.
+ * User_function - Called when a matching object is found
+ * Context - Passed to user function
+ * Return_value - Location where return value of
+ * User_function is put if terminated early
+ *
+ * RETURNS Return value from the User_function if terminated early.
+ * Otherwise, returns NULL.
+ *
+ * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
+ * starting (and ending) at the object specified by Start_handle.
+ * The User_function is called whenever an object that matches
+ * the type parameter is found. If the user function returns
+ * a non-zero value, the search is terminated immediately and this
+ * value is returned to the caller.
+ *
+ * This is a wrapper for Walk_namespace, but the callback performs
+ * additional filtering. Please see Acpi_get_device_callback.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_get_devices (
+ NATIVE_CHAR *HID,
+ acpi_walk_callback user_function,
+ void *context,
+ void **return_value)
+{
+ acpi_status status;
+ acpi_get_devices_info info;
+
+
+ ACPI_FUNCTION_TRACE ("Acpi_get_devices");
+
+
+ /* Parameter validation */
+
+ if (!user_function) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * We're going to call their callback from OUR callback, so we need
+ * to know what it is, and their context parameter.
+ */
+ info.context = context;
+ info.user_function = user_function;
+ info.hid = HID;
+
+ /*
+ * Lock the namespace around the walk.
+ * The namespace will be unlocked/locked around each call
+ * to the user function - since this function
+ * must be allowed to make Acpi calls itself.
+ */
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
+ ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK,
+ acpi_ns_get_device_callback, &info,
+ return_value);
+
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_attach_data
+ *
+ * PARAMETERS:
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_attach_data (
+ acpi_handle obj_handle,
+ ACPI_OBJECT_HANDLER handler,
+ void *data)
+{
+ acpi_namespace_node *node;
+ acpi_status status;
+
+
+ /* Parameter validation */
+
+ if (!obj_handle ||
+ !handler ||
+ !data) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Convert and validate the handle */
+
+ node = acpi_ns_map_handle_to_node (obj_handle);
+ if (!node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ status = acpi_ns_attach_data (node, handler, data);
+
+unlock_and_exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_detach_data
+ *
+ * PARAMETERS:
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_detach_data (
+ acpi_handle obj_handle,
+ ACPI_OBJECT_HANDLER handler)
+{
+ acpi_namespace_node *node;
+ acpi_status status;
+
+
+ /* Parameter validation */
+
+ if (!obj_handle ||
+ !handler) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Convert and validate the handle */
+
+ node = acpi_ns_map_handle_to_node (obj_handle);
+ if (!node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ status = acpi_ns_detach_data (node, handler);
+
+unlock_and_exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_get_data
+ *
+ * PARAMETERS:
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_get_data (
+ acpi_handle obj_handle,
+ ACPI_OBJECT_HANDLER handler,
+ void **data)
+{
+ acpi_namespace_node *node;
+ acpi_status status;
+
+
+ /* Parameter validation */
+
+ if (!obj_handle ||
+ !handler ||
+ !data) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Convert and validate the handle */
+
+ node = acpi_ns_map_handle_to_node (obj_handle);
+ if (!node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ status = acpi_ns_get_attached_data (node, handler, data);
+
+unlock_and_exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index def0a7318950..703308421005 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -2,7 +2,7 @@
*
* Module Name: nsxfobj - Public interfaces to the ACPI subsystem
* ACPI Object oriented interfaces
- * $Revision: 112 $
+ * $Revision: 113 $
*
******************************************************************************/
@@ -32,384 +32,6 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME ("nsxfobj")
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_evaluate_object_typed
- *
- * PARAMETERS: Handle - Object handle (optional)
- * *Pathname - Object pathname (optional)
- * **External_params - List of parameters to pass to method,
- * terminated by NULL. May be NULL
- * if no parameters are being passed.
- * *Return_buffer - Where to put method's return value (if
- * any). If NULL, no value is returned.
- * Return_type - Expected type of return object
- *
- * RETURN: Status
- *
- * DESCRIPTION: Find and evaluate the given object, passing the given
- * parameters if necessary. One of "Handle" or "Pathname" must
- * be valid (non-null)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_evaluate_object_typed (
- acpi_handle handle,
- acpi_string pathname,
- acpi_object_list *external_params,
- acpi_buffer *return_buffer,
- acpi_object_type return_type)
-{
- acpi_status status;
- u8 must_free = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("Acpi_evaluate_object_typed");
-
-
- /* Return buffer must be valid */
-
- if (!return_buffer) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
- must_free = TRUE;
- }
-
- /* Evaluate the object */
-
- status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- /* Type ANY means "don't care" */
-
- if (return_type == ACPI_TYPE_ANY) {
- return_ACPI_STATUS (AE_OK);
- }
-
- if (return_buffer->length == 0) {
- /* Error because caller specifically asked for a return value */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No return value\n"));
-
- return_ACPI_STATUS (AE_NULL_OBJECT);
- }
-
- /* Examine the object type returned from Evaluate_object */
-
- if (((acpi_object *) return_buffer->pointer)->type == return_type) {
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Return object type does not match requested type */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Incorrect return type [%s] requested [%s]\n",
- acpi_ut_get_type_name (((acpi_object *) return_buffer->pointer)->type),
- acpi_ut_get_type_name (return_type)));
-
- if (must_free) {
- /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
-
- acpi_os_free (return_buffer->pointer);
- return_buffer->pointer = NULL;
- }
-
- return_buffer->length = 0;
- return_ACPI_STATUS (AE_TYPE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_evaluate_object
- *
- * PARAMETERS: Handle - Object handle (optional)
- * *Pathname - Object pathname (optional)
- * **External_params - List of parameters to pass to method,
- * terminated by NULL. May be NULL
- * if no parameters are being passed.
- * *Return_buffer - Where to put method's return value (if
- * any). If NULL, no value is returned.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Find and evaluate the given object, passing the given
- * parameters if necessary. One of "Handle" or "Pathname" must
- * be valid (non-null)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_evaluate_object (
- acpi_handle handle,
- acpi_string pathname,
- acpi_object_list *external_params,
- acpi_buffer *return_buffer)
-{
- acpi_status status;
- acpi_operand_object **internal_params = NULL;
- acpi_operand_object *internal_return_obj = NULL;
- ACPI_SIZE buffer_space_needed;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("Acpi_evaluate_object");
-
-
- /*
- * If there are parameters to be passed to the object
- * (which must be a control method), the external objects
- * must be converted to internal objects
- */
- if (external_params && external_params->count) {
- /*
- * Allocate a new parameter block for the internal objects
- * Add 1 to count to allow for null terminated internal list
- */
- internal_params = ACPI_MEM_CALLOCATE (((ACPI_SIZE) external_params->count + 1) *
- sizeof (void *));
- if (!internal_params) {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- /*
- * Convert each external object in the list to an
- * internal object
- */
- for (i = 0; i < external_params->count; i++) {
- status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
- &internal_params[i]);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_internal_object_list (internal_params);
- return_ACPI_STATUS (status);
- }
- }
- internal_params[external_params->count] = NULL;
- }
-
- /*
- * Three major cases:
- * 1) Fully qualified pathname
- * 2) No handle, not fully qualified pathname (error)
- * 3) Valid handle
- */
- if ((pathname) &&
- (acpi_ns_valid_root_prefix (pathname[0]))) {
- /*
- * The path is fully qualified, just evaluate by name
- */
- status = acpi_ns_evaluate_by_name (pathname, internal_params,
- &internal_return_obj);
- }
- else if (!handle) {
- /*
- * A handle is optional iff a fully qualified pathname
- * is specified. Since we've already handled fully
- * qualified names above, this is an error
- */
- if (!pathname) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Both Handle and Pathname are NULL\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Handle is NULL and Pathname is relative\n"));
- }
-
- status = AE_BAD_PARAMETER;
- }
- else {
- /*
- * We get here if we have a handle -- and if we have a
- * pathname it is relative. The handle will be validated
- * in the lower procedures
- */
- if (!pathname) {
- /*
- * The null pathname case means the handle is for
- * the actual object to be evaluated
- */
- status = acpi_ns_evaluate_by_handle (handle, internal_params,
- &internal_return_obj);
- }
- else {
- /*
- * Both a Handle and a relative Pathname
- */
- status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
- &internal_return_obj);
- }
- }
-
-
- /*
- * If we are expecting a return value, and all went well above,
- * copy the return value to an external object.
- */
- if (return_buffer) {
- if (!internal_return_obj) {
- return_buffer->length = 0;
- }
- else {
- if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
- /*
- * If we received a NS Node as a return object, this means that
- * the object we are evaluating has nothing interesting to
- * return (such as a mutex, etc.) We return an error because
- * these types are essentially unsupported by this interface.
- * We don't check up front because this makes it easier to add
- * support for various types at a later date if necessary.
- */
- status = AE_TYPE;
- internal_return_obj = NULL; /* No need to delete a NS Node */
- return_buffer->length = 0;
- }
-
- if (ACPI_SUCCESS (status)) {
- /*
- * Find out how large a buffer is needed
- * to contain the returned object
- */
- status = acpi_ut_get_object_size (internal_return_obj,
- &buffer_space_needed);
- if (ACPI_SUCCESS (status)) {
- /* Validate/Allocate/Clear caller buffer */
-
- status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
- if (ACPI_FAILURE (status)) {
- /*
- * Caller's buffer is too small or a new one can't be allocated
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Needed buffer size %X, %s\n",
- (u32) buffer_space_needed, acpi_format_exception (status)));
- }
- else {
- /*
- * We have enough space for the object, build it
- */
- status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
- return_buffer);
- }
- }
- }
- }
- }
-
- /* Delete the return and parameter objects */
-
- if (internal_return_obj) {
- /*
- * Delete the internal return object. (Or at least
- * decrement the reference count by one)
- */
- acpi_ut_remove_reference (internal_return_obj);
- }
-
- /*
- * Free the input parameter list (if we created one),
- */
- if (internal_params) {
- /* Free the allocated parameter block */
-
- acpi_ut_delete_internal_object_list (internal_params);
- }
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_get_next_object
- *
- * PARAMETERS: Type - Type of object to be searched for
- * Parent - Parent object whose children we are getting
- * Last_child - Previous child that was found.
- * The NEXT child will be returned
- * Ret_handle - Where handle to the next object is placed
- *
- * RETURN: Status
- *
- * DESCRIPTION: Return the next peer object within the namespace. If Handle is
- * valid, Scope is ignored. Otherwise, the first object within
- * Scope is returned.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_get_next_object (
- acpi_object_type type,
- acpi_handle parent,
- acpi_handle child,
- acpi_handle *ret_handle)
-{
- acpi_status status;
- acpi_namespace_node *node;
- acpi_namespace_node *parent_node = NULL;
- acpi_namespace_node *child_node = NULL;
-
-
- /* Parameter validation */
-
- if (type > ACPI_TYPE_MAX) {
- return (AE_BAD_PARAMETER);
- }
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
-
- /* If null handle, use the parent */
-
- if (!child) {
- /* Start search at the beginning of the specified scope */
-
- parent_node = acpi_ns_map_handle_to_node (parent);
- if (!parent_node) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
- }
- else {
- /* Non-null handle, ignore the parent */
- /* Convert and validate the handle */
-
- child_node = acpi_ns_map_handle_to_node (child);
- if (!child_node) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
- }
-
- /* Internal function does the real work */
-
- node = acpi_ns_get_next_node (type, parent_node, child_node);
- if (!node) {
- status = AE_NOT_FOUND;
- goto unlock_and_exit;
- }
-
- if (ret_handle) {
- *ret_handle = acpi_ns_convert_entry_to_handle (node);
- }
-
-
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return (status);
-}
-
-
/*******************************************************************************
*
* FUNCTION: Acpi_get_type
@@ -535,271 +157,38 @@ unlock_and_exit:
/*******************************************************************************
*
- * FUNCTION: Acpi_walk_namespace
- *
- * PARAMETERS: Type - acpi_object_type to search for
- * Start_object - Handle in namespace where search begins
- * Max_depth - Depth to which search is to reach
- * User_function - Called when an object of "Type" is found
- * Context - Passed to user function
- * Return_value - Location where return value of
- * User_function is put if terminated early
- *
- * RETURNS Return value from the User_function if terminated early.
- * Otherwise, returns NULL.
- *
- * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
- * starting (and ending) at the object specified by Start_handle.
- * The User_function is called whenever an object that matches
- * the type parameter is found. If the user function returns
- * a non-zero value, the search is terminated immediately and this
- * value is returned to the caller.
- *
- * The point of this procedure is to provide a generic namespace
- * walk routine that can be called from multiple places to
- * provide multiple services; the User Function can be tailored
- * to each task, whether it is a print function, a compare
- * function, etc.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_walk_namespace (
- acpi_object_type type,
- acpi_handle start_object,
- u32 max_depth,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("Acpi_walk_namespace");
-
-
- /* Parameter validation */
-
- if ((type > ACPI_TYPE_MAX) ||
- (!max_depth) ||
- (!user_function)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- /*
- * Lock the namespace around the walk.
- * The namespace will be unlocked/locked around each call
- * to the user function - since this function
- * must be allowed to make Acpi calls itself.
- */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK,
- user_function, context, return_value);
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ns_get_device_callback
+ * FUNCTION: Acpi_get_next_object
*
- * PARAMETERS: Callback from Acpi_get_device
+ * PARAMETERS: Type - Type of object to be searched for
+ * Parent - Parent object whose children we are getting
+ * Last_child - Previous child that was found.
+ * The NEXT child will be returned
+ * Ret_handle - Where handle to the next object is placed
*
* RETURN: Status
*
- * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non-
- * present devices, or if they specified a HID, it filters based
- * on that.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ns_get_device_callback (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value)
-{
- acpi_status status;
- acpi_namespace_node *node;
- u32 flags;
- acpi_device_id hid;
- acpi_device_id cid;
- acpi_get_devices_info *info;
-
-
- info = context;
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
-
- node = acpi_ns_map_handle_to_node (obj_handle);
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
-
- if (!node) {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * Run _STA to determine if device is present
- */
- status = acpi_ut_execute_STA (node, &flags);
- if (ACPI_FAILURE (status)) {
- return (AE_CTRL_DEPTH);
- }
-
- if (!(flags & 0x01)) {
- /* Don't return at the device or children of the device if not there */
- return (AE_CTRL_DEPTH);
- }
-
- /*
- * Filter based on device HID & CID
- */
- if (info->hid != NULL) {
- status = acpi_ut_execute_HID (node, &hid);
- if (status == AE_NOT_FOUND) {
- return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
- return (AE_CTRL_DEPTH);
- }
-
- if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) {
- status = acpi_ut_execute_CID (node, &cid);
- if (status == AE_NOT_FOUND) {
- return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
- return (AE_CTRL_DEPTH);
- }
-
- /* TBD: Handle CID packages */
-
- if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) {
- return (AE_OK);
- }
- }
- }
-
- status = info->user_function (obj_handle, nesting_level, info->context, return_value);
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_get_devices
- *
- * PARAMETERS: HID - HID to search for. Can be NULL.
- * User_function - Called when a matching object is found
- * Context - Passed to user function
- * Return_value - Location where return value of
- * User_function is put if terminated early
- *
- * RETURNS Return value from the User_function if terminated early.
- * Otherwise, returns NULL.
- *
- * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
- * starting (and ending) at the object specified by Start_handle.
- * The User_function is called whenever an object that matches
- * the type parameter is found. If the user function returns
- * a non-zero value, the search is terminated immediately and this
- * value is returned to the caller.
- *
- * This is a wrapper for Walk_namespace, but the callback performs
- * additional filtering. Please see Acpi_get_device_callback.
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ * valid, Scope is ignored. Otherwise, the first object within
+ * Scope is returned.
*
******************************************************************************/
acpi_status
-acpi_get_devices (
- NATIVE_CHAR *HID,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_get_next_object (
+ acpi_object_type type,
+ acpi_handle parent,
+ acpi_handle child,
+ acpi_handle *ret_handle)
{
acpi_status status;
- acpi_get_devices_info info;
-
-
- ACPI_FUNCTION_TRACE ("Acpi_get_devices");
-
-
- /* Parameter validation */
-
- if (!user_function) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- /*
- * We're going to call their callback from OUR callback, so we need
- * to know what it is, and their context parameter.
- */
- info.context = context;
- info.user_function = user_function;
- info.hid = HID;
-
- /*
- * Lock the namespace around the walk.
- * The namespace will be unlocked/locked around each call
- * to the user function - since this function
- * must be allowed to make Acpi calls itself.
- */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK,
- acpi_ns_get_device_callback, &info,
- return_value);
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_attach_data
- *
- * PARAMETERS:
- *
- * RETURN: Status
- *
- * DESCRIPTION:
- *
- ******************************************************************************/
-
-acpi_status
-acpi_attach_data (
- acpi_handle obj_handle,
- ACPI_OBJECT_HANDLER handler,
- void *data)
-{
acpi_namespace_node *node;
- acpi_status status;
+ acpi_namespace_node *parent_node = NULL;
+ acpi_namespace_node *child_node = NULL;
/* Parameter validation */
- if (!obj_handle ||
- !handler ||
- !data) {
+ if (type > ACPI_TYPE_MAX) {
return (AE_BAD_PARAMETER);
}
@@ -808,117 +197,43 @@ acpi_attach_data (
return (status);
}
- /* Convert and validate the handle */
-
- node = acpi_ns_map_handle_to_node (obj_handle);
- if (!node) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
-
- status = acpi_ns_attach_data (node, handler, data);
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_detach_data
- *
- * PARAMETERS:
- *
- * RETURN: Status
- *
- * DESCRIPTION:
- *
- ******************************************************************************/
-
-acpi_status
-acpi_detach_data (
- acpi_handle obj_handle,
- ACPI_OBJECT_HANDLER handler)
-{
- acpi_namespace_node *node;
- acpi_status status;
-
+ /* If null handle, use the parent */
- /* Parameter validation */
+ if (!child) {
+ /* Start search at the beginning of the specified scope */
- if (!obj_handle ||
- !handler) {
- return (AE_BAD_PARAMETER);
+ parent_node = acpi_ns_map_handle_to_node (parent);
+ if (!parent_node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
}
+ else {
+ /* Non-null handle, ignore the parent */
+ /* Convert and validate the handle */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return (status);
+ child_node = acpi_ns_map_handle_to_node (child);
+ if (!child_node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
}
- /* Convert and validate the handle */
+ /* Internal function does the real work */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_get_next_node (type, parent_node, child_node);
if (!node) {
- status = AE_BAD_PARAMETER;
+ status = AE_NOT_FOUND;
goto unlock_and_exit;
}
- status = acpi_ns_detach_data (node, handler);
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_get_data
- *
- * PARAMETERS:
- *
- * RETURN: Status
- *
- * DESCRIPTION:
- *
- ******************************************************************************/
-
-acpi_status
-acpi_get_data (
- acpi_handle obj_handle,
- ACPI_OBJECT_HANDLER handler,
- void **data)
-{
- acpi_namespace_node *node;
- acpi_status status;
-
-
- /* Parameter validation */
-
- if (!obj_handle ||
- !handler ||
- !data) {
- return (AE_BAD_PARAMETER);
- }
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
-
- /* Convert and validate the handle */
-
- node = acpi_ns_map_handle_to_node (obj_handle);
- if (!node) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
+ if (ret_handle) {
+ *ret_handle = acpi_ns_convert_entry_to_handle (node);
}
- status = acpi_ns_get_attached_data (node, handler, data);
unlock_and_exit:
+
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return (status);
}
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index bd9dab948f38..4fa6579cd8c3 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psargs - Parse AML opcode arguments
- * $Revision: 61 $
+ * $Revision: 62 $
*
*****************************************************************************/
@@ -332,7 +332,7 @@ acpi_ps_get_next_namepath (
NATIVE_CHAR *path;
acpi_parse_object *name_op;
acpi_status status;
- acpi_namespace_node *method_node = NULL;
+ acpi_operand_object *method_desc;
acpi_namespace_node *node;
acpi_generic_state scope_info;
@@ -369,30 +369,36 @@ acpi_ps_get_next_namepath (
&node);
if (ACPI_SUCCESS (status)) {
if (node->type == ACPI_TYPE_METHOD) {
- method_node = node;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%p\n",
- method_node, path));
+ method_desc = acpi_ns_get_attached_object (node);
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p Desc %p Path=%p\n",
+ node, method_desc, path));
name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
- if (name_op) {
- /* Change arg into a METHOD CALL and attach name to it */
+ if (!name_op) {
+ return_VOID;
+ }
- acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
+ /* Change arg into a METHOD CALL and attach name to it */
- name_op->common.value.name = path;
+ acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
- /* Point METHODCALL/NAME to the METHOD Node */
+ name_op->common.value.name = path;
- name_op->common.node = method_node;
- acpi_ps_append_arg (arg, name_op);
+ /* Point METHODCALL/NAME to the METHOD Node */
- if (!acpi_ns_get_attached_object (method_node)) {
- return_VOID;
- }
+ name_op->common.node = node;
+ acpi_ps_append_arg (arg, name_op);
- *arg_count = (acpi_ns_get_attached_object (method_node))->method.param_count;
+ if (!method_desc) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p has no attached object\n",
+ node));
+ return_VOID;
}
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p Args %X\n",
+ node, method_desc->method.param_count));
+
+ *arg_count = method_desc->method.param_count;
return_VOID;
}
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 42fad5f92a77..2f2c593f330e 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psopcode - Parser/Interpreter opcode information table
- * $Revision: 70 $
+ * $Revision: 71 $
*
*****************************************************************************/
@@ -734,7 +734,7 @@ NATIVE_CHAR *
acpi_ps_get_opcode_name (
u16 opcode)
{
-#ifdef ACPI_DEBUG
+#ifdef ACPI_DISASSEMBLER
const acpi_opcode_info *op;
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 0e24c31c6135..fd61b0863d25 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psparse - Parser top level AML parse routines
- * $Revision: 128 $
+ * $Revision: 129 $
*
*****************************************************************************/
@@ -473,7 +473,7 @@ acpi_ps_parse_loop (
parser_state = &walk_state->parser_state;
walk_state->arg_types = 0;
-#ifndef PARSER_ONLY
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
/* We are restarting a preempted control method */
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index d8df196e3080..7c8950786d35 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psutils - Parser miscellaneous utilities (Parser only)
- * $Revision: 52 $
+ * $Revision: 54 $
*
*****************************************************************************/
@@ -88,7 +88,7 @@ acpi_ps_init_op (
op->common.data_type = ACPI_DESC_TYPE_PARSER;
op->common.aml_opcode = opcode;
- ACPI_DEBUG_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name,
+ ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name,
(acpi_ps_get_opcode_info (opcode))->name, sizeof (op->common.aml_op_name)));
}
@@ -186,7 +186,7 @@ acpi_ps_free_op (
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op));
}
- if (op->common.flags == ACPI_PARSEOP_GENERIC) {
+ if (op->common.flags & ACPI_PARSEOP_GENERIC) {
acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op);
}
else {
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index a2b1cd595057..5d5edb42f24c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -1,5 +1,5 @@
/*
- * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 10 $)
+ * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 2320a8e016bd..b94b85b1cea4 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -1,5 +1,5 @@
/*
- * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 33 $)
+ * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -54,13 +54,13 @@ static int acpi_pci_link_add (struct acpi_device *device);
static int acpi_pci_link_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_pci_link_driver = {
- name: ACPI_PCI_LINK_DRIVER_NAME,
- class: ACPI_PCI_LINK_CLASS,
- ids: ACPI_PCI_LINK_HID,
- ops: {
- add: acpi_pci_link_add,
- remove: acpi_pci_link_remove,
- },
+ .name = ACPI_PCI_LINK_DRIVER_NAME,
+ .class = ACPI_PCI_LINK_CLASS,
+ .ids = ACPI_PCI_LINK_HID,
+ .ops = {
+ .add = acpi_pci_link_add,
+ .remove = acpi_pci_link_remove,
+ },
};
struct acpi_pci_link_irq {
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7fef16be6d47..a56fedea61b4 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -1,5 +1,5 @@
/*
- * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 39 $)
+ * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -47,13 +47,13 @@ static int acpi_pci_root_add (struct acpi_device *device);
static int acpi_pci_root_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_pci_root_driver = {
- name: ACPI_PCI_ROOT_DRIVER_NAME,
- class: ACPI_PCI_ROOT_CLASS,
- ids: ACPI_PCI_ROOT_HID,
- ops: {
- add: acpi_pci_root_add,
- remove: acpi_pci_root_remove,
- },
+ .name = ACPI_PCI_ROOT_DRIVER_NAME,
+ .class = ACPI_PCI_ROOT_CLASS,
+ .ids = ACPI_PCI_ROOT_HID,
+ .ops = {
+ .add = acpi_pci_root_add,
+ .remove = acpi_pci_root_remove,
+ },
};
struct acpi_pci_root {
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 5e4f55dbfc90..986ebd729528 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -1,5 +1,5 @@
/*
- * acpi_power.c - ACPI Bus Power Management ($Revision: 38 $)
+ * acpi_power.c - ACPI Bus Power Management ($Revision: 39 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -43,13 +43,13 @@ int acpi_power_add (struct acpi_device *device);
int acpi_power_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_power_driver = {
- name: ACPI_POWER_DRIVER_NAME,
- class: ACPI_POWER_CLASS,
- ids: ACPI_POWER_HID,
- ops: {
- add: acpi_power_add,
- remove: acpi_power_remove,
- },
+ .name = ACPI_POWER_DRIVER_NAME,
+ .class = ACPI_POWER_CLASS,
+ .ids = ACPI_POWER_HID,
+ .ops = {
+ .add = acpi_power_add,
+ .remove = acpi_power_remove,
+ },
};
struct acpi_power_resource
diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c
index 028ee228dcb0..933251d46b19 100644
--- a/drivers/acpi/processor.c
+++ b/drivers/acpi/processor.c
@@ -1,5 +1,5 @@
/*
- * acpi_processor.c - ACPI Processor Driver ($Revision: 69 $)
+ * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -78,13 +78,13 @@ static int acpi_processor_add (struct acpi_device *device);
static int acpi_processor_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_processor_driver = {
- name: ACPI_PROCESSOR_DRIVER_NAME,
- class: ACPI_PROCESSOR_CLASS,
- ids: ACPI_PROCESSOR_HID,
- ops: {
- add: acpi_processor_add,
- remove: acpi_processor_remove,
- },
+ .name = ACPI_PROCESSOR_DRIVER_NAME,
+ .class = ACPI_PROCESSOR_CLASS,
+ .ids = ACPI_PROCESSOR_HID,
+ .ops = {
+ .add = acpi_processor_add,
+ .remove = acpi_processor_remove,
+ },
};
/* Power Management */
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index 11b2382e6ec2..3eda881b5ca0 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: rsio - IO and DMA resource descriptors
- * $Revision: 21 $
+ * $Revision: 22 $
*
******************************************************************************/
@@ -399,7 +399,7 @@ acpi_rs_dma_resource (
buffer += 1;
temp8 = *buffer;
- /* Decode the IRQ bits */
+ /* Decode the DMA channel bits */
for (i = 0, index = 0; index < 8; index++) {
if ((temp8 >> index) & 0x01) {
@@ -407,19 +407,16 @@ acpi_rs_dma_resource (
i++;
}
}
- if (i == 0) {
- /* Zero channels is invalid! */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found Zero DMA channels in resource list\n"));
- return_ACPI_STATUS (AE_BAD_DATA);
- }
- output_struct->data.dma.number_of_channels = i;
+ /* Zero DMA channels is valid */
- /*
- * Calculate the structure size based upon the number of interrupts
- */
- struct_size += ((ACPI_SIZE) output_struct->data.dma.number_of_channels - 1) * 4;
+ output_struct->data.dma.number_of_channels = i;
+ if (i > 0) {
+ /*
+ * Calculate the structure size based upon the number of interrupts
+ */
+ struct_size += ((ACPI_SIZE) i - 1) * 4;
+ }
/*
* Point to Byte 2
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 5366f27dcad7..ab0d142895f9 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: rsirq - IRQ resource descriptors
- * $Revision: 29 $
+ * $Revision: 30 $
*
******************************************************************************/
@@ -96,18 +96,15 @@ acpi_rs_irq_resource (
}
}
- if (i == 0) {
- /* Zero interrupts is invalid! */
+ /* Zero interrupts is valid */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found Zero interrupt levels in resource list\n"));
- return_ACPI_STATUS (AE_BAD_DATA);
- }
output_struct->data.irq.number_of_interrupts = i;
-
- /*
- * Calculate the structure size based upon the number of interrupts
- */
- struct_size += ((ACPI_SIZE) output_struct->data.irq.number_of_interrupts - 1) * 4;
+ if (i > 0) {
+ /*
+ * Calculate the structure size based upon the number of interrupts
+ */
+ struct_size += ((ACPI_SIZE) i - 1) * 4;
+ }
/*
* Point to Byte 3 if it is used
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 1bd1555510b0..bfd02982e234 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -1,5 +1,5 @@
/*
- * acpi_system.c - ACPI System Driver ($Revision: 60 $)
+ * acpi_system.c - ACPI System Driver ($Revision: 63 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -63,13 +63,13 @@ static int acpi_system_add (struct acpi_device *device);
static int acpi_system_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_system_driver = {
- name: ACPI_SYSTEM_DRIVER_NAME,
- class: ACPI_SYSTEM_CLASS,
- ids: ACPI_SYSTEM_HID,
- ops: {
- add: acpi_system_add,
- remove: acpi_system_remove
- },
+ .name = ACPI_SYSTEM_DRIVER_NAME,
+ .class = ACPI_SYSTEM_CLASS,
+ .ids = ACPI_SYSTEM_HID,
+ .ops = {
+ .add = acpi_system_add,
+ .remove = acpi_system_remove
+ },
};
struct acpi_system
@@ -383,10 +383,10 @@ static unsigned int acpi_system_poll_event(struct file *file, poll_table *wait);
static struct file_operations acpi_system_event_ops = {
- open: acpi_system_open_event,
- read: acpi_system_read_event,
- release: acpi_system_close_event,
- poll: acpi_system_poll_event,
+ .open = acpi_system_open_event,
+ .read = acpi_system_read_event,
+ .release = acpi_system_close_event,
+ .poll = acpi_system_poll_event,
};
static int
@@ -479,7 +479,7 @@ acpi_system_poll_event(
static ssize_t acpi_system_read_dsdt (struct file*, char*, size_t, loff_t*);
static struct file_operations acpi_system_dsdt_ops = {
- read: acpi_system_read_dsdt,
+ .read = acpi_system_read_dsdt,
};
static ssize_t
@@ -522,7 +522,7 @@ acpi_system_read_dsdt (
static ssize_t acpi_system_read_fadt (struct file*, char*, size_t, loff_t*);
static struct file_operations acpi_system_fadt_ops = {
- read: acpi_system_read_fadt,
+ .read = acpi_system_read_fadt,
};
static ssize_t
@@ -1165,15 +1165,15 @@ acpi_system_remove_fs (
/* Simple wrapper calling power down function. */
static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
acpi_power_off();
}
struct sysrq_key_op sysrq_acpi_poweroff_op = {
- handler: &acpi_sysrq_power_off,
- help_msg: "Off",
- action_msg: "Power Off\n"
+ .handler = &acpi_sysrq_power_off,
+ .help_msg = "Off",
+ .action_msg = "Power Off\n"
};
#endif /* CONFIG_MAGIC_SYSRQ */
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 8d5057758bfc..4a9f20ffa730 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -330,6 +330,11 @@ acpi_table_get_sdt (
return -ENODEV;
}
+ if (acpi_table_compute_checksum(header, header->length)) {
+ printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n");
+ return -ENODEV;
+ }
+
sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3;
if (sdt.count > ACPI_MAX_TABLES) {
printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
@@ -370,6 +375,11 @@ acpi_table_get_sdt (
return -ENODEV;
}
+ if (acpi_table_compute_checksum(header, header->length)) {
+ printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n");
+ return -ENODEV;
+ }
+
sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2;
if (sdt.count > ACPI_MAX_TABLES) {
printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index 9aa4f425f2c2..3fe14948152b 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: tbrsdt - ACPI RSDT table utilities
- * $Revision: 1 $
+ * $Revision: 2 $
*
*****************************************************************************/
@@ -271,12 +271,6 @@ acpi_tb_get_table_rsdt (
return_ACPI_STATUS (status);
}
- /*
- * Valid RSDT signature, verify the checksum. If it fails, just
- * print a warning and ignore it.
- */
- status = acpi_tb_verify_table_checksum (table_info.pointer);
-
/* Get the number of tables defined in the RSDT or XSDT */
acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info.pointer);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 0836b31843ca..bf5521e3403f 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1,5 +1,5 @@
/*
- * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 40 $)
+ * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -65,13 +65,13 @@ static int acpi_thermal_add (struct acpi_device *device);
static int acpi_thermal_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_thermal_driver = {
- name: ACPI_THERMAL_DRIVER_NAME,
- class: ACPI_THERMAL_CLASS,
- ids: ACPI_THERMAL_HID,
- ops: {
- add: acpi_thermal_add,
- remove: acpi_thermal_remove,
- },
+ .name = ACPI_THERMAL_DRIVER_NAME,
+ .class = ACPI_THERMAL_CLASS,
+ .ids = ACPI_THERMAL_HID,
+ .ops = {
+ .add = acpi_thermal_add,
+ .remove = acpi_thermal_remove,
+ },
};
struct acpi_thermal_state {
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 3641d106b886..97389a318f07 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: utglobal - Global variables for the ACPI subsystem
- * $Revision: 164 $
+ * $Revision: 165 $
*
*****************************************************************************/
@@ -27,6 +27,7 @@
#include "acpi.h"
#include "acnamesp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utglobal")
@@ -357,15 +358,15 @@ acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
/* Region type decoding */
-static const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
+const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
{
"System_memory",
"System_iO",
- "PCIConfig",
+ "PCI_Config",
"Embedded_control",
"SMBus",
"CMOS",
- "PCIBar_target",
+ "PCIBARTarget",
"Data_table",
};
@@ -555,55 +556,6 @@ acpi_ut_get_mutex_name (
}
-/* Various strings for future use */
-
-#if 0
-#include "amlcode.h"
-
-/* Data used in keeping track of fields */
-
-static const NATIVE_CHAR *acpi_gbl_FEnames[NUM_FIELD_NAMES] =
-{
- "skip",
- "?access?"
-}; /* FE = Field Element */
-
-
-static const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS] =
-{
- "Error",
- "MTR",
- "MEQ",
- "MLE",
- "MLT",
- "MGE",
- "MGT"
-};
-
-
-/* Access type decoding */
-
-static const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES] =
-{
- "Any_acc",
- "Byte_acc",
- "Word_acc",
- "DWord_acc",
- "QWord_acc",
- "Buffer_acc",
-};
-
-
-/* Update rule decoding */
-
-static const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES] =
-{
- "Preserve",
- "Write_as_ones",
- "Write_as_zeros"
-};
-#endif /* Future use */
-
#endif
diff --git a/drivers/base/fs.c b/drivers/base/fs.c
index 754d789f53e8..65225deedf7d 100644
--- a/drivers/base/fs.c
+++ b/drivers/base/fs.c
@@ -106,13 +106,17 @@ static void fill_devpath(struct device * dev, char * path, int length)
static int create_symlink(struct driver_dir_entry * parent, char * name, char * path)
{
struct driver_file_entry * entry;
+ int error;
entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->name = name;
entry->mode = S_IRUGO;
- return driverfs_create_symlink(parent,entry,path);
+ error = driverfs_create_symlink(parent,entry,path);
+ if (error)
+ kfree(entry);
+ return error;
}
int device_bus_link(struct device * dev)
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index dc372aa4dbb1..59e4b53dfce5 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -2884,7 +2884,7 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
Command->BufferHeader = Request->bio;
Command->RequestBuffer = Request->buffer;
blkdev_dequeue_request(Request);
- blkdev_release_request(Request);
+ blk_put_request(Request);
DAC960_QueueReadWriteCommand(Command);
return true;
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index e73c1d823428..53f1706d2877 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1233,9 +1233,47 @@ struct request *__blk_get_request(request_queue_t *q, int rw)
return rq;
}
-void blk_put_request(struct request *rq)
+/**
+ * blk_insert_request - insert a special request in to a request queue
+ * @q: request queue where request should be inserted
+ * @rq: request to be inserted
+ * @at_head: insert request at head or tail of queue
+ * @data: private data
+ *
+ * Description:
+ * Many block devices need to execute commands asynchronously, so they don't
+ * block the whole kernel from preemption during request execution. This is
+ * accomplished normally by inserting aritficial requests tagged as
+ * REQ_SPECIAL in to the corresponding request queue, and letting them be
+ * scheduled for actual execution by the request queue.
+ *
+ * We have the option of inserting the head or the tail of the queue.
+ * Typically we use the tail for new ioctls and so forth. We use the head
+ * of the queue for things like a QUEUE_FULL message from a device, or a
+ * host that is unable to accept a particular command.
+ */
+void blk_insert_request(request_queue_t *q, struct request *rq,
+ int at_head, void *data)
{
- blkdev_release_request(rq);
+ unsigned long flags;
+
+ /*
+ * tell I/O scheduler that this isn't a regular read/write (ie it
+ * must not attempt merges on this) and that it acts as a soft
+ * barrier
+ */
+ rq->flags &= REQ_QUEUED;
+ rq->flags |= REQ_SPECIAL | REQ_BARRIER;
+
+ rq->special = data;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ /* If command is tagged, release the tag */
+ if(blk_rq_tagged(rq))
+ blk_queue_end_tag(q, rq);
+ _elv_add_request(q, rq, !at_head, 0);
+ q->request_fn(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
}
/* RO fail safe mechanism */
@@ -1307,7 +1345,7 @@ static inline void add_request(request_queue_t * q, struct request * req,
/*
* Must be called with queue lock held and interrupts disabled
*/
-void blkdev_release_request(struct request *req)
+void blk_put_request(struct request *req)
{
struct request_list *rl = req->rl;
request_queue_t *q = req->q;
@@ -1370,7 +1408,7 @@ static void attempt_merge(request_queue_t *q, struct request *req,
req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
- blkdev_release_request(next);
+ blk_put_request(next);
}
}
@@ -1568,7 +1606,7 @@ get_rq:
add_request(q, req, insert_here);
out:
if (freereq)
- blkdev_release_request(freereq);
+ blk_put_request(freereq);
spin_unlock_irq(q->queue_lock);
return 0;
@@ -2003,7 +2041,7 @@ void end_that_request_last(struct request *req)
if (req->waiting)
complete(req->waiting);
- blkdev_release_request(req);
+ blk_put_request(req);
}
#define MB(kb) ((kb) << 10)
@@ -2064,7 +2102,6 @@ EXPORT_SYMBOL(blk_cleanup_queue);
EXPORT_SYMBOL(blk_queue_make_request);
EXPORT_SYMBOL(blk_queue_bounce_limit);
EXPORT_SYMBOL(generic_make_request);
-EXPORT_SYMBOL(blkdev_release_request);
EXPORT_SYMBOL(generic_unplug_device);
EXPORT_SYMBOL(blk_plug_device);
EXPORT_SYMBOL(blk_remove_plug);
@@ -2088,6 +2125,7 @@ EXPORT_SYMBOL(blk_hw_contig_segment);
EXPORT_SYMBOL(blk_get_request);
EXPORT_SYMBOL(__blk_get_request);
EXPORT_SYMBOL(blk_put_request);
+EXPORT_SYMBOL(blk_insert_request);
EXPORT_SYMBOL(blk_queue_prep_rq);
diff --git a/drivers/char/serial_21285.c b/drivers/char/serial_21285.c
deleted file mode 100644
index d775644e96ad..000000000000
--- a/drivers/char/serial_21285.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * linux/drivers/char/serial_21285.c
- *
- * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
- *
- * Based on drivers/char/serial.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/dec21285.h>
-#include <asm/hardware.h>
-
-#define BAUD_BASE (mem_fclk_21285/64)
-
-#define SERIAL_21285_NAME "ttyFB"
-#define SERIAL_21285_MAJOR 204
-#define SERIAL_21285_MINOR 4
-
-#define SERIAL_21285_AUXNAME "cuafb"
-#define SERIAL_21285_AUXMAJOR 205
-#define SERIAL_21285_AUXMINOR 4
-
-static struct tty_driver rs285_driver, callout_driver;
-static int rs285_refcount;
-static struct tty_struct *rs285_table[1];
-
-static struct termios *rs285_termios[1];
-static struct termios *rs285_termios_locked[1];
-
-static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
-static struct tty_struct *rs285_tty;
-static int rs285_use_count;
-
-static int rs285_write_room(struct tty_struct *tty)
-{
- return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
-}
-
-static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- if (!rs285_tty) {
- disable_irq(IRQ_CONRX);
- return;
- }
- while (!(*CSR_UARTFLG & 0x10)) {
- int ch, flag;
- ch = *CSR_UARTDR;
- flag = *CSR_RXSTAT;
- if (flag & 4)
- tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
- if (flag & 2)
- flag = TTY_PARITY;
- else if (flag & 1)
- flag = TTY_FRAME;
- tty_insert_flip_char(rs285_tty, ch, flag);
- }
- tty_flip_buffer_push(rs285_tty);
-}
-
-static void rs285_send_xchar(struct tty_struct *tty, char ch)
-{
- x_char = ch;
- enable_irq(IRQ_CONTX);
-}
-
-static void rs285_throttle(struct tty_struct *tty)
-{
- if (I_IXOFF(tty))
- rs285_send_xchar(tty, STOP_CHAR(tty));
-}
-
-static void rs285_unthrottle(struct tty_struct *tty)
-{
- if (I_IXOFF(tty)) {
- if (x_char)
- x_char = 0;
- else
- rs285_send_xchar(tty, START_CHAR(tty));
- }
-}
-
-static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- while (!(*CSR_UARTFLG & 0x20)) {
- if (x_char) {
- *CSR_UARTDR = x_char;
- x_char = 0;
- continue;
- }
- if (putp == getp) {
- disable_irq(IRQ_CONTX);
- break;
- }
- *CSR_UARTDR = *getp;
- if (++getp >= wbuf + sizeof(wbuf))
- getp = wbuf;
- }
- if (rs285_tty)
- wake_up_interruptible(&rs285_tty->write_wait);
-}
-
-static inline int rs285_xmit(int ch)
-{
- if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
- return 0;
- *putp = ch;
- if (++putp >= wbuf + sizeof(wbuf))
- putp = wbuf;
- enable_irq(IRQ_CONTX);
- return 1;
-}
-
-static int rs285_write(struct tty_struct *tty, int from_user,
- const u_char * buf, int count)
-{
- int i;
-
- if (from_user && verify_area(VERIFY_READ, buf, count))
- return -EINVAL;
-
- for (i = 0; i < count; i++) {
- char ch;
- if (from_user)
- __get_user(ch, buf + i);
- else
- ch = buf[i];
- if (!rs285_xmit(ch))
- break;
- }
- return i;
-}
-
-static void rs285_put_char(struct tty_struct *tty, u_char ch)
-{
- rs285_xmit(ch);
-}
-
-static int rs285_chars_in_buffer(struct tty_struct *tty)
-{
- return sizeof(wbuf) - rs285_write_room(tty);
-}
-
-static void rs285_flush_buffer(struct tty_struct *tty)
-{
- disable_irq(IRQ_CONTX);
- putp = getp = wbuf;
- if (x_char)
- enable_irq(IRQ_CONTX);
-}
-
-static inline void rs285_set_cflag(int cflag)
-{
- int h_lcr, baud, quot;
-
- switch (cflag & CSIZE) {
- case CS5:
- h_lcr = 0x10;
- break;
- case CS6:
- h_lcr = 0x30;
- break;
- case CS7:
- h_lcr = 0x50;
- break;
- default: /* CS8 */
- h_lcr = 0x70;
- break;
-
- }
- if (cflag & CSTOPB)
- h_lcr |= 0x08;
- if (cflag & PARENB)
- h_lcr |= 0x02;
- if (!(cflag & PARODD))
- h_lcr |= 0x04;
-
- switch (cflag & CBAUD) {
- case B200: baud = 200; break;
- case B300: baud = 300; break;
- case B1200: baud = 1200; break;
- case B1800: baud = 1800; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default:
- case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
- }
-
- /*
- * The documented expression for selecting the divisor is:
- * BAUD_BASE / baud - 1
- * However, typically BAUD_BASE is not divisible by baud, so
- * we want to select the divisor that gives us the minimum
- * error. Therefore, we want:
- * int(BAUD_BASE / baud - 0.5) ->
- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
- * int((BAUD_BASE - (baud >> 1)) / baud)
- */
- quot = (BAUD_BASE - (baud >> 1)) / baud;
-
- *CSR_UARTCON = 0;
- *CSR_L_UBRLCR = quot & 0xff;
- *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
- *CSR_H_UBRLCR = h_lcr;
- *CSR_UARTCON = 1;
-}
-
-static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
-{
- if (old && tty->termios->c_cflag == old->c_cflag)
- return;
- rs285_set_cflag(tty->termios->c_cflag);
-}
-
-
-static void rs285_stop(struct tty_struct *tty)
-{
- disable_irq(IRQ_CONTX);
-}
-
-static void rs285_start(struct tty_struct *tty)
-{
- enable_irq(IRQ_CONTX);
-}
-
-static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- int orig_jiffies = jiffies;
- while (*CSR_UARTFLG & 8) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
- current->state = TASK_RUNNING;
-}
-
-static int rs285_open(struct tty_struct *tty, struct file *filp)
-{
- int line;
-
- MOD_INC_USE_COUNT;
- line = minor(tty->device) - tty->driver.minor_start;
- if (line) {
- MOD_DEC_USE_COUNT;
- return -ENODEV;
- }
-
- tty->driver_data = NULL;
- if (!rs285_tty)
- rs285_tty = tty;
-
- enable_irq(IRQ_CONRX);
- rs285_use_count++;
- return 0;
-}
-
-static void rs285_close(struct tty_struct *tty, struct file *filp)
-{
- if (!--rs285_use_count) {
- rs285_wait_until_sent(tty, 0);
- disable_irq(IRQ_CONRX);
- disable_irq(IRQ_CONTX);
- rs285_tty = NULL;
- }
- MOD_DEC_USE_COUNT;
-}
-
-static int __init rs285_init(void)
-{
- int baud = B9600;
-
- if (machine_is_personal_server())
- baud = B57600;
-
- rs285_driver.magic = TTY_DRIVER_MAGIC;
- rs285_driver.driver_name = "serial_21285";
- rs285_driver.name = SERIAL_21285_NAME;
- rs285_driver.major = SERIAL_21285_MAJOR;
- rs285_driver.minor_start = SERIAL_21285_MINOR;
- rs285_driver.num = 1;
- rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
- rs285_driver.subtype = SERIAL_TYPE_NORMAL;
- rs285_driver.init_termios = tty_std_termios;
- rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
- rs285_driver.flags = TTY_DRIVER_REAL_RAW;
- rs285_driver.refcount = &rs285_refcount;
- rs285_driver.table = rs285_table;
- rs285_driver.termios = rs285_termios;
- rs285_driver.termios_locked = rs285_termios_locked;
-
- rs285_driver.open = rs285_open;
- rs285_driver.close = rs285_close;
- rs285_driver.write = rs285_write;
- rs285_driver.put_char = rs285_put_char;
- rs285_driver.write_room = rs285_write_room;
- rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
- rs285_driver.flush_buffer = rs285_flush_buffer;
- rs285_driver.throttle = rs285_throttle;
- rs285_driver.unthrottle = rs285_unthrottle;
- rs285_driver.send_xchar = rs285_send_xchar;
- rs285_driver.set_termios = rs285_set_termios;
- rs285_driver.stop = rs285_stop;
- rs285_driver.start = rs285_start;
- rs285_driver.wait_until_sent = rs285_wait_until_sent;
-
- callout_driver = rs285_driver;
- callout_driver.name = SERIAL_21285_AUXNAME;
- callout_driver.major = SERIAL_21285_AUXMAJOR;
- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-
- if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
- panic("Couldn't get rx irq for rs285");
-
- if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
- panic("Couldn't get tx irq for rs285");
-
- if (tty_register_driver(&rs285_driver))
- printk(KERN_ERR "Couldn't register 21285 serial driver\n");
- if (tty_register_driver(&callout_driver))
- printk(KERN_ERR "Couldn't register 21285 callout driver\n");
-
- return 0;
-}
-
-static void __exit rs285_fini(void)
-{
- unsigned long flags;
- int ret;
-
- save_flags(flags);
- cli();
- ret = tty_unregister_driver(&callout_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 callout driver "
- "(%d)\n", ret);
- ret = tty_unregister_driver(&rs285_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
- ret);
- free_irq(IRQ_CONTX, NULL);
- free_irq(IRQ_CONRX, NULL);
- restore_flags(flags);
-}
-
-module_init(rs285_init);
-module_exit(rs285_fini);
-
-#ifdef CONFIG_SERIAL_21285_CONSOLE
-/************** console driver *****************/
-
-static void rs285_console_write(struct console *co, const char *s, u_int count)
-{
- int i;
-
- disable_irq(IRQ_CONTX);
- for (i = 0; i < count; i++) {
- while (*CSR_UARTFLG & 0x20);
- *CSR_UARTDR = s[i];
- if (s[i] == '\n') {
- while (*CSR_UARTFLG & 0x20);
- *CSR_UARTDR = '\r';
- }
- }
- enable_irq(IRQ_CONTX);
-}
-
-static kdev_t rs285_console_device(struct console *c)
-{
- return mk_kdev(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
-}
-
-static int __init rs285_console_setup(struct console *co, char *options)
-{
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int cflag = CREAD | HUPCL | CLOCAL;
-
- if (machine_is_personal_server())
- baud = 57600;
-
- if (options) {
- char *s = options;
- baud = simple_strtoul(options, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s)
- parity = *s++;
- if (*s)
- bits = *s - '0';
- }
-
- /*
- * Now construct a cflag setting.
- */
- switch (baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 9600:
- cflag |= B9600;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- default:
- cflag |= B9600;
- break;
- }
- switch (bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- cflag |= CS8;
- break;
- }
- switch (parity) {
- case 'o':
- case 'O':
- cflag |= PARODD;
- break;
- case 'e':
- case 'E':
- cflag |= PARENB;
- break;
- }
- co->cflag = cflag;
- rs285_set_cflag(cflag);
- rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
- if (options)
- rs285_console_write(NULL, options, strlen(options));
- else
- rs285_console_write(NULL, "no options", 10);
- rs285_console_write(NULL, "\n", 1);
-
- return 0;
-}
-
-static struct console rs285_cons =
-{
- name: SERIAL_21285_NAME,
- write: rs285_console_write,
- device: rs285_console_device,
- setup: rs285_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
-};
-
-void __init rs285_console_init(void)
-{
- register_console(&rs285_cons);
-}
-
-#endif /* CONFIG_SERIAL_21285_CONSOLE */
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/serial_amba.c b/drivers/char/serial_amba.c
deleted file mode 100644
index 48d416e6277e..000000000000
--- a/drivers/char/serial_amba.c
+++ /dev/null
@@ -1,2014 +0,0 @@
-/*
- * linux/drivers/char/serial_amba.c
- *
- * Driver for AMBA serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * This is a generic driver for ARM AMBA-type serial ports. They
- * have a lot of 16550-like features, but are not register compatable.
- * Note that although they do have CTS, DCD and DSR inputs, they do
- * not have an RI input, nor do they have DTR or RTS outputs. If
- * required, these have to be supplied via some other means (eg, GPIO)
- * and hooked into this driver.
- *
- * This could very easily become a generic serial driver for dumb UARTs
- * (eg, {82,16x}50, 21285, SA1100).
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/circ_buf.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-
-#include <asm/hardware/serial_amba.h>
-
-#define SERIAL_AMBA_NAME "ttyAM"
-#define SERIAL_AMBA_MAJOR 204
-#define SERIAL_AMBA_MINOR 16
-#define SERIAL_AMBA_NR 2
-
-#define CALLOUT_AMBA_NAME "cuaam"
-#define CALLOUT_AMBA_MAJOR 205
-#define CALLOUT_AMBA_MINOR 16
-#define CALLOUT_AMBA_NR SERIAL_AMBA_NR
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define DEBUG 0
-#define DEBUG_LEDS 0
-
-#if DEBUG_LEDS
-extern int get_leds(void);
-extern int set_leds(int);
-#endif
-
-/*
- * Access routines for the AMBA UARTs
- */
-#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR)
-#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR)
-#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR)
-#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
-#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR)
-#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR)
-#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
-#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L)
-#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
-#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M)
-#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
-#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H)
-#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
-#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
-#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
-#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
-
-#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
-#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
-
-/*
- * Things needed by tty driver
- */
-static struct tty_driver ambanormal_driver, ambacallout_driver;
-static int ambauart_refcount;
-static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
-static struct termios *ambauart_termios[SERIAL_AMBA_NR];
-static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
-
-#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-/*
- * Things needed internally to this driver
- */
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static u_char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-#define AMBA_ISR_PASS_LIMIT 256
-
-#define EVT_WRITE_WAKEUP 0
-
-struct amba_icount {
- __u32 cts;
- __u32 dsr;
- __u32 rng;
- __u32 dcd;
- __u32 rx;
- __u32 tx;
- __u32 frame;
- __u32 overrun;
- __u32 parity;
- __u32 brk;
- __u32 buf_overrun;
-};
-
-/*
- * Static information about the port
- */
-struct amba_port {
- unsigned int uart_base;
- unsigned int irq;
- unsigned int uartclk;
- unsigned int fifosize;
- unsigned int tiocm_support;
- void (*set_mctrl)(struct amba_port *, u_int mctrl);
-};
-
-/*
- * This is the state information which is persistent across opens
- */
-struct amba_state {
- struct amba_icount icount;
- unsigned int line;
- unsigned int close_delay;
- unsigned int closing_wait;
- unsigned int custom_divisor;
- unsigned int flags;
- struct termios normal_termios;
- struct termios callout_termios;
-
- int count;
- struct amba_info *info;
-};
-
-#define AMBA_XMIT_SIZE 1024
-/*
- * This is the state information which is only valid when the port is open.
- */
-struct amba_info {
- struct amba_port *port;
- struct amba_state *state;
- struct tty_struct *tty;
- unsigned char x_char;
- unsigned char old_status;
- unsigned char read_status_mask;
- unsigned char ignore_status_mask;
- struct circ_buf xmit;
- unsigned int flags;
-#ifdef SUPPORT_SYSRQ
- unsigned long sysrq;
-#endif
-
- unsigned int event;
- unsigned int timeout;
- unsigned int lcr_h;
- unsigned int mctrl;
- int blocked_open;
- pid_t session;
- pid_t pgrp;
-
- struct tasklet_struct tlet;
-
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
- wait_queue_head_t delta_msr_wait;
-};
-
-#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-static struct console ambauart_cons;
-#endif
-static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
-static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
-
-#if 1 //def CONFIG_SERIAL_INTEGRATOR
-static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
-{
-}
-
-static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
- {
- uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE),
- irq: IRQ_UARTINT0,
- uartclk: 14745600,
- fifosize: 8,
- set_mctrl: amba_set_mctrl_null,
- },
- {
- uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE),
- irq: IRQ_UARTINT1,
- uartclk: 14745600,
- fifosize: 8,
- set_mctrl: amba_set_mctrl_null,
- }
-};
-#endif
-
-static struct amba_state amba_state[SERIAL_AMBA_NR];
-
-static void ambauart_enable_rx_interrupt(struct amba_info *info)
-{
- unsigned int cr;
-
- cr = UART_GET_CR(info->port);
- cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
- UART_PUT_CR(info->port, cr);
-}
-
-static void ambauart_disable_rx_interrupt(struct amba_info *info)
-{
- unsigned int cr;
-
- cr = UART_GET_CR(info->port);
- cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
- UART_PUT_CR(info->port, cr);
-}
-
-static void ambauart_enable_tx_interrupt(struct amba_info *info)
-{
- unsigned int cr;
-
- cr = UART_GET_CR(info->port);
- cr |= AMBA_UARTCR_TIE;
- UART_PUT_CR(info->port, cr);
-}
-
-static void ambauart_disable_tx_interrupt(struct amba_info *info)
-{
- unsigned int cr;
-
- cr = UART_GET_CR(info->port);
- cr &= ~AMBA_UARTCR_TIE;
- UART_PUT_CR(info->port, cr);
-}
-
-static void ambauart_stop(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
- save_flags(flags); cli();
- ambauart_disable_tx_interrupt(info);
- restore_flags(flags);
-}
-
-static void ambauart_start(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
- save_flags(flags); cli();
- if (info->xmit.head != info->xmit.tail
- && info->xmit.buf)
- ambauart_enable_tx_interrupt(info);
- restore_flags(flags);
-}
-
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static void ambauart_event(struct amba_info *info, int event)
-{
- info->event |= 1 << event;
- tasklet_schedule(&info->tlet);
-}
-
-static void
-#ifdef SUPPORT_SYSRQ
-ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
-#else
-ambauart_rx_chars(struct amba_info *info)
-#endif
-{
- struct tty_struct *tty = info->tty;
- unsigned int status, ch, rsr, flg, ignored = 0;
- struct amba_icount *icount = &info->state->icount;
- struct amba_port *port = info->port;
-
- status = UART_GET_FR(port);
- while (UART_RX_DATA(status)) {
- ch = UART_GET_CHAR(port);
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
- icount->rx++;
-
- flg = TTY_NORMAL;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- rsr = UART_GET_RSR(port);
- if (rsr & AMBA_UARTRSR_ANY)
- goto handle_error;
-#ifdef SUPPORT_SYSRQ
- if (info->sysrq) {
- if (ch && time_before(jiffies, info->sysrq)) {
- handle_sysrq(ch, regs, NULL, NULL);
- info->sysrq = 0;
- goto ignore_char;
- }
- info->sysrq = 0;
- }
-#endif
- error_return:
- *tty->flip.flag_buf_ptr++ = flg;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- ignore_char:
- status = UART_GET_FR(port);
- }
-out:
- tty_flip_buffer_push(tty);
- return;
-
-handle_error:
- if (rsr & AMBA_UARTRSR_BE) {
- rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
- icount->brk++;
-
-#ifdef SUPPORT_SYSRQ
- if (info->state->line == ambauart_cons.index) {
- if (!info->sysrq) {
- info->sysrq = jiffies + HZ*5;
- goto ignore_char;
- }
- }
-#endif
- } else if (rsr & AMBA_UARTRSR_PE)
- icount->parity++;
- else if (rsr & AMBA_UARTRSR_FE)
- icount->frame++;
- if (rsr & AMBA_UARTRSR_OE)
- icount->overrun++;
-
- if (rsr & info->ignore_status_mask) {
- if (++ignored > 100)
- goto out;
- goto ignore_char;
- }
- rsr &= info->read_status_mask;
-
- if (rsr & AMBA_UARTRSR_BE)
- flg = TTY_BREAK;
- else if (rsr & AMBA_UARTRSR_PE)
- flg = TTY_PARITY;
- else if (rsr & AMBA_UARTRSR_FE)
- flg = TTY_FRAME;
-
- if (rsr & AMBA_UARTRSR_OE) {
- /*
- * CHECK: does overrun affect the current character?
- * ASSUMPTION: it does not.
- */
- *tty->flip.flag_buf_ptr++ = flg;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
- ch = 0;
- flg = TTY_OVERRUN;
- }
-#ifdef SUPPORT_SYSRQ
- info->sysrq = 0;
-#endif
- goto error_return;
-}
-
-static void ambauart_tx_chars(struct amba_info *info)
-{
- struct amba_port *port = info->port;
- int count;
-
- if (info->x_char) {
- UART_PUT_CHAR(port, info->x_char);
- info->state->icount.tx++;
- info->x_char = 0;
- return;
- }
- if (info->xmit.head == info->xmit.tail
- || info->tty->stopped
- || info->tty->hw_stopped) {
- ambauart_disable_tx_interrupt(info);
- return;
- }
-
- count = port->fifosize;
- do {
- UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
- info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
- info->state->icount.tx++;
- if (info->xmit.head == info->xmit.tail)
- break;
- } while (--count > 0);
-
- if (CIRC_CNT(info->xmit.head,
- info->xmit.tail,
- AMBA_XMIT_SIZE) < WAKEUP_CHARS)
- ambauart_event(info, EVT_WRITE_WAKEUP);
-
- if (info->xmit.head == info->xmit.tail) {
- ambauart_disable_tx_interrupt(info);
- }
-}
-
-static void ambauart_modem_status(struct amba_info *info)
-{
- unsigned int status, delta;
- struct amba_icount *icount = &info->state->icount;
-
- status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
-
- delta = status ^ info->old_status;
- info->old_status = status;
-
- if (!delta)
- return;
-
- if (delta & AMBA_UARTFR_DCD) {
- icount->dcd++;
-#ifdef CONFIG_HARD_PPS
- if ((info->flags & ASYNC_HARDPPS_CD) &&
- (status & AMBA_UARTFR_DCD)
- hardpps();
-#endif
- if (info->flags & ASYNC_CHECK_CD) {
- if (status & AMBA_UARTFR_DCD)
- wake_up_interruptible(&info->open_wait);
- else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_CALLOUT_NOHUP))) {
- if (info->tty)
- tty_hangup(info->tty);
- }
- }
- }
-
- if (delta & AMBA_UARTFR_DSR)
- icount->dsr++;
-
- if (delta & AMBA_UARTFR_CTS) {
- icount->cts++;
-
- if (info->flags & ASYNC_CTS_FLOW) {
- status &= AMBA_UARTFR_CTS;
-
- if (info->tty->hw_stopped) {
- if (status) {
- info->tty->hw_stopped = 0;
- ambauart_enable_tx_interrupt(info);
- ambauart_event(info, EVT_WRITE_WAKEUP);
- }
- } else {
- if (!status) {
- info->tty->hw_stopped = 1;
- ambauart_disable_tx_interrupt(info);
- }
- }
- }
- }
- wake_up_interruptible(&info->delta_msr_wait);
-
-}
-
-static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct amba_info *info = dev_id;
- unsigned int status, pass_counter = 0;
-
-#if DEBUG_LEDS
- // tell the world
- set_leds(get_leds() | RED_LED);
-#endif
-
- status = UART_GET_INT_STATUS(info->port);
- do {
- /*
- * FIXME: what about clearing the interrupts?
- */
-
- if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
-#ifdef SUPPORT_SYSRQ
- ambauart_rx_chars(info, regs);
-#else
- ambauart_rx_chars(info);
-#endif
- if (status & AMBA_UARTIIR_TIS)
- ambauart_tx_chars(info);
- if (status & AMBA_UARTIIR_MIS)
- ambauart_modem_status(info);
- if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
- break;
-
- status = UART_GET_INT_STATUS(info->port);
- } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
-
-#if DEBUG_LEDS
- // tell the world
- set_leds(get_leds() & ~RED_LED);
-#endif
-}
-
-static void ambauart_tasklet_action(unsigned long data)
-{
- struct amba_info *info = (struct amba_info *)data;
- struct tty_struct *tty;
-
- tty = info->tty;
- if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
- return;
-
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
- wake_up_interruptible(&tty->write_wait);
-}
-
-static int ambauart_startup(struct amba_info *info)
-{
- unsigned long flags;
- unsigned long page;
- int retval = 0;
-
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- save_flags(flags); cli();
-
- if (info->flags & ASYNC_INITIALIZED) {
- free_page(page);
- goto errout;
- }
-
- if (info->xmit.buf)
- free_page(page);
- else
- info->xmit.buf = (unsigned char *) page;
-
- /*
- * Allocate the IRQ
- */
- retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
- if (retval) {
- if (capable(CAP_SYS_ADMIN)) {
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- retval = 0;
- }
- goto errout;
- }
-
- info->mctrl = 0;
- if (info->tty->termios->c_cflag & CBAUD)
- info->mctrl = TIOCM_RTS | TIOCM_DTR;
- info->port->set_mctrl(info->port, info->mctrl);
-
- /*
- * initialise the old status of the modem signals
- */
- info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
-
- /*
- * Finally, enable interrupts
- */
- ambauart_enable_rx_interrupt(info);
-
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- info->xmit.head = info->xmit.tail = 0;
-
- /*
- * Set up the tty->alt_speed kludge
- */
- if (info->tty) {
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- }
-
- /*
- * and set the speed of the serial port
- */
- ambauart_change_speed(info, 0);
-
- info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
- return 0;
-
-errout:
- restore_flags(flags);
- return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void ambauart_shutdown(struct amba_info *info)
-{
- unsigned long flags;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
- save_flags(flags); cli(); /* Disable interrupts */
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
- * here so the queue might never be woken up
- */
- wake_up_interruptible(&info->delta_msr_wait);
-
- /*
- * Free the IRQ
- */
- free_irq(info->port->irq, info);
-
- if (info->xmit.buf) {
- unsigned long pg = (unsigned long) info->xmit.buf;
- info->xmit.buf = NULL;
- free_page(pg);
- }
-
- /*
- * disable all interrupts, disable the port
- */
- UART_PUT_CR(info->port, 0);
-
- /* disable break condition and fifos */
- UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
- ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
-
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
- info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
- info->port->set_mctrl(info->port, info->mctrl);
-
- /* kill off our tasklet */
- tasklet_kill(&info->tlet);
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
-}
-
-static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
-{
- unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
- unsigned long flags;
-
- if (!info->tty || !info->tty->termios)
- return;
-
- cflag = info->tty->termios->c_cflag;
-
-#if DEBUG
- printk("ambauart_set_cflag(0x%x) called\n", cflag);
-#endif
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break;
- case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break;
- case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break;
- default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
- }
- if (cflag & CSTOPB) {
- lcr_h |= AMBA_UARTLCR_H_STP2;
- bits ++;
- }
- if (cflag & PARENB) {
- lcr_h |= AMBA_UARTLCR_H_PEN;
- bits++;
- if (!(cflag & PARODD))
- lcr_h |= AMBA_UARTLCR_H_EPS;
- }
- if (info->port->fifosize > 1)
- lcr_h |= AMBA_UARTLCR_H_FEN;
-
- do {
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(info->tty);
- if (!baud)
- baud = 9600;
-
- if (baud == 38400 &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
- quot = info->state->custom_divisor;
- else
- quot = (info->port->uartclk / (16 * baud)) - 1;
-
- if (!quot && old_termios) {
- info->tty->termios->c_cflag &= ~CBAUD;
- info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
- old_termios = NULL;
- }
- } while (quot == 0 && old_termios);
-
- /* As a last resort, if the quotient is zero, default to 9600 bps */
- if (!quot)
- quot = (info->port->uartclk / (16 * 9600)) - 1;
-
- info->timeout = (info->port->fifosize * HZ * bits * quot) /
- (info->port->uartclk / 16);
- info->timeout += HZ/50; /* Add .02 seconds of slop */
-
- if (cflag & CRTSCTS)
- info->flags |= ASYNC_CTS_FLOW;
- else
- info->flags &= ~ASYNC_CTS_FLOW;
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else
- info->flags |= ASYNC_CHECK_CD;
-
- /*
- * Set up parity check flag
- */
-#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- info->read_status_mask = AMBA_UARTRSR_OE;
- if (I_INPCK(info->tty))
- info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
- if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
- info->read_status_mask |= AMBA_UARTRSR_BE;
-
- /*
- * Characters to ignore
- */
- info->ignore_status_mask = 0;
- if (I_IGNPAR(info->tty))
- info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
- if (I_IGNBRK(info->tty)) {
- info->ignore_status_mask |= AMBA_UARTRSR_BE;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns to (for real raw support).
- */
- if (I_IGNPAR(info->tty))
- info->ignore_status_mask |= AMBA_UARTRSR_OE;
- }
-
- /* first, disable everything */
- save_flags(flags); cli();
- old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
-
- if ((info->flags & ASYNC_HARDPPS_CD) ||
- (cflag & CRTSCTS) ||
- !(cflag & CLOCAL))
- old_cr |= AMBA_UARTCR_MSIE;
-
- UART_PUT_CR(info->port, 0);
- restore_flags(flags);
-
- /* Set baud rate */
- UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
- UART_PUT_LCRL(info->port, (quot & 0xff));
-
- /*
- * ----------v----------v----------v----------v-----
- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
- * ----------^----------^----------^----------^-----
- */
- UART_PUT_LCRH(info->port, lcr_h);
- UART_PUT_CR(info->port, old_cr);
-}
-
-static void ambauart_put_char(struct tty_struct *tty, u_char ch)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
- if (!tty || !info->xmit.buf)
- return;
-
- save_flags(flags); cli();
- if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
- info->xmit.buf[info->xmit.head] = ch;
- info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
- }
- restore_flags(flags);
-}
-
-static void ambauart_flush_chars(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
- if (info->xmit.head == info->xmit.tail
- || tty->stopped
- || tty->hw_stopped
- || !info->xmit.buf)
- return;
-
- save_flags(flags); cli();
- ambauart_enable_tx_interrupt(info);
- restore_flags(flags);
-}
-
-static int ambauart_write(struct tty_struct *tty, int from_user,
- const u_char * buf, int count)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
- int c, ret = 0;
-
- if (!tty || !info->xmit.buf || !tmp_buf)
- return 0;
-
- save_flags(flags);
- if (from_user) {
- down(&tmp_buf_sem);
- while (1) {
- int c1;
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- AMBA_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- c -= copy_from_user(tmp_buf, buf, c);
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- cli();
- c1 = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- AMBA_XMIT_SIZE);
- if (c1 < c)
- c = c1;
- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
- info->xmit.head = (info->xmit.head + c) &
- (AMBA_XMIT_SIZE - 1);
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
- }
- up(&tmp_buf_sem);
- } else {
- cli();
- while (1) {
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- AMBA_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
- memcpy(info->xmit.buf + info->xmit.head, buf, c);
- info->xmit.head = (info->xmit.head + c) &
- (AMBA_XMIT_SIZE - 1);
- buf += c;
- count -= c;
- ret += c;
- }
- restore_flags(flags);
- }
- if (info->xmit.head != info->xmit.tail
- && !tty->stopped
- && !tty->hw_stopped)
- ambauart_enable_tx_interrupt(info);
- return ret;
-}
-
-static int ambauart_write_room(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
-
- return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
-}
-
-static int ambauart_chars_in_buffer(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
-
- return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
-}
-
-static void ambauart_flush_buffer(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
-#if DEBUG
- printk("ambauart_flush_buffer(%d) called\n",
- minor(tty->device) - tty->driver.minor_start);
-#endif
- save_flags(flags); cli();
- info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
- wake_up_interruptible(&tty->write_wait);
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void ambauart_send_xchar(struct tty_struct *tty, char ch)
-{
- struct amba_info *info = tty->driver_data;
-
- info->x_char = ch;
- if (ch)
- ambauart_enable_tx_interrupt(info);
-}
-
-static void ambauart_throttle(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
-
- if (I_IXOFF(tty))
- ambauart_send_xchar(tty, STOP_CHAR(tty));
-
- if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags); cli();
- info->mctrl &= ~TIOCM_RTS;
- info->port->set_mctrl(info->port, info->mctrl);
- restore_flags(flags);
- }
-}
-
-static void ambauart_unthrottle(struct tty_struct *tty)
-{
- struct amba_info *info = (struct amba_info *) tty->driver_data;
- unsigned long flags;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- ambauart_send_xchar(tty, START_CHAR(tty));
- }
-
- if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags); cli();
- info->mctrl |= TIOCM_RTS;
- info->port->set_mctrl(info->port, info->mctrl);
- restore_flags(flags);
- }
-}
-
-static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
-{
- struct amba_state *state = info->state;
- struct amba_port *port = info->port;
- struct serial_struct tmp;
-
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = 0;
- tmp.line = state->line;
- tmp.port = port->uart_base;
- if (HIGH_BITS_OFFSET)
- tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
- tmp.irq = port->irq;
- tmp.flags = 0;
- tmp.xmit_fifo_size = port->fifosize;
- tmp.baud_base = port->uartclk / 16;
- tmp.close_delay = state->close_delay;
- tmp.closing_wait = state->closing_wait;
- tmp.custom_divisor = state->custom_divisor;
-
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
- return 0;
-}
-
-static int set_serial_info(struct amba_info *info,
- struct serial_struct *newinfo)
-{
- struct serial_struct new_serial;
- struct amba_state *state, old_state;
- struct amba_port *port;
- unsigned long new_port;
- unsigned int i, change_irq, change_port;
- int retval = 0;
-
- if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
- return -EFAULT;
-
- state = info->state;
- old_state = *state;
- port = info->port;
-
- new_port = new_serial.port;
- if (HIGH_BITS_OFFSET)
- new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-
- change_irq = new_serial.irq != port->irq;
- change_port = new_port != port->uart_base;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if (change_irq || change_port ||
- (new_serial.baud_base != port->uartclk / 16) ||
- (new_serial.close_delay != state->close_delay) ||
- (new_serial.xmit_fifo_size != port->fifosize) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (state->flags & ~ASYNC_USR_MASK)))
- return -EPERM;
- state->flags = ((state->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- state->custom_divisor = new_serial.custom_divisor;
- goto check_and_exit;
- }
-
- if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
- (new_serial.baud_base < 9600))
- return -EINVAL;
-
- if (new_serial.type && change_port) {
- for (i = 0; i < SERIAL_AMBA_NR; i++)
- if ((port != amba_ports + i) &&
- amba_ports[i].uart_base != new_port)
- return -EADDRINUSE;
- }
-
- if ((change_port || change_irq) && (state->count > 1))
- return -EBUSY;
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
- port->uartclk = new_serial.baud_base * 16;
- state->flags = ((state->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
- info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
- (info->flags & ASYNC_INTERNAL_FLAGS));
- state->custom_divisor = new_serial.custom_divisor;
- state->close_delay = new_serial.close_delay * HZ / 100;
- state->closing_wait = new_serial.closing_wait * HZ / 100;
- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
- port->fifosize = new_serial.xmit_fifo_size;
-
- if (change_port || change_irq) {
- /*
- * We need to shutdown the serial port at the old
- * port/irq combination.
- */
- ambauart_shutdown(info);
- port->irq = new_serial.irq;
- port->uart_base = new_port;
- }
-
-check_and_exit:
- if (!port->uart_base)
- return 0;
- if (info->flags & ASYNC_INITIALIZED) {
- if ((old_state.flags & ASYNC_SPD_MASK) !=
- (state->flags & ASYNC_SPD_MASK) ||
- (old_state.custom_divisor != state->custom_divisor)) {
- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- ambauart_change_speed(info, NULL);
- }
- } else
- retval = ambauart_startup(info);
- return retval;
-}
-
-
-/*
- * get_lsr_info - get line status register info
- */
-static int get_lsr_info(struct amba_info *info, unsigned int *value)
-{
- unsigned int result, status;
- unsigned long flags;
-
- save_flags(flags); cli();
- status = UART_GET_FR(info->port);
- restore_flags(flags);
- result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
-
- /*
- * If we're about to load something into the transmit
- * register, we'll pretend the transmitter isn't empty to
- * avoid a race condition (depending on when the transmit
- * interrupt happens).
- */
- if (info->x_char ||
- ((CIRC_CNT(info->xmit.head, info->xmit.tail,
- AMBA_XMIT_SIZE) > 0) &&
- !info->tty->stopped && !info->tty->hw_stopped))
- result &= TIOCSER_TEMT;
-
- return put_user(result, value);
-}
-
-static int get_modem_info(struct amba_info *info, unsigned int *value)
-{
- unsigned int result = info->mctrl;
- unsigned int status;
-
- status = UART_GET_FR(info->port);
- if (status & AMBA_UARTFR_DCD)
- result |= TIOCM_CAR;
- if (status & AMBA_UARTFR_DSR)
- result |= TIOCM_DSR;
- if (status & AMBA_UARTFR_CTS)
- result |= TIOCM_CTS;
-
- return put_user(result, value);
-}
-
-static int set_modem_info(struct amba_info *info, unsigned int cmd,
- unsigned int *value)
-{
- unsigned int arg, old;
- unsigned long flags;
-
- if (get_user(arg, value))
- return -EFAULT;
-
- old = info->mctrl;
- switch (cmd) {
- case TIOCMBIS:
- info->mctrl |= arg;
- break;
-
- case TIOCMBIC:
- info->mctrl &= ~arg;
- break;
-
- case TIOCMSET:
- info->mctrl = arg;
- break;
-
- default:
- return -EINVAL;
- }
- save_flags(flags); cli();
- if (old != info->mctrl)
- info->port->set_mctrl(info->port, info->mctrl);
- restore_flags(flags);
- return 0;
-}
-
-static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
- unsigned int lcr_h;
-
- save_flags(flags); cli();
- lcr_h = UART_GET_LCRH(info->port);
- if (break_state == -1)
- lcr_h |= AMBA_UARTLCR_H_BRK;
- else
- lcr_h &= ~AMBA_UARTLCR_H_BRK;
- UART_PUT_LCRH(info->port, lcr_h);
- restore_flags(flags);
-}
-
-static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct amba_info *info = tty->driver_data;
- struct amba_icount cprev, cnow;
- struct serial_icounter_struct icount;
- unsigned long flags;
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *)arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *)arg);
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *)arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *)arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *)arg);
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
- save_flags(flags); cli();
- /* note the counters on entry */
- cprev = info->state->icount;
- /* Force modem status interrupts on */
- UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
- restore_flags(flags);
- while (1) {
- interruptible_sleep_on(&info->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- save_flags(flags); cli();
- cnow = info->state->icount; /* atomic copy */
- restore_flags(flags);
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
-
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- save_flags(flags); cli();
- cnow = info->state->icount;
- restore_flags(flags);
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- return copy_to_user((void *)arg, &icount, sizeof(icount))
- ? -EFAULT : 0;
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- struct amba_info *info = tty->driver_data;
- unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
-
- if ((cflag ^ old_termios->c_cflag) == 0 &&
- RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
- return;
-
- ambauart_change_speed(info, old_termios);
-
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(cflag & CBAUD)) {
- save_flags(flags); cli();
- info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
- info->port->set_mctrl(info->port, info->mctrl);
- restore_flags(flags);
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (cflag & CBAUD)) {
- save_flags(flags); cli();
- info->mctrl |= TIOCM_DTR;
- if (!(cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags))
- info->mctrl |= TIOCM_RTS;
- info->port->set_mctrl(info->port, info->mctrl);
- restore_flags(flags);
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- ambauart_start(tty);
- }
-
-#if 0
- /*
- * No need to wake up processes in open wait, since they
- * sample the CLOCAL flag once, and don't recheck it.
- * XXX It's not clear whether the current behavior is correct
- * or not. Hence, this may change.....
- */
- if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-static void ambauart_close(struct tty_struct *tty, struct file *filp)
-{
- struct amba_info *info = tty->driver_data;
- struct amba_state *state;
- unsigned long flags;
-
- if (!info)
- return;
-
- state = info->state;
-
-#if DEBUG
- printk("ambauart_close() called\n");
-#endif
-
- save_flags(flags); cli();
-
- if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
- restore_flags(flags);
- return;
- }
-
- if ((tty->count == 1) && (state->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("ambauart_close: bad serial port count; tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
- }
- if (--state->count < 0) {
- printk("rs_close: bad serial port count for %s%d: %d\n",
- tty->driver.name, info->state->line, state->count);
- state->count = 0;
- }
- if (state->count) {
- MOD_DEC_USE_COUNT;
- restore_flags(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
- restore_flags(flags);
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (info->flags & ASYNC_NORMAL_ACTIVE)
- info->state->normal_termios = *tty->termios;
- if (info->flags & ASYNC_CALLOUT_ACTIVE)
- info->state->callout_termios = *tty->termios;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->state->closing_wait);
- /*
- * At this point, we stop accepting input. To do this, we
- * disable the receive line status interrupts.
- */
- if (info->flags & ASYNC_INITIALIZED) {
- ambauart_disable_rx_interrupt(info);
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- ambauart_wait_until_sent(tty, info->timeout);
- }
- ambauart_shutdown(info);
- if (tty->driver.flush_buffer)
- tty->driver.flush_buffer(tty);
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
- tty->closing = 0;
- info->event = 0;
- info->tty = NULL;
- if (info->blocked_open) {
- if (info->state->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->state->close_delay);
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
- ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- MOD_DEC_USE_COUNT;
-}
-
-static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- struct amba_info *info = (struct amba_info *) tty->driver_data;
- unsigned long char_time, expire;
- unsigned int status;
-
- if (info->port->fifosize == 0)
- return;
-
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (info->timeout - HZ/50) / info->port->fifosize;
- char_time = char_time / 5;
- if (char_time == 0)
- char_time = 1;
- if (timeout && timeout < char_time)
- char_time = timeout;
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than info->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*info->timeout.
- */
- if (!timeout || timeout > 2 * info->timeout)
- timeout = 2 * info->timeout;
-
- expire = jiffies + timeout;
-#if DEBUG
- printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
- minor(tty->device) - tty->driver.minor_start, jiffies,
- expire);
-#endif
- while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, expire))
- break;
- status = UART_GET_FR(info->port);
- }
- set_current_state(TASK_RUNNING);
-}
-
-static void ambauart_hangup(struct tty_struct *tty)
-{
- struct amba_info *info = tty->driver_data;
- struct amba_state *state = info->state;
-
- ambauart_flush_buffer(tty);
- if (info->flags & ASYNC_CLOSING)
- return;
- ambauart_shutdown(info);
- info->event = 0;
- state->count = 0;
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
- info->tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct amba_info *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct amba_state *state = info->state;
- unsigned long flags;
- int do_clocal = 0, extra_count = 0, retval;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
- return (info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS;
- }
-
- /*
- * If this is a callout device, then just make sure the normal
- * device isn't being used.
- */
- if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
- if (info->flags & ASYNC_NORMAL_ACTIVE)
- return -EBUSY;
- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_SESSION_LOCKOUT) &&
- (info->session != current->session))
- return -EBUSY;
- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_PGRP_LOCKOUT) &&
- (info->pgrp != current->pgrp))
- return -EBUSY;
- info->flags |= ASYNC_CALLOUT_ACTIVE;
- return 0;
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- if (info->flags & ASYNC_CALLOUT_ACTIVE)
- return -EBUSY;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (info->flags & ASYNC_CALLOUT_ACTIVE) {
- if (state->normal_termios.c_cflag & CLOCAL)
- do_clocal = 1;
- } else {
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
- }
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, state->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
- save_flags(flags); cli();
- if (!tty_hung_up_p(filp)) {
- extra_count = 1;
- state->count--;
- }
- restore_flags(flags);
- info->blocked_open++;
- while (1) {
- save_flags(flags); cli();
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (tty->termios->c_cflag & CBAUD)) {
- info->mctrl = TIOCM_DTR | TIOCM_RTS;
- info->port->set_mctrl(info->port, info->mctrl);
- }
- restore_flags(flags);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
- !(info->flags & ASYNC_CLOSING) &&
- (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->open_wait, &wait);
- if (extra_count)
- state->count++;
- info->blocked_open--;
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static struct amba_info *ambauart_get(int line)
-{
- struct amba_info *info;
- struct amba_state *state = amba_state + line;
-
- state->count++;
- if (state->info)
- return state->info;
- info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
- if (info) {
- memset(info, 0, sizeof(struct amba_info));
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->delta_msr_wait);
- info->flags = state->flags;
- info->state = state;
- info->port = amba_ports + line;
- tasklet_init(&info->tlet, ambauart_tasklet_action,
- (unsigned long)info);
- }
- if (state->info) {
- kfree(info);
- return state->info;
- }
- state->info = info;
- return info;
-}
-
-static int ambauart_open(struct tty_struct *tty, struct file *filp)
-{
- struct amba_info *info;
- int retval, line = minor(tty->device) - tty->driver.minor_start;
-
-#if DEBUG
- printk("ambauart_open(%d) called\n", line);
-#endif
-
- // is this a line that we've got?
- MOD_INC_USE_COUNT;
- if (line >= SERIAL_AMBA_NR) {
- MOD_DEC_USE_COUNT;
- return -ENODEV;
- }
-
- info = ambauart_get(line);
- if (!info)
- return -ENOMEM;
-
- tty->driver_data = info;
- info->tty = tty;
- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- /*
- * Make sure we have the temporary buffer allocated
- */
- if (!tmp_buf) {
- unsigned long page = get_zeroed_page(GFP_KERNEL);
- if (tmp_buf)
- free_page(page);
- else if (!page) {
- MOD_DEC_USE_COUNT;
- return -ENOMEM;
- }
- tmp_buf = (u_char *)page;
- }
-
- /*
- * If the port is in the middle of closing, bail out now.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
-
- /*
- * Start up the serial port
- */
- retval = ambauart_startup(info);
- if (retval) {
- MOD_DEC_USE_COUNT;
- return retval;
- }
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
- MOD_DEC_USE_COUNT;
- return retval;
- }
-
- if ((info->state->count == 1) &&
- (info->flags & ASYNC_SPLIT_TERMIOS)) {
- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
- *tty->termios = info->state->normal_termios;
- else
- *tty->termios = info->state->callout_termios;
- }
-#ifdef CONFIG_SERIAL_AMBA_CONSOLE
- if (ambauart_cons.cflag && ambauart_cons.index == line) {
- tty->termios->c_cflag = ambauart_cons.cflag;
- ambauart_cons.cflag = 0;
- }
-#endif
- ambauart_change_speed(info, NULL);
- info->session = current->session;
- info->pgrp = current->pgrp;
- return 0;
-}
-
-int __init ambauart_init(void)
-{
- int i;
-
- ambanormal_driver.magic = TTY_DRIVER_MAGIC;
- ambanormal_driver.driver_name = "serial_amba";
- ambanormal_driver.name = SERIAL_AMBA_NAME;
- ambanormal_driver.major = SERIAL_AMBA_MAJOR;
- ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
- ambanormal_driver.num = SERIAL_AMBA_NR;
- ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
- ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
- ambanormal_driver.init_termios = tty_std_termios;
- ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
- ambanormal_driver.refcount = &ambauart_refcount;
- ambanormal_driver.table = ambauart_table;
- ambanormal_driver.termios = ambauart_termios;
- ambanormal_driver.termios_locked = ambauart_termios_locked;
-
- ambanormal_driver.open = ambauart_open;
- ambanormal_driver.close = ambauart_close;
- ambanormal_driver.write = ambauart_write;
- ambanormal_driver.put_char = ambauart_put_char;
- ambanormal_driver.flush_chars = ambauart_flush_chars;
- ambanormal_driver.write_room = ambauart_write_room;
- ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
- ambanormal_driver.flush_buffer = ambauart_flush_buffer;
- ambanormal_driver.ioctl = ambauart_ioctl;
- ambanormal_driver.throttle = ambauart_throttle;
- ambanormal_driver.unthrottle = ambauart_unthrottle;
- ambanormal_driver.send_xchar = ambauart_send_xchar;
- ambanormal_driver.set_termios = ambauart_set_termios;
- ambanormal_driver.stop = ambauart_stop;
- ambanormal_driver.start = ambauart_start;
- ambanormal_driver.hangup = ambauart_hangup;
- ambanormal_driver.break_ctl = ambauart_break_ctl;
- ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
- ambanormal_driver.read_proc = NULL;
-
- /*
- * The callout device is just like the normal device except for
- * the major number and the subtype code.
- */
- ambacallout_driver = ambanormal_driver;
- ambacallout_driver.name = CALLOUT_AMBA_NAME;
- ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
- ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
- ambacallout_driver.read_proc = NULL;
- ambacallout_driver.proc_entry = NULL;
-
- if (tty_register_driver(&ambanormal_driver))
- panic("Couldn't register AMBA serial driver\n");
- if (tty_register_driver(&ambacallout_driver))
- panic("Couldn't register AMBA callout driver\n");
-
- for (i = 0; i < SERIAL_AMBA_NR; i++) {
- struct amba_state *state = amba_state + i;
- state->line = i;
- state->close_delay = 5 * HZ / 10;
- state->closing_wait = 30 * HZ;
- state->callout_termios = ambacallout_driver.init_termios;
- state->normal_termios = ambanormal_driver.init_termios;
- }
-
- return 0;
-}
-
-__initcall(ambauart_init);
-
-#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-/************** console driver *****************/
-
-/*
- * This code is currently never used; console->read is never called.
- * Therefore, although we have an implementation, we don't use it.
- * FIXME: the "const char *s" should be fixed to "char *s" some day.
- * (when the definition in include/linux/console.h is also fixed)
- */
-#ifdef used_and_not_const_char_pointer
-static int ambauart_console_read(struct console *co, const char *s, u_int count)
-{
- struct amba_port *port = &amba_ports[co->index];
- unsigned int status;
- char *w;
- int c;
-#if DEBUG
- printk("ambauart_console_read() called\n");
-#endif
-
- c = 0;
- w = s;
- while (c < count) {
- status = UART_GET_FR(port);
- if (UART_RX_DATA(status)) {
- *w++ = UART_GET_CHAR(port);
- c++;
- } else {
- // nothing more to get, return
- return c;
- }
- }
- // return the count
- return c;
-}
-#endif
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console must be locked when we get here.
- */
-static void ambauart_console_write(struct console *co, const char *s, u_int count)
-{
- struct amba_port *port = &amba_ports[co->index];
- unsigned int status, old_cr;
- int i;
-
- /*
- * First save the CR then disable the interrupts
- */
- old_cr = UART_GET_CR(port);
- UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++) {
- do {
- status = UART_GET_FR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, s[i]);
- if (s[i] == '\n') {
- do {
- status = UART_GET_FR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, '\r');
- }
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the TCR
- */
- do {
- status = UART_GET_FR(port);
- } while (status & AMBA_UARTFR_BUSY);
- UART_PUT_CR(port, old_cr);
-}
-
-static kdev_t ambauart_console_device(struct console *c)
-{
- return mk_kdev(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
-}
-
-static int __init ambauart_console_setup(struct console *co, char *options)
-{
- struct amba_port *port;
- int baud = 38400;
- int bits = 8;
- int parity = 'n';
- u_int cflag = CREAD | HUPCL | CLOCAL;
- u_int lcr_h, quot;
-
- if (co->index >= SERIAL_AMBA_NR)
- co->index = 0;
-
- port = &amba_ports[co->index];
-
- if (options) {
- char *s = options;
- baud = simple_strtoul(s, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s) parity = *s++;
- if (*s) bits = *s - '0';
- }
-
- /*
- * Now construct a cflag setting.
- */
- switch (baud) {
- case 1200: cflag |= B1200; break;
- case 2400: cflag |= B2400; break;
- case 4800: cflag |= B4800; break;
- default: cflag |= B9600; baud = 9600; break;
- case 19200: cflag |= B19200; break;
- case 38400: cflag |= B38400; break;
- case 57600: cflag |= B57600; break;
- case 115200: cflag |= B115200; break;
- }
- switch (bits) {
- case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break;
- default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break;
- }
- switch (parity) {
- case 'o':
- case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
- case 'e':
- case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
- AMBA_UARTLCR_H_EPS; break;
- }
-
- co->cflag = cflag;
-
- if (port->fifosize > 1)
- lcr_h |= AMBA_UARTLCR_H_FEN;
-
- quot = (port->uartclk / (16 * baud)) - 1;
-
- UART_PUT_LCRL(port, (quot & 0xff));
- UART_PUT_LCRM(port, (quot >> 8));
- UART_PUT_LCRH(port, lcr_h);
-
- /* we will enable the port as we need it */
- UART_PUT_CR(port, 0);
-
- return 0;
-}
-
-static struct console ambauart_cons =
-{
- name: SERIAL_AMBA_NAME,
- write: ambauart_console_write,
-#ifdef used_and_not_const_char_pointer
- read: ambauart_console_read,
-#endif
- device: ambauart_console_device,
- setup: ambauart_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
-};
-
-void __init ambauart_console_init(void)
-{
- register_console(&ambauart_cons);
-}
-
-#endif /* CONFIG_SERIAL_AMBA_CONSOLE */
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 52ab887430e3..501ec0c753f3 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -545,6 +545,7 @@ void tty_vhangup(struct tty_struct * tty)
#endif
do_tty_hangup((void *) tty);
}
+EXPORT_SYMBOL(tty_vhangup);
int tty_hung_up_p(struct file * filp)
{
diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help
index 74668ed23673..3375dee859dc 100644
--- a/drivers/ide/Config.help
+++ b/drivers/ide/Config.help
@@ -84,6 +84,16 @@ CONFIG_BLK_DEV_IDECS
Support for outboard IDE disks, tape drives, and CD-ROM drives
connected through a PCMCIA card.
+CONFIG_ATAPI
+ If you wish to enable basic support for devices attached to the system
+ through the ATA interface, and which are using using the ATAPI protocol
+ (CD-ROM, CD-RW, DVD, DVD-RW, LS120, ZIP, ...), say Y.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called atapi.o.
+
CONFIG_BLK_DEV_IDECD
If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is
a newer protocol used by IDE CD-ROM and TAPE drives, similar to the
diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in
index f2c8fe680de1..5a48bc9a7b78 100644
--- a/drivers/ide/Config.in
+++ b/drivers/ide/Config.in
@@ -1,40 +1,37 @@
#
-# IDE ATA ATAPI Block device driver configuration
+# ATA/ATAPI block device driver configuration
#
-# Andre Hedrick <andre@linux-ide.org>
-#
-mainmenu_option next_comment
-comment 'ATA and ATAPI Block devices'
-
-dep_tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE $CONFIG_IDE
-comment 'Please see Documentation/ide.txt for help/info on IDE drives'
+dep_tristate 'Enhanced ATA/ATAPI device (disk,cdrom,...) support' CONFIG_BLK_DEV_IDE $CONFIG_IDE
if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE $CONFIG_X86
define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_IDE
- dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
- dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK
- dep_mbool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK
- dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA
- dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
- dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
- dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
- dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI
+ dep_tristate ' ATA disk support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
+ dep_bool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK
+ dep_bool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK
+
+ dep_tristate ' ATAPI device support (CD-ROM, floppy)' CONFIG_ATAPI $CONFIG_BLK_DEV_IDE
+ dep_tristate ' CD-ROM support' CONFIG_BLK_DEV_IDECD $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE
+ dep_tristate ' Tape support' CONFIG_BLK_DEV_IDETAPE $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE
+ dep_tristate ' Floppy support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE
+ dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI
+
+ dep_tristate ' PCMCIA/CardBus support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA
- comment 'ATA host chip set support'
- dep_bool ' CMD640 chip set bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86
+ comment 'ATA host controller support'
+ dep_bool ' RZ1000 bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86
+ dep_bool ' CMD640 bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86
dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640
dep_bool ' ISA-PNP support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP
- if [ "$CONFIG_PCI" = "y" ]; then
- dep_bool ' RZ1000 chip set bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86
- comment ' PCI host chip set support'
- dep_bool ' Boot off-board chip sets first support' CONFIG_BLK_DEV_OFFBOARD $CONFIG_PCI
- dep_bool ' Sharing PCI ATA interrupts support' CONFIG_IDEPCI_SHARE_IRQ $CONFIG_PCI
+ if [ "$CONFIG_PCI" != "n" ]; then
+ comment ' PCI host controller support'
+ dep_bool ' Boot off-board controllers first' CONFIG_BLK_DEV_OFFBOARD $CONFIG_PCI
+ dep_bool ' Sharing PCI ATA interrupts' CONFIG_IDEPCI_SHARE_IRQ $CONFIG_PCI
dep_bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_PCI
dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_bool ' ATA tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
+ dep_bool ' Tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
@@ -110,7 +107,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
fi
# assume no ISA -> also no VLB
- dep_bool ' Other ISA/VLB IDE chipset support' CONFIG_IDE_CHIPSETS $CONFIG_ISA
+ dep_bool ' ISA/VLB IDE chipset support' CONFIG_IDE_CHIPSETS $CONFIG_ISA
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters'
bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
@@ -122,15 +119,13 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_tristate ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE
bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
fi
- if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \
- "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \
- "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then
+ if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" != "n" -o \
+ "$CONFIG_BLK_DEV_IDEDMA_PMAC" != "n" -o \
+ "$CONFIG_BLK_DEV_IDEDMA_ICS" != "n" ]; then
bool ' IGNORE word93 Validation BITS' CONFIG_IDEDMA_IVB
fi
-
- define_bool CONFIG_ATAPI y
else
- bool 'Old hard disk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
+ bool 'Old disk only (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_ONLY
fi
@@ -142,8 +137,6 @@ else
define_bool CONFIG_IDEDMA_AUTO n
fi
-dep_tristate 'Support for IDE Raid controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL
-dep_tristate ' Support Promise software RAID (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
-dep_tristate ' Highpoint 370 software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
-
-endmenu
+dep_tristate 'Support for software RAID controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL
+dep_tristate ' Support Promise (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
+dep_tristate ' Highpoint 370 EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 010311bd8fec..57aaeb7a3ce8 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o
obj-$(CONFIG_BLK_DEV_IDE) += ide-mod.o
obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
-# obj-$(CONFIG_ATAPI) += atapi.o
+obj-$(CONFIG_ATAPI) += atapi.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
@@ -69,6 +69,6 @@ obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o
obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o
ide-mod-objs := device.o ide-taskfile.o main.o ide.o probe.o \
- ioctl.o atapi.o ata-timing.o $(ide-obj-y)
+ ioctl.o ata-timing.o $(ide-obj-y)
include $(TOPDIR)/Rules.make
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index d2dca5e1a1a4..468a4b788644 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -42,10 +42,11 @@
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define AEC_DRIVE_TIMING 0x40
@@ -167,7 +168,7 @@ static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio)
return;
}
- aec_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
+ aec_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5));
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index 33f175c92e0b..9d2e97c47d36 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -37,12 +37,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/ide.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index f8422ad5e897..e862b5c98dfd 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -26,30 +26,30 @@
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
-static byte m5229_revision;
-static byte chip_is_1543c_e;
+static u8 m5229_revision;
+static int chip_is_1543c_e;
static struct pci_dev *isa_dev;
-static void ali15x3_tune_drive(struct ata_device *drive, byte pio)
+static void ali15x3_tune_drive(struct ata_device *drive, u8 pio)
{
struct ata_timing *t;
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
int s_time, a_time, c_time;
- byte s_clc, a_clc, r_clc;
+ u8 s_clc, a_clc, r_clc;
unsigned long flags;
int port = hwif->unit ? 0x5c : 0x58;
int portFIFO = hwif->unit ? 0x55 : 0x54;
- byte cd_dma_fifo = 0;
+ u8 cd_dma_fifo = 0;
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- pio = XFER_PIO_0 + min_t(byte, pio, 4);
+ pio = XFER_PIO_0 + min_t(u8, pio, 4);
t = ata_timing_data(pio);
@@ -100,15 +100,15 @@ static void ali15x3_tune_drive(struct ata_device *drive, byte pio)
local_irq_restore(flags);
}
-static int ali15x3_tune_chipset(struct ata_device *drive, byte speed)
+static int ali15x3_tune_chipset(struct ata_device *drive, u8 speed)
{
struct pci_dev *dev = drive->channel->pci_dev;
- byte unit = (drive->select.b.unit & 0x01);
- byte tmpbyte = 0x00;
- int m5229_udma = drive->channel->unit ? 0x57 : 0x56;
+ u8 unit = (drive->select.b.unit & 0x01);
+ u8 tmpbyte = 0x00;
+ int m5229_udma = drive->channel->unit ? 0x57 : 0x56;
if (speed < XFER_UDMA_0) {
- byte ultra_enable = (unit) ? 0x7f : 0xf7;
+ u8 ultra_enable = unit ? 0x7f : 0xf7;
/*
* clear "ultra enable" bit
*/
@@ -135,7 +135,7 @@ static int ali15x3_tune_chipset(struct ata_device *drive, byte speed)
pci_write_config_byte(dev, 0x4b, tmpbyte);
}
}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif
return ide_config_drive_speed(drive, speed);
}
@@ -212,10 +212,10 @@ static unsigned int __init ali15x3_ata66_check(struct ata_channel *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
unsigned int ata66 = 0;
- byte cable_80_pin[2] = { 0, 0 };
+ u8 cable_80_pin[2] = { 0, 0 };
unsigned long flags;
- byte tmpbyte;
+ u8 tmpbyte;
local_irq_save(flags);
@@ -305,8 +305,8 @@ static unsigned int __init ali15x3_ata66_check(struct ata_channel *hwif)
static void __init ali15x3_init_channel(struct ata_channel *hwif)
{
#ifndef CONFIG_SPARC64
- byte ideic, inmir;
- byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
+ u8 ideic, inmir;
+ u8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
1, 11, 0, 12, 0, 14, 0, 15 };
hwif->irq = hwif->unit ? 15 : 14;
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 485f31e3f4cb..5e2e1e27e850 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -42,11 +42,12 @@
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define AMD_IDE_ENABLE (0x00 + amd_config->base)
@@ -171,7 +172,7 @@ static void amd74xx_tune_drive(struct ata_device *drive, u8 pio)
return;
}
- amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
+ amd_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5));
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/drivers/ide/ata-timing.c b/drivers/ide/ata-timing.c
index 01a312044242..f713a15b047a 100644
--- a/drivers/ide/ata-timing.c
+++ b/drivers/ide/ata-timing.c
@@ -23,7 +23,10 @@
*/
#include <linux/kernel.h>
-#include "ata-timing.h"
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include "timing.h"
/*
* PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). These were taken
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index 0c5f45be113a..e8325b9e7690 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -106,13 +106,13 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/init.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
/*
* This flag is set in ide.c by the parameter: ide0=cmd640_vlb
@@ -200,7 +200,7 @@ static struct ata_device *cmd_drives[4];
* Interface to access cmd640x registers
*/
static unsigned int cmd640_key;
-static void (*put_cmd640_reg)(unsigned short reg, byte val);
+static void (*put_cmd640_reg)(unsigned short reg, u8 val);
static u8 (*get_cmd640_reg)(unsigned short reg);
/*
@@ -214,17 +214,19 @@ static unsigned int cmd640_chip_version;
* Therefore, we must use direct IO instead.
*/
+/* This is broken, but no more so than the old code.. */
+static spinlock_t cmd640_lock = SPIN_LOCK_UNLOCKED;
+
/* PCI method 1 access */
-static void put_cmd640_reg_pci1 (unsigned short reg, byte val)
+static void put_cmd640_reg_pci1 (unsigned short reg, u8 val)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
outb_p(val, (reg & 3) | 0xcfc);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
static u8 get_cmd640_reg_pci1 (unsigned short reg)
@@ -232,11 +234,10 @@ static u8 get_cmd640_reg_pci1 (unsigned short reg)
u8 b;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
b = inb_p((reg & 3) | 0xcfc);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return b;
}
@@ -246,12 +247,11 @@ static void put_cmd640_reg_pci2 (unsigned short reg, u8 val)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(0x10, 0xcf8);
outb_p(val, cmd640_key + reg);
outb_p(0, 0xcf8);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
static u8 get_cmd640_reg_pci2 (unsigned short reg)
@@ -259,12 +259,11 @@ static u8 get_cmd640_reg_pci2 (unsigned short reg)
u8 b;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(0x10, 0xcf8);
b = inb_p(cmd640_key + reg);
outb_p(0, 0xcf8);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return b;
}
@@ -274,11 +273,10 @@ static void put_cmd640_reg_vlb (unsigned short reg, u8 val)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(reg, cmd640_key);
outb_p(val, cmd640_key + 4);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
static u8 get_cmd640_reg_vlb (unsigned short reg)
@@ -286,11 +284,10 @@ static u8 get_cmd640_reg_vlb (unsigned short reg)
u8 b;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(reg, cmd640_key);
b = inb_p(cmd640_key + 4);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return b;
}
@@ -367,8 +364,7 @@ static int __init secondary_port_responding (void)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */
udelay(100);
@@ -376,11 +372,11 @@ static int __init secondary_port_responding (void)
outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
udelay(100);
if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 0; /* nothing responded */
}
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
return 1; /* success */
}
@@ -461,8 +457,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
u8 b;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&cmd640_lock, flags);
b = get_cmd640_reg(reg);
if (mode) { /* want prefetch on? */
# if CMD640_PREFETCH_MASKS
@@ -478,7 +473,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
b |= prefetch_masks[index]; /* disable prefetch */
}
put_cmd640_reg(reg, b);
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
/*
@@ -579,8 +574,7 @@ static void program_drive_counts (unsigned int index)
/*
* Now that everything is ready, program the new timings
*/
- save_flags (flags);
- cli();
+ spin_lock(&cmd640_lock, flags);
/*
* Program the address_setup clocks into ARTTIM reg,
* and then the active/recovery counts into the DRWTIM reg
@@ -589,7 +583,7 @@ static void program_drive_counts (unsigned int index)
setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f;
put_cmd640_reg(arttim_regs[index], setup_count);
put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
- restore_flags(flags);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
}
/*
@@ -647,7 +641,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
/*
* Drive PIO mode selection:
*/
-static void cmd640_tune_drive(struct ata_device *drive, byte mode_wanted)
+static void cmd640_tune_drive(struct ata_device *drive, u8 mode_wanted)
{
u8 b;
struct ata_timing *t;
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 188aeac9074c..0d6c087b361f 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -18,13 +18,13 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define CMD_DEBUG 0
@@ -81,8 +81,8 @@
* Registers and masks for easy access by drive index:
*/
#if 0
-static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
-static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
+static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
+static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
#endif
/*
@@ -93,15 +93,15 @@ static void program_drive_counts(struct ata_device *drive, int setup_count, int
{
unsigned long flags;
struct ata_device *drives = drive->channel->drives;
- byte temp_b;
- static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
- static const byte recovery_counts[] =
+ u8 temp_b;
+ static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+ static const u8 recovery_counts[] =
{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
- static const byte arttim_regs[2][2] = {
+ static const u8 arttim_regs[2][2] = {
{ ARTTIM0, ARTTIM1 },
{ ARTTIM23, ARTTIM23 }
};
- static const byte drwtim_regs[2][2] = {
+ static const u8 drwtim_regs[2][2] = {
{ DRWTIM0, DRWTIM1 },
{ DRWTIM2, DRWTIM3 }
};
@@ -142,11 +142,11 @@ static void program_drive_counts(struct ata_device *drive, int setup_count, int
*/
(void) pci_read_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], &temp_b);
(void) pci_write_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave],
- ((byte) setup_count) | (temp_b & 0x3f));
+ ((u8) setup_count) | (temp_b & 0x3f));
(void) pci_write_config_byte(drive->channel->pci_dev, drwtim_regs[channel][slave],
- (byte) ((active_count << 4) | recovery_count));
- cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
- cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
+ (u8) ((active_count << 4) | recovery_count));
+ cmdprintk ("Write %x to %x\n", ((u8) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
+ cmdprintk ("Write %x to %x\n", (u8) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
local_irq_restore(flags);
}
@@ -405,7 +405,7 @@ static int cmd64x_tune_chipset(struct ata_device *drive, u8 speed)
return ide_config_drive_speed(drive, speed);
}
-static int cmd680_tune_chipset(struct ata_device *drive, byte speed)
+static int cmd680_tune_chipset(struct ata_device *drive, u8 speed)
{
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
@@ -520,9 +520,9 @@ static int cmd64x_udma_stop(struct ata_device *drive)
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
if (jack_slap) {
- byte dma_intr = 0;
- byte dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
- byte dma_reg = (ch->unit) ? ARTTIM2 : CFR;
+ u8 dma_intr = 0;
+ u8 dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+ u8 dma_reg = (ch->unit) ? ARTTIM2 : CFR;
(void) pci_read_config_byte(dev, dma_reg, &dma_intr);
/*
* DAMN BMIDE is not connected to PCI space!
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index b761e7896385..89ee79cfcda3 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -20,22 +20,22 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
/*
* Set a new transfer mode at the drive
*/
-int cs5530_set_xfer_mode(struct ata_device *drive, byte mode)
+int cs5530_set_xfer_mode(struct ata_device *drive, u8 mode)
{
int error = 0;
@@ -67,7 +67,7 @@ static unsigned int cs5530_pio_timings[2][5] =
* The ide_init_cs5530() routine guarantees that all drives
* will have valid default PIO timings set up before we get here.
*/
-static void cs5530_tuneproc(struct ata_device *drive, byte pio) /* pio=255 means "autotune" */
+static void cs5530_tuneproc(struct ata_device *drive, u8 pio)
{
struct ata_channel *hwif = drive->channel;
unsigned int format, basereg = CS5530_BASEREG(hwif);
@@ -75,7 +75,7 @@ static void cs5530_tuneproc(struct ata_device *drive, byte pio) /* pio=255 means
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- pio = XFER_PIO_0 + min_t(byte, pio, 4);
+ pio = XFER_PIO_0 + min_t(u8, pio, 4);
if (!cs5530_set_xfer_mode(drive, pio)) {
format = (inl(basereg+4) >> 31) & 1;
@@ -206,7 +206,7 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
unsigned short pcicmd = 0;
unsigned long flags;
- pci_for_each_dev (dev) {
+ pci_for_each_dev(dev) {
if (dev->vendor == PCI_VENDOR_ID_CYRIX) {
switch (dev->device) {
case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
@@ -256,7 +256,7 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
*/
pci_write_config_byte(master_0, 0x40, 0x1e);
- /*
+ /*
* Set max PCI burst size (16-bytes seems to work best):
* 16bytes: set bit-1 at 0x41 (reg value of 0x16)
* all others: clear bit-1 at 0x41, and do:
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index 297b55d18ce2..acf889aad4dd 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -47,11 +47,12 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
/* the current version */
@@ -141,7 +142,7 @@ static u8 calc_clk(int time, int bus_speed)
* for mode 3 and 4 drives 8 and 16-bit timings are the same
*
*/
-/* FIXME: use generic ata-timings library --bkz */
+/* FIXME: use generic timings library --bkz */
static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
{
struct ata_timing *t;
@@ -186,8 +187,8 @@ static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
*/
static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single)
{
- byte index;
- byte data;
+ u8 index;
+ u8 data;
if (mode>2) /* make sure we set a valid mode */
mode = 2;
@@ -206,7 +207,7 @@ static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single)
printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, (data&0x3), ((data>>2)&1));
#endif
- data = (byte)mode|(byte)(single<<2);
+ data = (u8) mode | (u8) (single << 2);
OUT_BYTE(index, CY82_INDEX_PORT);
OUT_BYTE(data, CY82_DATA_PORT);
@@ -271,7 +272,7 @@ static int cy82c693_udma_setup(struct ata_device *drive, int map)
/*
* tune ide drive - set PIO mode
*/
-static void cy82c693_tune_drive(struct ata_device *drive, byte pio)
+static void cy82c693_tune_drive(struct ata_device *drive, u8 pio)
{
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 45cd4d9c7f81..8d947231d2ab 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -9,13 +9,13 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/init.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
/*
* Changing this #undef to #define may solve start up problems in some systems.
@@ -66,7 +66,7 @@ static void sub22 (char b, char c)
}
}
-static void tune_dtc2278(struct ata_device *drive, byte pio)
+static void tune_dtc2278(struct ata_device *drive, u8 pio)
{
unsigned long flags;
diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c
index 9f5d08d42f2c..8fb181800602 100644
--- a/drivers/ide/hpt34x.c
+++ b/drivers/ide/hpt34x.c
@@ -21,16 +21,16 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define HPT343_DEBUG_DRIVE_INFO 0
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index a24e170bee2e..c2204b5b7ef4 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -53,18 +53,17 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
diff --git a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c
index 43b45c6e06eb..d4742834b864 100644
--- a/drivers/ide/hptraid.c
+++ b/drivers/ide/hptraid.c
@@ -105,10 +105,10 @@ static int hptraid_ioctl(struct inode *inode, struct file *file,
if (!loc)
return -EINVAL;
val = 255;
- if (put_user(val, (byte *) & loc->heads))
+ if (put_user(val, (u8 *) & loc->heads))
return -EFAULT;
val = 63;
- if (put_user(val, (byte *) & loc->sectors))
+ if (put_user(val, (u8 *) & loc->sectors))
return -EFAULT;
bios_cyl = raid[minor].sectors / 63 / 255;
if (put_user
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 55f39b8c506e..34207cd5d911 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -38,13 +38,13 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/init.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
/* #define DEBUG */ /* remove comments for DEBUG messages */
@@ -61,7 +61,7 @@
* bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?)
*/
#define HT_CONFIG_PORT 0x3e6
-#define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8)
+#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
/*
* FIFO + PREFETCH (both a/b-model)
*/
@@ -107,7 +107,7 @@
* Active Time for each drive. Smaller value gives higher speed.
* In case of failures you should probably fall back to a higher value.
*/
-#define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff)
+#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
#define HT_TIMING_DEFAULT 0xff
/*
@@ -194,7 +194,7 @@ static int __init try_to_init_ht6560b(void)
return 1;
}
-static byte ht_pio2timings(struct ata_device *drive, byte pio)
+static u8 ht_pio2timings(struct ata_device *drive, u8 pio)
{
int active_time, recovery_time;
int active_cycles, recovery_cycles;
@@ -204,7 +204,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio)
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- pio = XFER_PIO_0 + min_t(byte, pio, 4);
+ pio = XFER_PIO_0 + min_t(u8, pio, 4);
t = ata_timing_data(pio);
@@ -233,7 +233,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio)
drive->name, pio - XFER_PIO_0, recovery_cycles, recovery_time, active_cycles, active_time);
#endif
- return (byte)((recovery_cycles << 4) | active_cycles);
+ return (u8)((recovery_cycles << 4) | active_cycles);
} else {
#ifdef DEBUG
@@ -247,7 +247,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio)
/*
* Enable/Disable so called prefetch mode
*/
-static void ht_set_prefetch(struct ata_device *drive, byte state)
+static void ht_set_prefetch(struct ata_device *drive, u8 state)
{
unsigned long flags;
int t = HT_PREFETCH_MODE << 8;
@@ -274,10 +274,10 @@ static void ht_set_prefetch(struct ata_device *drive, byte state)
#endif
}
-static void tune_ht6560b(struct ata_device *drive, byte pio)
+static void tune_ht6560b(struct ata_device *drive, u8 pio)
{
unsigned long flags;
- byte timing;
+ u8 timing;
switch (pio) {
case 8: /* set prefetch off */
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index cd2af4ca8faa..a93846b806a6 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -377,7 +377,7 @@ icside_config_if(struct ata_device *drive, int xfer_mode)
return on;
}
-static int icside_set_speed(struct ata_device *drive, byte speed)
+static int icside_set_speed(struct ata_device *drive, u8 speed)
{
return icside_config_if(drive, speed);
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 166971c7307d..1e4dbbebcec7 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1716,7 +1716,7 @@ void msf_from_bcd (struct atapi_msf *msf)
static inline
-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
+void lba_to_msf(int lba, u8 *m, u8 *s, u8 *f)
{
lba += CD_MSF_OFFSET;
lba &= 0xffffff; /* negative lbas use only 24 bits */
@@ -1728,7 +1728,7 @@ void lba_to_msf (int lba, byte *m, byte *s, byte *f)
static inline
-int msf_to_lba (byte m, byte s, byte f)
+int msf_to_lba(u8 m, u8 s, u8 f)
{
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index dcd660ce6ce1..7f4ac20a5b5a 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -80,7 +80,7 @@ struct ide_cd_config_flags {
__u8 close_tray : 1; /* can close the tray */
__u8 writing : 1; /* pseudo write in progress */
__u8 reserved : 3;
- byte max_speed; /* Max speed of the drive */
+ u8 max_speed; /* Max speed of the drive */
};
#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
@@ -92,7 +92,7 @@ struct ide_cd_state_flags {
__u8 door_locked : 1; /* We think that the drive door is locked. */
__u8 writing : 1; /* the drive is currently writing */
__u8 reserved : 4;
- byte current_speed; /* Current speed of the drive */
+ u8 current_speed; /* Current speed of the drive */
};
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
@@ -132,7 +132,7 @@ struct atapi_toc_header {
} __attribute__((packed));
struct atapi_toc_entry {
- byte reserved1;
+ u8 reserved1;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 adr : 4;
__u8 control : 4;
@@ -142,8 +142,8 @@ struct atapi_toc_entry {
#else
#error "Please fix <asm/byteorder.h>"
#endif
- byte track;
- byte reserved2;
+ u8 track;
+ u8 reserved2;
union {
unsigned lba;
struct atapi_msf msf;
@@ -176,8 +176,8 @@ struct atapi_cdrom_subchnl {
#else
#error "Please fix <asm/byteorder.h>"
#endif
- u_char acdsc_trk;
- u_char acdsc_ind;
+ u8 acdsc_trk;
+ u8 acdsc_ind;
union {
struct atapi_msf msf;
int lba;
@@ -207,7 +207,7 @@ struct atapi_capabilities_page {
#error "Please fix <asm/byteorder.h>"
#endif
- byte page_length;
+ u8 page_length;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 reserved2 : 2;
@@ -435,8 +435,8 @@ struct atapi_mechstat_header {
#error "Please fix <asm/byteorder.h>"
#endif
- byte curlba[3];
- byte nslots;
+ u8 curlba[3];
+ u8 nslots;
__u16 slot_tablelen;
};
@@ -454,7 +454,7 @@ struct atapi_slot {
#error "Please fix <asm/byteorder.h>"
#endif
- byte reserved2[3];
+ u8 reserved2[3];
};
struct atapi_changer_info {
@@ -514,13 +514,11 @@ struct cdrom_info {
#define ABORTED_COMMAND 0x0b
#define MISCOMPARE 0x0e
-
-
/* This stuff should be in cdrom.h, since it is now generic... */
#if VERBOSE_IDE_CD_ERRORS
/* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
const struct {
unsigned short packet_command;
const char * const text;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index cd3fd43b4b23..4070de3d2832 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -24,8 +24,9 @@
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index a05c8b00c9ce..e346d1d12b58 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -245,8 +245,8 @@ typedef struct {
/*
* Last error information
*/
- byte sense_key, asc, ascq;
- byte ticks; /* delay this long before sending packet command */
+ u8 sense_key, asc, ascq;
+ u8 ticks; /* delay this long before sending packet command */
int progress_indication;
/*
diff --git a/drivers/ide/ide-m8xx.c b/drivers/ide/ide-m8xx.c
index a04398c9e12c..c842699af329 100644
--- a/drivers/ide/ide-m8xx.c
+++ b/drivers/ide/ide-m8xx.c
@@ -29,8 +29,9 @@
#include <linux/init.h>
#include <linux/blk.h>
#include <linux/ioport.h>
-#include <linux/ide.h>
#include <linux/bootmem.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/mpc8xx.h>
#include <asm/mmu.h>
@@ -43,7 +44,7 @@
#include <asm/machdep.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
static int identify (volatile unsigned char *p);
static void print_fixed (volatile unsigned char *p);
@@ -51,7 +52,7 @@ static void print_funcid (int func);
static int check_ide_device (unsigned long base);
static int ide_interrupt_ack(struct ata_channel *);
-static void m8xx_ide_tuneproc(struct ata_device *drive, byte pio);
+static void m8xx_ide_tuneproc(struct ata_device *drive, u8 pio);
typedef struct ide_ioport_desc {
unsigned long base_off; /* Offset to PCMCIA memory */
@@ -437,7 +438,7 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
/* Calculate PIO timings */
static void
-m8xx_ide_tuneproc(struct ata_device *drive, byte pio)
+m8xx_ide_tuneproc(struct ata_device *drive, u8 pio)
{
#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
volatile pcmconf8xx_t *pcmp;
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index e9076cb4869c..a9173ffad2dd 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
@@ -30,7 +31,7 @@
/*
* This is the list of registered PCI chipset driver data structures.
*/
-static struct ata_pci_device *ata_pci_device_list = NULL;
+static struct ata_pci_device *ata_pci_device_list; /* = NULL */
/*
* This function supplies the data necessary to detect the particular chipset.
diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c
index 5a52c4fa4169..4630dbc4fe5d 100644
--- a/drivers/ide/ide-pmac.c
+++ b/drivers/ide/ide-pmac.c
@@ -34,8 +34,9 @@
#include <linux/jiffies.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/prom.h>
#include <asm/io.h>
@@ -51,7 +52,7 @@
#include <linux/adb.h>
#include <linux/pmu.h>
#endif
-#include "ata-timing.h"
+#include "timing.h"
#undef IDE_PMAC_DEBUG
@@ -262,8 +263,8 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq);
static int pmac_udma_irq_status(struct ata_device *drive);
static int pmac_udma_setup(struct ata_device *drive, int map);
static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr);
-static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed);
-static void pmac_ide_tuneproc(struct ata_device *drive, byte pio);
+static int pmac_ide_tune_chipset(struct ata_device *drive, u8 speed);
+static void pmac_ide_tuneproc(struct ata_device *drive, u8 pio);
static void pmac_ide_selectproc(struct ata_device *drive);
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -457,7 +458,7 @@ out:
/* Calculate PIO timings */
static void __pmac
-pmac_ide_tuneproc(struct ata_device *drive, byte pio)
+pmac_ide_tuneproc(struct ata_device *drive, u8 pio)
{
struct ata_timing *t;
int i;
@@ -472,7 +473,7 @@ pmac_ide_tuneproc(struct ata_device *drive, byte pio)
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- pio = XFER_PIO_0 + min_t(byte, pio, 4);
+ pio = XFER_PIO_0 + min_t(u8, pio, 4);
t = ata_timing_data(pio);
@@ -523,8 +524,7 @@ pmac_ide_tuneproc(struct ata_device *drive, byte pio)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-static int __pmac
-set_timings_udma(u32 *timings, byte speed)
+static int __pmac set_timings_udma(u32 *timings, u8 speed)
{
unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
@@ -546,7 +546,7 @@ set_timings_udma(u32 *timings, byte speed)
}
static int __pmac
-set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
+set_timings_mdma(int intf_type, u32 *timings, u8 speed, int drive_cycle_time)
{
int cycleTime, accessTime, recTime;
unsigned accessTicks, recTicks;
@@ -659,7 +659,7 @@ set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
* our, normal mdma function is supposed to be more precise
*/
static int __pmac
-pmac_ide_tune_chipset (struct ata_device *drive, byte speed)
+pmac_ide_tune_chipset (struct ata_device *drive, u8 speed)
{
int intf = pmac_ide_find(drive);
int unit = (drive->select.b.unit & 0x01);
@@ -1211,8 +1211,8 @@ udma_bits_to_command(unsigned char bits, int high_speed)
static int __pmac
pmac_ide_mdma_enable(struct ata_device *drive, int idx)
{
- byte bits = drive->id->dma_mword & 0x07;
- byte feature = dma_bits_to_command(bits);
+ u8 bits = drive->id->dma_mword & 0x07;
+ u8 feature = dma_bits_to_command(bits);
u32 *timings;
int drive_cycle_time;
struct hd_driveid *id = drive->id;
@@ -1249,8 +1249,8 @@ pmac_ide_mdma_enable(struct ata_device *drive, int idx)
static int __pmac
pmac_ide_udma_enable(struct ata_device *drive, int idx, int high_speed)
{
- byte bits = drive->id->dma_ultra & 0x1f;
- byte feature = udma_bits_to_command(bits, high_speed);
+ u8 bits = drive->id->dma_ultra & 0x1f;
+ u8 feature = udma_bits_to_command(bits, high_speed);
u32 *timings;
int ret;
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 2c1fe77c4cb2..4dc463ba33fa 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -827,7 +827,7 @@ typedef struct {
/*
* Read position information
*/
- byte partition;
+ u8 partition;
unsigned int first_frame_position; /* Current block */
unsigned int last_frame_position;
unsigned int blocks_in_buffer;
@@ -835,7 +835,7 @@ typedef struct {
/*
* Last error information
*/
- byte sense_key, asc, ascq;
+ u8 sense_key, asc, ascq;
/*
* Character device operation
@@ -1237,7 +1237,7 @@ static int idetape_chrdev_present = 0;
* DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI
*/
-char *idetape_sense_key_verbose (byte idetape_sense_key)
+char *idetape_sense_key_verbose(u8 idetape_sense_key)
{
switch (idetape_sense_key) {
default: {
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 230bad45d91d..0c9d9a41b390 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -49,12 +49,13 @@
#endif
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
#include <linux/device.h>
#include <linux/kmod.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -62,7 +63,7 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#include "ioctl.h"
@@ -258,7 +259,7 @@ static struct ata_bit_messages ata_error_msgs[] = {
{ MARK_ERR, MARK_ERR, "addr mark not found" }
};
-static void dump_bits(struct ata_bit_messages *msgs, int nr, byte bits)
+static void dump_bits(struct ata_bit_messages *msgs, int nr, u8 bits)
{
int i;
int first = 1;
@@ -516,49 +517,21 @@ void ide_stall_queue(struct ata_device *drive, unsigned long timeout)
* Issue a new request.
* Caller must have already done spin_lock_irqsave(channel->lock, ...)
*/
-static void do_request(struct ata_channel *channel)
+void do_ide_request(request_queue_t *q)
{
- struct ata_channel *ch;
- struct ata_device *drive = NULL;
- unsigned int unit;
- ide_startstop_t ret;
+ struct ata_channel *channel = q->queuedata;
- local_irq_disable(); /* necessary paranoia */
-
- /*
- * Select the next device which will be serviced. This selects
- * only between devices on the same channel, since everything
- * else will be scheduled on the queue level.
- */
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- struct ata_device *tmp = &channel->drives[unit];
-
- if (!tmp->present)
- continue;
-
- /* There are no requests pending for this device.
- */
- if (blk_queue_empty(&tmp->queue))
- continue;
-
-
- /* This device still wants to remain idle.
- */
- if (tmp->sleep && time_after(tmp->sleep, jiffies))
- continue;
+ while (!test_and_set_bit(IDE_BUSY, channel->active)) {
+ struct ata_channel *ch;
+ struct ata_device *drive = NULL;
+ unsigned int unit;
+ ide_startstop_t ret;
- /* Take this device, if there is no device choosen thus
- * far or which is more urgent.
+ /*
+ * Select the next device which will be serviced. This selects
+ * only between devices on the same channel, since everything
+ * else will be scheduled on the queue level.
*/
- if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
- if (!blk_queue_plugged(&tmp->queue))
- drive = tmp;
- }
- }
-
- if (!drive) {
- unsigned long sleep = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *tmp = &channel->drives[unit];
@@ -566,208 +539,229 @@ static void do_request(struct ata_channel *channel)
if (!tmp->present)
continue;
- /* This device is sleeping and waiting to be serviced
- * earlier than any other device we checked thus far.
- */
- if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
- sleep = tmp->sleep;
- }
-
- if (sleep) {
- /*
- * Take a short snooze, and then wake up again. Just
- * in case there are big differences in relative
- * throughputs.. don't want to hog the cpu too much.
+ /* There are no requests pending for this device.
*/
+ if (blk_queue_empty(&tmp->queue))
+ continue;
- if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
- sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
- if (timer_pending(&channel->timer))
- printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
-#endif
- set_bit(IDE_SLEEP, channel->active);
- mod_timer(&channel->timer, sleep);
- /*
- * We purposely leave us busy while sleeping becouse we
- * are prepared to handle the IRQ from it.
- *
- * FIXME: Make sure sleeping can't interferre with
- * operations of other devices on the same channel.
- */
- } else {
- /* FIXME: use queue plugging instead of active to block
- * upper layers from stomping on us */
- /* Ugly, but how can we sleep for the lock otherwise?
- * */
-
- ide_release_lock(&ide_irq_lock);/* for atari only */
- clear_bit(IDE_BUSY, channel->active);
-
- /* All requests are done.
- *
- * Disable IRQs from the last drive on this channel, to
- * make sure that it wan't throw stones at us when we
- * are not prepared to take them.
+ /* This device still wants to remain idle.
*/
+ if (tmp->sleep && time_after(tmp->sleep, jiffies))
+ continue;
- if (channel->drive && !channel->drive->using_tcq)
- ata_irq_enable(channel->drive, 0);
+ /* Take this device, if there is no device choosen thus
+ * far or which is more urgent.
+ */
+ if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
+ if (!blk_queue_plugged(&tmp->queue))
+ drive = tmp;
+ }
}
- return;
- }
+ if (!drive) {
+ unsigned long sleep = 0;
- /* Remember the last drive we where acting on.
- */
- ch = drive->channel;
- ch->drive = drive;
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ struct ata_device *tmp = &channel->drives[unit];
- /* Feed commands to a drive until it barfs.
- */
- do {
- struct request *rq = NULL;
- sector_t block;
-
- /* Abort early if we can't queue another command. for non tcq,
- * ata_can_queue is always 1 since we never get here unless the
- * drive is idle.
- */
+ if (!tmp->present)
+ continue;
- if (!ata_can_queue(drive)) {
- if (!ata_pending_commands(drive)) {
- clear_bit(IDE_BUSY, ch->active);
- if (drive->using_tcq)
- ata_irq_enable(drive, 0);
+ /* This device is sleeping and waiting to be serviced
+ * earlier than any other device we checked thus far.
+ */
+ if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
+ sleep = tmp->sleep;
}
- break;
- }
- drive->sleep = 0;
+ if (sleep) {
+ /*
+ * Take a short snooze, and then wake up again. Just
+ * in case there are big differences in relative
+ * throughputs.. don't want to hog the cpu too much.
+ */
+
+ if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
+ sleep = jiffies + WAIT_MIN_SLEEP;
+#if 1
+ if (timer_pending(&channel->timer))
+ printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
+#endif
+ set_bit(IDE_SLEEP, channel->active);
+ mod_timer(&channel->timer, sleep);
+
+ /*
+ * We purposely leave us busy while sleeping becouse we
+ * are prepared to handle the IRQ from it.
+ *
+ * FIXME: Make sure sleeping can't interferre with
+ * operations of other devices on the same channel.
+ */
+ } else {
+ /* FIXME: use queue plugging instead of active to block
+ * upper layers from stomping on us */
+ /* Ugly, but how can we sleep for the lock otherwise?
+ * */
+
+ ide_release_lock(&ide_irq_lock);/* for atari only */
+ clear_bit(IDE_BUSY, channel->active);
+
+ /* All requests are done.
+ *
+ * Disable IRQs from the last drive on this channel, to
+ * make sure that it wan't throw stones at us when we
+ * are not prepared to take them.
+ */
+
+ if (channel->drive && !channel->drive->using_tcq)
+ ata_irq_enable(channel->drive, 0);
+ }
- if (test_bit(IDE_DMA, ch->active)) {
- printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
- break;
+ return;
}
- /* There's a small window between where the queue could be
- * replugged while we are in here when using tcq (in which case
- * the queue is probably empty anyways...), so check and leave
- * if appropriate. When not using tcq, this is still a severe
- * BUG!
+ /* Remember the last drive we where acting on.
*/
+ ch = drive->channel;
+ ch->drive = drive;
- if (blk_queue_plugged(&drive->queue)) {
- BUG_ON(!drive->using_tcq);
- break;
- }
+ /* Feed commands to a drive until it barfs.
+ */
+ do {
+ struct request *rq = NULL;
+ sector_t block;
+
+ /* Abort early if we can't queue another command. for non tcq,
+ * ata_can_queue is always 1 since we never get here unless the
+ * drive is idle.
+ */
- if (!(rq = elv_next_request(&drive->queue))) {
- if (!ata_pending_commands(drive)) {
- clear_bit(IDE_BUSY, ch->active);
- if (drive->using_tcq)
- ata_irq_enable(drive, 0);
+ if (!ata_can_queue(drive)) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
+ }
+ break;
}
- drive->rq = NULL;
- break;
- }
+ drive->sleep = 0;
- /* If there are queued commands, we can't start a
- * non-fs request (really, a non-queuable command)
- * until the queue is empty.
- */
- if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
- break;
+ if (test_bit(IDE_DMA, ch->active)) {
+ printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
+ break;
+ }
- drive->rq = rq;
+ /* There's a small window between where the queue could be
+ * replugged while we are in here when using tcq (in which case
+ * the queue is probably empty anyways...), so check and leave
+ * if appropriate. When not using tcq, this is still a severe
+ * BUG!
+ */
- spin_unlock(ch->lock);
- /* allow other IRQs while we start this request */
- local_irq_enable();
+ if (blk_queue_plugged(&drive->queue)) {
+ BUG_ON(!drive->using_tcq);
+ break;
+ }
- /*
- * This initiates handling of a new I/O request.
- */
+ if (!(rq = elv_next_request(&drive->queue))) {
+ if (!ata_pending_commands(drive)) {
+ clear_bit(IDE_BUSY, ch->active);
+ if (drive->using_tcq)
+ ata_irq_enable(drive, 0);
+ }
+ drive->rq = NULL;
+
+ break;
+ }
+
+ /* If there are queued commands, we can't start a
+ * non-fs request (really, a non-queuable command)
+ * until the queue is empty.
+ */
+ if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
+ break;
+
+ drive->rq = rq;
+
+ spin_unlock(ch->lock);
+ /* allow other IRQs while we start this request */
+ local_irq_enable();
+
+ /*
+ * This initiates handling of a new I/O request.
+ */
- BUG_ON(!(rq->flags & REQ_STARTED));
+ BUG_ON(!(rq->flags & REQ_STARTED));
#ifdef DEBUG
- printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
+ printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
#endif
- /* bail early if we've exceeded max_failures */
- if (drive->max_failures && (drive->failures > drive->max_failures))
- goto kill_rq;
+ /* bail early if we've exceeded max_failures */
+ if (drive->max_failures && (drive->failures > drive->max_failures))
+ goto kill_rq;
- block = rq->sector;
+ block = rq->sector;
- /* Strange disk manager remap.
- */
- if (rq->flags & REQ_CMD)
- if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
- block += drive->sect0;
+ /* Strange disk manager remap.
+ */
+ if (rq->flags & REQ_CMD)
+ if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
+ block += drive->sect0;
- /* Yecch - this will shift the entire interval, possibly killing some
- * innocent following sector.
- */
- if (block == 0 && drive->remap_0_to_1 == 1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
+ /* Yecch - this will shift the entire interval, possibly killing some
+ * innocent following sector.
+ */
+ if (block == 0 && drive->remap_0_to_1 == 1)
+ block = 1; /* redirect MBR access to EZ-Drive partn table */
- ata_select(drive, 0);
- ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
- WAIT_READY, rq);
+ ata_select(drive, 0);
+ ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
+ WAIT_READY, rq);
- if (ret != ATA_OP_READY) {
- printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
+ if (ret != ATA_OP_READY) {
+ printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
- goto kill_rq;
- }
+ goto kill_rq;
+ }
- if (!ata_ops(drive)) {
- printk(KERN_WARNING "%s: device type %d not supported\n",
- drive->name, drive->type);
- goto kill_rq;
- }
+ if (!ata_ops(drive)) {
+ printk(KERN_WARNING "%s: device type %d not supported\n",
+ drive->name, drive->type);
+ goto kill_rq;
+ }
- /* The normal way of execution is to pass and execute the request
- * handler down to the device type driver.
- */
+ /* The normal way of execution is to pass and execute the request
+ * handler down to the device type driver.
+ */
- if (ata_ops(drive)->do_request) {
- ret = ata_ops(drive)->do_request(drive, rq, block);
- } else {
+ if (ata_ops(drive)->do_request) {
+ ret = ata_ops(drive)->do_request(drive, rq, block);
+ } else {
kill_rq:
- if (ata_ops(drive) && ata_ops(drive)->end_request)
- ata_ops(drive)->end_request(drive, rq, 0);
- else
- ata_end_request(drive, rq, 0, 0);
- ret = ATA_OP_FINISHED;
+ if (ata_ops(drive) && ata_ops(drive)->end_request)
+ ata_ops(drive)->end_request(drive, rq, 0);
+ else
+ ata_end_request(drive, rq, 0, 0);
+ ret = ATA_OP_FINISHED;
- }
- spin_lock_irq(ch->lock);
-
- /* continue if command started, so we are busy */
- } while (ret != ATA_OP_CONTINUES);
- /* make sure the BUSY bit is set */
- /* FIXME: perhaps there is some place where we miss to set it? */
-// set_bit(IDE_BUSY, ch->active);
-}
-
-void do_ide_request(request_queue_t *q)
-{
- struct ata_channel *ch = q->queuedata;
+ }
+ spin_lock_irq(ch->lock);
- while (!test_and_set_bit(IDE_BUSY, ch->active)) {
- do_request(ch);
+ /* continue if command started, so we are busy */
+ } while (ret != ATA_OP_CONTINUES);
+ /* make sure the BUSY bit is set */
+ /* FIXME: perhaps there is some place where we miss to set it? */
+ // set_bit(IDE_BUSY, ch->active);
}
}
/*
* This is our timeout function for all drive operations. But note that it can
* also be invoked as a result of a "sleep" operation triggered by the
- * mod_timer() call in do_request.
+ * mod_timer() call in do_ide_request.
*
* FIXME: This should take a drive context instead of a channel.
* FIXME: This should not explicitly reenter the request handling engine.
@@ -892,7 +886,8 @@ void ide_timer_expiry(unsigned long data)
if (ret == ATA_OP_FINISHED) {
/* Reenter the request handling engine. */
- do_request(ch);
+ clear_bit(IDE_BUSY, ch->active);
+ do_ide_request(&drive->queue);
}
}
spin_unlock_irqrestore(ch->lock, flags);
@@ -1049,9 +1044,10 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
* another interrupt.
*/
- if (!ch->handler)
- do_request(ch);
- else
+ if (!ch->handler) {
+ clear_bit(IDE_BUSY, ch->active);
+ do_ide_request(&drive->queue);
+ } else
printk("%s: %s: huh? expected NULL handler on exit\n",
drive->name, __FUNCTION__);
}
diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c
index 003b743b4772..d1b5f6f8d4ad 100644
--- a/drivers/ide/ioctl.c
+++ b/drivers/ide/ioctl.c
@@ -26,7 +26,7 @@
#include <linux/delay.h>
#include <linux/cdrom.h>
#include <linux/device.h>
-
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
@@ -230,13 +230,13 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
return -EINVAL;
- if (put_user(drive->bios_head, (byte *) &loc->heads))
+ if (put_user(drive->bios_head, (u8 *) &loc->heads))
return -EFAULT;
- if (put_user(drive->bios_sect, (byte *) &loc->sectors))
+ if (put_user(drive->bios_sect, (u8 *) &loc->sectors))
return -EFAULT;
- if (put_user(bios_cyl, (unsigned short *) &loc->cylinders))
+ if (put_user(bios_cyl, (u16 *) &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
@@ -283,18 +283,18 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
case HDIO_GET_NICE:
- return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
- drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP,
+ return put_user(drive->dsc_overlap | drive->atapi_overlap << 1,
(long *) arg);
case HDIO_SET_NICE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP))))
+ if (arg != (arg & 1))
return -EPERM;
- drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
+ drive->dsc_overlap = arg & 1;
+
/* Only CD-ROM's and tapes support DSC overlap. */
if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) {
drive->dsc_overlap = 0;
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
index 002dc1766fd0..838718764c4f 100644
--- a/drivers/ide/it8172.c
+++ b/drivers/ide/it8172.c
@@ -33,16 +33,15 @@
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/it8172/it8172_int.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
diff --git a/drivers/ide/main.c b/drivers/ide/main.c
index a3e134deef6b..50bc8732e38b 100644
--- a/drivers/ide/main.c
+++ b/drivers/ide/main.c
@@ -35,12 +35,13 @@
#endif
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
#include <linux/device.h>
#include <linux/kmod.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -48,7 +49,7 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#include "ioctl.h"
@@ -1068,7 +1069,6 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
}
drive->revalidate = 1;
- drive->suspend_reset = 0;
return 0;
}
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index 379bde73032d..61f9b75eef67 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -126,7 +126,7 @@ static void __init ide_init_ns87415(struct ata_channel *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
unsigned int ctrl, using_inta;
- byte progif;
+ u8 progif;
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index 6b025f3e93ce..c141def6663d 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -99,7 +99,7 @@
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define OPTI621_MAX_PIO 3
@@ -137,7 +137,7 @@ int reg_base;
/* there are stored pio numbers from other calls of opti621_tune_drive */
-static void compute_pios(struct ata_device *drive, byte pio)
+static void compute_pios(struct ata_device *drive, u8 pio)
/* Store values into drive->drive_data
* second_contr - 0 for primary controller, 1 for secondary
* slave_drive - 0 -> pio is for master, 1 -> pio is for slave
@@ -178,7 +178,7 @@ static int cmpt_clk(int time, int bus_speed)
return ((time*bus_speed+999999)/1000000);
}
-static void write_reg(byte value, int reg)
+static void write_reg(u8 value, int reg)
/* Write value to register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
@@ -192,14 +192,14 @@ static void write_reg(byte value, int reg)
outb(0x83, reg_base+2);
}
-static byte read_reg(int reg)
+static u8 read_reg(int reg)
/* Read value from register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
{
- byte ret;
+ u8 ret;
inw(reg_base+1);
inw(reg_base+1);
outb(3, reg_base+2);
@@ -245,16 +245,16 @@ static void compute_clocks(int pio, pio_clocks_t *clks)
}
/* Main tune procedure, called from tuneproc. */
-static void opti621_tune_drive(struct ata_device *drive, byte pio)
+static void opti621_tune_drive(struct ata_device *drive, u8 pio)
{
/* primary and secondary drives share some registers,
* so we have to program both drives
*/
unsigned long flags;
- byte pio1, pio2;
+ u8 pio1, pio2;
pio_clocks_t first, second;
int ax, drdy;
- byte cycle1, cycle2, misc;
+ u8 cycle1, cycle2, misc;
struct ata_channel *hwif = drive->channel;
/* sets drive->drive_data for both drives */
diff --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c
index a476693a3820..2674e69327dc 100644
--- a/drivers/ide/pcidma.c
+++ b/drivers/ide/pcidma.c
@@ -24,10 +24,11 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/ide.h>
#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
-#include "ata-timing.h"
+#include "timing.h"
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
index 28f888d4a9c4..1d871fdcc1d2 100644
--- a/drivers/ide/pdc202xx.c
+++ b/drivers/ide/pdc202xx.c
@@ -48,16 +48,16 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define PDC202XX_DEBUG_DRIVE_INFO 0
@@ -105,7 +105,7 @@ static struct pdc_bit_messages pdc_reg_C[] = {
/* MC3-MC0 - DMA "C" timing */
};
-static void pdc_dump_bits(struct pdc_bit_messages *msgs, byte bits)
+static void pdc_dump_bits(struct pdc_bit_messages *msgs, u8 bits)
{
int i;
@@ -174,7 +174,7 @@ static int __init pdc202xx_modes_map(struct ata_channel *ch)
return map;
}
-static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed)
+static int pdc202xx_tune_chipset(struct ata_device *drive, u8 speed)
{
struct pci_dev *dev = drive->channel->pci_dev;
u32 drive_conf;
@@ -315,7 +315,7 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed)
OUT_BYTE(value, reg); \
mdelay(delay);
-static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
+static int pdc202xx_new_tune_chipset(struct ata_device *drive, u8 speed)
{
struct ata_channel *hwif = drive->channel;
u32 high_16 = pci_resource_start(hwif->pci_dev, 4);
@@ -453,7 +453,7 @@ static void pdc202xx_tune_drive(struct ata_device *drive, u8 pio)
if (pio == 255)
speed = ata_best_pio_mode(drive);
else
- speed = XFER_PIO_0 + min_t(byte, pio, 4);
+ speed = XFER_PIO_0 + min_t(u8, pio, 4);
pdc202xx_tune_chipset(drive, speed);
}
@@ -695,7 +695,7 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
break;
default:
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
- byte irq = 0, irq2 = 0;
+ u8 irq = 0, irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE,
&irq);
pci_read_config_byte(dev, (PCI_INTERRUPT_LINE) | 0x80, &irq2); /* 0xbc */
diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c
index 323be48b0e30..c08a6914c7ff 100644
--- a/drivers/ide/pdc4030.c
+++ b/drivers/ide/pdc4030.c
@@ -175,10 +175,10 @@ static void promise_selectproc(struct ata_device *drive)
* by command F0. They all have the same success/failure notification -
* 'P' (=0x50) on success, 'p' (=0x70) on failure.
*/
-int pdc4030_cmd(struct ata_device *drive, byte cmd)
+int pdc4030_cmd(struct ata_device *drive, u8 cmd)
{
unsigned long timeout, timer;
- byte status_val;
+ u8 status_val;
promise_selectproc(drive); /* redundant? */
outb(0xF3, IDE_SECTOR_REG);
diff --git a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c
index d1bd67ba7f45..f4b7fc0f82e1 100644
--- a/drivers/ide/pdcraid.c
+++ b/drivers/ide/pdcraid.c
@@ -135,11 +135,11 @@ static int pdcraid_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (put_user
(raid[minor].geom.heads,
- (byte *) & loc->heads))
+ (u8 *) & loc->heads))
return -EFAULT;
if (put_user
(raid[minor].geom.sectors,
- (byte *) & loc->sectors))
+ (u8 *) & loc->sectors))
return -EFAULT;
if (put_user
(bios_cyl, (unsigned short *) &loc->cylinders))
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index a5fb9998bf56..b56759830069 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -45,11 +45,12 @@
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define PIIX_IDETIM0 0x40
@@ -240,7 +241,7 @@ static void piix_tune_drive(struct ata_device *drive, unsigned char pio)
return;
}
- piix_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
+ piix_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5));
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/drivers/ide/probe.c b/drivers/ide/probe.c
index abe93fece6cf..3766b7531c78 100644
--- a/drivers/ide/probe.c
+++ b/drivers/ide/probe.c
@@ -28,9 +28,10 @@
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -302,18 +303,18 @@ void ide_fixstring(char *s, const int bytecount, const int byteswap)
/*
* All hosts that use the 80c ribbon must use this!
*/
-byte eighty_ninty_three(struct ata_device *drive)
+int eighty_ninty_three(struct ata_device *drive)
{
- return ((u8) ((drive->channel->udma_four) &&
+ return ((drive->channel->udma_four) &&
#ifndef CONFIG_IDEDMA_IVB
(drive->id->hw_config & 0x4000) &&
#endif
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
+ (drive->id->hw_config & 0x6000)) ? 1 : 0;
}
/* FIXME: Channel lock should be held.
*/
-int ide_config_drive_speed(struct ata_device *drive, byte speed)
+int ide_config_drive_speed(struct ata_device *drive, u8 speed)
{
struct ata_channel *ch = drive->channel;
int ret;
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index 6fce3b4bf491..633a75950d60 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -29,12 +29,13 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/init.h>
+
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "qd65xx.h"
/*
@@ -85,7 +86,7 @@
static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
-static void qd_write_reg(byte content, byte reg)
+static void qd_write_reg(u8 content, unsigned int reg)
{
unsigned long flags;
@@ -95,10 +96,10 @@ static void qd_write_reg(byte content, byte reg)
restore_flags(flags); /* all CPUs */
}
-byte __init qd_read_reg(byte reg)
+static u8 __init qd_read_reg(unsigned int reg)
{
unsigned long flags;
- byte read;
+ u8 read;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
@@ -115,8 +116,8 @@ byte __init qd_read_reg(byte reg)
static void qd_select(struct ata_device *drive)
{
- byte index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
- (QD_TIMREG(drive) & 0x02);
+ u8 index = (((QD_TIMREG(drive)) & 0x80 ) >> 7) |
+ (QD_TIMREG(drive) & 0x02);
if (timings[index] != QD_TIMING(drive))
qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
@@ -130,9 +131,9 @@ static void qd_select(struct ata_device *drive)
* upper nibble represents recovery time, in count of VLB clocks
*/
-static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time)
+static u8 qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time)
{
- byte active_cycle,recovery_cycle;
+ u8 active_cycle,recovery_cycle;
if (system_bus_speed <= 33333) {
active_cycle = 9 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 9);
@@ -151,12 +152,12 @@ static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int
* idem for qd6580
*/
-static byte qd6580_compute_timing(int active_time, int recovery_time)
+static u8 qd6580_compute_timing(int active_time, int recovery_time)
{
- byte active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17);
- byte recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15);
+ u8 active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17);
+ u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15);
- return((recovery_cycle<<4) | active_cycle);
+ return (recovery_cycle<<4) | active_cycle;
}
/*
@@ -205,7 +206,7 @@ static int qd_timing_ok(struct ata_device drives[])
* records the timing, and enables selectproc as needed
*/
-static void qd_set_timing(struct ata_device *drive, byte timing)
+static void qd_set_timing(struct ata_device *drive, u8 timing)
{
struct ata_channel *hwif = drive->channel;
@@ -224,7 +225,7 @@ static void qd_set_timing(struct ata_device *drive, byte timing)
* qd6500_tune_drive
*/
-static void qd6500_tune_drive(struct ata_device *drive, byte pio)
+static void qd6500_tune_drive(struct ata_device *drive, u8 pio)
{
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
@@ -245,7 +246,7 @@ static void qd6500_tune_drive(struct ata_device *drive, byte pio)
* qd6580_tune_drive
*/
-static void qd6580_tune_drive(struct ata_device *drive, byte pio)
+static void qd6580_tune_drive(struct ata_device *drive, u8 pio)
{
struct ata_timing *t;
int base = drive->channel->select_data;
@@ -257,7 +258,7 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio)
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- pio = XFER_PIO_0 + min_t(byte, pio, 4);
+ pio = XFER_PIO_0 + min_t(u8, pio, 4);
t = ata_timing_data(pio);
@@ -305,8 +306,8 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio)
static int __init qd_testreg(int port)
{
- byte savereg;
- byte readreg;
+ u8 savereg;
+ u8 readreg;
unsigned long flags;
save_flags(flags); /* all CPUs */
@@ -333,7 +334,7 @@ static int __init qd_testreg(int port)
* called to setup an ata channel : adjusts attributes & links for tuning
*/
-void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, byte pio))
+void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, u8 pio))
{
struct ata_channel *hwif = &ide_hwifs[unit];
@@ -354,7 +355,7 @@ void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigne
*/
void __init qd_unsetup(int unit) {
struct ata_channel *hwif = &ide_hwifs[unit];
- byte config = hwif->config_data;
+ u8 config = hwif->config_data;
int base = hwif->select_data;
void *tuneproc = (void *) hwif->tuneproc;
@@ -390,7 +391,7 @@ void __init qd_unsetup(int unit) {
int __init qd_probe(int base)
{
- byte config;
+ u8 config;
int unit;
config = qd_read_reg(QD_CONFIG_PORT);
@@ -417,7 +418,7 @@ int __init qd_probe(int base)
}
if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
- byte control;
+ u8 control;
if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
/* bad registers */
diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h
index 73a7d76bbf6e..e0136907954c 100644
--- a/drivers/ide/qd65xx.h
+++ b/drivers/ide/qd65xx.h
@@ -34,8 +34,8 @@
#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff)
#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8)
-#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff)
-#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8)
+#define QD_TIMING(drive) (u8)(((drive)->drive_data) & 0x00ff)
+#define QD_TIMREG(drive) (u8)((((drive)->drive_data) & 0xff00) >> 8)
#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
diff --git a/drivers/ide/quirks.c b/drivers/ide/quirks.c
index d4cd05578193..740cfe5632fe 100644
--- a/drivers/ide/quirks.c
+++ b/drivers/ide/quirks.c
@@ -24,8 +24,9 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/ide.h>
#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -153,14 +154,14 @@ int check_drive_lists(struct ata_device *drive, int good_bad)
/* Consult the list of known "good" drives */
list = good_dma_drives;
while (*list) {
- if (!strcmp(*list++,id->model))
+ if (!strcmp(*list++, id->model))
return 1;
}
} else {
/* Consult the list of known "bad" drives */
list = bad_dma_drives;
while (*list) {
- if (!strcmp(*list++,id->model)) {
+ if (!strcmp(*list++, id->model)) {
printk("%s: Disabling (U)DMA for %s\n",
drive->name, id->model);
return 1;
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index ff8e39ef3b9f..1aa9c7199d71 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -85,14 +85,14 @@
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#undef SVWKS_DEBUG_DRIVE_INFO
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index fb1a56cd0140..efe3d4a882ad 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -44,13 +44,13 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/ide.h>
#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
/* When DEBUG is defined it outputs initial PCI config register
@@ -84,7 +84,7 @@ static unsigned char chipset_family;
Fewer might be used depending on the actual chipset */
static unsigned char ide_regs_copy[0x58];
-static byte sis5513_max_config_register(void) {
+static u8 sis5513_max_config_register(void) {
switch(chipset_family) {
case ATA_00:
case ATA_16: return 0x4f;
@@ -100,9 +100,9 @@ static byte sis5513_max_config_register(void) {
/* Read config registers, print differences from previous read */
static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) {
int i;
- byte reg_val;
- byte changed=0;
- byte max = sis5513_max_config_register();
+ u8 reg_val;
+ u8 changed = 0;
+ u8 max = sis5513_max_config_register();
printk("SIS5513: %s, changed registers:\n", info);
for(i=0; i<=max; i++) {
@@ -121,9 +121,10 @@ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) {
}
/* Load config registers, no printing */
-static void sis5513_load_registers(struct pci_dev* dev) {
+static void sis5513_load_registers(struct pci_dev* dev)
+{
int i;
- byte max = sis5513_max_config_register();
+ u8 max = sis5513_max_config_register();
for(i=0; i<=max; i++) {
pci_read_config_byte(dev, i, &(ide_regs_copy[i]));
@@ -131,14 +132,15 @@ static void sis5513_load_registers(struct pci_dev* dev) {
}
/* Print a register */
-static void sis5513_print_register(int reg) {
+static void sis5513_print_register(int reg)
+{
printk(" %0#x:%0#x", reg, ide_regs_copy[reg]);
}
/* Print valuable registers */
static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
int i;
- byte max = sis5513_max_config_register();
+ u8 max = sis5513_max_config_register();
sis5513_load_registers(dev);
printk("SIS5513 %s\n", marker);
@@ -193,9 +195,9 @@ static const struct {
/* Cycle time bits and values vary accross chip dma capabilities
These three arrays hold the register layout and the values to set.
Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
-static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
-static byte cycle_time_range[] = {0,0,2,3,3,4,4};
-static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
+static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
+static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
+static u8 cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
{0,0,0,0,0,0}, /* no udma */
{0,0,0,0,0,0}, /* no udma */
{3,2,1,0,0,0},
@@ -317,7 +319,7 @@ static int sis5513_tune_chipset(struct ata_device *drive, u8 speed)
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
- byte drive_pci, reg;
+ u8 drive_pci, reg;
#ifdef DEBUG
sis5513_load_verify_registers(dev, "sis5513_tune_chipset start");
@@ -418,7 +420,7 @@ static unsigned int __init pci_init_sis5513(struct pci_dev *dev)
#endif
if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
- byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
+ u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
}
}
@@ -427,7 +429,7 @@ static unsigned int __init pci_init_sis5513(struct pci_dev *dev)
1/ tell IDE channels to operate in Compabitility mode only
2/ tell old chips to allow per drive IDE timings */
if (host_dev) {
- byte reg;
+ u8 reg;
switch(chipset_family) {
case ATA_133:
case ATA_100:
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 488b0018bb43..d348331d2006 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -19,14 +19,14 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
/*
@@ -82,7 +82,7 @@ static void config_for_pio(struct ata_device *drive, int pio, int report)
if (pio == 255)
xfer_mode = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
- xfer_mode = XFER_PIO_0 + min_t(byte, pio, 4);
+ xfer_mode = XFER_PIO_0 + min_t(u8, pio, 4);
t = ata_timing_data(xfer_mode);
@@ -258,7 +258,7 @@ static void sl82c105_lostirq(struct ata_device *drive)
* We only deal with PIO mode here - DMA mode 'using_dma' is not
* initialised at the point that this function is called.
*/
-static void tune_sl82c105(struct ata_device *drive, byte pio)
+static void tune_sl82c105(struct ata_device *drive, u8 pio)
{
config_for_pio(drive, pio, 1);
@@ -320,7 +320,7 @@ static unsigned int __init sl82c105_init_chipset(struct pci_dev *dev)
static void __init sl82c105_init_dma(struct ata_channel *ch, unsigned long dma_base)
{
unsigned int bridge_rev;
- byte dma_state;
+ u8 dma_state;
dma_state = inb(dma_base + 2);
bridge_rev = sl82c105_bridge_revision(ch->pci_dev);
diff --git a/drivers/ide/tcq.c b/drivers/ide/tcq.c
index 83c63ff13f7d..f6ce02e194e2 100644
--- a/drivers/ide/tcq.c
+++ b/drivers/ide/tcq.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/delay.h>
diff --git a/drivers/ide/ata-timing.h b/drivers/ide/timing.h
index 9f01f07e8329..f413a85723d0 100644
--- a/drivers/ide/ata-timing.h
+++ b/drivers/ide/timing.h
@@ -1,14 +1,7 @@
-#ifndef _ATA_TIMING_H
-#define _ATA_TIMING_H
-
/*
- * $Id: ata-timing.h,v 2.0 2002/03/12 13:02:22 vojtech Exp $
- *
* Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord
* Copyright (C) 1999-2001 Vojtech Pavlik
- */
-
-/*
+ *
* This program is free software; you can redistribute 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
@@ -24,9 +17,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-
#define XFER_PIO_5 0x0d
#define XFER_UDMA_SLOW 0x4f
@@ -91,5 +81,3 @@ extern struct ata_timing* ata_timing_data(short speed);
extern int ata_timing_compute(struct ata_device *drive,
short speed, struct ata_timing *t, int T, int UT);
extern u8 ata_best_pio_mode(struct ata_device *drive);
-
-#endif
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 4e1995b62a47..d37b405e4759 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -251,7 +251,7 @@ static void __init trm290_init_channel(struct ata_channel *hwif)
{
unsigned int cfgbase = 0;
unsigned long flags;
- byte reg;
+ u8 reg;
struct pci_dev *dev = hwif->pci_dev;
hwif->chipset = ide_trm290;
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index fb7f1a6116b9..61c986d226b3 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -46,13 +46,13 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
-#include <linux/init.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
/*
* Default speeds. These can be changed with "auto-tune" and/or hdparm.
@@ -62,11 +62,11 @@
#define UMC_DRIVE2 1 /* 11 = Fastest Speed */
#define UMC_DRIVE3 1 /* In case of crash reduce speed */
-static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
-static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
+static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
+static const u8 pio_to_umc[5] = {0,3,7,10,11}; /* rough guesses */
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
-static const byte speedtab [3][12] = {
+static const u8 speedtab[3][12] = {
{0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
{0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
{0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
@@ -77,13 +77,13 @@ static void out_umc (char port,char wert)
outb_p (wert,0x109);
}
-static inline byte in_umc (char port)
+static inline u8 in_umc (char port)
{
outb_p (port,0x108);
return inb_p (0x109);
}
-static void umc_set_speeds (byte speeds[])
+static void umc_set_speeds(u8 speeds[])
{
int i, tmp;
@@ -106,14 +106,14 @@ static void umc_set_speeds (byte speeds[])
speeds[0], speeds[1], speeds[2], speeds[3]);
}
-static void tune_umc(struct ata_device *drive, byte pio)
+static void tune_umc(struct ata_device *drive, u8 pio)
{
unsigned long flags;
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
else
- pio = min_t(byte, pio, 4);
+ pio = min_t(u8, pio, 4);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]);
save_flags(flags); /* all CPUs */
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 54838f9a8975..45cc8fd3fa80 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -65,11 +65,12 @@
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
-#include "ata-timing.h"
+#include "timing.h"
#include "pcihost.h"
#define VIA_IDE_ENABLE 0x40
@@ -217,7 +218,7 @@ static void via82cxxx_tune_drive(struct ata_device *drive, unsigned char pio)
return;
}
- via_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
+ via_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5));
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 37552f09dd46..2ef1d9a2d4e5 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2058,7 +2058,6 @@ static int __devinit irq_probe_ECP(struct parport *pb)
int i;
unsigned long irqs;
- sti();
irqs = probe_irq_on();
ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
@@ -2093,7 +2092,6 @@ static int __devinit irq_probe_EPP(struct parport *pb)
if (pb->modes & PARPORT_MODE_PCECR)
oecr = inb (ECONTROL (pb));
- sti();
irqs = probe_irq_on();
if (pb->modes & PARPORT_MODE_PCECR)
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 49ab78ba1413..4985f18b9d1f 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -1006,14 +1006,20 @@ int parport_claim_or_block(struct pardevice *dev)
#ifdef PARPORT_DEBUG_SHARING
printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
#endif
- save_flags (flags);
- cli();
+ /*
+ * FIXME!!! Use the proper locking for dev->waiting,
+ * and make this use the "wait_event_interruptible()"
+ * interfaces. The cli/sti that used to be here
+ * did nothing.
+ *
+ * See also parport_release()
+ */
+
/* If dev->waiting is clear now, an interrupt
gave us the port and we would deadlock if we slept. */
if (dev->waiting) {
interruptible_sleep_on (&dev->wait_q);
if (signal_pending (current)) {
- restore_flags (flags);
return -EINTR;
}
r = 1;
@@ -1024,7 +1030,7 @@ int parport_claim_or_block(struct pardevice *dev)
dev->name);
#endif
}
- restore_flags(flags);
+
#ifdef PARPORT_DEBUG_SHARING
if (dev->port->physport->cad != dev)
printk(KERN_DEBUG "%s: exiting parport_claim_or_block "
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 0bbb215e7a8d..9f516d0d204d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -51,53 +51,6 @@
*/
/*
- * Function: __scsi_insert_special()
- *
- * Purpose: worker for scsi_insert_special_*()
- *
- * Arguments: q - request queue where request should be inserted
- * rq - request to be inserted
- * data - private data
- * at_head - insert request at head or tail of queue
- *
- * Lock status: Assumed that queue lock is not held upon entry.
- *
- * Returns: Nothing
- */
-static void __scsi_insert_special(request_queue_t *q, struct request *rq,
- void *data, int at_head)
-{
- unsigned long flags;
-
- ASSERT_LOCK(q->queue_lock, 0);
-
- /*
- * tell I/O scheduler that this isn't a regular read/write (ie it
- * must not attempt merges on this) and that it acts as a soft
- * barrier
- */
- rq->flags &= REQ_QUEUED;
- rq->flags |= REQ_SPECIAL | REQ_BARRIER;
-
- rq->special = data;
-
- /*
- * We have the option of inserting the head or the tail of the queue.
- * Typically we use the tail for new ioctls and so forth. We use the
- * head of the queue for things like a QUEUE_FULL message from a
- * device, or a host that is unable to accept a particular command.
- */
- spin_lock_irqsave(q->queue_lock, flags);
- /* If command is tagged, release the tag */
- if(blk_rq_tagged(rq))
- blk_queue_end_tag(q, rq);
- _elv_add_request(q, rq, !at_head, 0);
- q->request_fn(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
-}
-
-
-/*
* Function: scsi_insert_special_cmd()
*
* Purpose: Insert pre-formed command into request queue.
@@ -121,7 +74,7 @@ int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head)
{
request_queue_t *q = &SCpnt->device->request_queue;
- __scsi_insert_special(q, SCpnt->request, SCpnt, at_head);
+ blk_insert_request(q, SCpnt->request, at_head, SCpnt);
return 0;
}
@@ -149,7 +102,7 @@ int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head)
{
request_queue_t *q = &SRpnt->sr_device->request_queue;
- __scsi_insert_special(q, SRpnt->sr_request, SRpnt, at_head);
+ blk_insert_request(q, SRpnt->sr_request, at_head, SRpnt);
return 0;
}
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 369e6cceb574..cc0b6ef0f1d1 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -344,33 +344,33 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct
}
static struct uart_ops serial21285_ops = {
- tx_empty: serial21285_tx_empty,
- get_mctrl: serial21285_get_mctrl,
- set_mctrl: serial21285_set_mctrl,
- stop_tx: serial21285_stop_tx,
- start_tx: serial21285_start_tx,
- stop_rx: serial21285_stop_rx,
- enable_ms: serial21285_enable_ms,
- break_ctl: serial21285_break_ctl,
- startup: serial21285_startup,
- shutdown: serial21285_shutdown,
- change_speed: serial21285_change_speed,
- type: serial21285_type,
- release_port: serial21285_release_port,
- request_port: serial21285_request_port,
- config_port: serial21285_config_port,
- verify_port: serial21285_verify_port,
+ .tx_empty = serial21285_tx_empty,
+ .get_mctrl = serial21285_get_mctrl,
+ .set_mctrl = serial21285_set_mctrl,
+ .stop_tx = serial21285_stop_tx,
+ .start_tx = serial21285_start_tx,
+ .stop_rx = serial21285_stop_rx,
+ .enable_ms = serial21285_enable_ms,
+ .break_ctl = serial21285_break_ctl,
+ .startup = serial21285_startup,
+ .shutdown = serial21285_shutdown,
+ .change_speed = serial21285_change_speed,
+ .type = serial21285_type,
+ .release_port = serial21285_release_port,
+ .request_port = serial21285_request_port,
+ .config_port = serial21285_config_port,
+ .verify_port = serial21285_verify_port,
};
static struct uart_port serial21285_port = {
- membase: 0,
- mapbase: 0x42000160,
- iotype: SERIAL_IO_MEM,
- irq: NO_IRQ,
- uartclk: 0,
- fifosize: 16,
- ops: &serial21285_ops,
- flags: ASYNC_BOOT_AUTOCONF,
+ .membase = 0,
+ .mapbase = 0x42000160,
+ .iotype = SERIAL_IO_MEM,
+ .irq = NO_IRQ,
+ .uartclk = 0,
+ .fifosize = 16,
+ .ops = &serial21285_ops,
+ .flags = ASYNC_BOOT_AUTOCONF,
};
static void serial21285_setup_ports(void)
@@ -466,23 +466,23 @@ static int __init serial21285_console_setup(struct console *co, char *options)
#ifdef CONFIG_SERIAL_21285_OLD
static struct console serial21285_old_cons =
{
- name: SERIAL_21285_OLD_NAME,
- write: serial21285_console_write,
- device: serial21285_console_device,
- setup: serial21285_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = SERIAL_21285_OLD_NAME,
+ .write = serial21285_console_write,
+ .device = serial21285_console_device,
+ .setup = serial21285_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
#endif
static struct console serial21285_console =
{
- name: SERIAL_21285_NAME,
- write: serial21285_console_write,
- device: serial21285_console_device,
- setup: serial21285_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = SERIAL_21285_NAME,
+ .write = serial21285_console_write,
+ .device = serial21285_console_device,
+ .setup = serial21285_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init rs285_console_init(void)
@@ -497,17 +497,17 @@ void __init rs285_console_init(void)
#endif
static struct uart_driver serial21285_reg = {
- owner: THIS_MODULE,
- driver_name: "ttyFB",
+ .owner = THIS_MODULE,
+ .driver_name = "ttyFB",
#ifdef CONFIG_DEVFS_FS
- dev_name: "ttyFB%d",
+ .dev_name = "ttyFB%d",
#else
- dev_name: "ttyFB",
+ .dev_name = "ttyFB",
#endif
- major: SERIAL_21285_MAJOR,
- minor: SERIAL_21285_MINOR,
- nr: 1,
- cons: SERIAL_21285_CONSOLE,
+ .major = SERIAL_21285_MAJOR,
+ .minor = SERIAL_21285_MINOR,
+ .nr = 1,
+ .cons = SERIAL_21285_CONSOLE,
};
static int __init serial21285_init(void)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 51836215e1c3..141aa7c49718 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1336,7 +1336,7 @@ serial8250_change_speed(struct uart_port *port, unsigned int cflag,
fcr |= UART_FCR7_64BYTE;
up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (iflag & IGNPAR)
+ if (iflag & INPCK)
up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
if (iflag & (BRKINT | PARMRK))
up->port.read_status_mask |= UART_LSR_BI;
@@ -1672,23 +1672,23 @@ serial8250_type(struct uart_port *port)
}
static struct uart_ops serial8250_pops = {
- tx_empty: serial8250_tx_empty,
- set_mctrl: serial8250_set_mctrl,
- get_mctrl: serial8250_get_mctrl,
- stop_tx: serial8250_stop_tx,
- start_tx: serial8250_start_tx,
- stop_rx: serial8250_stop_rx,
- enable_ms: serial8250_enable_ms,
- break_ctl: serial8250_break_ctl,
- startup: serial8250_startup,
- shutdown: serial8250_shutdown,
- change_speed: serial8250_change_speed,
- pm: serial8250_pm,
- type: serial8250_type,
- release_port: serial8250_release_port,
- request_port: serial8250_request_port,
- config_port: serial8250_config_port,
- verify_port: serial8250_verify_port,
+ .tx_empty = serial8250_tx_empty,
+ .set_mctrl = serial8250_set_mctrl,
+ .get_mctrl = serial8250_get_mctrl,
+ .stop_tx = serial8250_stop_tx,
+ .start_tx = serial8250_start_tx,
+ .stop_rx = serial8250_stop_rx,
+ .enable_ms = serial8250_enable_ms,
+ .break_ctl = serial8250_break_ctl,
+ .startup = serial8250_startup,
+ .shutdown = serial8250_shutdown,
+ .change_speed = serial8250_change_speed,
+ .pm = serial8250_pm,
+ .type = serial8250_type,
+ .release_port = serial8250_release_port,
+ .request_port = serial8250_request_port,
+ .config_port = serial8250_config_port,
+ .verify_port = serial8250_verify_port,
};
static struct uart_8250_port serial8250_ports[UART_NR];
@@ -1836,12 +1836,12 @@ static int __init serial8250_console_setup(struct console *co, char *options)
}
static struct console serial8250_console = {
- name: "ttyS",
- write: serial8250_console_write,
- device: serial8250_console_device,
- setup: serial8250_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = "ttyS",
+ .write = serial8250_console_write,
+ .device = serial8250_console_device,
+ .setup = serial8250_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init serial8250_console_init(void)
@@ -1856,17 +1856,17 @@ void __init serial8250_console_init(void)
#endif
static struct uart_driver serial8250_reg = {
- owner: THIS_MODULE,
- driver_name: "serial",
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
#ifdef CONFIG_DEVFS_FS
- dev_name: "tts/%d",
+ .dev_name = "tts/%d",
#else
- dev_name: "ttyS",
+ .dev_name = "ttyS",
#endif
- major: TTY_MAJOR,
- minor: 64,
- nr: UART_NR,
- cons: SERIAL8250_CONSOLE,
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = UART_NR,
+ .cons = SERIAL8250_CONSOLE,
};
/*
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index ef925d32febe..d6dcbcff8680 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1112,10 +1112,10 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = {
#endif
static struct pci_driver serial_pci_driver = {
- name: "serial",
- probe: pci_init_one,
- remove: __devexit_p(pci_remove_one),
- id_table: serial_pci_tbl,
+ .name = "serial",
+ .probe = pci_init_one,
+ .remove = __devexit_p(pci_remove_one),
+ .id_table = serial_pci_tbl,
};
static int __init serial8250_pci_init(void)
diff --git a/drivers/serial/amba.c b/drivers/serial/amba.c
index c5d3157db265..b350a5598663 100644
--- a/drivers/serial/amba.c
+++ b/drivers/serial/amba.c
@@ -557,54 +557,54 @@ static int ambauart_verify_port(struct uart_port *port, struct serial_struct *se
}
static struct uart_ops amba_pops = {
- tx_empty: ambauart_tx_empty,
- set_mctrl: ambauart_set_mctrl,
- get_mctrl: ambauart_get_mctrl,
- stop_tx: ambauart_stop_tx,
- start_tx: ambauart_start_tx,
- stop_rx: ambauart_stop_rx,
- enable_ms: ambauart_enable_ms,
- break_ctl: ambauart_break_ctl,
- startup: ambauart_startup,
- shutdown: ambauart_shutdown,
- change_speed: ambauart_change_speed,
- type: ambauart_type,
- release_port: ambauart_release_port,
- request_port: ambauart_request_port,
- config_port: ambauart_config_port,
- verify_port: ambauart_verify_port,
+ .tx_empty = ambauart_tx_empty,
+ .set_mctrl = ambauart_set_mctrl,
+ .get_mctrl = ambauart_get_mctrl,
+ .stop_tx = ambauart_stop_tx,
+ .start_tx = ambauart_start_tx,
+ .stop_rx = ambauart_stop_rx,
+ .enable_ms = ambauart_enable_ms,
+ .break_ctl = ambauart_break_ctl,
+ .startup = ambauart_startup,
+ .shutdown = ambauart_shutdown,
+ .change_speed = ambauart_change_speed,
+ .type = ambauart_type,
+ .release_port = ambauart_release_port,
+ .request_port = ambauart_request_port,
+ .config_port = ambauart_config_port,
+ .verify_port = ambauart_verify_port,
};
static struct uart_amba_port amba_ports[UART_NR] = {
{
- port: {
- membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
- mapbase: INTEGRATOR_UART0_BASE,
- iotype: SERIAL_IO_MEM,
- irq: IRQ_UARTINT0,
- uartclk: 14745600,
- fifosize: 16,
- ops: &amba_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 0,
+ .port = {
+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ .mapbase = INTEGRATOR_UART0_BASE,
+ .iotype = SERIAL_IO_MEM,
+ .irq = IRQ_UARTINT0,
+ .uartclk = 14745600,
+ .fifosize = 16,
+ .ops = &amba_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
},
- dtr_mask: 1 << 5,
- rts_mask: 1 << 4,
+ .dtr_mask = 1 << 5,
+ .rts_mask = 1 << 4,
},
{
- port: {
- membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
- mapbase: INTEGRATOR_UART1_BASE,
- iotype: SERIAL_IO_MEM,
- irq: IRQ_UARTINT1,
- uartclk: 14745600,
- fifosize: 16,
- ops: &amba_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 1,
+ .port = {
+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
+ .mapbase = INTEGRATOR_UART1_BASE,
+ .iotype = SERIAL_IO_MEM,
+ .irq = IRQ_UARTINT1,
+ .uartclk = 14745600,
+ .fifosize = 16,
+ .ops = &amba_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 1,
},
- dtr_mask: 1 << 7,
- rts_mask: 1 << 6,
+ .dtr_mask = 1 << 7,
+ .rts_mask = 1 << 6,
}
};
@@ -706,12 +706,12 @@ static int __init ambauart_console_setup(struct console *co, char *options)
}
static struct console amba_console = {
- name: "ttyAM",
- write: ambauart_console_write,
- device: ambauart_console_device,
- setup: ambauart_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = "ttyAM",
+ .write = ambauart_console_write,
+ .device = ambauart_console_device,
+ .setup = ambauart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init ambauart_console_init(void)
@@ -725,17 +725,17 @@ void __init ambauart_console_init(void)
#endif
static struct uart_driver amba_reg = {
- owner: THIS_MODULE,
- driver_name: "ttyAM",
+ .owner = THIS_MODULE,
+ .driver_name = "ttyAM",
#ifdef CONFIG_DEVFS_FS
- dev_name: "ttyAM%d",
+ .dev_name = "ttyAM%d",
#else
- dev_name: "ttyAM",
+ .dev_name = "ttyAM",
#endif
- major: SERIAL_AMBA_MAJOR,
- minor: SERIAL_AMBA_MINOR,
- nr: UART_NR,
- cons: AMBA_CONSOLE,
+ .major = SERIAL_AMBA_MAJOR,
+ .minor = SERIAL_AMBA_MINOR,
+ .nr = UART_NR,
+ .cons = AMBA_CONSOLE,
};
static int __init ambauart_init(void)
diff --git a/drivers/serial/anakin.c b/drivers/serial/anakin.c
index f01e383a2624..dcb19b6630c9 100644
--- a/drivers/serial/anakin.c
+++ b/drivers/serial/anakin.c
@@ -322,65 +322,65 @@ static const char *anakin_type(struct port *port)
}
static struct uart_ops anakin_pops = {
- tx_empty: anakin_tx_empty,
- set_mctrl: anakin_set_mctrl,
- get_mctrl: anakin_get_mctrl,
- stop_tx: anakin_stop_tx,
- start_tx: anakin_start_tx,
- stop_rx: anakin_stop_rx,
- enable_ms: anakin_enable_ms,
- break_ctl: anakin_break_ctl,
- startup: anakin_startup,
- shutdown: anakin_shutdown,
- change_speed: anakin_change_speed,
- type: anakin_type,
+ .tx_empty = anakin_tx_empty,
+ .set_mctrl = anakin_set_mctrl,
+ .get_mctrl = anakin_get_mctrl,
+ .stop_tx = anakin_stop_tx,
+ .start_tx = anakin_start_tx,
+ .stop_rx = anakin_stop_rx,
+ .enable_ms = anakin_enable_ms,
+ .break_ctl = anakin_break_ctl,
+ .startup = anakin_startup,
+ .shutdown = anakin_shutdown,
+ .change_speed = anakin_change_speed,
+ .type = anakin_type,
};
static struct uart_port anakin_ports[UART_NR] = {
{
- base: IO_BASE + UART0,
- irq: IRQ_UART0,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 0,
+ .base = IO_BASE + UART0,
+ .irq = IRQ_UART0,
+ .uartclk = 3686400,
+ .fifosize = 0,
+ .ops = &anakin_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
},
{
- base: IO_BASE + UART1,
- irq: IRQ_UART1,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 1,
+ .base = IO_BASE + UART1,
+ .irq = IRQ_UART1,
+ .uartclk = 3686400,
+ .fifosize = 0,
+ .ops = &anakin_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 1,
},
{
- base: IO_BASE + UART2,
- irq: IRQ_UART2,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 2,
+ .base = IO_BASE + UART2,
+ .irq = IRQ_UART2,
+ .uartclk = 3686400,
+ .fifosize = 0,
+ .ops = &anakin_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 2,
},
{
- base: IO_BASE + UART3,
- irq: IRQ_UART3,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 3,
+ .base = IO_BASE + UART3,
+ .irq = IRQ_UART3,
+ .uartclk = 3686400,
+ .fifosize = 0,
+ .ops = &anakin_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 3,
},
{
- base: IO_BASE + UART4,
- irq: IRQ_UART4,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
- flags: ASYNC_BOOT_AUTOCONF,
- line: 4,
+ .base = IO_BASE + UART4,
+ .irq = IRQ_UART4,
+ .uartclk = 3686400,
+ .fifosize = 0,
+ .ops = &anakin_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 4,
},
};
@@ -485,12 +485,12 @@ anakin_console_setup(struct console *co, char *options)
}
static struct console anakin_console = {
- name: SERIAL_ANAKIN_NAME,
- write: anakin_console_write,
- device: anakin_console_device,
- setup: anakin_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = SERIAL_ANAKIN_NAME,
+ .write = anakin_console_write,
+ .device = anakin_console_device,
+ .setup = anakin_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init
@@ -505,12 +505,12 @@ anakin_console_init(void)
#endif
static struct uart_register anakin_reg = {
- driver_name: SERIAL_ANAKIN_NAME,
- dev_name: SERIAL_ANAKIN_NAME,
- major: SERIAL_ANAKIN_MAJOR,
- minor: SERIAL_ANAKIN_MINOR,
- nr: UART_NR,
- cons: ANAKIN_CONSOLE,
+ .driver_name = SERIAL_ANAKIN_NAME,
+ .dev_name = SERIAL_ANAKIN_NAME,
+ .major = SERIAL_ANAKIN_MAJOR,
+ .minor = SERIAL_ANAKIN_MINOR,
+ .nr = UART_NR,
+ .cons = ANAKIN_CONSOLE,
};
static int __init
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index bc79f73a6a16..b67f857fa588 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -418,39 +418,39 @@ static int clps711xuart_request_port(struct uart_port *port)
}
static struct uart_ops clps711x_pops = {
- tx_empty: clps711xuart_tx_empty,
- set_mctrl: clps711xuart_set_mctrl_null,
- get_mctrl: clps711xuart_get_mctrl,
- stop_tx: clps711xuart_stop_tx,
- start_tx: clps711xuart_start_tx,
- stop_rx: clps711xuart_stop_rx,
- enable_ms: clps711xuart_enable_ms,
- break_ctl: clps711xuart_break_ctl,
- startup: clps711xuart_startup,
- shutdown: clps711xuart_shutdown,
- change_speed: clps711xuart_change_speed,
- type: clps711xuart_type,
- config_port: clps711xuart_config_port,
- release_port: clps711xuart_release_port,
- request_port: clps711xuart_request_port,
+ .tx_empty = clps711xuart_tx_empty,
+ .set_mctrl = clps711xuart_set_mctrl_null,
+ .get_mctrl = clps711xuart_get_mctrl,
+ .stop_tx = clps711xuart_stop_tx,
+ .start_tx = clps711xuart_start_tx,
+ .stop_rx = clps711xuart_stop_rx,
+ .enable_ms = clps711xuart_enable_ms,
+ .break_ctl = clps711xuart_break_ctl,
+ .startup = clps711xuart_startup,
+ .shutdown = clps711xuart_shutdown,
+ .change_speed = clps711xuart_change_speed,
+ .type = clps711xuart_type,
+ .config_port = clps711xuart_config_port,
+ .release_port = clps711xuart_release_port,
+ .request_port = clps711xuart_request_port,
};
static struct uart_port clps711x_ports[UART_NR] = {
{
- iobase: SYSCON1,
- irq: IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
- uartclk: 3686400,
- fifosize: 16,
- ops: &clps711x_pops,
- flags: ASYNC_BOOT_AUTOCONF,
+ .iobase = SYSCON1,
+ .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
+ .uartclk = 3686400,
+ .fifosize = 16,
+ .ops = &clps711x_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
},
{
- iobase: SYSCON2,
- irq: IRQ_UTXINT2, /* IRQ_URXINT2 */
- uartclk: 3686400,
- fifosize: 16,
- ops: &clps711x_pops,
- flags: ASYNC_BOOT_AUTOCONF,
+ .iobase = SYSCON2,
+ .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
+ .uartclk = 3686400,
+ .fifosize = 16,
+ .ops = &clps711x_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
}
};
@@ -560,12 +560,12 @@ static int __init clps711xuart_console_setup(struct console *co, char *options)
}
static struct console clps711x_console = {
- name: SERIAL_CLPS711X_NAME,
- write: clps711xuart_console_write,
- device: clps711xuart_console_device,
- setup: clps711xuart_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = SERIAL_CLPS711X_NAME,
+ .write = clps711xuart_console_write,
+ .device = clps711xuart_console_device,
+ .setup = clps711xuart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init clps711xuart_console_init(void)
@@ -579,18 +579,18 @@ void __init clps711xuart_console_init(void)
#endif
static struct uart_driver clps711x_reg = {
- driver_name: "ttyCL",
+ .driver_name = "ttyCL",
#ifdef CONFIG_DEVFS_FS
- dev_name: SERIAL_CLPS711X_NAME,
+ .dev_name = SERIAL_CLPS711X_NAME,
#else
- dev_name: SERIAL_CLPS711X_NAME,
+ .dev_name = SERIAL_CLPS711X_NAME,
#endif
- major: SERIAL_CLPS711X_MAJOR,
- minor: SERIAL_CLPS711X_MINOR,
- nr: UART_NR,
+ .major = SERIAL_CLPS711X_MAJOR,
+ .minor = SERIAL_CLPS711X_MINOR,
+ .nr = UART_NR,
- cons: CLPS711X_CONSOLE,
+ .cons = CLPS711X_CONSOLE,
};
static int __init clps711xuart_init(void)
diff --git a/drivers/serial/core.c b/drivers/serial/core.c
index 026b54b191d6..b5910ea9d868 100644
--- a/drivers/serial/core.c
+++ b/drivers/serial/core.c
@@ -1450,6 +1450,9 @@ uart_block_til_ready(struct file *filp, struct uart_info *info)
if (signal_pending(current))
return -ERESTARTSYS;
+ if (info->tty->flags & (1 << TTY_IO_ERROR))
+ return 0;
+
if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED))
return (port->flags & UPF_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
@@ -2425,7 +2428,7 @@ int uart_register_port(struct uart_driver *drv, struct uart_port *port)
state->port->regshift = port->regshift;
state->port->iotype = port->iotype;
state->port->flags = port->flags;
- state->port->line = drv->state - state;
+ state->port->line = state - drv->state;
__uart_register_port(drv, state, state->port);
@@ -2469,6 +2472,8 @@ EXPORT_SYMBOL(uart_register_driver);
EXPORT_SYMBOL(uart_unregister_driver);
EXPORT_SYMBOL(uart_register_port);
EXPORT_SYMBOL(uart_unregister_port);
+EXPORT_SYMBOL(uart_add_one_port);
+EXPORT_SYMBOL(uart_remove_one_port);
MODULE_DESCRIPTION("Serial driver core");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index b10ad6329dbe..aced0fa1b70b 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -602,22 +602,22 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
}
static struct uart_ops sa1100_pops = {
- tx_empty: sa1100_tx_empty,
- set_mctrl: sa1100_set_mctrl,
- get_mctrl: sa1100_get_mctrl,
- stop_tx: sa1100_stop_tx,
- start_tx: sa1100_start_tx,
- stop_rx: sa1100_stop_rx,
- enable_ms: sa1100_enable_ms,
- break_ctl: sa1100_break_ctl,
- startup: sa1100_startup,
- shutdown: sa1100_shutdown,
- change_speed: sa1100_change_speed,
- type: sa1100_type,
- release_port: sa1100_release_port,
- request_port: sa1100_request_port,
- config_port: sa1100_config_port,
- verify_port: sa1100_verify_port,
+ .tx_empty = sa1100_tx_empty,
+ .set_mctrl = sa1100_set_mctrl,
+ .get_mctrl = sa1100_get_mctrl,
+ .stop_tx = sa1100_stop_tx,
+ .start_tx = sa1100_start_tx,
+ .stop_rx = sa1100_stop_rx,
+ .enable_ms = sa1100_enable_ms,
+ .break_ctl = sa1100_break_ctl,
+ .startup = sa1100_startup,
+ .shutdown = sa1100_shutdown,
+ .change_speed = sa1100_change_speed,
+ .type = sa1100_type,
+ .release_port = sa1100_release_port,
+ .request_port = sa1100_request_port,
+ .config_port = sa1100_config_port,
+ .verify_port = sa1100_verify_port,
};
static struct sa1100_port sa1100_ports[NR_PORTS];
@@ -820,12 +820,12 @@ sa1100_console_setup(struct console *co, char *options)
}
static struct console sa1100_console = {
- name: "ttySA",
- write: sa1100_console_write,
- device: sa1100_console_device,
- setup: sa1100_console_setup,
- flags: CON_PRINTBUFFER,
- index: -1,
+ .name = "ttySA",
+ .write = sa1100_console_write,
+ .device = sa1100_console_device,
+ .setup = sa1100_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
void __init sa1100_rs_console_init(void)
@@ -840,17 +840,17 @@ void __init sa1100_rs_console_init(void)
#endif
static struct uart_driver sa1100_reg = {
- owner: THIS_MODULE,
- driver_name: "ttySA",
+ .owner = THIS_MODULE,
+ .driver_name = "ttySA",
#ifdef CONFIG_DEVFS_FS
- dev_name: "ttySA%d",
+ .dev_name = "ttySA%d",
#else
- dev_name: "ttySA",
+ .dev_name = "ttySA",
#endif
- major: SERIAL_SA1100_MAJOR,
- minor: MINOR_START,
- nr: NR_PORTS,
- cons: SA1100_CONSOLE,
+ .major = SERIAL_SA1100_MAJOR,
+ .minor = MINOR_START,
+ .nr = NR_PORTS,
+ .cons = SA1100_CONSOLE,
};
static int __init sa1100_serial_init(void)
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
index 41f09f633e55..18cdd391e82f 100644
--- a/drivers/serial/uart00.c
+++ b/drivers/serial/uart00.c
@@ -498,35 +498,35 @@ static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
}
static struct uart_ops uart00_pops = {
- tx_empty: uart00_tx_empty,
- set_mctrl: uart00_set_mctrl_null,
- get_mctrl: uart00_get_mctrl,
- stop_tx: uart00_stop_tx,
- start_tx: uart00_start_tx,
- stop_rx: uart00_stop_rx,
- enable_ms: uart00_enable_ms,
- break_ctl: uart00_break_ctl,
- startup: uart00_startup,
- shutdown: uart00_shutdown,
- change_speed: uart00_change_speed,
- type: uart00_type,
- release_port: uart00_release_port,
- request_port: uart00_request_port,
- config_port: uart00_config_port,
- verify_port: uart00_verify_port,
+ .tx_empty = uart00_tx_empty,
+ .set_mctrl = uart00_set_mctrl_null,
+ .get_mctrl = uart00_get_mctrl,
+ .stop_tx = uart00_stop_tx,
+ .start_tx = uart00_start_tx,
+ .stop_rx = uart00_stop_rx,
+ .enable_ms = uart00_enable_ms,
+ .break_ctl = uart00_break_ctl,
+ .startup = uart00_startup,
+ .shutdown = uart00_shutdown,
+ .change_speed = uart00_change_speed,
+ .type = uart00_type,
+ .release_port = uart00_release_port,
+ .request_port = uart00_request_port,
+ .config_port = uart00_config_port,
+ .verify_port = uart00_verify_port,
};
#ifdef CONFIG_ARCH_CAMELOT
static struct uart_port epxa10db_port = {
- membase: (void*)IO_ADDRESS(EXC_UART00_BASE),
- mapbase: EXC_UART00_BASE,
- iotype: SERIAL_IO_MEM,
- irq: IRQ_UART,
- uartclk: EXC_AHB2_CLK_FREQUENCY,
- fifosize: 16,
- ops: &uart00_pops,
- flags: ASYNC_BOOT_AUTOCONF,
+ .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
+ .mapbase = EXC_UART00_BASE,
+ .iotype = SERIAL_IO_MEM,
+ .irq = IRQ_UART,
+ .uartclk = EXC_AHB2_CLK_FREQUENCY,
+ .fifosize = 16,
+ .ops = &uart00_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
};
#endif
@@ -633,12 +633,12 @@ static int __init uart00_console_setup(struct console *co, char *options)
}
static struct console uart00_console = {
- name: SERIAL_UART00_NAME,
- write: uart00_console_write,
- device: uart00_console_device,
- setup: uart00_console_setup,
- flags: CON_PRINTBUFFER,
- index: 0,
+ .name = SERIAL_UART00_NAME,
+ .write = uart00_console_write,
+ .device = uart00_console_device,
+ .setup = uart00_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = 0,
};
void __init uart00_console_init(void)
@@ -652,13 +652,13 @@ void __init uart00_console_init(void)
#endif
static struct uart_driver uart00_reg = {
- owner: NULL,
- driver_name: SERIAL_UART00_NAME,
- dev_name: SERIAL_UART00_NAME,
- major: SERIAL_UART00_MAJOR,
- minor: SERIAL_UART00_MINOR,
- nr: UART_NR,
- cons: UART00_CONSOLE,
+ .owner = NULL,
+ .driver_name = SERIAL_UART00_NAME,
+ .dev_name = SERIAL_UART00_NAME,
+ .major = SERIAL_UART00_MAJOR,
+ .minor = SERIAL_UART00_MINOR,
+ .nr = UART_NR,
+ .cons = UART00_CONSOLE,
};
struct dev_port_entry{
diff --git a/drivers/usb/Config.help b/drivers/usb/Config.help
index fa161a19725b..034627ab0e43 100644
--- a/drivers/usb/Config.help
+++ b/drivers/usb/Config.help
@@ -11,13 +11,18 @@ CONFIG_USB
to the PC via those ports.
Say Y here if your computer has a USB port and you want to use USB
- devices. You then need to say Y to at least one of "UHCI support"
- or "OHCI support" below (the type of interface that the USB hardware
+ devices. You then need to say Y to at least one of "UHCI HCD support"
+ or "OHCI HCD support" below (the type of interface that the USB hardware
in your computer provides to the operating system) and then choose
- from among the drivers for USB peripherals. You may want to check
+ from amongst the drivers for USB peripherals. You may want to check
out the information provided in <file:Documentation/usb/> and
especially the links given in <file:Documentation/usb/usb-help.txt>.
+ If you have a new USB 2.0 High Speed system, you should also choose
+ "EHCI HCD (USB 2.0) support" as well as at least one of UHCI or OHCI.
+
+ It doesn't normally hurt to select them all if you are not certain.
+
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbcore.o. If you want to compile it as a
@@ -39,7 +44,7 @@ CONFIG_USB_LONG_TIMEOUT
CONFIG_USB_DEVICEFS
If you say Y here (and to "/proc file system support" in the "File
- systems section, above), you will get a file /proc/bus/usb/devices
+ systems" section, above), you will get a file /proc/bus/usb/devices
which lists the devices currently connected to your USB bus or
busses, a file /proc/bus/usb/drivers which lists the USB kernel
client drivers currently loaded, and for every connected device a
diff --git a/drivers/usb/class/Config.help b/drivers/usb/class/Config.help
index 8387ea4b8f77..d745878ca6f6 100644
--- a/drivers/usb/class/Config.help
+++ b/drivers/usb/class/Config.help
@@ -3,6 +3,10 @@ CONFIG_USB_ACM
Communication Device Class Abstract Control Model interface.
Please read <file:Documentation/usb/acm.txt> for details.
+ If your modem only reports "Cls=ff(vend.)" in the descriptors in
+ /proc/bus/usb/devices, then your modem will not work with this
+ driver.
+
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called acm.o. If you want to compile it as a
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 07c5ea5b7e81..1187e7b58ecc 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -2745,8 +2745,8 @@ static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
static struct usb_device_id usb_audio_ids [] = {
- { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
- bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1},
+ { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
+ .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = 1},
{ } /* Terminating entry */
};
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index f1884e5ec9c2..4f53715471fb 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -947,8 +947,8 @@ static void usb_find_drivers(struct usb_device *dev)
/* register this interface with driverfs */
interface->dev.parent = &dev->dev;
interface->dev.bus = &usb_bus_type;
- sprintf (&interface->dev.bus_id[0], "%s:%d",
- dev->devpath,
+ sprintf (&interface->dev.bus_id[0], "%s-%s:%d",
+ dev->bus->bus_name, dev->devpath,
interface->altsetting->bInterfaceNumber);
if (!desc->iInterface
|| usb_string (dev, desc->iInterface,
diff --git a/drivers/usb/host/Config.help b/drivers/usb/host/Config.help
index 7cfd9ff8e5aa..e344fde05e8f 100644
--- a/drivers/usb/host/Config.help
+++ b/drivers/usb/host/Config.help
@@ -12,7 +12,8 @@ CONFIG_USB_EHCI_HCD
will connect to EHCI if it the device is high speed, otherwise they
connect to a companion controller. If you configure EHCI, you should
probably configure the OHCI (for NEC and some other vendors) USB Host
- Controller Driver too.
+ Controller Driver or UHCI (for Via motherboards) Host Controller
+ Driver too.
You may want to read <file:Documentation/usb/ehci.txt>.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 74496b06a130..dcb10d5dc2cd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -65,6 +65,8 @@
*
* HISTORY:
*
+ * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
+ * clean up HC run state handshaking.
* 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
* 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other
* missing pieces: enabling 64bit dma, handoff from BIOS/SMM.
@@ -83,7 +85,7 @@
* 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
-#define DRIVER_VERSION "2002-May-24"
+#define DRIVER_VERSION "2002-Jul-25"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
@@ -113,42 +115,105 @@ MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
/*-------------------------------------------------------------------------*/
/*
+ * handshake - spin reading hc until handshake completes or fails
+ * @ptr: address of hc register to be read
+ * @mask: bits to look at in result of read
+ * @done: value of those bits when handshake succeeds
+ * @usec: timeout in microseconds
+ *
+ * Returns negative errno, or zero on success
+ *
+ * Success happens when the "mask" bits have the specified value (hardware
+ * handshake done). There are two failure modes: "usec" have passed (major
+ * hardware flakeout), or the register reads as all-ones (hardware removed).
+ *
+ * That last failure should_only happen in cases like physical cardbus eject
+ * before driver shutdown. But it also seems to be caused by bugs in cardbus
+ * bridge shutdown: shutting down the bridge before the devices using it.
+ */
+static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+{
+ u32 result;
+
+ do {
+ result = readl (ptr);
+ if (result == ~(u32)0) /* card removed */
+ return -ENODEV;
+ result &= mask;
+ if (result == done)
+ return 0;
+ udelay (1);
+ usec--;
+ } while (usec > 0);
+ return -ETIMEDOUT;
+}
+
+/*
* hc states include: unknown, halted, ready, running
* transitional states are messy just now
* trying to avoid "running" unless urbs are active
* a "ready" hc can be finishing prefetched work
*/
-/* halt a non-running controller */
-static void ehci_reset (struct ehci_hcd *ehci)
+/* force HC to halt state from unknown (EHCI spec section 2.3) */
+static int ehci_halt (struct ehci_hcd *ehci)
+{
+ u32 temp = readl (&ehci->regs->status);
+
+ if ((temp & STS_HALT) != 0)
+ return 0;
+
+ temp = readl (&ehci->regs->command);
+ temp &= ~CMD_RUN;
+ writel (temp, &ehci->regs->command);
+ return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
+}
+
+/* reset a non-running (STS_HALT == 1) controller */
+static int ehci_reset (struct ehci_hcd *ehci)
{
u32 command = readl (&ehci->regs->command);
command |= CMD_RESET;
dbg_cmd (ehci, "reset", command);
writel (command, &ehci->regs->command);
- while (readl (&ehci->regs->command) & CMD_RESET)
- continue;
ehci->hcd.state = USB_STATE_HALT;
+ return handshake (&ehci->regs->command, CMD_RESET, 0, 050);
}
/* idle the controller (from running) */
static void ehci_ready (struct ehci_hcd *ehci)
{
- u32 command;
+ u32 temp;
#ifdef DEBUG
if (!HCD_IS_RUNNING (ehci->hcd.state))
BUG ();
#endif
- while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS)))
- udelay (100);
- command = readl (&ehci->regs->command);
- command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
- writel (command, &ehci->regs->command);
+ /* wait for any schedule enables/disables to take effect */
+ temp = 0;
+ if (ehci->async)
+ temp = STS_ASS;
+ if (ehci->next_uframe != -1)
+ temp |= STS_PSS;
+ if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
+ temp, 16 * 125) != 0) {
+ ehci->hcd.state = USB_STATE_HALT;
+ return;
+ }
- // hardware can take 16 microframes to turn off ...
+ /* then disable anything that's still active */
+ temp = readl (&ehci->regs->command);
+ temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
+ writel (temp, &ehci->regs->command);
+
+ /* hardware can take 16 microframes to turn off ... */
+ if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
+ 0, 16 * 125) != 0) {
+ ehci->hcd.state = USB_STATE_HALT;
+ return;
+ }
ehci->hcd.state = USB_STATE_READY;
}
@@ -236,6 +301,10 @@ static int ehci_start (struct usb_hcd *hcd)
/* cache this readonly data; minimize PCI reads */
ehci->hcs_params = readl (&ehci->caps->hcs_params);
+ /* force HC to halt state */
+ if ((retval = ehci_halt (ehci)) != 0)
+ return retval;
+
/*
* hw default: 1K periodic list heads, one per frame.
* periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -257,8 +326,10 @@ static int ehci_start (struct usb_hcd *hcd)
/* controller state: unknown --> reset */
/* EHCI spec section 4.1 */
- // FIXME require STS_HALT before reset...
- ehci_reset (ehci);
+ if ((retval = ehci_reset (ehci)) != 0) {
+ ehci_mem_cleanup (ehci);
+ return retval;
+ }
writel (INTR_MASK, &ehci->regs->intr_enable);
writel (ehci->periodic_dma, &ehci->regs->frame_list);
@@ -335,8 +406,6 @@ done2:
if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci);
- while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
- udelay (100);
ehci_reset (ehci);
hcd->self.root_hub = 0;
usb_free_dev (udev);
@@ -355,16 +424,14 @@ static void ehci_stop (struct usb_hcd *hcd)
dbg ("%s: stop", hcd->self.bus_name);
+ /* no more interrupts ... */
if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci);
- while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
- udelay (100);
ehci_reset (ehci);
- // root hub is shut down separately (first, when possible)
- scan_async (ehci);
- if (ehci->next_uframe != -1)
- scan_periodic (ehci);
+ /* root hub is shut down separately (first, when possible) */
+ tasklet_disable (&ehci->tasklet);
+ ehci_tasklet ((unsigned long) ehci);
ehci_mem_cleanup (ehci);
dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
@@ -412,8 +479,6 @@ dbg ("%s: suspend port %d", hcd->self.bus_name, i);
if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci);
- while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
- udelay (100);
writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);
// save pci FLADJ value
@@ -489,6 +554,12 @@ static void ehci_irq (struct usb_hcd *hcd)
u32 status = readl (&ehci->regs->status);
int bh;
+ /* e.g. cardbus physical eject */
+ if (status == ~(u32) 0) {
+ dbg ("%s: device removed!", hcd->self.bus_name);
+ goto dead;
+ }
+
status &= INTR_MASK;
if (!status) /* irq sharing? */
return;
@@ -517,10 +588,13 @@ static void ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
- err ("%s: fatal error, state %x", hcd->self.bus_name, hcd->state);
+ err ("%s: fatal error, state %x",
+ hcd->self.bus_name, hcd->state);
+dead:
ehci_reset (ehci);
- // generic layer kills/unlinks all urbs
- // then tasklet cleans up the rest
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
bh = 1;
}
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 53062380a93f..3057d75b0fed 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -718,8 +718,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
u32 cmd = readl (&ehci->regs->command);
/* in case a clear of CMD_ASE didn't take yet */
- while (readl (&ehci->regs->status) & STS_ASS)
- udelay (100);
+ (void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
qh->qh_next.qh = qh;
@@ -917,11 +916,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (ehci->hcd.state != USB_STATE_HALT) {
if (cmd & CMD_PSE)
writel (cmd & ~CMD_ASE, &ehci->regs->command);
- else {
+ else
ehci_ready (ehci);
- while (readl (&ehci->regs->status) & STS_ASS)
- udelay (100);
- }
}
qh->qh_next.qh = ehci->async = 0;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index a2f25cd4d598..5e08204d34d9 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -171,15 +171,19 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
/*-------------------------------------------------------------------------*/
-static void enable_periodic (struct ehci_hcd *ehci)
+static int enable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
+ int status;
/* did clearing PSE did take effect yet?
* takes effect only at frame boundaries...
*/
- while (readl (&ehci->regs->status) & STS_PSS)
- udelay (20);
+ status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
+ if (status != 0) {
+ ehci->hcd.state = USB_STATE_HALT;
+ return status;
+ }
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
@@ -189,23 +193,29 @@ static void enable_periodic (struct ehci_hcd *ehci)
/* make sure tasklet scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
% (ehci->periodic_size << 3);
+ return 0;
}
-static void disable_periodic (struct ehci_hcd *ehci)
+static int disable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
+ int status;
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
- while (!(readl (&ehci->regs->status) & STS_PSS))
- udelay (20);
+ status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
+ if (status != 0) {
+ ehci->hcd.state = USB_STATE_HALT;
+ return status;
+ }
cmd = readl (&ehci->regs->command) & ~CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... */
ehci->next_uframe = -1;
+ return 0;
}
/*-------------------------------------------------------------------------*/
@@ -217,6 +227,7 @@ static void intr_deschedule (
unsigned period
) {
unsigned long flags;
+ int status;
period >>= 3; // FIXME microframe periods not handled yet
@@ -234,9 +245,11 @@ static void intr_deschedule (
/* maybe turn off periodic schedule */
if (!ehci->periodic_urbs)
- disable_periodic (ehci);
- else
+ status = disable_periodic (ehci);
+ else {
+ status = 0;
vdbg ("periodic schedule still enabled");
+ }
spin_unlock_irqrestore (&ehci->lock, flags);
@@ -245,7 +258,7 @@ static void intr_deschedule (
* (yeech!) to be sure it's done.
* No other threads may be mucking with this qh.
*/
- if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0)
+ if (!status && ((ehci_get_frame (&ehci->hcd) - frame) % period) == 0)
udelay (125);
qh->qh_state = QH_STATE_IDLE;
@@ -501,7 +514,7 @@ static int intr_submit (
/* maybe enable periodic schedule processing */
if (!ehci->periodic_urbs++)
- enable_periodic (ehci);
+ status = enable_periodic (ehci);
break;
} while (frame);
@@ -913,8 +926,12 @@ itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
usb_claim_bandwidth (urb->dev, urb, usecs, 1);
/* maybe enable periodic schedule processing */
- if (!ehci->periodic_urbs++)
- enable_periodic (ehci);
+ if (!ehci->periodic_urbs++) {
+ if ((status = enable_periodic (ehci)) != 0) {
+ // FIXME deschedule right away
+ err ("itd_schedule, enable = %d", status);
+ }
+ }
return 0;
@@ -994,7 +1011,7 @@ itd_complete (
/* defer stopping schedule; completion can submit */
ehci->periodic_urbs--;
if (!ehci->periodic_urbs)
- disable_periodic (ehci);
+ (void) disable_periodic (ehci);
return flags;
}
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index b968cfe92d35..4545a999df90 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -281,16 +281,21 @@ static void ohci_dump_td (char *label, struct td *td)
cbp ? (be + 1 - cbp) : 0);
} else {
unsigned i;
- dbg (" info %08x CC=%x DI=%d START=%04x", tmp,
- TD_CC_GET(tmp), /* FC, */
+ dbg (" info %08x CC=%x FC=%d DI=%d SF=%04x", tmp,
+ TD_CC_GET(tmp),
+ (tmp >> 24) & 0x07,
(tmp & TD_DI) >> 21,
tmp & 0x0000ffff);
dbg (" bp0 %08x be %08x",
le32_to_cpup (&td->hwCBP) & ~0x0fff,
le32_to_cpup (&td->hwBE));
for (i = 0; i < MAXPSW; i++) {
- dbg (" psw [%d] = %2x", i,
- le16_to_cpu (td->hwPSW [i]));
+ u16 psw = le16_to_cpup (&td->hwPSW [i]);
+ int cc = (psw >> 12) & 0x0f;
+ dbg (" psw [%d] = %2x, CC=%x %s=%d", i,
+ psw, cc,
+ (cc >= 0x0e) ? "OFFSET" : "SIZE",
+ psw & 0x0fff);
}
}
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 2ee09b0a3bcd..d7cc8c544068 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -10,8 +10,15 @@
* [ (C) Copyright 1999 Gregory P. Smith]
*
*
+ * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller
+ * interfaces (though some non-x86 Intel chips use it). It supports
+ * smarter hardware than UHCI. A download link for the spec available
+ * through the http://www.usb.org website.
+ *
* History:
*
+ * 2002/07/19 fixes to management of ED and schedule state.
+ * 2002/06/09 SA-1111 support (Christopher Hoover)
* 2002/06/01 remember frame when HC won't see EDs any more; use that info
* to fix urb unlink races caused by interrupt latency assumptions;
* minor ED field and function naming updates
@@ -95,12 +102,12 @@
/*
* TO DO:
*
- * - "disabled" should be the hcd state
+ * - "disabled" and "sleeping" should be in hcd->state
* - bandwidth alloc to generic code
* - lots more testing!!
*/
-#define DRIVER_VERSION "2002-Jun-15"
+#define DRIVER_VERSION "2002-Jul-19"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
@@ -118,6 +125,12 @@
#include "ohci.h"
+static inline void disable (struct ohci_hcd *ohci)
+{
+ ohci->disabled = 1;
+ ohci->hcd.state = USB_STATE_HALT;
+}
+
#include "ohci-hub.c"
#include "ohci-dbg.c"
#include "ohci-mem.c"
@@ -140,6 +153,7 @@ static int ohci_urb_enqueue (
int i, size = 0;
unsigned long flags;
int bustime = 0;
+ int retval = 0;
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "SUB", usb_pipein (pipe));
@@ -150,12 +164,18 @@ static int ohci_urb_enqueue (
return -ENOMEM;
/* for the private part of the URB we need the number of TDs (size) */
- switch (usb_pipetype (pipe)) {
+ switch (ed->type) {
case PIPE_CONTROL:
+ /* td_submit_urb() doesn't yet handle these */
+ if (urb->transfer_buffer_length > 4096)
+ return -EMSGSIZE;
+
/* 1 TD for setup, 1 for ACK, plus ... */
size = 2;
/* FALLTHROUGH */
- case PIPE_BULK:
+ // case PIPE_INTERRUPT:
+ // case PIPE_BULK:
+ default:
/* one TD for every 4096 Bytes (can be upto 8K) */
size += urb->transfer_buffer_length / 4096;
/* ... and for any remaining bytes ... */
@@ -179,9 +199,6 @@ static int ohci_urb_enqueue (
urb->iso_frame_desc [i].status = -EXDEV;
}
break;
- case PIPE_INTERRUPT: /* one TD */
- size = 1;
- break;
}
/* allocate the private part of the URB */
@@ -191,19 +208,25 @@ static int ohci_urb_enqueue (
return -ENOMEM;
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
+ spin_lock_irqsave (&ohci->lock, flags);
+
+ /* don't submit to a dead HC */
+ if (ohci->disabled || ohci->sleeping) {
+ retval = -ENODEV;
+ goto fail;
+ }
+
/* fill the private part of the URB */
urb_priv->length = size;
urb_priv->ed = ed;
/* allocate the TDs (updating hash chains) */
- spin_lock_irqsave (&ohci->lock, flags);
for (i = 0; i < size; i++) {
urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
if (!urb_priv->td [i]) {
urb_priv->length = i;
- urb_free_priv (ohci, urb_priv);
- spin_unlock_irqrestore (&ohci->lock, flags);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto fail;
}
}
@@ -217,20 +240,19 @@ static int ohci_urb_enqueue (
switch (usb_pipetype (pipe)) {
case PIPE_ISOCHRONOUS:
if (urb->transfer_flags & USB_ISO_ASAP) {
- urb->start_frame = ( (ed->state == ED_OPER)
+ urb->start_frame = ((ed->state != ED_IDLE)
? (ed->intriso.last_iso + 1)
: (le16_to_cpu (ohci->hcca->frame_no)
+ 10)) & 0xffff;
- }
+ }
/* FALLTHROUGH */
case PIPE_INTERRUPT:
if (urb->bandwidth == 0) {
bustime = usb_check_bandwidth (urb->dev, urb);
}
if (bustime < 0) {
- urb_free_priv (ohci, urb_priv);
- spin_unlock_irqrestore (&ohci->lock, flags);
- return bustime;
+ retval = bustime;
+ goto fail;
}
usb_claim_bandwidth (urb->dev, urb,
bustime, usb_pipeisoc (urb->pipe));
@@ -238,18 +260,20 @@ static int ohci_urb_enqueue (
urb->hcpriv = urb_priv;
- /* link the ed into a chain if is not already */
- if (ed->state != ED_OPER)
- ep_link (ohci, ed);
+ /* schedule the ed if needed */
+ if (ed->state == ED_IDLE)
+ ed_schedule (ohci, ed);
/* fill the TDs and link them to the ed; and
* enable that part of the schedule, if needed
*/
- td_submit_urb (urb);
+ td_submit_urb (ohci, urb);
+fail:
+ if (retval)
+ urb_free_priv (ohci, urb_priv);
spin_unlock_irqrestore (&ohci->lock, flags);
-
- return 0;
+ return retval;
}
/*
@@ -270,19 +294,17 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
if (!ohci->disabled) {
urb_priv_t *urb_priv;
- /* flag the urb's data for deletion in some upcoming
- * SF interrupt's delete list processing
+ /* Unless an IRQ completed the unlink while it was being
+ * handed to us, flag it for unlink and giveback, and force
+ * some upcoming INTR_SF to call finish_unlinks()
*/
spin_lock_irqsave (&ohci->lock, flags);
urb_priv = urb->hcpriv;
-
- if (!urb_priv || (urb_priv->state == URB_DEL)) {
- spin_unlock_irqrestore (&ohci->lock, flags);
- return 0;
+ if (urb_priv) {
+ urb_priv->state = URB_DEL;
+ if (urb_priv->ed->state == ED_OPER)
+ start_urb_unlink (ohci, urb_priv->ed);
}
-
- urb_priv->state = URB_DEL;
- start_urb_unlink (ohci, urb_priv->ed);
spin_unlock_irqrestore (&ohci->lock, flags);
} else {
/*
@@ -290,12 +312,16 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
* any more ... just clean up every urb's memory.
*/
finish_urb (ohci, urb);
- }
+ }
return 0;
}
/*-------------------------------------------------------------------------*/
+/* frees config/altsetting state for endpoints,
+ * including ED memory, dummy TD, and bulk/intr data toggle
+ */
+
static void
ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
{
@@ -303,7 +329,11 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv;
int i;
unsigned long flags;
+#ifdef DEBUG
+ int rescans = 0;
+#endif
+rescan:
/* free any eds, and dummy tds, still hanging around */
spin_lock_irqsave (&ohci->lock, flags);
for (i = 0; i < 32; i++) {
@@ -312,27 +342,47 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
if (!ed)
continue;
- ed->state &= ~ED_URB_DEL;
- if (ohci->disabled && ed->state == ED_OPER)
- ed->state = ED_UNLINK;
+ if (ohci->disabled && ed->state != ED_IDLE)
+ ed->state = ED_IDLE;
switch (ed->state) {
- case ED_NEW:
- break;
- case ED_UNLINK:
+ case ED_UNLINK: /* wait a frame? */
+ goto do_rescan;
+ case ED_IDLE: /* fully unlinked */
td_free (ohci, ed->dummy);
break;
-
- case ED_OPER:
default:
+#ifdef DEBUG
err ("illegal ED %d state in free_config, %d",
i, ed->state);
-#ifdef DEBUG
- BUG ();
#endif
+ /* ED_OPER: some driver disconnect() is broken,
+ * it didn't even start its unlinks much less wait
+ * for their completions.
+ * OTHERWISE: hcd bug, ed is garbage
+ */
+ BUG ();
}
ed_free (ohci, ed);
}
spin_unlock_irqrestore (&ohci->lock, flags);
+ return;
+
+do_rescan:
+#ifdef DEBUG
+ /* a driver->disconnect() returned before its unlinks completed? */
+ if (in_interrupt ()) {
+ dbg ("WARNING: spin in interrupt; driver->disconnect() bug");
+ dbg ("dev usb-%s-%s ep 0x%x",
+ ohci->hcd.self.bus_name, udev->devpath, i);
+ }
+ BUG_ON (!(readl (&ohci->regs->intrenable) & OHCI_INTR_SF));
+ BUG_ON (rescans >= 2); /* HWBUG */
+ rescans++;
+#endif
+
+ spin_unlock_irqrestore (&ohci->lock, flags);
+ wait_ms (1);
+ goto rescan;
}
static int ohci_get_frame (struct usb_hcd *hcd)
@@ -471,7 +521,7 @@ static int hc_start (struct ohci_hcd *ohci)
ohci->hcd.self.root_hub = udev = usb_alloc_dev (NULL, &ohci->hcd.self);
ohci->hcd.state = USB_STATE_READY;
if (!udev) {
- ohci->disabled = 1;
+ disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
return -ENOMEM;
@@ -481,7 +531,7 @@ static int hc_start (struct ohci_hcd *ohci)
udev->speed = USB_SPEED_FULL;
if (usb_register_root_hub (udev, ohci->parent_dev) != 0) {
usb_free_dev (udev);
- ohci->disabled = 1;
+ disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
return -ENODEV;
@@ -507,8 +557,8 @@ static void ohci_irq (struct usb_hcd *hcd)
/* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
- ohci->disabled++;
- err ("%s device removed!", hcd->self.bus_name);
+ disable (ohci);
+ dbg ("%s device removed!", hcd->self.bus_name);
return;
/* interrupt for some other device? */
@@ -520,7 +570,7 @@ static void ohci_irq (struct usb_hcd *hcd)
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
if (ints & OHCI_INTR_UE) {
- ohci->disabled++;
+ disable (ohci);
err ("OHCI Unrecoverable Error, %s disabled", hcd->self.bus_name);
// e.g. due to PCI Master/Target Abort
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index e38860089a8b..9fd76677717d 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -22,7 +22,9 @@
*/
#define read_roothub(hc, register, mask) ({ \
u32 temp = readl (&hc->regs->roothub.register); \
- if (hc->flags & OHCI_QUIRK_AMD756) \
+ if (temp == -1) \
+ disable (hc); \
+ else if (hc->flags & OHCI_QUIRK_AMD756) \
while (temp & mask) \
temp = readl (&hc->regs->roothub.register); \
temp; })
@@ -71,8 +73,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
ports = roothub_a (ohci) & RH_A_NDP;
if (ports > MAX_ROOT_PORTS) {
- err ("%s: bogus NDP=%d", hcd->self.bus_name, ports);
- err ("rereads as NDP=%d",
+ if (ohci->disabled)
+ return -ESHUTDOWN;
+ err ("%s bogus NDP=%d, rereads as NDP=%d",
+ hcd->self.bus_name, ports,
readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
return 0;
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 1d3de55b90b9..0fe88b71cc30 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -77,12 +77,12 @@ static void finish_urb (struct ohci_hcd *ohci, struct urb *urb)
usb_hcd_giveback_urb (&ohci->hcd, urb);
}
-static void td_submit_urb (struct urb *urb);
+static void td_submit_urb (struct ohci_hcd *ohci, struct urb *urb);
/* Report interrupt transfer completion, maybe reissue */
-static void intr_resub (struct ohci_hcd *hc, struct urb *urb)
+static inline void intr_resub (struct ohci_hcd *hc, struct urb *urb)
{
- urb_priv_t *urb_priv = urb->hcpriv;
+ struct urb_priv *urb_priv = urb->hcpriv;
unsigned long flags;
// FIXME rewrite this resubmit path. use pci_dma_sync_single()
@@ -120,7 +120,7 @@ static void intr_resub (struct ohci_hcd *hc, struct urb *urb)
spin_unlock (&urb->lock);
spin_lock (&hc->lock);
- td_submit_urb (urb);
+ td_submit_urb (hc, urb);
spin_unlock_irqrestore (&hc->lock, flags);
}
@@ -170,50 +170,50 @@ static int ep_rev (int num_bits, int word)
/* link an ed into one of the HC chains */
-static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
+static void ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
int int_branch, i;
int inter, interval, load;
__u32 *ed_p;
- volatile struct ed *ed = edi;
ed->state = ED_OPER;
+ ed->hwNextED = 0;
+ wmb ();
+
+ /* we care about rm_list when setting CLE/BLE in case the HC was at
+ * work on some TD when CLE/BLE was turned off, and isn't quiesced
+ * yet. finish_unlinks() restarts as needed, some upcoming INTR_SF.
+ */
switch (ed->type) {
case PIPE_CONTROL:
- ed->hwNextED = 0;
if (ohci->ed_controltail == NULL) {
writel (ed->dma, &ohci->regs->ed_controlhead);
} else {
ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
}
ed->ed_prev = ohci->ed_controltail;
- if (!ohci->ed_controltail
- && !ohci->ed_rm_list
- && !ohci->sleeping
- ) {
+ if (!ohci->ed_controltail && !ohci->ed_rm_list) {
ohci->hc_control |= OHCI_CTRL_CLE;
+ writel (0, &ohci->regs->ed_controlcurrent);
writel (ohci->hc_control, &ohci->regs->control);
}
- ohci->ed_controltail = edi;
+ ohci->ed_controltail = ed;
break;
case PIPE_BULK:
- ed->hwNextED = 0;
if (ohci->ed_bulktail == NULL) {
writel (ed->dma, &ohci->regs->ed_bulkhead);
} else {
ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
}
ed->ed_prev = ohci->ed_bulktail;
- if (!ohci->ed_bulktail
- && !ohci->ed_rm_list
- && !ohci->sleeping
- ) {
+ if (!ohci->ed_bulktail && !ohci->ed_rm_list) {
ohci->hc_control |= OHCI_CTRL_BLE;
+ writel (0, &ohci->regs->ed_bulkcurrent);
writel (ohci->hc_control, &ohci->regs->control);
}
- ohci->ed_bulktail = edi;
+ ohci->ed_bulktail = ed;
break;
case PIPE_INTERRUPT:
@@ -231,17 +231,16 @@ static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
ed->hwNextED = *ed_p;
*ed_p = cpu_to_le32 (ed->dma);
}
+ wmb ();
#ifdef OHCI_VERBOSE_DEBUG
ohci_dump_periodic (ohci, "LINK_INT");
#endif
break;
case PIPE_ISOCHRONOUS:
- ed->hwNextED = 0;
- ed->interval = 1;
+ ed->ed_prev = ohci->ed_isotail;
if (ohci->ed_isotail != NULL) {
ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
- ed->ed_prev = ohci->ed_isotail;
} else {
for ( i = 0; i < NUM_INTS; i += inter) {
inter = 1;
@@ -251,15 +250,18 @@ static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval);
*ed_p = cpu_to_le32 (ed->dma);
}
- ed->ed_prev = NULL;
}
- ohci->ed_isotail = edi;
+ wmb ();
+ ohci->ed_isotail = ed;
#ifdef OHCI_VERBOSE_DEBUG
ohci_dump_periodic (ohci, "LINK_ISO");
#endif
break;
}
- return 0;
+
+ /* the HC may not see the schedule updates yet, but if it does
+ * then they'll be properly ordered.
+ */
}
/*-------------------------------------------------------------------------*/
@@ -288,9 +290,8 @@ static void periodic_unlink (
* just the link to the ed is unlinked.
* the link from the ed still points to another operational ed or 0
* so the HC can eventually finish the processing of the unlinked ed
- * caller guarantees the ED has no active TDs.
*/
-static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
+static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
{
int i;
@@ -361,15 +362,14 @@ static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
break;
}
- /* FIXME ED's "unlink" state is indeterminate;
- * the HC might still be caching it (till SOF).
- * - use ed_rm_list and finish_unlinks(), adding some state that
- * prevents clobbering hw linkage before the appropriate SOF
- * - a speedup: when only one urb is queued on the ed, save 1msec
- * by making start_urb_unlink() use this routine to deschedule.
+ /* FIXME Except for a couple of exceptionally clean unlink cases
+ * (like unlinking the only c/b ED, with no TDs) HCs may still be
+ * caching this (till SOF).
+ *
+ * To avoid racing with the hardware, this needs to use ED_UNLINK
+ * and delay til next INTR_SF. Merge with start_urb_unlink().
*/
- ed->state = ED_UNLINK;
- return 0;
+ ed->state = ED_IDLE;
}
@@ -403,35 +403,27 @@ static struct ed *ed_get (
spin_lock_irqsave (&ohci->lock, flags);
if (!(ed = dev->ep [ep])) {
+ struct td *td;
+
ed = ed_alloc (ohci, SLAB_ATOMIC);
if (!ed) {
/* out of memory */
goto done;
}
dev->ep [ep] = ed;
- }
- if (ed->state & ED_URB_DEL) {
- /* pending unlink request */
- ed = 0;
- goto done;
- }
-
- if (ed->state == ED_NEW) {
- struct td *td;
-
- ed->hwINFO = ED_SKIP;
/* dummy td; end of td list for ed */
td = td_alloc (ohci, SLAB_ATOMIC);
if (!td) {
/* out of memory */
+ ed_free (ohci, ed);
ed = 0;
goto done;
}
ed->dummy = td;
ed->hwTailP = cpu_to_le32 (td->td_dma);
ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
- ed->state = ED_UNLINK;
+ ed->state = ED_IDLE;
ed->type = type;
}
@@ -439,7 +431,7 @@ static struct ed *ed_get (
* state/mode info. Currently the upper layers don't support such
* guarantees; we're lucky changing config/altsetting is rare.
*/
- if (ed->state == ED_UNLINK) {
+ if (ed->state == ED_IDLE) {
u32 info;
info = usb_pipedevice (pipe);
@@ -494,30 +486,13 @@ done:
/*-------------------------------------------------------------------------*/
/* request unlinking of an endpoint from an operational HC.
- * put the ep on the rm_list and stop the bulk or ctrl list
+ * put the ep on the rm_list
* real work is done at the next start frame (SF) hardware interrupt
*/
static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
{
- /* already pending? */
- if (ed->state & ED_URB_DEL)
- return;
- ed->state |= ED_URB_DEL;
-
- ed->hwINFO |= ED_SKIP;
-
- switch (ed->type) {
- case PIPE_CONTROL: /* stop control list */
- ohci->hc_control &= ~OHCI_CTRL_CLE;
- writel (ohci->hc_control,
- &ohci->regs->control);
- break;
- case PIPE_BULK: /* stop bulk list */
- ohci->hc_control &= ~OHCI_CTRL_BLE;
- writel (ohci->hc_control,
- &ohci->regs->control);
- break;
- }
+ ed_deschedule (ohci, ed);
+ ed->state = ED_UNLINK;
/* SF interrupt might get delayed; record the frame counter value that
* indicates when the HC isn't looking at it, so concurrent unlinks
@@ -526,7 +501,7 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
*/
ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1;
- ed->ed_rm_list = ohci->ed_rm_list;
+ ed->ed_next = ohci->ed_rm_list;
ohci->ed_rm_list = ed;
/* enable SOF interrupt */
@@ -543,12 +518,12 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static void
-td_fill (struct ohci_hcd *ohci, unsigned int info,
+td_fill (unsigned int info,
dma_addr_t data, int len,
struct urb *urb, int index)
{
struct td *td, *td_pt;
- urb_priv_t *urb_priv = urb->hcpriv;
+ struct urb_priv *urb_priv = urb->hcpriv;
int is_iso = info & TD_ISO;
if (index >= urb_priv->length) {
@@ -607,28 +582,30 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
/*-------------------------------------------------------------------------*/
-/* prepare all TDs of a transfer */
-
-static void td_submit_urb (struct urb *urb)
-{
- urb_priv_t *urb_priv = urb->hcpriv;
- struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv);
+/* Prepare all TDs of a transfer, and queue them onto the ED.
+ * Caller guarantees HC is active.
+ * Usually the ED is already on the schedule, so TDs might be
+ * processed as soon as they're queued.
+ */
+static void td_submit_urb (
+ struct ohci_hcd *ohci,
+ struct urb *urb
+) {
+ struct urb_priv *urb_priv = urb->hcpriv;
dma_addr_t data;
int data_len = urb->transfer_buffer_length;
- int cnt = 0;
- __u32 info = 0;
- unsigned int toggle = 0;
+ int cnt = 0;
+ u32 info = 0;
int is_out = usb_pipeout (urb->pipe);
- /* OHCI handles the DATA-toggles itself, we just use the
- * USB-toggle bits for resetting
+ /* OHCI handles the bulk/interrupt data toggles itself. We just
+ * use the device toggle bits for resetting, and rely on the fact
+ * that resetting toggle is meaningless if the endpoint is active.
*/
- if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
- toggle = TD_T_TOGGLE;
- } else {
- toggle = TD_T_DATA0;
+ if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
is_out, 1);
+ urb_priv->ed->hwHeadP &= ~ED_C;
}
urb_priv->td_cnt = 0;
@@ -644,91 +621,88 @@ static void td_submit_urb (struct urb *urb)
/* NOTE: TD_CC is set so we can tell which TDs the HC processed by
* using TD_CC_GET, as well as by seeing them on the done list.
+ * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.)
*/
- switch (usb_pipetype (urb->pipe)) {
- case PIPE_BULK:
- info = is_out
- ? TD_CC | TD_DP_OUT
- : TD_CC | TD_DP_IN ;
- /* TDs _could_ transfer up to 8K each */
- while (data_len > 4096) {
- td_fill (ohci,
- info | (cnt? TD_T_TOGGLE:toggle),
- data, 4096, urb, cnt);
- data += 4096; data_len -= 4096; cnt++;
- }
- /* maybe avoid ED halt on final TD short read */
- if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
- info |= TD_R;
- td_fill (ohci, info | (cnt ? TD_T_TOGGLE : toggle),
- data, data_len, urb, cnt);
+ switch (urb_priv->ed->type) {
+
+ /* Bulk and interrupt are identical except for where in the schedule
+ * their EDs live.
+ */
+ // case PIPE_BULK:
+ // case PIPE_INTERRUPT:
+ default:
+ info = is_out
+ ? TD_T_TOGGLE | TD_CC | TD_DP_OUT
+ : TD_T_TOGGLE | TD_CC | TD_DP_IN;
+ /* TDs _could_ transfer up to 8K each */
+ while (data_len > 4096) {
+ td_fill (info, data, 4096, urb, cnt);
+ data += 4096;
+ data_len -= 4096;
cnt++;
- if ((urb->transfer_flags & USB_ZERO_PACKET)
- && cnt < urb_priv->length) {
- td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
- 0, 0, urb, cnt);
- cnt++;
- }
- /* start bulk list */
- if (!ohci->sleeping) {
- wmb ();
- writel (OHCI_BLF, &ohci->regs->cmdstatus);
- }
- break;
+ }
+ /* maybe avoid ED halt on final TD short read */
+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ info |= TD_R;
+ td_fill (info, data, data_len, urb, cnt);
+ cnt++;
+ if ((urb->transfer_flags & USB_ZERO_PACKET)
+ && cnt < urb_priv->length) {
+ td_fill (info, 0, 0, urb, cnt);
+ cnt++;
+ }
+ /* maybe kickstart bulk list */
+ if (urb_priv->ed->type == PIPE_BULK) {
+ wmb ();
+ writel (OHCI_BLF, &ohci->regs->cmdstatus);
+ }
+ break;
- case PIPE_INTERRUPT:
- /* current policy: only one TD per request.
- * otherwise identical to bulk, except for BLF
- */
- info = TD_CC | toggle;
- info |= is_out
- ? TD_DP_OUT
- : TD_R | TD_DP_IN;
- td_fill (ohci, info, data, data_len, urb, cnt++);
- break;
-
- case PIPE_CONTROL:
- /* control requests don't use toggle state */
- info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
- td_fill (ohci, info,
- pci_map_single (ohci->hcd.pdev,
- urb->setup_packet, 8,
- PCI_DMA_TODEVICE),
- 8, urb, cnt++);
- if (data_len > 0) {
- info = TD_CC | TD_R | TD_T_DATA1;
- info |= is_out ? TD_DP_OUT : TD_DP_IN;
- /* NOTE: mishandles transfers >8K, some >4K */
- td_fill (ohci, info, data, data_len,
- urb, cnt++);
- }
- info = is_out
- ? TD_CC | TD_DP_IN | TD_T_DATA1
- : TD_CC | TD_DP_OUT | TD_T_DATA1;
- td_fill (ohci, info, data, 0, urb, cnt++);
- /* start control list */
- if (!ohci->sleeping) {
- wmb ();
- writel (OHCI_CLF, &ohci->regs->cmdstatus);
- }
- break;
-
- case PIPE_ISOCHRONOUS:
- for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
- int frame = urb->start_frame;
-
- // FIXME scheduling should handle frame counter
- // roll-around ... exotic case (and OHCI has
- // a 2^16 iso range, vs other HCs max of 2^10)
- frame += cnt * urb->interval;
- frame &= 0xffff;
- td_fill (ohci, TD_CC | TD_ISO | frame,
- data + urb->iso_frame_desc [cnt].offset,
- urb->iso_frame_desc [cnt].length, urb, cnt);
- }
- break;
- }
- if (urb_priv->length != cnt)
+ /* control manages DATA0/DATA1 toggle per-request; SETUP resets it,
+ * any DATA phase works normally, and the STATUS ack is special.
+ */
+ case PIPE_CONTROL:
+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+ td_fill (info,
+ pci_map_single (ohci->hcd.pdev,
+ urb->setup_packet, 8,
+ PCI_DMA_TODEVICE),
+ 8, urb, cnt++);
+ if (data_len > 0) {
+ info = TD_CC | TD_R | TD_T_DATA1;
+ info |= is_out ? TD_DP_OUT : TD_DP_IN;
+ /* NOTE: mishandles transfers >8K, some >4K */
+ td_fill (info, data, data_len, urb, cnt++);
+ }
+ info = is_out
+ ? TD_CC | TD_DP_IN | TD_T_DATA1
+ : TD_CC | TD_DP_OUT | TD_T_DATA1;
+ td_fill (info, data, 0, urb, cnt++);
+ /* maybe kickstart control list */
+ wmb ();
+ writel (OHCI_CLF, &ohci->regs->cmdstatus);
+ break;
+
+ /* ISO has no retransmit, so no toggle; and it uses special TDs.
+ * Each TD could handle multiple consecutive frames (interval 1);
+ * we could often reduce the number of TDs here.
+ */
+ case PIPE_ISOCHRONOUS:
+ for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+ int frame = urb->start_frame;
+
+ // FIXME scheduling should handle frame counter
+ // roll-around ... exotic case (and OHCI has
+ // a 2^16 iso range, vs other HCs max of 2^10)
+ frame += cnt * urb->interval;
+ frame &= 0xffff;
+ td_fill (TD_CC | TD_ISO | frame,
+ data + urb->iso_frame_desc [cnt].offset,
+ urb->iso_frame_desc [cnt].length, urb, cnt);
+ }
+ break;
+ }
+ if (urb_priv->length != cnt)
dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
}
@@ -744,13 +718,17 @@ static void td_done (struct urb *urb, struct td *td)
u32 tdINFO = le32_to_cpup (&td->hwINFO);
int cc = 0;
-
/* ISO ... drivers see per-TD length/status */
if (tdINFO & TD_ISO) {
u16 tdPSW = le16_to_cpu (td->hwPSW [0]);
int dlen = 0;
+ /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */
+
cc = (tdPSW >> 12) & 0xF;
+ if (tdINFO & TD_CC) /* hc didn't touch? */
+ return;
+
if (usb_pipeout (urb->pipe))
dlen = urb->iso_frame_desc [td->index].length;
else
@@ -759,9 +737,11 @@ static void td_done (struct urb *urb, struct td *td)
urb->iso_frame_desc [td->index].actual_length = dlen;
urb->iso_frame_desc [td->index].status = cc_to_error [cc];
- if (cc != 0)
+#ifdef VERBOSE_DEBUG
+ if (cc != TD_CC_NOERROR)
dbg (" urb %p iso TD %p (%d) len %d CC %d",
urb, td, 1 + td->index, dlen, cc);
+#endif
/* BULK, INT, CONTROL ... drivers see aggregate length/status,
* except that "setup" bytes aren't counted and "short" transfers
@@ -783,7 +763,7 @@ static void td_done (struct urb *urb, struct td *td)
if (cc == TD_DATAUNDERRUN
&& !(urb->transfer_flags & URB_SHORT_NOT_OK))
cc = TD_CC_NOERROR;
- if (cc != TD_CC_NOERROR) {
+ if (cc != TD_CC_NOERROR && cc < 0x0E) {
spin_lock (&urb->lock);
if (urb->status == -EINPROGRESS)
urb->status = cc_to_error [cc];
@@ -801,7 +781,7 @@ static void td_done (struct urb *urb, struct td *td)
}
#ifdef VERBOSE_DEBUG
- if (cc != 0)
+ if (cc != TD_CC_NOERROR && cc < 0x0E)
dbg (" urb %p TD %p (%d) CC %d, len=%d/%d",
urb, td, 1 + td->index, cc,
urb->actual_length,
@@ -876,28 +856,39 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
{
struct ed *ed, **last;
- int ctrl = 0, bulk = 0;
+rescan_all:
for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) {
struct td *td, *td_next, *tdHeadP, *tdTailP;
u32 *td_p;
- int unlinked;
+ int completed, modified;
/* only take off EDs that the HC isn't using, accounting for
- * frame counter wraps. completion callbacks might prepend
- * EDs to the list, they'll be checked next irq.
+ * frame counter wraps.
*/
- if (tick_before (tick, ed->tick)) {
- last = &ed->ed_rm_list;
+ if (tick_before (tick, ed->tick) && !ohci->disabled) {
+ last = &ed->ed_next;
continue;
}
- *last = ed->ed_rm_list;
- ed->ed_rm_list = 0;
- unlinked = 0;
- /* unlink urbs from first one requested to queue end;
- * leave earlier urbs alone
+ /* reentrancy: if we drop the schedule lock, someone might
+ * have modified this list. normally it's just prepending
+ * entries (which we'd ignore), but paranoia won't hurt.
*/
+ *last = ed->ed_next;
+ ed->ed_next = 0;
+ modified = 0;
+
+ /* unlink urbs as requested, but rescan the list after
+ * we call a completion since it might have unlinked
+ * another (earlier) urb
+ *
+ * FIXME use td_list to scan, not ed hashtables.
+ * completely abolish ed hashtables!
+ */
+rescan_this:
+ completed = 0;
+
tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP));
tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
td_p = &ed->hwHeadP;
@@ -908,21 +899,18 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
td_next = dma_to_td (ohci,
le32_to_cpup (&td->hwNextTD));
- if (unlinked || (urb_priv->state == URB_DEL)) {
- u32 tdINFO = le32_to_cpup (&td->hwINFO);
-
- unlinked = 1;
+ if (urb_priv->state == URB_DEL) {
/* HC may have partly processed this TD */
- if (TD_CC_GET (tdINFO) < 0xE)
- td_done (urb, td);
+ td_done (urb, td);
+ urb_priv->td_cnt++;
+
*td_p = td->hwNextTD | (*td_p
& __constant_cpu_to_le32 (0x3));
/* URB is done; clean up */
- if (++ (urb_priv->td_cnt) == urb_priv->length) {
- if (urb->status == -EINPROGRESS)
- urb->status = -ECONNRESET;
+ if (urb_priv->td_cnt == urb_priv->length) {
+ modified = completed = 1;
spin_unlock (&ohci->lock);
finish_urb (ohci, urb);
spin_lock (&ohci->lock);
@@ -932,49 +920,52 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
}
}
- /* FIXME actually want four cases here:
- * (a) finishing URB unlink
- * [a1] no URBs queued, so start ED unlink
- * [a2] some (earlier) URBs still linked, re-enable
- * (b) finishing ED unlink
- * [b1] no URBs queued, ED is truly idle now
- * ... we could set state ED_NEW and free dummy
- * [b2] URBs now queued, link ED back into schedule
- * right now we only have (a)
- */
- ed->state &= ~ED_URB_DEL;
- tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
-
- if (tdHeadP == tdTailP) {
- if (ed->state == ED_OPER)
- start_ed_unlink (ohci, ed);
- } else
- ed->hwINFO &= ~ED_SKIP;
+ /* ED's now officially unlinked, hc doesn't see */
+ ed->state = ED_IDLE;
+ ed->hwINFO &= ~ED_SKIP;
+ ed->hwHeadP &= ~cpu_to_le32 (ED_H);
+ ed->hwNextED = 0;
- switch (ed->type) {
- case PIPE_CONTROL:
- ctrl = 1;
- break;
- case PIPE_BULK:
- bulk = 1;
- break;
+ /* but if there's work queued, reschedule */
+ tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
+ if (tdHeadP != tdTailP) {
+ if (completed)
+ goto rescan_this;
+ if (!ohci->disabled && !ohci->sleeping)
+ ed_schedule (ohci, ed);
}
+
+ if (modified)
+ goto rescan_all;
}
/* maybe reenable control and bulk lists */
- if (!ohci->disabled) {
- if (ctrl) /* reset control list */
- writel (0, &ohci->regs->ed_controlcurrent);
- if (bulk) /* reset bulk list */
- writel (0, &ohci->regs->ed_bulkcurrent);
- if (!ohci->ed_rm_list) {
- if (ohci->ed_controltail)
- ohci->hc_control |= OHCI_CTRL_CLE;
- if (ohci->ed_bulktail)
- ohci->hc_control |= OHCI_CTRL_BLE;
- writel (ohci->hc_control, &ohci->regs->control);
+ if (!ohci->disabled && !ohci->ed_rm_list) {
+ u32 command = 0, control = 0;
+
+ if (ohci->ed_controltail) {
+ command |= OHCI_CLF;
+ if (!(ohci->hc_control & OHCI_CTRL_CLE)) {
+ control |= OHCI_CTRL_CLE;
+ writel (0, &ohci->regs->ed_controlcurrent);
+ }
}
- }
+ if (ohci->ed_bulktail) {
+ command |= OHCI_BLF;
+ if (!(ohci->hc_control & OHCI_CTRL_BLE)) {
+ control |= OHCI_CTRL_BLE;
+ writel (0, &ohci->regs->ed_bulkcurrent);
+ }
+ }
+
+ /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
+ if (control) {
+ ohci->hc_control |= control;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ if (command)
+ writel (command, &ohci->regs->cmdstatus);
+ }
}
@@ -1026,7 +1017,7 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td)
if ((ed->hwHeadP & __constant_cpu_to_le32 (TD_MASK))
== ed->hwTailP
&& (ed->state == ED_OPER))
- start_ed_unlink (ohci, ed);
+ ed_deschedule (ohci, ed);
td = td_next;
}
spin_unlock_irqrestore (&ohci->lock, flags);
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 7969e669052d..4af5cdf0aa34 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -31,15 +31,21 @@ struct ed {
/* rest are purely for the driver's use */
dma_addr_t dma; /* addr of ED */
+ struct td *dummy; /* next TD to activate */
+
+ /* host's view of schedule */
+ struct ed *ed_next; /* on schedule or rm_list */
struct ed *ed_prev; /* for non-interrupt EDs */
- struct td *dummy;
struct list_head td_list; /* "shadow list" of our TDs */
- u8 state; /* ED_{NEW,UNLINK,OPER} */
-#define ED_NEW 0x00 /* unused, no dummy td */
-#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */
-#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */
-#define ED_URB_DEL 0x08 /* for unlinking; masked in */
+ /* create --> IDLE --> OPER --> ... --> IDLE --> destroy
+ * usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
+ * some special cases : OPER --> IDLE ...
+ */
+ u8 state; /* ED_{IDLE,UNLINK,OPER} */
+#define ED_IDLE 0x00 /* NOT linked to HC */
+#define ED_UNLINK 0x01 /* being unlinked from hc */
+#define ED_OPER 0x02 /* IS linked to hc */
u8 type; /* PIPE_{BULK,...} */
u16 interval; /* interrupt, isochronous */
@@ -53,7 +59,6 @@ struct ed {
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
u16 tick;
- struct ed *ed_rm_list;
} __attribute__ ((aligned(16)));
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
@@ -396,5 +401,5 @@ struct ohci_hcd {
struct usb_hcd hcd;
};
-#define hcd_to_ohci(hcd_ptr) list_entry(hcd_ptr, struct ohci_hcd, hcd)
+#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
index 0fa9036358dc..6d726223090a 100644
--- a/drivers/usb/image/scanner.h
+++ b/drivers/usb/image/scanner.h
@@ -93,9 +93,12 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
/* Canon */
- { USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
+ { USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */
+ { USB_DEVICE(0x04a9, 0x2204) }, /* CanoScan FB630U/FB636U */
+ { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */
+ { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */
+ { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */
{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
- { USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
/* Colorado -- See Primax/Colorado below */
/* Epson -- See Seiko/Epson below */
/* Genius */
diff --git a/drivers/usb/input/Config.help b/drivers/usb/input/Config.help
index aad9102e43ae..58370e3c6c46 100644
--- a/drivers/usb/input/Config.help
+++ b/drivers/usb/input/Config.help
@@ -18,28 +18,35 @@ CONFIG_USB_HID
CONFIG_USB_HIDINPUT
Say Y here if you want to use a USB keyboard, mouse or joystick,
- or any other HID input device. You also need Input layer support,
- (CONFIG_INPUT) which you select under "Input core support".
+ or any other HID input device. You also need "Input core support",
+ (CONFIG_INPUT), which you select under "Input device support", above.
If unsure, say Y.
CONFIG_HID_FF
- Say Y here is you want force feedback support for a few hid devices. See
+ Say Y here is you want force feedback support for a few HID devices. See
below for a list of supported devices.
See Documentation/input/ff.txt for a description of the force feedback API.
If unsure, say N.
-CONFIG_LOGITECH_RUMBLE
- Say Y here if you have a Logitech WingMan Cordless rumble pad and if you
- want to enable force feedback. Note: if you say N here, this device will
- still be supported, but without force feedback.
+CONFIG_LOGITECH_FF
+ Say Y here if you have one of these devices:
+ - Logitech WingMan Cordless RumblePad
+ - Logitech WingMan Force 3D
+ and if you want to enable force feedback for them.
+ Note: if you say N here, this device will still be supported, but without
+ force feedback.
CONFIG_HID_PID
- Say Y yes if you have a PID-compliant joystick and wish to enable force
+ Say Y here if you have a PID-compliant joystick and wish to enable force
feedback for it. The Microsoft Sidewinder Force Feedback 2 is one such
device.
+CONFIG_LOGITECH_3D
+ Say Y here if you have a Logitech force feedback device from the
+ *3D family.
+
CONFIG_USB_HIDDEV
Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface
diff --git a/drivers/usb/input/Config.in b/drivers/usb/input/Config.in
index 9c354df9e1a1..9eef9842e6b5 100644
--- a/drivers/usb/input/Config.in
+++ b/drivers/usb/input/Config.in
@@ -11,8 +11,7 @@ fi
dep_mbool ' HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID
dep_mbool ' Force feedback support (EXPERIMENTAL)' CONFIG_HID_FF $CONFIG_USB_HIDINPUT $CONFIG_EXPERIMENTAL
dep_mbool ' PID Devices' CONFIG_HID_PID $CONFIG_USB_HID $CONFIG_HID_FF
-dep_mbool ' Logitech RumblePad support' CONFIG_LOGITECH_RUMBLE $CONFIG_USB_HID $CONFIG_HID_FF
-dep_mbool ' Logitech WingMan Force 3D support' CONFIG_LOGITECH_3D $CONFIG_USB_HID $CONFIG_HID_FF
+dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_HID $CONFIG_HID_FF
dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
if [ "$CONFIG_USB_HID" != "y" ]; then
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 610e68ca25dd..5e324c467793 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -16,12 +16,9 @@ endif
ifeq ($(CONFIG_HID_PID),y)
hid-objs += pid.o
endif
-ifeq ($(CONFIG_LOGITECH_RUMBLE),y)
+ifeq ($(CONFIG_LOGITECH_FF),y)
hid-objs += hid-lgff.o
endif
-ifeq ($(CONFIG_LOGITECH_3D),y)
- hid-objs += hid-lg3dff.o
-endif
ifeq ($(CONFIG_HID_FF),y)
hid-objs += hid-ff.o
endif
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h
index 1b3066daea1f..e20fa1a44b35 100644
--- a/drivers/usb/input/fixp-arith.h
+++ b/drivers/usb/input/fixp-arith.h
@@ -66,7 +66,13 @@ inline fixp_t fixp_new16(s16 a)
inline fixp_t fixp_cos(unsigned int degrees)
{
int quadrant = (degrees / 90) & 3;
- unsigned int i = (degrees % 90) >> 1;
+ unsigned int i = degrees % 90;
+
+ if (quadrant == 1 || quadrant == 3) {
+ i = 89 - i;
+ }
+
+ i >>= 1;
return (quadrant == 1 || quadrant == 2)? -cos_table[i] : cos_table[i];
}
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 8c941083376c..b5743d2ac59b 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1281,10 +1281,8 @@ void hid_init_reports(struct hid_device *hid)
usb_unlink_urb(hid->urbout);
}
- if (err) {
+ if (err)
warn("timeout initializing reports\n");
- return;
- }
report_enum = hid->report_enum + HID_INPUT_REPORT;
list = report_enum->report_list.next;
@@ -1551,8 +1549,8 @@ static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
}
static struct usb_device_id hid_usb_ids [] = {
- { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
- bInterfaceClass: USB_INTERFACE_CLASS_HID },
+ { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
+ .bInterfaceClass = USB_INTERFACE_CLASS_HID },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index dc0fcaf424fa..ad6d27769db2 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -1,5 +1,5 @@
/*
- * $Id: hid-ff.c,v 1.3 2002/06/09 11:06:38 jdeneux Exp $
+ * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $
*
* Force feedback support for hid devices.
* Not all hid devices use the same protocol. For example, some use PID,
@@ -44,17 +44,15 @@ extern int hid_pid_init(struct hid_device* hid);
* devices, you need to add the USB vendor and product ids here.
*/
struct hid_ff_initializer {
- __u16 idVendor;
- __u16 idProduct;
+ u16 idVendor;
+ u16 idProduct;
int (*init)(struct hid_device*);
};
static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_RUMBLE
+#ifdef CONFIG_LOGITECH_FF
{0x46d, 0xc211, hid_lgff_init},
-#endif
-#ifdef CONFIG_LOGITECH_3D
- {0x46d, 0xc283, hid_lg3d_init},
+ {0x46d, 0xc283, hid_lgff_init},
#endif
#ifdef CONFIG_HID_PID
{0x45e, 0x001b, hid_pid_init},
@@ -68,8 +66,8 @@ static struct hid_ff_initializer *hid_get_ff_init(__u16 idVendor,
struct hid_ff_initializer *init;
for (init = inits;
init->idVendor
- && !(init->idVendor == idVendor
- && init->idProduct == idProduct);
+ && !(init->idVendor == idVendor
+ && init->idProduct == idProduct);
init++);
return init->idVendor? init : NULL;
diff --git a/drivers/usb/input/hid-lg3dff.c b/drivers/usb/input/hid-lg3dff.c
deleted file mode 100644
index b9f5636dd614..000000000000
--- a/drivers/usb/input/hid-lg3dff.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * $$
- *
- * Force feedback support for hid-compliant devices of the Logitech *3D family
- *
- * Copyright (c) 2002 Johann Deneux
- */
-
-/*
- * This program is free software; you can redistribute 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
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <deneux@ifrance.com>
- */
-
-#include <linux/input.h>
-#include <linux/sched.h>
-
-#define DEBUG
-#include <linux/usb.h>
-
-#include <linux/circ_buf.h>
-
-#include "hid.h"
-#include "fixp-arith.h"
-
-#define RUN_AT(t) (jiffies + (t))
-
-/* Periodicity of the update */
-#define PERIOD (HZ/10)
-
-/* Effect status: lg3d_effect::flags */
-#define EFFECT_STARTED 0 /* Effect is going to play after some time
- (ff_replay.delay) */
-#define EFFECT_PLAYING 1 /* Effect is being played */
-#define EFFECT_USED 2
-
-/* Check that the current process can access an effect */
-#define CHECK_OWNERSHIP(i, l) \
- (i>=0 && i<N_EFFECTS \
- && test_bit(EFFECT_USED, l->effects[i].flags) \
- && (current->pid == 0 \
- || l->effects[i].owner == current->pid))
-
-#define N_EFFECTS 8
-
-struct lg3d_effect {
- pid_t owner;
-
- struct ff_effect effect; /* Description of the effect */
-
- unsigned int count; /* Number of times left to play */
- unsigned long flags[1];
-
- unsigned long started_at; /* When the effect started to play */
-};
-
-// For lg3d_device::flags
-#define DEVICE_USB_XMIT 0 /* An URB is being sent */
-#define DEVICE_CLOSING 1 /* The driver is being unitialised */
-
-struct lg3d_device {
- struct hid_device* hid;
-
- struct urb* urbffout; /* Output URB used to send ff commands */
- struct usb_ctrlrequest ffcr; /* ff commands use control URBs */
- char buf[8];
-
- struct lg3d_effect effects[N_EFFECTS];
- spinlock_t lock; /* device-level lock. Having locks on
- a per-effect basis could be nice, but
- isn't really necessary */
- struct timer_list timer;
- unsigned long last_time; /* Last time the timer handler was
- executed */
-
- unsigned long flags[1]; /* Contains various information about the
- state of the driver for this device */
-};
-
-static void hid_lg3d_ctrl_out(struct urb *urb);
-static void hid_lg3d_exit(struct hid_device* hid);
-static int hid_lg3d_event(struct hid_device *hid, struct input_dev *input,
- unsigned int type, unsigned int code, int value);
-static int hid_lg3d_flush(struct input_dev *input, struct file *file);
-static int hid_lg3d_upload_effect(struct input_dev *input,
- struct ff_effect *effect);
-static int hid_lg3d_erase(struct input_dev *input, int id);
-static void hid_lg3d_timer(unsigned long timer_data);
-
-
-int hid_lg3d_init(struct hid_device* hid)
-{
- struct lg3d_device *private;
-
- /* Private data */
- private = kmalloc(sizeof(struct lg3d_device), GFP_KERNEL);
- if (!private) return -1;
-
- memset(private, 0, sizeof(struct lg3d_device));
-
- hid->ff_private = private;
-
- private->hid = hid;
- spin_lock_init(&private->lock);
-
- /* Timer for the periodic update task */
- init_timer(&private->timer);
- private->timer.data = (unsigned long)private;
- private->timer.function = hid_lg3d_timer;
-
- /* Event and exit callbacks */
- hid->ff_exit = hid_lg3d_exit;
- hid->ff_event = hid_lg3d_event;
-
- /* USB init */
- if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
- kfree(hid->ff_private);
- return -1;
- }
-
- usb_fill_control_urb(private->urbffout, hid->dev, 0,
- (void*) &private->ffcr, private->buf, 8,
- hid_lg3d_ctrl_out, hid);
- dbg("Created ff output control urb");
-
- /* Input init */
- hid->input.upload_effect = hid_lg3d_upload_effect;
- hid->input.flush = hid_lg3d_flush;
- set_bit(FF_CONSTANT, hid->input.ffbit);
- set_bit(EV_FF, hid->input.evbit);
- hid->input.ff_effects_max = N_EFFECTS;
-
- printk(KERN_INFO "Force feedback for Logitech *3D devices by Johann Deneux <deneux@ifrance.com>\n");
-
- /* Start the update task */
- private->timer.expires = RUN_AT(PERIOD);
- add_timer(&private->timer); /*TODO: only run the timer when at least
- one effect is playing */
-
- return 0;
-}
-
-static void hid_lg3d_exit(struct hid_device* hid)
-{
- struct lg3d_device *lg3d = hid->ff_private;
- unsigned long flags;
-
- spin_lock_irqsave(&lg3d->lock, flags);
- set_bit(DEVICE_CLOSING, lg3d->flags);
- spin_unlock_irqrestore(&lg3d->lock, flags);
-
- del_timer_sync(&lg3d->timer);
-
- if (lg3d->urbffout) {
- usb_unlink_urb(lg3d->urbffout);
- usb_free_urb(lg3d->urbffout);
- }
-
- kfree(lg3d);
-}
-
-static int hid_lg3d_event(struct hid_device *hid, struct input_dev* input,
- unsigned int type, unsigned int code, int value)
-{
- struct lg3d_device *lg3d = hid->ff_private;
- struct lg3d_effect *effect = lg3d->effects + code;
- unsigned long flags;
-
- if (type != EV_FF) return -EINVAL;
- if (!CHECK_OWNERSHIP(code, lg3d)) return -EACCES;
- if (value < 0) return -EINVAL;
-
- spin_lock_irqsave(&lg3d->lock, flags);
-
- if (value > 0) {
- if (test_bit(EFFECT_STARTED, effect->flags)) {
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return -EBUSY;
- }
- if (test_bit(EFFECT_PLAYING, effect->flags)) {
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return -EBUSY;
- }
-
- effect->count = value;
-
- if (effect->effect.replay.delay) {
- set_bit(EFFECT_STARTED, effect->flags);
- } else {
- set_bit(EFFECT_PLAYING, effect->flags);
- }
- effect->started_at = jiffies;
- }
- else { /* value == 0 */
- clear_bit(EFFECT_STARTED, effect->flags);
- clear_bit(EFFECT_PLAYING, effect->flags);
- }
-
- spin_unlock_irqrestore(&lg3d->lock, flags);
-
- return 0;
-}
-
-/* Erase all effects this process owns */
-static int hid_lg3d_flush(struct input_dev *dev, struct file *file)
-{
- struct hid_device *hid = dev->private;
- struct lg3d_device *lg3d = hid->ff_private;
- int i;
-
- for (i=0; i<dev->ff_effects_max; ++i) {
-
- /*NOTE: no need to lock here. The only times EFFECT_USED is
- modified is when effects are uploaded or when an effect is
- erased. But a process cannot close its dev/input/eventX fd
- and perform ioctls on the same fd all at the same time */
- if ( current->pid == lg3d->effects[i].owner
- && test_bit(EFFECT_USED, lg3d->effects[i].flags)) {
-
- if (hid_lg3d_erase(dev, i))
- warn("erase effect %d failed", i);
- }
-
- }
-
- return 0;
-}
-
-static int hid_lg3d_erase(struct input_dev *dev, int id)
-{
- struct hid_device *hid = dev->private;
- struct lg3d_device *lg3d = hid->ff_private;
- unsigned long flags;
-
- if (!CHECK_OWNERSHIP(id, lg3d)) return -EACCES;
-
- spin_lock_irqsave(&lg3d->lock, flags);
- lg3d->effects[id].flags[0] = 0;
- spin_unlock_irqrestore(&lg3d->lock, flags);
-
- return 0;
-}
-
-static int hid_lg3d_upload_effect(struct input_dev* input,
- struct ff_effect* effect)
-{
- struct hid_device *hid = input->private;
- struct lg3d_device *lg3d = hid->ff_private;
- struct lg3d_effect new;
- int id;
- unsigned long flags;
-
- dbg("ioctl upload");
-
- if (!test_bit(effect->type, input->ffbit)) return -EINVAL;
-
- if (effect->type != FF_CONSTANT) return -EINVAL;
-
- spin_lock_irqsave(&lg3d->lock, flags);
-
- if (effect->id == -1) {
- int i;
-
- for (i=0; i<N_EFFECTS && test_bit(EFFECT_USED, lg3d->effects[i].flags); ++i);
- if (i >= N_EFFECTS) {
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return -ENOSPC;
- }
-
- effect->id = i;
- lg3d->effects[i].owner = current->pid;
- lg3d->effects[i].flags[0] = 0;
- set_bit(EFFECT_USED, lg3d->effects[i].flags);
- }
- else if (!CHECK_OWNERSHIP(effect->id, lg3d)) {
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return -EACCES;
- }
-
- id = effect->id;
- new = lg3d->effects[id];
-
- new.effect = *effect;
- new.effect.replay = effect->replay;
-
- if (test_bit(EFFECT_STARTED, lg3d->effects[id].flags)
- || test_bit(EFFECT_STARTED, lg3d->effects[id].flags)) {
-
- /* Changing replay parameters is not allowed (for the time
- being) */
- if (new.effect.replay.delay != lg3d->effects[id].effect.replay.delay
- || new.effect.replay.length != lg3d->effects[id].effect.replay.length) {
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return -ENOSYS;
- }
-
- lg3d->effects[id] = new;
-
- } else {
- lg3d->effects[id] = new;
- }
-
- spin_unlock_irqrestore(&lg3d->lock, flags);
- return 0;
-}
-
-static void hid_lg3d_ctrl_out(struct urb *urb)
-{
- struct hid_device *hid = urb->context;
- struct lg3d_device *lg3d = hid->ff_private;
- unsigned long flags;
-
- spin_lock_irqsave(&lg3d->lock, flags);
-
- if (urb->status)
- warn("hid_irq_ffout status %d received", urb->status);
- clear_bit(DEVICE_USB_XMIT, lg3d->flags);
- dbg("xmit = 0");
-
- spin_unlock_irqrestore(&lg3d->lock, flags);
-}
-
-static void hid_lg3d_timer(unsigned long timer_data)
-{
- struct lg3d_device *lg3d = (struct lg3d_device*)timer_data;
- struct hid_device *hid = lg3d->hid;
- unsigned long flags;
- int x, y;
- int i;
- int err;
-
- spin_lock_irqsave(&lg3d->lock, flags);
-
- if (test_bit(DEVICE_USB_XMIT, lg3d->flags)) {
- if (lg3d->urbffout->status != -EINPROGRESS) {
- warn("xmit *not* in progress");
- }
- else {
- dbg("xmit in progress");
- }
-
- spin_unlock_irqrestore(&lg3d->lock, flags);
-
- lg3d->timer.expires = RUN_AT(PERIOD);
- add_timer(&lg3d->timer);
-
- return;
- }
-
- x = 0x7f;
- y = 0x7f;
-
- for (i=0; i<N_EFFECTS; ++i) {
- struct lg3d_effect* effect = lg3d->effects +i;
-
- if (test_bit(EFFECT_PLAYING, effect->flags)) {
-
- if (effect->effect.type == FF_CONSTANT) {
- //TODO: handle envelopes
- int degrees = effect->effect.direction * 360 >> 16;
- x += fixp_mult(fixp_sin(degrees),
- fixp_new16(effect->effect.u.constant.level));
- y += fixp_mult(-fixp_cos(degrees),
- fixp_new16(effect->effect.u.constant.level));
- }
-
- /* One run of the effect is finished playing */
- if (time_after(jiffies,
- effect->started_at
- + effect->effect.replay.delay*HZ/1000
- + effect->effect.replay.length*HZ/1000)) {
- dbg("Finished playing once");
- if (--effect->count <= 0) {
- dbg("Stopped");
- clear_bit(EFFECT_PLAYING, effect->flags);
- }
- else {
- dbg("Start again");
- if (effect->effect.replay.length != 0) {
- clear_bit(EFFECT_PLAYING, effect->flags);
- set_bit(EFFECT_STARTED, effect->flags);
- }
- effect->started_at = jiffies;
- }
- }
-
- } else if (test_bit(EFFECT_STARTED, lg3d->effects[i].flags)) {
- dbg("Started");
- /* Check if we should start playing the effect */
- if (time_after(jiffies,
- lg3d->effects[i].started_at
- + lg3d->effects[i].effect.replay.delay*HZ/1000)) {
- dbg("Now playing");
- clear_bit(EFFECT_STARTED, lg3d->effects[i].flags);
- set_bit(EFFECT_PLAYING, lg3d->effects[i].flags);
- }
- }
- }
-
- if (x < 0) x = 0;
- if (x > 0xff) x = 0xff;
- if (y < 0) y = 0;
- if (y > 0xff) y = 0xff;
-
- lg3d->urbffout->pipe = usb_sndctrlpipe(hid->dev, 0);
- lg3d->ffcr.bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
- lg3d->urbffout->transfer_buffer_length = lg3d->ffcr.wLength = 8;
- lg3d->ffcr.bRequest = 9;
- lg3d->ffcr.wValue = 0x0200; /*NOTE: Potential problem with
- little/big endian */
- lg3d->ffcr.wIndex = 0;
-
- lg3d->urbffout->dev = hid->dev;
-
- lg3d->buf[0] = 0x51;
- lg3d->buf[1] = 0x08;
- lg3d->buf[2] = x;
- lg3d->buf[3] = y;
-
- if ((err=usb_submit_urb(lg3d->urbffout, GFP_ATOMIC)))
- warn("usb_submit_urb returned %d", err);
- else
- set_bit(DEVICE_USB_XMIT, lg3d->flags);
-
- if (!test_bit(DEVICE_CLOSING, lg3d->flags)) {
- lg3d->timer.expires = RUN_AT(PERIOD);
- add_timer(&lg3d->timer);
- }
-
- spin_unlock_irqrestore(&lg3d->lock, flags);
-}
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 8ae5cf004cfa..788c171c7b6f 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -4,6 +4,7 @@
* Force feedback support for hid-compliant for some of the devices from
* Logitech, namely:
* - WingMan Cordless RumblePad
+ * - WingMan Force 3D
*
* Copyright (c) 2002 Johann Deneux
*/
@@ -36,6 +37,11 @@
#include <linux/circ_buf.h>
#include "hid.h"
+#include "fixp-arith.h"
+
+
+/* Periodicity of the update */
+#define PERIOD (HZ/10)
#define RUN_AT(t) (jiffies + (t))
@@ -48,145 +54,243 @@
#define EFFECT_PLAYING 1 /* Effect is being played */
#define EFFECT_USED 2
+// For lgff_device::flags
+#define DEVICE_CLOSING 0 /* The driver is being unitialised */
+
/* Check that the current process can access an effect */
#define CHECK_OWNERSHIP(effect) (current->pid == 0 \
|| effect.owner == current->pid)
-/* **************************************************************************/
-/* Implements the protocol used by the Logitech WingMan Cordless RumblePad */
-/* **************************************************************************/
-
#define LGFF_CHECK_OWNERSHIP(i, l) \
(i>=0 && i<LGFF_EFFECTS \
&& test_bit(EFFECT_USED, l->effects[i].flags) \
&& CHECK_OWNERSHIP(l->effects[i]))
-#define LGFF_BUFFER_SIZE 64
#define LGFF_EFFECTS 8
-struct lgff_magnitudes {
- unsigned char left;
- unsigned char right;
+struct device_type {
+ u16 idVendor;
+ u16 idProduct;
+ signed short *ff;
};
struct lgff_effect {
- int id;
- struct hid_ff_logitech* lgff;
-
pid_t owner;
- unsigned char left; /* Magnitude of vibration for left motor */
- unsigned char right; /* Magnitude of vibration for right motor */
- struct ff_replay replay;
- unsigned int count; /* Number of times to play */
- struct timer_list timer;
+
+ struct ff_effect effect;
+
unsigned long flags[1];
+ unsigned int count; /* Number of times left to play */
+ unsigned long started_at; /* When the effect started to play */
};
-struct hid_ff_logitech {
+struct lgff_device {
struct hid_device* hid;
- struct urb* urbffout; /* Output URB used to send ff commands */
- struct usb_ctrlrequest ffcr; /* ff commands use control URBs */
- char buf[8];
-
- spinlock_t xmit_lock;
- unsigned int xmit_head, xmit_tail;
- struct lgff_magnitudes xmit_data[LGFF_BUFFER_SIZE];
- long xmit_flags[1];
+ struct hid_report* constant;
+ struct hid_report* rumble;
+ struct hid_report* condition;
struct lgff_effect effects[LGFF_EFFECTS];
spinlock_t lock; /* device-level lock. Having locks on
a per-effect basis could be nice, but
isn't really necessary */
+
+ unsigned long flags[1]; /* Contains various information about the
+ state of the driver for this device */
+
+ struct timer_list timer;
};
-static void hid_lgff_ctrl_out(struct urb *urb);
+/* Callbacks */
static void hid_lgff_exit(struct hid_device* hid);
static int hid_lgff_event(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value);
-static void hid_lgff_make_rumble(struct hid_device* hid);
-
static int hid_lgff_flush(struct input_dev *input, struct file *file);
static int hid_lgff_upload_effect(struct input_dev *input,
struct ff_effect *effect);
static int hid_lgff_erase(struct input_dev *input, int id);
-static void hid_lgff_ctrl_playback(struct hid_device* hid, struct lgff_effect*,
- int play);
+
+/* Local functions */
+static void hid_lgff_input_init(struct hid_device* hid);
static void hid_lgff_timer(unsigned long timer_data);
+static struct hid_report* hid_lgff_duplicate_report(struct hid_report*);
+static void hid_lgff_delete_report(struct hid_report*);
+
+static signed short ff_rumble[] = {
+ FF_RUMBLE,
+ -1
+};
+
+static signed short ff_joystick[] = {
+ FF_CONSTANT,
+ -1
+};
+static struct device_type devices[] = {
+ {0x046d, 0xc211, ff_rumble},
+ {0x046d, 0xc283, ff_joystick},
+ {0x0000, 0x0000, ff_joystick}
+};
int hid_lgff_init(struct hid_device* hid)
{
- struct hid_ff_logitech *private;
- int i;
-
- /* Private data */
- private = kmalloc(sizeof(struct hid_ff_logitech), GFP_KERNEL);
- if (!private) return -1;
+ struct lgff_device *private;
+ struct hid_report* report;
+ struct hid_field* field;
- memset(private, 0, sizeof(struct hid_ff_logitech));
+ /* Find the report to use */
+ if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
+ err("No output report found");
+ return -1;
+ }
+ /* Check that the report looks ok */
+ report = (struct hid_report*)hid->report_enum[HID_OUTPUT_REPORT].report_list.next;
+ if (!report) {
+ err("NULL output report");
+ return -1;
+ }
+ field = report->field[0];
+ if (!field) {
+ err("NULL field");
+ return -1;
+ }
+ private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL);
+ if (!private) return -1;
+ memset(private, 0, sizeof(struct lgff_device));
hid->ff_private = private;
- private->hid = hid;
- spin_lock_init(&private->lock);
- spin_lock_init(&private->xmit_lock);
+ /* Input init */
+ hid_lgff_input_init(hid);
+
- private->buf[0] = 0x03;
- private->buf[1] = 0x42;
+ private->constant = hid_lgff_duplicate_report(report);
+ if (!private->constant) {
+ kfree(private);
+ return -1;
+ }
+ private->constant->field[0]->value[0] = 0x51;
+ private->constant->field[0]->value[1] = 0x08;
+ private->constant->field[0]->value[2] = 0x7f;
+ private->constant->field[0]->value[3] = 0x7f;
+
+ private->rumble = hid_lgff_duplicate_report(report);
+ if (!private->rumble) {
+ hid_lgff_delete_report(private->constant);
+ kfree(private);
+ return -1;
+ }
+ private->rumble->field[0]->value[0] = 0x03;
+ private->rumble->field[0]->value[1] = 0x42;
- for (i=0; i<LGFF_EFFECTS; ++i) {
- struct lgff_effect* effect = &private->effects[i];
- struct timer_list* timer = &effect->timer;
- init_timer(timer);
- effect->id = i;
- effect->lgff = private;
- timer->data = (unsigned long)effect;
- timer->function = hid_lgff_timer;
+ private->condition = hid_lgff_duplicate_report(report);
+ if (!private->condition) {
+ hid_lgff_delete_report(private->rumble);
+ hid_lgff_delete_report(private->constant);
+ kfree(private);
+ return -1;
}
+ private->hid = hid;
+
+ spin_lock_init(&private->lock);
+ init_timer(&private->timer);
+ private->timer.data = (unsigned long)private;
+ private->timer.function = hid_lgff_timer;
+
/* Event and exit callbacks */
hid->ff_exit = hid_lgff_exit;
hid->ff_event = hid_lgff_event;
- /* USB init */
- if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
- kfree(hid->ff_private);
- return -1;
+ /* Start the update task */
+ private->timer.expires = RUN_AT(PERIOD);
+ add_timer(&private->timer); /*TODO: only run the timer when at least
+ one effect is playing */
+
+ printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <deneux@ifrance.com>\n");
+
+ return 0;
+}
+
+static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report)
+{
+ struct hid_report* ret;
+
+ ret = kmalloc(sizeof(struct lgff_device), GFP_KERNEL);
+ if (!ret) return NULL;
+ *ret = *report;
+
+ ret->field[0] = kmalloc(sizeof(struct hid_field), GFP_KERNEL);
+ if (!ret->field[0]) {
+ kfree(ret);
+ return NULL;
}
+ *ret->field[0] = *report->field[0];
- usb_fill_control_urb(private->urbffout, hid->dev, 0,
- (void*) &private->ffcr, private->buf, 8,
- hid_lgff_ctrl_out, hid);
- dbg("Created ff output control urb");
+ ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL);
+ if (!ret->field[0]->value) {
+ kfree(ret->field[0]);
+ kfree(ret);
+ return NULL;
+ }
+ memset(ret->field[0]->value, 0, sizeof(s32[8]));
+
+ return ret;
+}
+
+static void hid_lgff_delete_report(struct hid_report* report)
+{
+ if (report) {
+ kfree(report->field[0]->value);
+ kfree(report->field[0]);
+ kfree(report);
+ }
+}
+
+static void hid_lgff_input_init(struct hid_device* hid)
+{
+ struct device_type* dev = devices;
+ signed short* ff;
+ u16 idVendor = hid->dev->descriptor.idVendor;
+ u16 idProduct = hid->dev->descriptor.idProduct;
+
+ while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct))
+ dev++;
+
+ ff = dev->ff;
+
+ while (*ff >= 0) {
+ set_bit(*ff, hid->input.ffbit);
+ ++ff;
+ }
- /* Input init */
hid->input.upload_effect = hid_lgff_upload_effect;
hid->input.flush = hid_lgff_flush;
- set_bit(FF_RUMBLE, hid->input.ffbit);
+
set_bit(EV_FF, hid->input.evbit);
hid->input.ff_effects_max = LGFF_EFFECTS;
-
- printk(KERN_INFO "Force feedback for Logitech rumble devices by Johann Deneux <deneux@ifrance.com>\n");
-
- return 0;
}
static void hid_lgff_exit(struct hid_device* hid)
{
- struct hid_ff_logitech *lgff = hid->ff_private;
+ struct lgff_device *lgff = hid->ff_private;
- if (lgff->urbffout) {
- usb_unlink_urb(lgff->urbffout);
- usb_free_urb(lgff->urbffout);
- }
+ set_bit(DEVICE_CLOSING, lgff->flags);
+ del_timer_sync(&lgff->timer);
+
+ hid_lgff_delete_report(lgff->condition);
+ hid_lgff_delete_report(lgff->rumble);
+ hid_lgff_delete_report(lgff->constant);
+
+ kfree(lgff);
}
static int hid_lgff_event(struct hid_device *hid, struct input_dev* input,
unsigned int type, unsigned int code, int value)
{
- struct hid_ff_logitech *lgff = hid->ff_private;
+ struct lgff_device *lgff = hid->ff_private;
struct lgff_effect *effect = lgff->effects + code;
unsigned long flags;
@@ -208,27 +312,16 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input,
effect->count = value;
- if (effect->replay.delay) {
+ if (effect->effect.replay.delay) {
set_bit(EFFECT_STARTED, effect->flags);
- effect->timer.expires = RUN_AT(effect->replay.delay * HZ / 1000);
} else {
- hid_lgff_ctrl_playback(hid, effect, value);
- effect->timer.expires = RUN_AT(effect->replay.length * HZ / 1000);
+ set_bit(EFFECT_PLAYING, effect->flags);
}
-
- add_timer(&effect->timer);
+ effect->started_at = jiffies;
}
else { /* value == 0 */
- if (test_and_clear_bit(EFFECT_STARTED, effect->flags)) {
- del_timer(&effect->timer);
-
- } else if (test_and_clear_bit(EFFECT_PLAYING, effect->flags)) {
- del_timer(&effect->timer);
- hid_lgff_ctrl_playback(hid, effect, value);
- }
-
- if (test_bit(EFFECT_PLAYING, effect->flags))
- warn("Effect %d still playing", code);
+ clear_bit(EFFECT_STARTED, effect->flags);
+ clear_bit(EFFECT_PLAYING, effect->flags);
}
spin_unlock_irqrestore(&lgff->lock, flags);
@@ -241,7 +334,7 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input,
static int hid_lgff_flush(struct input_dev *dev, struct file *file)
{
struct hid_device *hid = dev->private;
- struct hid_ff_logitech *lgff = hid->ff_private;
+ struct lgff_device *lgff = hid->ff_private;
int i;
for (i=0; i<dev->ff_effects_max; ++i) {
@@ -265,13 +358,12 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file)
static int hid_lgff_erase(struct input_dev *dev, int id)
{
struct hid_device *hid = dev->private;
- struct hid_ff_logitech *lgff = hid->ff_private;
+ struct lgff_device *lgff = hid->ff_private;
unsigned long flags;
if (!LGFF_CHECK_OWNERSHIP(id, lgff)) return -EACCES;
spin_lock_irqsave(&lgff->lock, flags);
- hid_lgff_ctrl_playback(hid, lgff->effects + id, 0);
lgff->effects[id].flags[0] = 0;
spin_unlock_irqrestore(&lgff->lock, flags);
@@ -282,7 +374,7 @@ static int hid_lgff_upload_effect(struct input_dev* input,
struct ff_effect* effect)
{
struct hid_device *hid = input->private;
- struct hid_ff_logitech *lgff = hid->ff_private;
+ struct lgff_device *lgff = hid->ff_private;
struct lgff_effect new;
int id;
unsigned long flags;
@@ -291,8 +383,6 @@ static int hid_lgff_upload_effect(struct input_dev* input,
if (!test_bit(effect->type, input->ffbit)) return -EINVAL;
- if (effect->type != FF_RUMBLE) return -EINVAL;
-
spin_lock_irqsave(&lgff->lock, flags);
if (effect->id == -1) {
@@ -317,25 +407,20 @@ static int hid_lgff_upload_effect(struct input_dev* input,
id = effect->id;
new = lgff->effects[id];
- new.right = effect->u.rumble.strong_magnitude >> 9;
- new.left = effect->u.rumble.weak_magnitude >> 9;
- new.replay = effect->replay;
+ new.effect = *effect;
- /* If we updated an effect that was being played, we need to remake
- the rumble effect */
if (test_bit(EFFECT_STARTED, lgff->effects[id].flags)
|| test_bit(EFFECT_STARTED, lgff->effects[id].flags)) {
/* Changing replay parameters is not allowed (for the time
being) */
- if (new.replay.delay != lgff->effects[id].replay.delay
- || new.replay.length != lgff->effects[id].replay.length) {
+ if (new.effect.replay.delay != lgff->effects[id].effect.replay.delay
+ || new.effect.replay.length != lgff->effects[id].effect.replay.length) {
spin_unlock_irqrestore(&lgff->lock, flags);
return -ENOSYS;
}
lgff->effects[id] = new;
- hid_lgff_make_rumble(hid);
} else {
lgff->effects[id] = new;
@@ -345,151 +430,99 @@ static int hid_lgff_upload_effect(struct input_dev* input,
return 0;
}
-static void hid_lgff_xmit(struct hid_device* hid)
+static void hid_lgff_timer(unsigned long timer_data)
{
- struct hid_ff_logitech *lgff = hid->ff_private;
- int err;
- int tail;
+ struct lgff_device *lgff = (struct lgff_device*)timer_data;
+ struct hid_device *hid = lgff->hid;
unsigned long flags;
-
- spin_lock_irqsave(&lgff->xmit_lock, flags);
-
- tail = lgff->xmit_tail;
- if (lgff->xmit_head == tail) {
- clear_bit(XMIT_RUNNING, lgff->xmit_flags);
- spin_unlock_irqrestore(&lgff->xmit_lock, flags);
- return;
- }
- lgff->buf[3] = lgff->xmit_data[tail].left;
- lgff->buf[4] = lgff->xmit_data[tail].right;
- tail++; tail &= LGFF_BUFFER_SIZE -1;
- lgff->xmit_tail = tail;
-
- spin_unlock_irqrestore(&lgff->xmit_lock, flags);
-
- lgff->urbffout->pipe = usb_sndctrlpipe(hid->dev, 0);
- lgff->ffcr.bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
- lgff->urbffout->transfer_buffer_length = lgff->ffcr.wLength = 8;
- lgff->ffcr.bRequest = 9;
- lgff->ffcr.wValue = 0x0203; /*NOTE: Potential problem with
- little/big endian */
- lgff->ffcr.wIndex = 0;
-
- lgff->urbffout->dev = hid->dev;
-
- if ((err=usb_submit_urb(lgff->urbffout, GFP_ATOMIC)))
- warn("usb_submit_urb returned %d", err);
-}
-
-static void hid_lgff_make_rumble(struct hid_device* hid)
-{
- struct hid_ff_logitech *lgff = hid->ff_private;
- int left = 0, right = 0;
+ int x = 0x7f, y = 0x7f; // Coordinates of constant effects
+ unsigned int left = 0, right = 0; // Rumbling
int i;
- int head, tail;
- unsigned long flags;
-
- for (i=0; i<LGFF_EFFECTS; ++i) {
- if (test_bit(EFFECT_USED, lgff->effects[i].flags)
- && test_bit(EFFECT_PLAYING, lgff->effects[i].flags)) {
- left += lgff->effects[i].left;
- right += lgff->effects[i].right;
- }
- }
-
- spin_lock_irqsave(&lgff->xmit_lock, flags);
- head = lgff->xmit_head;
- tail = lgff->xmit_tail;
-
- if (CIRC_SPACE(head, tail, LGFF_BUFFER_SIZE) < 1) {
- warn("not enough space in xmit buffer to send new packet");
- spin_unlock_irqrestore(&lgff->xmit_lock, flags);
- return;
- }
+ spin_lock_irqsave(&lgff->lock, flags);
- lgff->xmit_data[head].left = left > 0x7f ? 0x7f : left;
- lgff->xmit_data[head].right = right > 0x7f ? 0x7f : right;
- head++; head &= LGFF_BUFFER_SIZE -1;
- lgff->xmit_head = head;
+ for (i=0; i<LGFF_EFFECTS; ++i) {
+ struct lgff_effect* effect = lgff->effects +i;
- if (test_and_set_bit(XMIT_RUNNING, lgff->xmit_flags))
- spin_unlock_irqrestore(&lgff->xmit_lock, flags);
- else {
- spin_unlock_irqrestore(&lgff->xmit_lock, flags);
- hid_lgff_xmit(hid);
- }
-}
+ if (test_bit(EFFECT_PLAYING, effect->flags)) {
-static void hid_lgff_ctrl_out(struct urb *urb)
-{
- struct hid_device *hid = urb->context;
+ switch (effect->effect.type) {
+ case FF_CONSTANT: {
+ //TODO: handle envelopes
+ int degrees = effect->effect.direction * 360 >> 16;
+ x += fixp_mult(fixp_sin(degrees),
+ fixp_new16(effect->effect.u.constant.level));
+ y += fixp_mult(-fixp_cos(degrees),
+ fixp_new16(effect->effect.u.constant.level));
+ } break;
+ case FF_RUMBLE:
+ right += effect->effect.u.rumble.strong_magnitude;
+ left += effect->effect.u.rumble.weak_magnitude;
+ break;
+ };
+
+ /* One run of the effect is finished playing */
+ if (time_after(jiffies,
+ effect->started_at
+ + effect->effect.replay.delay*HZ/1000
+ + effect->effect.replay.length*HZ/1000)) {
+ dbg("Finished playing once %d", i);
+ if (--effect->count <= 0) {
+ dbg("Stopped %d", i);
+ clear_bit(EFFECT_PLAYING, effect->flags);
+ }
+ else {
+ dbg("Start again %d", i);
+ if (effect->effect.replay.length != 0) {
+ clear_bit(EFFECT_PLAYING, effect->flags);
+ set_bit(EFFECT_STARTED, effect->flags);
+ }
+ effect->started_at = jiffies;
+ }
+ }
+
+ } else if (test_bit(EFFECT_STARTED, lgff->effects[i].flags)) {
+ /* Check if we should start playing the effect */
+ if (time_after(jiffies,
+ lgff->effects[i].started_at
+ + lgff->effects[i].effect.replay.delay*HZ/1000)) {
+ dbg("Now playing %d", i);
+ clear_bit(EFFECT_STARTED, lgff->effects[i].flags);
+ set_bit(EFFECT_PLAYING, lgff->effects[i].flags);
+ }
+ }
+ }
- if (urb->status)
- warn("hid_irq_ffout status %d received", urb->status);
+#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
- hid_lgff_xmit(hid);
-}
+ // Clamp values
+ CLAMP(x);
+ CLAMP(y);
+ CLAMP(left);
+ CLAMP(right);
-/* Lock must be held by caller */
-static void hid_lgff_ctrl_playback(struct hid_device *hid,
- struct lgff_effect *effect, int play)
-{
- if (play) {
- set_bit(EFFECT_PLAYING, effect->flags);
- hid_lgff_make_rumble(hid);
+#undef CLAMP
- } else {
- clear_bit(EFFECT_PLAYING, effect->flags);
- hid_lgff_make_rumble(hid);
+ if (x != lgff->constant->field[0]->value[2]
+ || y != lgff->constant->field[0]->value[3]) {
+ lgff->constant->field[0]->value[2] = x;
+ lgff->constant->field[0]->value[3] = y;
+ dbg("(x,y)=(%04x, %04x)", x, y);
+ hid_submit_report(hid, lgff->constant, USB_DIR_OUT);
}
-}
-
-static void hid_lgff_timer(unsigned long timer_data)
-{
- struct lgff_effect *effect = (struct lgff_effect*) timer_data;
- struct hid_ff_logitech* lgff = effect->lgff;
- int id = effect->id;
- unsigned long flags;
-
- dbg("in hid_lgff_timer");
-
- if (id < 0 || id >= LGFF_EFFECTS) {
- warn("Bad effect id %d", id);
- return;
+ if (left != lgff->rumble->field[0]->value[3]
+ || right != lgff->rumble->field[0]->value[4]) {
+ lgff->rumble->field[0]->value[3] = left;
+ lgff->rumble->field[0]->value[4] = right;
+ dbg("(left,right)=(%04x, %04x)", left, right);
+ hid_submit_report(hid, lgff->rumble, USB_DIR_OUT);
}
- effect = lgff->effects + id;
-
- spin_lock_irqsave(&lgff->lock, flags);
-
- if (!test_bit(EFFECT_USED, effect->flags)) {
- warn("Unused effect id %d", id);
-
- } else if (test_bit(EFFECT_STARTED, effect->flags)) {
- clear_bit(EFFECT_STARTED, effect->flags);
- set_bit(EFFECT_PLAYING, effect->flags);
- hid_lgff_ctrl_playback(lgff->hid, effect, 1);
- effect->timer.expires = RUN_AT(effect->replay.length * HZ / 1000);
- add_timer(&effect->timer);
-
- dbg("Effect %d starts playing", id);
- } else if (test_bit(EFFECT_PLAYING, effect->flags)) {
- clear_bit(EFFECT_PLAYING, effect->flags);
- hid_lgff_ctrl_playback(lgff->hid, effect, 0);
- if (--effect->count > 0) {
- /*TODO: check that replay.delay is non-null */
- set_bit(EFFECT_STARTED, effect->flags);
- effect->timer.expires = RUN_AT(effect->replay.delay * HZ / 1000);
- add_timer(&effect->timer);
- dbg("Effect %d restarted", id);
- } else {
- dbg("Effect %d stopped", id);
- }
- } else {
- warn("Effect %d is not started nor playing", id);
+ if (!test_bit(DEVICE_CLOSING, lgff->flags)) {
+ lgff->timer.expires = RUN_AT(PERIOD);
+ add_timer(&lgff->timer);
}
- spin_unlock_irqrestore(&lgff->lock, flags);
+ spin_unlock_irqrestore(&lgff->lock, flags);
}
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index e4a3b59f5668..b204affb8954 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -321,13 +321,13 @@ struct wacom_features wacom_features[] = {
};
struct usb_device_id wacom_ids[] = {
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 0 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 1 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 2 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 },
- { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), .driver_info = 0 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), .driver_info = 1 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), .driver_info = 2 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), .driver_info = 3 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), .driver_info = 4 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), .driver_info = 5 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), .driver_info = 6 },
{ }
};
diff --git a/drivers/usb/misc/Config.help b/drivers/usb/misc/Config.help
index 34bde6d406cd..6321df2998c1 100644
--- a/drivers/usb/misc/Config.help
+++ b/drivers/usb/misc/Config.help
@@ -7,7 +7,7 @@ CONFIG_USB_AUERSWALD
The module will be called auerswald.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
-CONFIG_USB_BRLVOYAGER
+CONFIG_USB_BRLVGER
Say Y here if you want to use the Voyager USB Braille display from
Tieman. See <file:Documentation/usb/brlvger.txt> for more
information.
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 2dd226a3a4c7..2440fa92405a 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -212,10 +212,10 @@ static void emi26_disconnect(struct usb_device *dev, void *drv_context)
}
struct usb_driver emi26_driver = {
-name: "emi26 - firmware loader",
-probe: emi26_probe,
-disconnect: emi26_disconnect,
-id_table: NULL,
+.name = "emi26 - firmware loader",
+.probe = emi26_probe,
+.disconnect = emi26_disconnect,
+.id_table = NULL,
};
static int __init emi26_init (void)
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 6728f5cfd6ce..908d7b32ad59 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -62,7 +62,7 @@ static int multicast_filter_limit = 32;
static struct usb_eth_dev usb_dev_id[] = {
#define PEGASUS_DEV(pn, vid, pid, flags) \
- {name:pn, vendor:vid, device:pid, private:flags},
+ {.name = pn, .vendor = vid, .device = pid, .private = flags},
#include "pegasus.h"
#undef PEGASUS_DEV
{NULL, 0, 0, 0}
@@ -70,7 +70,7 @@ static struct usb_eth_dev usb_dev_id[] = {
static struct usb_device_id pegasus_ids[] = {
#define PEGASUS_DEV(pn, vid, pid, flags) \
- {match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid},
+ {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
#include "pegasus.h"
#undef PEGASUS_DEV
{}
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index c6ac7dd2821e..c5bc8e92c8cf 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -300,7 +300,7 @@ static const struct driver_info an2720_info = {
// no reset available!
// no check_connect available!
- .in = 2, out: 2, // direction distinguishes these
+ .in = 2, .out = 2, // direction distinguishes these
.epsize =64,
};
@@ -321,7 +321,7 @@ static const struct driver_info an2720_info = {
static const struct driver_info belkin_info = {
.description = "Belkin, eTEK, or compatible",
- .in = 1, out: 1, // direction distinguishes these
+ .in = 1, .out = 1, // direction distinguishes these
.epsize =64,
};
@@ -636,7 +636,7 @@ static const struct driver_info genelink_info = {
.rx_fixup = genelink_rx_fixup,
.tx_fixup = genelink_tx_fixup,
- .in = 1, out: 2,
+ .in = 1, .out = 2,
.epsize =64,
#ifdef GENELINK_ACK
@@ -674,7 +674,7 @@ static const struct driver_info linuxdev_info = {
.description = "Linux Device",
// no reset defined (yet?)
.check_connect =linuxdev_check_connect,
- .in = 2, out: 1,
+ .in = 2, .out = 1,
.epsize =64,
};
@@ -1125,7 +1125,7 @@ static const struct driver_info net1080_info = {
.rx_fixup = net1080_rx_fixup,
.tx_fixup = net1080_tx_fixup,
- .in = 1, out: 1, // direction distinguishes these
+ .in = 1, .out = 1, // direction distinguishes these
.epsize =64,
};
@@ -1192,7 +1192,7 @@ static const struct driver_info prolific_info = {
/* some PL-2302 versions seem to fail usb_set_interface() */
.reset = pl_reset,
- .in = 3, out: 2,
+ .in = 3, .out = 2,
.epsize =64,
};
diff --git a/drivers/usb/serial/Config.help b/drivers/usb/serial/Config.help
index a677b959551b..3a00c995da1b 100644
--- a/drivers/usb/serial/Config.help
+++ b/drivers/usb/serial/Config.help
@@ -268,6 +268,16 @@ CONFIG_USB_SERIAL_EDGEPORT
The module will be called io_edgeport.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
+CONFIG_USB_SERIAL_EDGEPORT_TI
+ Say Y here if you want to use any of the devices from Inside Out
+ Networks (Digi) that are not supported by the io_edgeport driver.
+ This includes the Edgeport/1 device.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called io_ti.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
CONFIG_USB_SERIAL_KLSI
Say Y here if you want to use a KL5KUSB105 - based single port
serial adapter. The most widely known -- and currently the only
diff --git a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in
index d8be99dbf624..d277619c0322 100644
--- a/drivers/usb/serial/Config.in
+++ b/drivers/usb/serial/Config.in
@@ -19,6 +19,7 @@ dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_
dep_tristate ' USB Compaq iPAQ / HP Jornada / Casio EM500 Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Inside Out Edgeport Serial Driver' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL
+dep_tristate ' USB Inside Out Edgeport Serial Driver (TI devices)' CONFIG_USB_SERIAL_EDGEPORT_TI $CONFIG_USB_SERIAL
dep_tristate ' USB Keyspan PDA Single Port Serial Driver' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL
dep_tristate ' USB Keyspan USA-xxx Serial Driver' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL
dep_mbool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 962d94746de6..1d6f5946bf27 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
+obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index eee56288d2ea..c7bebf111b96 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1263,7 +1263,7 @@ static int digi_write( struct usb_serial_port *port, int from_user,
unsigned long flags = 0;
-dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%d",
+dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%ld",
priv->dp_port_num, count, from_user, in_interrupt() );
/* copy user data (which can sleep) before getting spin lock */
@@ -1744,7 +1744,7 @@ static void digi_shutdown( struct usb_serial *serial )
int i;
-dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() );
+dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() );
/* stop reads and writes on all ports */
for( i=0; i<serial->type->num_ports+1; i++ ) {
diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h
new file mode 100644
index 000000000000..56d319f0163d
--- /dev/null
+++ b/drivers/usb/serial/io_fw_down3.h
@@ -0,0 +1,799 @@
+//**************************************************************
+//* Edgeport Binary Image (for TI based products)
+//* Generated by TIBin2C v1.00
+//* Copyright(c) 2001 Inside Out Networks, All rights reserved.
+//**************************************************************
+
+
+static int IMAGE_SIZE = 12166;
+
+struct EDGE_FIRMWARE_VERSION_INFO
+{
+ unsigned char MajorVersion;
+ unsigned char MinorVersion;
+ unsigned short BuildNumber;
+};
+
+static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
+{
+ 4, 1, 0 // Major, Minor, Build
+
+};
+
+static unsigned char IMAGE_ARRAY_NAME[] =
+{
+// struct ImageHdr
+// {
+// WORD Length;
+// BYTE CheckSum;
+// };
+0x83, 0x2f,
+0x33,
+
+0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45,
+0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00,
+0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44,
+0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75,
+0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81,
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9,
+0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44,
+0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86,
+0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83,
+0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07,
+0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83,
+0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10,
+0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9,
+0x90, 0xff, 0x10, 0xe0, 0x54, 0x20, 0xfa, 0x90, 0xff, 0x50, 0xe0, 0x54, 0x20, 0xfb, 0x74, 0x00,
+0xf5, 0x82, 0x74, 0xf8, 0xf5, 0x83, 0xe0, 0xc8, 0xf0, 0x68, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0,
+0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04,
+0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0,
+0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05,
+0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03,
+0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5,
+0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c,
+0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20,
+0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25,
+0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82,
+0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c,
+0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20,
+0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25,
+0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82,
+0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14,
+0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e,
+0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64,
+0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02,
+0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22,
+0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3,
+0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80,
+0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2,
+0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60,
+0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60,
+0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95,
+0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02,
+0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90,
+0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec,
+0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01,
+0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff,
+0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d,
+0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53,
+0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12,
+0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0,
+0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0,
+0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90,
+0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05,
+0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e,
+0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9,
+0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34,
+0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02,
+0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01,
+0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13,
+0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60,
+0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac,
+0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60,
+0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac,
+0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb,
+0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30,
+0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb,
+0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01,
+0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac,
+0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14,
+0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3,
+0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e,
+0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1,
+0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0,
+0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94,
+0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70,
+0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac,
+0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07,
+0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54,
+0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b,
+0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce,
+0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a,
+0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a,
+0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80,
+0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5,
+0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac,
+0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac,
+0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90,
+0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff,
+0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c,
+0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5,
+0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa,
+0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff,
+0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03,
+0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e,
+0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd,
+0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08,
+0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35,
+0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac,
+0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac,
+0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03,
+0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac,
+0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e,
+0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60,
+0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18,
+0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e,
+0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80,
+0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30,
+0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12,
+0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90,
+0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae,
+0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03,
+0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23,
+0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90,
+0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50,
+0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12,
+0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e,
+0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa,
+0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b,
+0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18,
+0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12,
+0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e,
+0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35,
+0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02,
+0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5,
+0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03,
+0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06,
+0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02,
+0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03,
+0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba,
+0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18,
+0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e,
+0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c,
+0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c,
+0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e,
+0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02,
+0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e,
+0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c,
+0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3,
+0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e,
+0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03,
+0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12,
+0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90,
+0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff,
+0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01,
+0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06,
+0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c,
+0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5,
+0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93,
+0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20,
+0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef,
+0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5,
+0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70,
+0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c,
+0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35,
+0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24,
+0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30,
+0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c,
+0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03,
+0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f,
+0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e,
+0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02,
+0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12,
+0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c,
+0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0,
+0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07,
+0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02,
+0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4,
+0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12,
+0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05,
+0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e,
+0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18,
+0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02,
+0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61,
+0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54,
+0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19,
+0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78,
+0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02,
+0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc,
+0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e,
+0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00,
+0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa,
+0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70,
+0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba,
+0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5,
+0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18,
+0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30,
+0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff,
+0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6,
+0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0,
+0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60,
+0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0,
+0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54,
+0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02,
+0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90,
+0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90,
+0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09,
+0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0,
+0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90,
+0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90,
+0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09,
+0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0,
+0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6,
+0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0,
+0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44,
+0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5,
+0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12,
+0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13,
+0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12,
+0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff,
+0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5,
+0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74,
+0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94,
+0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e,
+0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65,
+0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40,
+0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23,
+0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4,
+0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a,
+0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25,
+0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41,
+0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90,
+0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62,
+0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f,
+0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5,
+0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e,
+0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60,
+0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23,
+0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0,
+0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12,
+0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60,
+0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2,
+0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90,
+0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02,
+0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07,
+0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22,
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41,
+0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab,
+0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0,
+0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00,
+0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f,
+0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12,
+0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f,
+0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75,
+0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b,
+0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23,
+0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04,
+0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde,
+0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0,
+0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0,
+0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12,
+0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54,
+0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15,
+0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83,
+0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0,
+0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda,
+0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8,
+0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08,
+0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04,
+0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0,
+0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07,
+0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0,
+0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0,
+0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08,
+0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80,
+0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02,
+0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82,
+0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60,
+0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f,
+0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82,
+0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12,
+0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20,
+0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00,
+0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90,
+0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48,
+0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80,
+0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e,
+0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2,
+0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e,
+0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03,
+0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e,
+0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef,
+0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef,
+0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08,
+0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80,
+0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5,
+0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00,
+0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24,
+0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78,
+0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82,
+0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0,
+0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04,
+0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49,
+0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90,
+0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8,
+0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75,
+0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf,
+0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79,
+0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08,
+0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02,
+0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7,
+0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88,
+0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf,
+0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3,
+0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf,
+0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80,
+0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80,
+0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89,
+0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc,
+0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d,
+0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed,
+0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5,
+0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8,
+0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88,
+0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00,
+0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82,
+0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02,
+0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01,
+0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9,
+0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82,
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82,
+0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01,
+0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06,
+0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5,
+0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15,
+0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15,
+0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82,
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09,
+0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8,
+0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3,
+0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22,
+0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3,
+0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83,
+0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6,
+0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4,
+0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa,
+0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3,
+0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0,
+0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93,
+0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef,
+0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90,
+0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00,
+0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37,
+0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06,
+0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5,
+0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74,
+0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff,
+0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90,
+0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7,
+0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12,
+0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15,
+0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74,
+0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12,
+0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05,
+0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06,
+0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08,
+0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08,
+0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f,
+0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13,
+0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37,
+0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24,
+0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53,
+0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4,
+0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19,
+0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a,
+0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9,
+0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0,
+0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24,
+0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9,
+0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18,
+0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4,
+0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4,
+0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4,
+0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16,
+0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90,
+0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0,
+0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14,
+0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9,
+0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5,
+0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5,
+0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f,
+0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d,
+0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5,
+0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4,
+0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13,
+0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0,
+0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4,
+0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f,
+0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6,
+0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75,
+0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24,
+0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0,
+0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef,
+0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0,
+0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08,
+0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75,
+0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75,
+0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08,
+0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22,
+0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b,
+0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5,
+0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4,
+0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4,
+0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08,
+0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff,
+0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc,
+0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65,
+0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9,
+0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08,
+0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02,
+0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34,
+0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4,
+0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19,
+0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd,
+0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24,
+0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0,
+0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3,
+0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0,
+0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0,
+0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed,
+0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3,
+0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0,
+0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90,
+0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25,
+0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04,
+0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83,
+0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82,
+0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80,
+0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10,
+0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42,
+0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14,
+0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95,
+0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07,
+0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd,
+0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d,
+0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60,
+0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14,
+0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5,
+0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80,
+0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07,
+0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65,
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf,
+0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05,
+0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80,
+0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb,
+0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05,
+0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0,
+0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19,
+0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90,
+0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14,
+0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20,
+0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0,
+0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00,
+0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00,
+0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0,
+0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5,
+0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43,
+0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43,
+0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03,
+0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03,
+0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59,
+0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee,
+0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f,
+0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90,
+0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07,
+0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14,
+0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9,
+0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24,
+0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20,
+0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14,
+0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa,
+0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90,
+0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00,
+0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08,
+0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf,
+0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56,
+0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e,
+0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94,
+0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff,
+0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90,
+0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90,
+0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d,
+0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58,
+0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9,
+0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5,
+0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24,
+0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f,
+0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0,
+0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0,
+0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0,
+0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0,
+0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0,
+0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10,
+0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6,
+0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa,
+0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6,
+0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90,
+0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90,
+0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44,
+0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa,
+0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0,
+0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0,
+0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4,
+0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90,
+0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46,
+0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2,
+0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50,
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0,
+0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d,
+0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a,
+0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13,
+0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda,
+0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00,
+0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08,
+0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6,
+0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06,
+0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02,
+0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90,
+0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22,
+0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83,
+0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54,
+0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07,
+0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86,
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82,
+0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce,
+0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0,
+0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65,
+0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21,
+0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12,
+0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef,
+0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4,
+0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff,
+0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14,
+0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0,
+0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68,
+0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb,
+0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c,
+0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff,
+0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc,
+0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f,
+0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24,
+0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82,
+0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0,
+0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20,
+0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46,
+0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf,
+0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3,
+0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01,
+0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64,
+0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0,
+0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78,
+0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12,
+0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14,
+0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9,
+0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06,
+0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa,
+0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26,
+0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80,
+0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa,
+0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12,
+0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0,
+0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90,
+0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03,
+0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe,
+0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d,
+0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d,
+0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa,
+0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa,
+0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0,
+0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa,
+0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80,
+0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a,
+0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78,
+0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15,
+0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c,
+0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8,
+0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2,
+0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8,
+0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44,
+0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3,
+0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42,
+0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42,
+0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd,
+0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41,
+0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91,
+0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6,
+0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c,
+0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01,
+0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28,
+0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f,
+0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8,
+0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca,
+0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde,
+0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24,
+0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94,
+0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19,
+0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa,
+0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c,
+0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75,
+0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef,
+0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3,
+0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff,
+0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4,
+0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80,
+0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3,
+0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22,
+0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e,
+0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc,
+0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19,
+0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4,
+0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2,
+0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12,
+0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12,
+0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50,
+0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5,
+0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12,
+0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d,
+0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0,
+0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa,
+0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa,
+0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12,
+0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0,
+0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07,
+0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b,
+0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85,
+0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30,
+0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f,
+0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78,
+0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa,
+0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b,
+0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75,
+0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12,
+0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54,
+0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa,
+0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa,
+0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52,
+0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04,
+0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65,
+0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0,
+0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a,
+0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91,
+0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f,
+0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78,
+0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d,
+0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f,
+0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8,
+0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27,
+0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71,
+0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4,
+0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30,
+0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14,
+0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0,
+0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48,
+0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00,
+0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00,
+0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00,
+0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9,
+0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65,
+0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82,
+0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94,
+0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31,
+0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee,
+0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82,
+0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f,
+0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05,
+0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa,
+0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf,
+0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff,
+0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a,
+0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f,
+0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00,
+0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b,
+0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a,
+0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e,
+0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab,
+0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22,
+0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef,
+0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02,
+0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00,
+0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22,
+0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa,
+0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57,
+0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0,
+0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c,
+0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a,
+0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02,
+0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b,
+0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4,
+0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09,
+0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90,
+0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90,
+0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80,
+0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90,
+0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f,
+0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1,
+0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16,
+0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90,
+0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a,
+0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12,
+0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14,
+0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6,
+0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78,
+0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78,
+0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60,
+0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07,
+0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02,
+0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f,
+0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08,
+0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74,
+0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12,
+0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20,
+0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5,
+0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f,
+0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20,
+0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04,
+0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c,
+0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35,
+0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40,
+0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a,
+0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e,
+0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12,
+0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10,
+0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c,
+0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6,
+0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf,
+0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83,
+0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74,
+0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64,
+0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff,
+0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12,
+0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff,
+0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01,
+0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78,
+0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0,
+0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65,
+0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee,
+0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a,
+0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66,
+0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89,
+0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78,
+0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c,
+0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67,
+0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31,
+0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12,
+0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8,
+0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77,
+0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5,
+0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0,
+0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0,
+0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5,
+0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12,
+0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22,
+0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40,
+0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7,
+0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff,
+0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f,
+0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18,
+0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f,
+0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12,
+0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22,
+0xc2, 0x08, 0x22,
+};
+
+#undef IMAGE_VERSION_NAME
+
+#undef IMAGE_ARRAY_NAME
+
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
new file mode 100644
index 000000000000..493ab2518435
--- /dev/null
+++ b/drivers/usb/serial/io_ti.c
@@ -0,0 +1,2684 @@
+/*
+ * Edgeport USB Serial Converter driver
+ *
+ * Copyright(c) 2000-2002 Inside Out Networks, All rights reserved.
+ * Copyright(c) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Supports the following devices:
+ * EP/1 EP/2 EP/4
+ *
+ * Version history:
+ *
+ * July 11, 2002 Removed 4 port device structure since all TI UMP
+ * chips have only 2 ports
+ * David Iacovelli (davidi@ionetworks.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/serial.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+ static int debug = 1;
+#else
+ static int debug;
+#endif
+
+#include "usb-serial.h"
+
+#include "io_16654.h"
+#include "io_usbvend.h"
+#include "io_ti.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.2"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
+#define DRIVER_DESC "Edgeport USB Serial Driver"
+
+
+/* firmware image code */
+#define IMAGE_VERSION_NAME PagableOperationalCodeImageVersion
+#define IMAGE_ARRAY_NAME PagableOperationalCodeImage
+#define IMAGE_SIZE PagableOperationalCodeSize
+#include "io_fw_down3.h" /* Define array OperationalCodeImage[] */
+
+#define EPROM_PAGE_SIZE 64
+
+
+struct edgeport_uart_buf_desc {
+ __u32 count; // Number of bytes currently in buffer
+};
+
+/* different hardware types */
+#define HARDWARE_TYPE_930 0
+#define HARDWARE_TYPE_TIUMP 1
+
+// IOCTL_PRIVATE_TI_GET_MODE Definitions
+#define TI_MODE_CONFIGURING 0 // Device has not entered start device
+#define TI_MODE_BOOT 1 // Staying in boot mode
+#define TI_MODE_DOWNLOAD 2 // Made it to download mode
+#define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode
+
+
+/* Product information read from the Edgeport */
+struct product_info
+{
+ int TiMode; // Current TI Mode
+ __u8 hardware_type; // Type of hardware
+} __attribute__((packed));
+
+
+struct edgeport_port {
+ __u16 uart_base;
+ __u16 dma_address;
+ __u8 shadow_msr;
+ __u8 shadow_mcr;
+ __u8 shadow_lsr;
+ __u8 lsr_mask;
+ __u32 ump_read_timeout; /* Number of miliseconds the UMP will
+ wait without data before completing
+ a read short */
+ int baud_rate;
+ int close_pending;
+ int lsr_event;
+ struct edgeport_uart_buf_desc tx;
+ struct async_icount icount;
+ wait_queue_head_t delta_msr_wait; /* for handling sleeping while
+ waiting for msr change to
+ happen */
+ struct edgeport_serial *edge_serial;
+ struct usb_serial_port *port;
+};
+
+struct edgeport_serial {
+ struct product_info product_info;
+ u8 TI_I2C_Type; // Type of I2C in UMP
+ u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode
+ int num_ports_open;
+ struct usb_serial *serial;
+};
+
+
+/* Devices that this driver supports */
+static struct usb_device_id edgeport_1port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
+ { }
+};
+
+static struct usb_device_id edgeport_2port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+ { }
+};
+
+/* Devices that this driver supports */
+static __devinitdata struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+ { }
+};
+
+MODULE_DEVICE_TABLE (usb, id_table_combined);
+
+
+static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion;
+
+static int TIStayInBootMode = 0;
+static int ignore_cpu_rev = 0;
+
+
+
+static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+
+static int TIReadVendorRequestSync (struct usb_device *dev,
+ __u8 request,
+ __u16 value,
+ __u16 index,
+ u8 *data,
+ int size)
+{
+ int status;
+
+ status = usb_control_msg (dev,
+ usb_rcvctrlpipe(dev, 0),
+ request,
+ (USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE |
+ USB_DIR_IN),
+ value,
+ index,
+ data,
+ size,
+ HZ);
+ if (status < 0)
+ return status;
+ if (status != size) {
+ dbg ("%s - wanted to write %d, but only wrote %d",
+ __FUNCTION__, size, status);
+ return -ECOMM;
+ }
+ return 0;
+}
+
+static int TISendVendorRequestSync (struct usb_device *dev,
+ __u8 request,
+ __u16 value,
+ __u16 index,
+ u8 *data,
+ int size)
+{
+ int status;
+
+ status = usb_control_msg (dev,
+ usb_sndctrlpipe(dev, 0),
+ request,
+ (USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE |
+ USB_DIR_OUT),
+ value,
+ index,
+ data,
+ size,
+ HZ);
+
+ if (status < 0)
+ return status;
+ if (status != size) {
+ dbg ("%s - wanted to write %d, but only wrote %d",
+ __FUNCTION__, size, status);
+ return -ECOMM;
+ }
+ return 0;
+}
+
+static int TIWriteCommandSync (struct usb_device *dev, __u8 command,
+ __u8 moduleid, __u16 value, u8 *data,
+ int size)
+{
+ return TISendVendorRequestSync (dev,
+ command, // Request
+ value, // wValue
+ moduleid, // wIndex
+ data, // TransferBuffer
+ size); // TransferBufferLength
+
+}
+
+
+/* clear tx/rx buffers and fifo in TI UMP */
+static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
+{
+ int port_number = port->number - port->serial->minor;
+
+ dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
+
+ return TIWriteCommandSync (port->serial->dev,
+ UMPC_PURGE_PORT,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ mask,
+ NULL,
+ 0);
+}
+
+/**
+ * TIReadDownloadMemory - Read edgeport memory from TI chip
+ * @dev: usb device pointer
+ * @address: Device CPU address at which to read
+ * @length: Length of above data
+ * @address_type: Can read both XDATA and I2C
+ * @buffer: pointer to input data buffer
+ */
+int TIReadDownloadMemory (struct usb_device *dev, int start_address, int length,
+ __u8 address_type, __u8 *buffer)
+{
+ int status = 0;
+ __u8 read_length;
+ __u16 be_start_address;
+
+ dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
+
+ /* Read in blocks of 64 bytes
+ * (TI firmware can't handle more than 64 byte reads)
+ */
+ while (length) {
+ if (length > 64)
+ read_length= 64;
+ else
+ read_length = (__u8)length;
+
+ if (read_length > 1) {
+ dbg ("%s - @ %x for %d", __FUNCTION__,
+ start_address, read_length);
+ }
+ be_start_address = cpu_to_be16 (start_address);
+ status = TIReadVendorRequestSync (dev,
+ UMPC_MEMORY_READ, // Request
+ (__u16)address_type, // wValue (Address type)
+ be_start_address, // wIndex (Address to read)
+ buffer, // TransferBuffer
+ read_length); // TransferBufferLength
+
+ if (status) {
+ dbg ("%s - ERROR %x", __FUNCTION__, status);
+ return status;
+ }
+
+ if (read_length > 1) {
+ usb_serial_debug_data (__FILE__, __FUNCTION__,
+ read_length, buffer);
+ }
+
+ /* Update pointers/length */
+ start_address += read_length;
+ buffer += read_length;
+ length -= read_length;
+ }
+
+ return status;
+}
+
+int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer)
+{
+ return TIReadDownloadMemory (dev,
+ start_address,
+ length,
+ DTK_ADDR_SPACE_XDATA,
+ buffer);
+}
+
+/* Read edgeport memory to a given block */
+static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer)
+{
+ int status = 0;
+ int i;
+
+ for (i=0; i< length; i++) {
+ status = TIReadVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_READ, // Request
+ serial->TI_I2C_Type, // wValue (Address type)
+ (__u16)(start_address+i), // wIndex
+ &buffer[i], // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status) {
+ dbg ("%s - ERROR %x", __FUNCTION__, status);
+ return status;
+ }
+ }
+
+ dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
+
+ serial->TiReadI2C = 1;
+
+ return status;
+}
+
+/* Write given block to TI EPROM memory */
+static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+{
+ int status = 0;
+ int i;
+ __u8 temp;
+
+ /* Must do a read before write */
+ if (!serial->TiReadI2C) {
+ status = TIReadBootMemory(serial, 0, 1, &temp);
+ if (status)
+ return status;
+ }
+
+ for (i=0; i < length; ++i) {
+ status = TISendVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_WRITE, // Request
+ buffer[i], // wValue
+ (__u16)(i+start_address), // wIndex
+ NULL, // TransferBuffer
+ 0); // TransferBufferLength
+ if (status)
+ return status;
+ }
+
+ dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
+
+ return status;
+}
+
+
+/* Write edgeport I2C memory to TI chip */
+static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer)
+{
+ int status = 0;
+ int write_length;
+ __u16 be_start_address;
+
+ /* We can only send a maximum of 1 aligned byte page at a time */
+
+ /* calulate the number of bytes left in the first page */
+ write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1));
+
+ if (write_length > length)
+ write_length = length;
+
+ dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, write_length, buffer);
+
+ /* Write first page */
+ be_start_address = cpu_to_be16 (start_address);
+ status = TISendVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_WRITE, // Request
+ (__u16)address_type, // wValue
+ be_start_address, // wIndex
+ buffer, // TransferBuffer
+ write_length);
+ if (status) {
+ dbg ("%s - ERROR %d", __FUNCTION__, status);
+ return status;
+ }
+
+ length -= write_length;
+ start_address += write_length;
+ buffer += write_length;
+
+ /* We should be aligned now -- can write max page size bytes at a time */
+ while (length) {
+ if (length > EPROM_PAGE_SIZE)
+ write_length = EPROM_PAGE_SIZE;
+ else
+ write_length = length;
+
+ dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, write_length, buffer);
+
+ /* Write next page */
+ be_start_address = cpu_to_be16 (start_address);
+ status = TISendVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_WRITE, // Request
+ (__u16)address_type, // wValue
+ be_start_address, // wIndex
+ buffer, // TransferBuffer
+ write_length); // TransferBufferLength
+ if (status) {
+ dbg ("%s - ERROR %d", __FUNCTION__, status);
+ return status;
+ }
+
+ length -= write_length;
+ start_address += write_length;
+ buffer += write_length;
+ }
+ return status;
+}
+
+/* Examine the UMP DMA registers and LSR
+ *
+ * Check the MSBit of the X and Y DMA byte count registers.
+ * A zero in this bit indicates that the TX DMA buffers are empty
+ * then check the TX Empty bit in the UART.
+ */
+static int TIIsTxActive (struct edgeport_port *port)
+{
+ int status;
+ struct out_endpoint_desc_block *oedb;
+ __u8 lsr;
+ int bytes_left = 0;
+
+ oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
+ if (!oedb) {
+ err ("%s - out of memory", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ /* Read the DMA Count Registers */
+ status = TIReadRam (port->port->serial->dev,
+ port->dma_address,
+ sizeof( *oedb),
+ (void *)oedb);
+
+ if (status)
+ goto exit_is_tx_active;
+
+ dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount);
+
+ /* and the LSR */
+ status = TIReadRam (port->port->serial->dev,
+ port->uart_base + UMPMEM_OFFS_UART_LSR,
+ 1,
+ &lsr);
+
+ if (status)
+ goto exit_is_tx_active;
+ dbg ("%s - LSR = 0x%X", __FUNCTION__, lsr);
+
+ /* If either buffer has data or we are transmitting then return TRUE */
+ if ((oedb->XByteCount & 0x80 ) != 0 )
+ bytes_left += 64;
+
+ if ((lsr & UMP_UART_LSR_TX_MASK ) == 0 )
+ bytes_left += 1;
+
+ /* We return Not Active if we get any kind of error */
+exit_is_tx_active:
+ dbg ("%s - return %d", __FUNCTION__, bytes_left );
+ return bytes_left;
+}
+
+static void TIChasePort(struct edgeport_port *port)
+{
+ int loops;
+ int last_count;
+ int write_size;
+
+restart_tx_loop:
+ // Base the LoopTime on the baud rate
+ if (port->baud_rate == 0)
+ port->baud_rate = 1200;
+
+ write_size = port->tx.count;
+ loops = max(100, (100*write_size)/(port->baud_rate/10));
+ dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__,
+ write_size, port->baud_rate, loops);
+
+ while (1) {
+ // Save Last count
+ last_count = port->tx.count;
+
+ dbg ("%s - Tx Buffer Size = %d loops = %d", __FUNCTION__,
+ last_count, loops);
+
+ /* Is the Edgeport Buffer empty? */
+ if (port->tx.count == 0)
+ break;
+
+ /* Block the thread for 10ms */
+ wait_ms (10);
+
+ if (last_count == port->tx.count) {
+ /* No activity.. count down. */
+ --loops;
+ if (loops == 0) {
+ dbg ("%s - Wait for TxEmpty - TIMEOUT",
+ __FUNCTION__);
+ return;
+ }
+ } else {
+ /* Reset timeout value back to a minimum of 1 second */
+ dbg ("%s - Wait for TxEmpty Reset Count", __FUNCTION__);
+ goto restart_tx_loop;
+ }
+ }
+
+ dbg ("%s - Local Tx Buffer Empty -- Waiting for TI UMP to EMPTY X/Y and FIFO",
+ __FUNCTION__);
+
+ write_size = TIIsTxActive (port);
+ loops = max(50, (100*write_size)/(port->baud_rate/10));
+ dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__,
+ write_size, port->baud_rate, loops);
+
+ while (1) {
+ /* This function takes 4 ms; */
+ if (!TIIsTxActive (port)) {
+ /* Delay a few char times */
+ wait_ms (50);
+ dbg ("%s - Empty", __FUNCTION__);
+ return;
+ }
+
+ --loops;
+ if (loops == 0) {
+ dbg ("%s - TIMEOUT", __FUNCTION__);
+ return;
+ }
+ }
+}
+
+static int TIChooseConfiguration (struct usb_device *dev)
+{
+ // There may be multiple configurations on this device, in which case
+ // we would need to read and parse all of them to find out which one
+ // we want. However, we just support one config at this point,
+ // configuration # 1, which is Config Descriptor 0.
+
+ dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->bNumInterfaces);
+ dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->MaxPower*2);
+
+ if (dev->config->bNumInterfaces != 1) {
+ err ("%s - bNumInterfaces is not 1, ERROR!", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+{
+ int status;
+
+ if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
+ status = TIReadDownloadMemory (serial->serial->dev,
+ start_address,
+ length,
+ serial->TI_I2C_Type,
+ buffer);
+ } else {
+ status = TIReadBootMemory (serial,
+ start_address,
+ length,
+ buffer);
+ }
+
+ return status;
+}
+
+int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+{
+ if (serial->product_info.TiMode == TI_MODE_BOOT)
+ return TIWriteBootMemory (serial,
+ start_address,
+ length,
+ buffer);
+
+ if (serial->product_info.TiMode == TI_MODE_DOWNLOAD)
+ return TIWriteDownloadI2C (serial,
+ start_address,
+ length,
+ serial->TI_I2C_Type,
+ buffer);
+
+ return -EINVAL;
+}
+
+
+
+/* Read a descriptor header from I2C based on type */
+static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc)
+{
+ int start_address;
+ int status;
+
+ /* Search for requested descriptor in I2C */
+ start_address = 2;
+ do {
+ status = TIReadRom (serial,
+ start_address,
+ sizeof(struct ti_i2c_desc),
+ (__u8 *)rom_desc );
+ if (status)
+ return 0;
+
+ if (rom_desc->Type == desc_type)
+ return start_address;
+
+ start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
+
+ } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
+
+ return 0;
+}
+
+/* Validate descriptor checksum */
+static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
+{
+ __u16 i;
+ __u8 cs = 0;
+
+ for (i=0; i < rom_desc->Size; i++) {
+ cs = (__u8)(cs + buffer[i]);
+ }
+ if (cs != rom_desc->CheckSum) {
+ dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* Make sure that the I2C image is good */
+static int TiValidateI2cImage (struct edgeport_serial *serial)
+{
+ int status = 0;
+ struct ti_i2c_desc *rom_desc;
+ int start_address = 2;
+ __u8 *buffer;
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+ err ("%s - out of memory", __FUNCTION__);
+ return -ENOMEM;
+ }
+ buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
+ if (!buffer) {
+ err ("%s - out of memory when allocating buffer", __FUNCTION__);
+ kfree (rom_desc);
+ return -ENOMEM;
+ }
+
+ // Read the first byte (Signature0) must be 0x52
+ status = TIReadRom (serial, 0, 1, buffer);
+ if (status)
+ goto ExitTiValidateI2cImage;
+
+ if (*buffer != 0x52) {
+ err ("%s - invalid buffer signature", __FUNCTION__);
+ status = -ENODEV;
+ goto ExitTiValidateI2cImage;
+ }
+
+ do {
+ // Validate the I2C
+ status = TIReadRom (serial,
+ start_address,
+ sizeof(struct ti_i2c_desc),
+ (__u8 *)rom_desc);
+ if (status)
+ break;
+
+ if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ status = -ENODEV;
+ dbg ("%s - structure too big, erroring out.", __FUNCTION__);
+ break;
+ }
+
+ dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
+
+ // Skip type 2 record
+ if ((rom_desc->Type & 0x0f) != I2C_DESC_TYPE_FIRMWARE_BASIC) {
+ // Read the descriptor data
+ status = TIReadRom(serial,
+ start_address+sizeof(struct ti_i2c_desc),
+ rom_desc->Size,
+ buffer);
+ if (status)
+ break;
+
+ status = ValidChecksum(rom_desc, buffer);
+ if (status)
+ break;
+ }
+ start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
+
+ } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE));
+
+ if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE))
+ status = -ENODEV;
+
+ExitTiValidateI2cImage:
+ kfree (buffer);
+ kfree (rom_desc);
+ return status;
+}
+
+static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+{
+ int status;
+ int start_address;
+ struct ti_i2c_desc *rom_desc;
+ struct edge_ti_manuf_descriptor *desc;
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+ err ("%s - out of memory", __FUNCTION__);
+ return -ENOMEM;
+ }
+ start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+
+ if (!start_address) {
+ dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__);
+ status = -ENODEV;
+ goto exit;
+ }
+
+ // Read the descriptor data
+ status = TIReadRom (serial,
+ start_address+sizeof(struct ti_i2c_desc),
+ rom_desc->Size,
+ buffer);
+ if (status)
+ goto exit;
+
+ status = ValidChecksum(rom_desc, buffer);
+
+ desc = (struct edge_ti_manuf_descriptor *)buffer;
+ dbg ( "%s - IonConfig 0x%x", __FUNCTION__, desc->IonConfig );
+ dbg ( "%s - Version %d", __FUNCTION__, desc->Version );
+ dbg ( "%s - Cpu/Board 0x%x", __FUNCTION__, desc->CpuRev_BoardRev );
+ dbg ( "%s - NumPorts %d", __FUNCTION__, desc->NumPorts );
+ dbg ( "%s - NumVirtualPorts %d", __FUNCTION__, desc->NumVirtualPorts );
+ dbg ( "%s - TotalPorts %d", __FUNCTION__, desc->TotalPorts );
+
+exit:
+ kfree (rom_desc);
+ return status;
+}
+
+/* Build firmware header used for firmware update */
+static int BuildI2CFirmwareHeader (__u8 *header)
+{
+ __u8 *buffer;
+ int buffer_size;
+ int i;
+ __u8 cs = 0;
+ struct ti_i2c_desc *i2c_header;
+ struct ti_i2c_image_header *img_header;
+ struct ti_i2c_firmware_rec *firmware_rec;
+
+ // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
+ // will download the latest firmware (padded to 15.5k) into the UMP ram.
+ // And finally when the device comes back up in download mode the driver will cause
+ // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
+ // the record type from 0xf2 to 0x02.
+
+ // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record)
+ buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec));
+
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ err ("%s - out of memory", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ // Set entire image of 0xffs
+ memset (buffer, 0xff, buffer_size);
+
+ // Copy version number into firmware record
+ firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
+
+ firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion;
+ firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion;
+
+ // Pointer to fw_down memory image
+ img_header = (struct ti_i2c_image_header *)&PagableOperationalCodeImage[0];
+
+ memcpy (buffer + sizeof(struct ti_i2c_firmware_rec),
+ &PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)],
+ img_header->Length);
+
+ for (i=0; i < buffer_size; i++) {
+ cs = (__u8)(cs + buffer[i]);
+ }
+
+ kfree (buffer);
+
+ // Build new header
+ i2c_header = (struct ti_i2c_desc *)header;
+ firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data;
+
+ i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK;
+ i2c_header->Size = (__u16)buffer_size;
+ i2c_header->CheckSum = cs;
+ firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion;
+ firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion;
+
+ return 0;
+}
+
+/* Try to figure out what type of I2c we have */
+static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+{
+ int status;
+ __u8 data;
+
+ // Try to read type 2
+ status = TIReadVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_READ, // Request
+ DTK_ADDR_SPACE_I2C_TYPE_II, // wValue (Address type)
+ 0, // wIndex
+ &data, // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status)
+ dbg ("%s - read 2 status error = %d", __FUNCTION__, status);
+ else
+ dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
+ if ((!status) && data == 0x52) {
+ dbg ("%s - ROM_TYPE_II", __FUNCTION__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ return 0;
+ }
+
+ // Try to read type 3
+ status = TIReadVendorRequestSync (serial->serial->dev,
+ UMPC_MEMORY_READ, // Request
+ DTK_ADDR_SPACE_I2C_TYPE_III, // wValue (Address type)
+ 0, // wIndex
+ &data, // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status)
+ dbg ("%s - read 3 status error = %d", __FUNCTION__, status);
+ else
+ dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
+ if ((!status) && data == 0x52) {
+ dbg ("%s - ROM_TYPE_III", __FUNCTION__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
+ return 0;
+ }
+
+ dbg ("%s - Unknown", __FUNCTION__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ return -ENODEV;
+}
+
+static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent)
+{
+ int status;
+
+ status = usb_bulk_msg (serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ serial->port[0].bulk_out_endpointAddress),
+ buffer,
+ length,
+ num_sent,
+ HZ);
+ return status;
+}
+
+/* Download given firmware image to the device (IN BOOT MODE) */
+static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length)
+{
+ int status = 0;
+ int pos;
+ int transfer;
+ int done;
+
+ // Transfer firmware image
+ for (pos = 0; pos < image_length; ) {
+ // Read the next buffer from file
+ transfer = image_length - pos;
+ if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE)
+ transfer = EDGE_FW_BULK_MAX_PACKET_SIZE;
+
+ // Transfer data
+ status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done);
+ if (status)
+ break;
+ // Advance buffer pointer
+ pos += done;
+ }
+
+ return status;
+}
+
+// FIXME!!!
+static int TIConfigureBootDevice (struct usb_device *dev)
+{
+ return 0;
+}
+
+/**
+ * DownloadTIFirmware - Download run-time operating firmware to the TI5052
+ *
+ * This routine downloads the main operating code into the TI5052, using the
+ * boot code already burned into E2PROM or ROM.
+ */
+static int TIDownloadFirmware (struct edgeport_serial *serial)
+{
+ int status = 0;
+ int start_address;
+ struct edge_ti_manuf_descriptor *ti_manuf_desc;
+ struct usb_interface_descriptor *interface;
+ int download_cur_ver;
+ int download_new_ver;
+
+ /* This routine is entered by both the BOOT mode and the Download mode
+ * We can determine which code is running by the reading the config
+ * descriptor and if we have only one bulk pipe it is in boot mode
+ */
+ serial->product_info.hardware_type = HARDWARE_TYPE_TIUMP;
+
+ /* Default to type 2 i2c */
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+
+ status = TIChooseConfiguration (serial->serial->dev);
+ if (status)
+ return status;
+
+ interface = serial->serial->dev->config->interface->altsetting;
+ if (!interface) {
+ err ("%s - no interface set, error!", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
+ // if we have more than one endpoint we are definitely in download mode
+ if (interface->bNumEndpoints > 1)
+ serial->product_info.TiMode = TI_MODE_DOWNLOAD;
+ else
+ // Otherwise we will remain in configuring mode
+ serial->product_info.TiMode = TI_MODE_CONFIGURING;
+
+ // Save Download Version Number
+ OperationalCodeImageVersion.MajorVersion = PagableOperationalCodeImageVersion.MajorVersion;
+ OperationalCodeImageVersion.MinorVersion = PagableOperationalCodeImageVersion.MinorVersion;
+ OperationalCodeImageVersion.BuildNumber = PagableOperationalCodeImageVersion.BuildNumber;
+
+ /********************************************************************/
+ /* Download Mode */
+ /********************************************************************/
+ if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
+ struct ti_i2c_desc *rom_desc;
+
+ dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
+
+ status = TiValidateI2cImage (serial);
+ if (status) {
+ dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
+ __FUNCTION__);
+ return status;
+ }
+
+ /* Validate Hardware version number
+ * Read Manufacturing Descriptor from TI Based Edgeport
+ */
+ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ if (!ti_manuf_desc) {
+ err ("%s - out of memory.", __FUNCTION__);
+ return -ENOMEM;
+ }
+ status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+ if (status) {
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ // Check version number of ION descriptor
+ if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+ dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
+ TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ kfree (ti_manuf_desc);
+ return -EINVAL;
+ }
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+ err ("%s - out of memory.", __FUNCTION__);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+ // Search for type 2 record (firmware record)
+ if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) {
+ struct ti_i2c_firmware_rec *firmware_version;
+ __u8 record;
+
+ dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
+
+ firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
+ if (!firmware_version) {
+ err ("%s - out of memory.", __FUNCTION__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+ // Validate version number
+ // Read the descriptor data
+ status = TIReadRom (serial,
+ start_address+sizeof(struct ti_i2c_desc),
+ sizeof(struct ti_i2c_firmware_rec),
+ (__u8 *)firmware_version);
+ if (status) {
+ kfree (firmware_version);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ // Check version number of download with current version in I2c
+ download_cur_ver = (firmware_version->Ver_Major << 8) +
+ (firmware_version->Ver_Minor);
+ download_new_ver = (OperationalCodeImageVersion.MajorVersion << 8) +
+ (OperationalCodeImageVersion.MinorVersion);
+
+ dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d",
+ __FUNCTION__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalCodeImageVersion.MajorVersion,
+ OperationalCodeImageVersion.MinorVersion);
+
+ // Check if we have an old version in the I2C and update if necessary
+ if (download_cur_ver != download_new_ver) {
+ dbg ("%s - Update I2C Download from %d.%d to %d.%d",
+ __FUNCTION__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalCodeImageVersion.MajorVersion,
+ OperationalCodeImageVersion.MinorVersion);
+
+ // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
+ // will download the latest firmware (padded to 15.5k) into the UMP ram.
+ // And finally when the device comes back up in download mode the driver will cause
+ // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
+ // the record type from 0xf2 to 0x02.
+
+ record = I2C_DESC_TYPE_FIRMWARE_BLANK;
+
+ // Change the I2C Firmware record type to 0xf2 to trigger an update
+ status = TIWriteRom (serial,
+ start_address,
+ sizeof(record),
+ &record);
+ if (status) {
+ kfree (firmware_version);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ // verify the write -- must do this in order for write to
+ // complete before we do the hardware reset
+ status = TIReadRom (serial,
+ start_address,
+ sizeof(record),
+ &record);
+
+ if (status) {
+ kfree (firmware_version);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+ err ("%s - error resetting device", __FUNCTION__);
+ kfree (firmware_version);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENODEV;
+ }
+
+ dbg ("%s - HARDWARE RESET", __FUNCTION__);
+
+ // Reset UMP -- Back to BOOT MODE
+ status = TISendVendorRequestSync (serial->serial->dev,
+ UMPC_HARDWARE_RESET, // Request
+ 0, // wValue
+ 0, // wIndex
+ NULL, // TransferBuffer
+ 0); // TransferBufferLength
+
+ dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
+
+ /* return an error on purpose. */
+ return -ENODEV;
+ }
+ }
+ // Search for type 0xF2 record (firmware blank record)
+ else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+ #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec))
+ __u8 *header;
+ __u8 *vheader;
+
+ header = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ if (!header) {
+ err ("%s - out of memory.", __FUNCTION__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+ vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ if (!vheader) {
+ err ("%s - out of memory.", __FUNCTION__);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+ dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__);
+
+ // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
+ // will download the latest firmware (padded to 15.5k) into the UMP ram.
+ // And finally when the device comes back up in download mode the driver will cause
+ // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
+ // the record type from 0xf2 to 0x02.
+ status = BuildI2CFirmwareHeader(header);
+ if (status) {
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ // Update I2C with type 0xf2 record with correct size and checksum
+ status = TIWriteRom (serial,
+ start_address,
+ HEADER_SIZE,
+ header);
+ if (status) {
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ // verify the write -- must do this in order for write to
+ // complete before we do the hardware reset
+ status = TIReadRom (serial,
+ start_address,
+ HEADER_SIZE,
+ vheader);
+
+ if (status) {
+ dbg ("%s - can't read header back", __FUNCTION__);
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+ if (memcmp(vheader, header, HEADER_SIZE)) {
+ dbg ("%s - write download record failed", __FUNCTION__);
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+
+ kfree (vheader);
+ kfree (header);
+
+ dbg ("%s - Start firmware update", __FUNCTION__);
+
+ // Tell firmware to copy download image into I2C
+ status = TISendVendorRequestSync (serial->serial->dev,
+ UMPC_COPY_DNLD_TO_I2C, // Request
+ 0, // wValue
+ 0, // wIndex
+ NULL, // TransferBuffer
+ 0); // TransferBufferLength
+
+ dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
+ if (status) {
+ dbg ("%s - UMPC_COPY_DNLD_TO_I2C failed", __FUNCTION__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+ }
+ }
+
+ // The device is running the download code
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return 0;
+ }
+
+ /********************************************************************/
+ /* Boot Mode */
+ /********************************************************************/
+ dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
+ __FUNCTION__);
+
+ // Configure the TI device so we can use the BULK pipes for download
+ status = TIConfigureBootDevice (serial->serial->dev);
+ if (status)
+ return status;
+
+ if (serial->serial->dev->descriptor.idVendor != USB_VENDOR_ID_ION) {
+ dbg ("%s - VID = 0x%x", __FUNCTION__,
+ serial->serial->dev->descriptor.idVendor);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ goto StayInBootMode;
+ }
+
+ // We have an ION device (I2c Must be programmed)
+ // Determine I2C image type
+ if (TIGetI2cTypeInBootMode(serial)) {
+ goto StayInBootMode;
+ }
+
+ // Registry variable set?
+ if (TIStayInBootMode) {
+ dbg ("%s - TIStayInBootMode", __FUNCTION__);
+ goto StayInBootMode;
+ }
+
+ // Check for ION Vendor ID and that the I2C is valid
+ if (!TiValidateI2cImage(serial)) {
+ struct ti_i2c_image_header *header;
+ int i;
+ __u8 cs = 0;
+ __u8 *buffer;
+ int buffer_size;
+
+ /* Validate Hardware version number
+ * Read Manufacturing Descriptor from TI Based Edgeport
+ */
+ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ if (!ti_manuf_desc) {
+ err ("%s - out of memory.", __FUNCTION__);
+ return -ENOMEM;
+ }
+ status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+ if (status) {
+ kfree (ti_manuf_desc);
+ goto StayInBootMode;
+ }
+
+ // Check for version 2
+ if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+ dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
+ TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ kfree (ti_manuf_desc);
+ goto StayInBootMode;
+ }
+
+ kfree (ti_manuf_desc);
+
+ // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
+ // will download the latest firmware (padded to 15.5k) into the UMP ram.
+ // And finally when the device comes back up in download mode the driver will cause
+ // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
+ // the record type from 0xf2 to 0x02.
+
+ /*
+ * Do we really have to copy the whole firmware image,
+ * or could we do this in place!
+ */
+
+ // Allocate a 15.5k buffer + 3 byte header
+ buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ err ("%s - out of memory", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ // Initialize the buffer to 0xff (pad the buffer)
+ memset (buffer, 0xff, buffer_size);
+
+ memcpy (buffer, &PagableOperationalCodeImage[0], PagableOperationalCodeSize);
+
+ for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) {
+ cs = (__u8)(cs + buffer[i]);
+ }
+
+ header = (struct ti_i2c_image_header *)buffer;
+
+ // update length and checksum after padding
+ header->Length = (__u16)(buffer_size - sizeof(struct ti_i2c_image_header));
+ header->CheckSum = cs;
+
+ // Download the operational code
+ dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
+ status = TIDownloadCodeImage (serial, buffer, buffer_size);
+
+ kfree (buffer);
+
+ if (status) {
+ dbg ("%s - Error downloading operational code image", __FUNCTION__);
+ return status;
+ }
+
+ // Device will reboot
+ serial->product_info.TiMode = TI_MODE_TRANSITIONING;
+
+ dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
+
+ /* return an error on purpose */
+ return -ENODEV;
+ }
+
+StayInBootMode:
+ // Eprom is invalid or blank stay in boot mode
+ dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
+ serial->product_info.TiMode = TI_MODE_BOOT;
+
+ return 0;
+}
+
+
+static int TISetDtr (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+ port->shadow_mcr |= MCR_DTR;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_DTR,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 1, /* set */
+ NULL,
+ 0);
+}
+
+static int TIClearDtr (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+ port->shadow_mcr &= ~MCR_DTR;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_DTR,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0, /* clear */
+ NULL,
+ 0);
+}
+
+static int TISetRts (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+ port->shadow_mcr |= MCR_RTS;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_RTS,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 1, /* set */
+ NULL,
+ 0);
+}
+
+static int TIClearRts (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+ port->shadow_mcr &= ~MCR_RTS;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_RTS,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0, /* clear */
+ NULL,
+ 0);
+}
+
+static int TISetLoopBack (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_LOOPBACK,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 1, /* set */
+ NULL,
+ 0);
+}
+
+static int TIClearLoopBack (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_LOOPBACK,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0, /* clear */
+ NULL,
+ 0);
+}
+
+static int TISetBreak (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_BREAK,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 1, /* set */
+ NULL,
+ 0);
+}
+
+static int TIClearBreak (struct edgeport_port *port)
+{
+ int port_number = port->port->number - port->port->serial->minor;
+
+ dbg ("%s", __FUNCTION__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_BREAK,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0, /* clear */
+ NULL,
+ 0);
+}
+
+static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
+{
+ int status = 0;
+
+ dbg ("%s - %x", __FUNCTION__, mcr);
+
+ if (mcr & MCR_DTR)
+ status = TISetDtr (port);
+ else
+ status = TIClearDtr (port);
+
+ if (status)
+ return status;
+
+ if (mcr & MCR_RTS)
+ status = TISetRts (port);
+ else
+ status = TIClearRts (port);
+
+ if (status)
+ return status;
+
+ if (mcr & MCR_LOOPBACK)
+ status = TISetLoopBack (port);
+ else
+ status = TIClearLoopBack (port);
+
+ return status;
+}
+
+
+
+/* Convert TI LSR to standard UART flags */
+static __u8 MapLineStatus (__u8 ti_lsr)
+{
+ __u8 lsr = 0;
+
+#define MAP_FLAG(flagUmp, flagUart) \
+ if (ti_lsr & flagUmp) lsr |= flagUart;
+
+ MAP_FLAG(UMP_UART_LSR_OV_MASK, LSR_OVER_ERR) /* overrun */
+ MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */
+ MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */
+ MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */
+ MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */
+ MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */
+
+#undef MAP_FLAG
+
+ return lsr;
+}
+
+static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
+{
+ struct async_icount *icount;
+
+ dbg ("%s - %02x", __FUNCTION__, msr);
+
+ if (msr & (MSR_DELTA_CTS | MSR_DELTA_DSR | MSR_DELTA_RI | MSR_DELTA_CD)) {
+ icount = &edge_port->icount;
+
+ /* update input line counters */
+ if (msr & MSR_DELTA_CTS)
+ icount->cts++;
+ if (msr & MSR_DELTA_DSR)
+ icount->dsr++;
+ if (msr & MSR_DELTA_CD)
+ icount->dcd++;
+ if (msr & MSR_DELTA_RI)
+ icount->rng++;
+ wake_up_interruptible (&edge_port->delta_msr_wait);
+ }
+
+ /* Save the new modem status */
+ edge_port->shadow_msr = msr & 0xf0;
+
+ return;
+}
+
+static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data)
+{
+ struct async_icount *icount;
+ __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+
+ dbg ("%s - %02x", __FUNCTION__, new_lsr);
+
+ edge_port->shadow_lsr = lsr;
+
+ if (new_lsr & LSR_BREAK) {
+ /*
+ * Parity and Framing errors only count if they
+ * occur exclusive of a break being received.
+ */
+ new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
+ }
+
+ /* Place LSR data byte into Rx buffer */
+ if (lsr_data && edge_port->port->tty) {
+ tty_insert_flip_char(edge_port->port->tty, data, 0);
+ tty_flip_buffer_push(edge_port->port->tty);
+ }
+
+ /* update input line counters */
+ icount = &edge_port->icount;
+ if (new_lsr & LSR_BREAK)
+ icount->brk++;
+ if (new_lsr & LSR_OVER_ERR)
+ icount->overrun++;
+ if (new_lsr & LSR_PAR_ERR)
+ icount->parity++;
+ if (new_lsr & LSR_FRM_ERR)
+ icount->frame++;
+}
+
+
+static void edge_interrupt_callback (struct urb *urb)
+{
+ struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
+ struct usb_serial_port *port;
+ struct edgeport_port *edge_port;
+ unsigned char *data = urb->transfer_buffer;
+ int length = urb->actual_length;
+ int port_number;
+ int function;
+ __u8 lsr;
+ __u8 msr;
+
+ dbg("%s", __FUNCTION__);
+
+ if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) {
+ return;
+ }
+
+ if (urb->status) {
+ dbg(__FUNCTION__" - nonzero control read status received: %d", urb->status);
+ return;
+ }
+
+ if (!length) {
+ dbg ("%s - no data in urb", __FUNCTION__);
+ return;
+ }
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, length, data);
+
+ if (length != 2) {
+ dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length);
+ return;
+ }
+
+ port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
+ function = TIUMP_GET_FUNC_FROM_CODE (data[0]);
+ dbg ("%s - port_number %d, function %d, info 0x%x",
+ __FUNCTION__, port_number, function, data[1]);
+ port = &edge_serial->serial->port[port_number];
+ if (port_paranoia_check (port, __FUNCTION__)) {
+ dbg ("%s - change found for port that is not present",
+ __FUNCTION__);
+ return;
+ }
+ edge_port = port->private;
+ if (!edge_port) {
+ dbg ("%s - edge_port not found", __FUNCTION__);
+ return;
+ }
+ switch (function) {
+ case TIUMP_INTERRUPT_CODE_LSR:
+ lsr = MapLineStatus(data[1]);
+ if (lsr & UMP_UART_LSR_DATA_MASK) {
+ /* Save the LSR event for bulk read completion routine */
+ dbg ("%s - LSR Event Port %u LSR Status = %02x",
+ __FUNCTION__, port_number, lsr);
+ edge_port->lsr_event = 1;
+ edge_port->lsr_mask = lsr;
+ } else {
+ dbg ("%s - ===== Port %d LSR Status = %02x ======",
+ __FUNCTION__, port_number, lsr);
+ handle_new_lsr (edge_port, 0, lsr, 0);
+ }
+ break;
+
+ case TIUMP_INTERRUPT_CODE_MSR: // MSR
+ /* Copy MSR from UMP */
+ msr = data[1];
+ dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
+ __FUNCTION__, port_number, msr);
+ handle_new_msr (edge_port, msr);
+ break;
+
+ default:
+ err ("%s - Unknown Interrupt code from UMP %x\n",
+ __FUNCTION__, data[1]);
+ break;
+
+ }
+}
+
+static void edge_bulk_in_callback (struct urb *urb)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ struct tty_struct *tty;
+ int status;
+ int i;
+ int port_number;
+
+ dbg("%s", __FUNCTION__);
+
+ if (port_paranoia_check (edge_port->port, __FUNCTION__))
+ return;
+
+ if (urb->status) {
+ dbg ("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, urb->status);
+
+ if (urb->status == -EPIPE) {
+ /* clear any problem that might have happened on this pipe */
+ usb_clear_halt (edge_port->port->serial->dev, urb->pipe);
+ goto exit;
+ }
+ return;
+ }
+
+ port_number = edge_port->port->number - edge_port->port->serial->minor;
+
+ if (edge_port->lsr_event) {
+ edge_port->lsr_event = 0;
+ dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
+ __FUNCTION__, port_number, edge_port->lsr_mask, *data);
+ handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
+ /* Adjust buffer length/pointer */
+ --urb->actual_length;
+ ++data;
+ }
+
+ tty = edge_port->port->tty;
+ if (tty && urb->actual_length) {
+ usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+ if (edge_port->close_pending) {
+ dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__);
+ } else {
+ for (i = 0; i < urb->actual_length ; ++i) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters,
+ * we drop them. */
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* this doesn't actually push the data through unless
+ * tty->low_latency is set */
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ }
+ edge_port->icount.rx += urb->actual_length;
+ }
+
+exit:
+ /* continue always trying to read */
+ urb->dev = edge_port->port->serial->dev;
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status)
+ err ("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, status);
+}
+
+static void edge_bulk_out_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+ struct tty_struct *tty;
+
+ dbg ("%s - port %d", __FUNCTION__, port->number);
+
+ if (!serial) {
+ dbg ("%s - bad serial pointer, exiting", __FUNCTION__);
+ return;
+ }
+
+ if (urb->status) {
+ dbg ("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, urb->status);
+
+ if (urb->status == -EPIPE) {
+ /* clear any problem that might have happened on this pipe */
+ usb_clear_halt (serial->dev, urb->pipe);
+ }
+ return;
+ }
+
+ tty = port->tty;
+ if (tty) {
+ /* let the tty driver wakeup if it has a special write_wakeup function */
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+ (tty->ldisc.write_wakeup)(tty);
+ }
+
+ /* tell the tty driver that something has changed */
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+static int edge_open (struct usb_serial_port *port, struct file * filp)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+ struct edgeport_serial *edge_serial;
+ struct usb_device *dev;
+ struct urb *urb;
+ int port_number;
+ int status;
+ u16 open_settings;
+ u8 transaction_timeout;
+
+ if (port_paranoia_check (port, __FUNCTION__))
+ return -ENODEV;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+
+ /* force low_latency on so that our tty_push actually forces the data through,
+ otherwise it is scheduled, and with high data rates (like with OHCI) data
+ can get lost. */
+ if (port->tty)
+ port->tty->low_latency = 1;
+
+ port_number = port->number - port->serial->minor;
+ switch (port_number) {
+ case 0:
+ edge_port->uart_base = UMPMEM_BASE_UART1;
+ edge_port->dma_address = UMPD_OEDB1_ADDRESS;
+ break;
+ case 1:
+ edge_port->uart_base = UMPMEM_BASE_UART2;
+ edge_port->dma_address = UMPD_OEDB2_ADDRESS;
+ break;
+ default:
+ err ("Unknown port number!!!");
+ return -ENODEV;
+ }
+
+ dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
+ __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address);
+
+ dev = port->serial->dev;
+
+ memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+ init_waitqueue_head (&edge_port->delta_msr_wait);
+
+ /* turn off loopback */
+ status = TIClearLoopBack (edge_port);
+ if (status)
+ return status;
+
+ /* set up the port settings */
+ edge_set_termios (port, NULL);
+
+ /* open up the port */
+
+ /* milliseconds to timeout for DMA transfer */
+ transaction_timeout = 2;
+
+ edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) );
+
+ // milliseconds to timeout for DMA transfer
+ open_settings = (u8)(UMP_DMA_MODE_CONTINOUS |
+ UMP_PIPE_TRANS_TIMEOUT_ENA |
+ (transaction_timeout << 2));
+
+ dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
+
+ /* Tell TI to open and start the port */
+ status = TIWriteCommandSync (dev,
+ UMPC_OPEN_PORT,
+ (u8)(UMPM_UART1_PORT + port_number),
+ open_settings,
+ NULL,
+ 0);
+ if (status)
+ return status;
+
+ /* Start the DMA? */
+ status = TIWriteCommandSync (dev,
+ UMPC_START_PORT,
+ (u8)(UMPM_UART1_PORT + port_number),
+ 0,
+ NULL,
+ 0);
+ if (status)
+ return status;
+
+ /* Clear TX and RX buffers in UMP */
+ status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
+ if (status)
+ return status;
+
+ /* Read Initial MSR */
+ status = TIReadVendorRequestSync (dev,
+ UMPC_READ_MSR, // Request
+ 0, // wValue
+ (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address)
+ &edge_port->shadow_msr, // TransferBuffer
+ 1); // TransferBufferLength
+ if (status)
+ return status;
+
+ dbg ("ShadowMSR 0x%X", edge_port->shadow_msr);
+
+ edge_serial = edge_port->edge_serial;
+ if (edge_serial->num_ports_open == 0) {
+ /* we are the first port to be opened, let's post the interrupt urb */
+ urb = edge_serial->serial->port[0].interrupt_in_urb;
+ if (!urb) {
+ err ("%s - no interrupt urb present, exiting", __FUNCTION__);
+ return -EINVAL;
+ }
+ urb->complete = edge_interrupt_callback;
+ urb->context = edge_serial;
+ urb->dev = dev;
+ status = usb_submit_urb (urb, GFP_KERNEL);
+ if (status) {
+ err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status);
+ return status;
+ }
+ }
+
+ /*
+ * reset the data toggle on the bulk endpoints to work around bug in
+ * host controllers where things get out of sync some times
+ */
+ usb_clear_halt (dev, port->write_urb->pipe);
+ usb_clear_halt (dev, port->read_urb->pipe);
+
+ /* start up our bulk read urb */
+ urb = port->read_urb;
+ if (!urb) {
+ err ("%s - no read urb present, exiting", __FUNCTION__);
+ return -EINVAL;
+ }
+ urb->complete = edge_bulk_in_callback;
+ urb->context = edge_port;
+ urb->dev = dev;
+ status = usb_submit_urb (urb, GFP_KERNEL);
+ if (status) {
+ err ("%s - read bulk usb_submit_urb failed with value %d", __FUNCTION__, status);
+ return status;
+ }
+
+ ++edge_serial->num_ports_open;
+
+ dbg("%s - exited", __FUNCTION__);
+
+ return 0;
+}
+
+static void edge_close (struct usb_serial_port *port, struct file * filp)
+{
+ struct usb_serial *serial;
+ struct edgeport_serial *edge_serial;
+ struct edgeport_port *edge_port;
+ int port_number;
+ int status;
+
+ if (port_paranoia_check (port, __FUNCTION__))
+ return;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ serial = get_usb_serial (port, __FUNCTION__);
+ if (!serial)
+ return;
+
+ edge_serial = (struct edgeport_serial *)serial->private;
+ edge_port = (struct edgeport_port *)port->private;
+ if ((edge_serial == NULL) || (edge_port == NULL))
+ return;
+
+ if (serial->dev) {
+ /* The bulkreadcompletion routine will check
+ * this flag and dump add read data */
+ edge_port->close_pending = 1;
+
+ /* chase the port close */
+ TIChasePort (edge_port);
+
+ usb_unlink_urb (port->read_urb);
+
+ /* assuming we can still talk to the device,
+ * send a close port command to it */
+ dbg("%s - send umpc_close_port", __FUNCTION__);
+ port_number = port->number - port->serial->minor;
+ status = TIWriteCommandSync (port->serial->dev,
+ UMPC_CLOSE_PORT,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0,
+ NULL,
+ 0);
+ --edge_port->edge_serial->num_ports_open;
+ if (edge_port->edge_serial->num_ports_open <= 0) {
+ /* last port is now closed, let's shut down our interrupt urb */
+ usb_unlink_urb (serial->port[0].interrupt_in_urb);
+ edge_port->edge_serial->num_ports_open = 0;
+ }
+ edge_port->close_pending = 0;
+ }
+
+ dbg(__FUNCTION__" exited");
+}
+
+static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count)
+{
+ struct usb_serial *serial = port->serial;
+ struct edgeport_port *edge_port = port->private;
+ int result;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (count == 0) {
+ dbg("%s - write request of 0 bytes", __FUNCTION__);
+ return 0;
+ }
+
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->close_pending == 1)
+ return -ENODEV;
+
+ if (port->write_urb->status == -EINPROGRESS) {
+ dbg ("%s - already writing", __FUNCTION__);
+ return 0;
+ }
+
+ count = min (count, port->bulk_out_size);
+
+ if (from_user) {
+ if (copy_from_user(port->write_urb->transfer_buffer, data, count))
+ return -EFAULT;
+ } else {
+ memcpy (port->write_urb->transfer_buffer, data, count);
+ }
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+
+ /* set up our urb */
+ usb_fill_bulk_urb (port->write_urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ edge_bulk_out_callback,
+ port);
+
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result)
+ err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+ else
+ result = count;
+
+ if (result > 0)
+ edge_port->icount.tx += count;
+
+ return result;
+}
+
+static int edge_write_room (struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ int room = 0;
+
+ dbg(__FUNCTION__);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->close_pending == 1)
+ return -ENODEV;
+
+ dbg(__FUNCTION__" - port %d", port->number);
+
+ if (port->write_urb->status != -EINPROGRESS)
+ room = port->bulk_out_size;
+
+ dbg(__FUNCTION__ " - returns %d", room);
+ return room;
+}
+
+static int edge_chars_in_buffer (struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ int chars = 0;
+
+ dbg(__FUNCTION__);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->close_pending == 1)
+ return -ENODEV;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (port->write_urb->status == -EINPROGRESS)
+ chars = port->write_urb->transfer_buffer_length;
+
+ dbg ("%s - returns %d", __FUNCTION__, chars);
+ return chars;
+}
+
+static void edge_throttle (struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct tty_struct *tty;
+ int status;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+ dbg ("%s - no tty available", __FUNCTION__);
+ return;
+ }
+ /* if we are implementing XON/XOFF, send the stop character */
+ if (I_IXOFF(tty)) {
+ unsigned char stop_char = STOP_CHAR(tty);
+ status = edge_write (port, 0, &stop_char, 1);
+ if (status <= 0) {
+ return;
+ }
+ }
+
+ /* if we are implementing RTS/CTS, toggle that line */
+ if (tty->termios->c_cflag & CRTSCTS) {
+ status = TIClearRts (edge_port);
+ }
+
+ usb_unlink_urb (port->read_urb);
+}
+
+static void edge_unthrottle (struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct tty_struct *tty;
+ int status;
+
+ dbg(__FUNCTION__" - port %d", port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+ dbg ("%s - no tty available", __FUNCTION__);
+ return;
+ }
+
+ /* if we are implementing XON/XOFF, send the start character */
+ if (I_IXOFF(tty)) {
+ unsigned char start_char = START_CHAR(tty);
+ status = edge_write (port, 0, &start_char, 1);
+ if (status <= 0) {
+ return;
+ }
+ }
+
+ /* if we are implementing RTS/CTS, toggle that line */
+ if (tty->termios->c_cflag & CRTSCTS) {
+ status = TISetRts (edge_port);
+ }
+
+ port->read_urb->dev = port->serial->dev;
+ status = usb_submit_urb (port->read_urb, GFP_ATOMIC);
+ if (status) {
+ err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status);
+ }
+}
+
+
+static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+{
+ struct ump_uart_config *config;
+ struct tty_struct *tty;
+ int baud;
+ int round;
+ unsigned cflag;
+ int status;
+ int port_number = edge_port->port->number - edge_port->port->serial->minor;
+
+ dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
+
+ tty = edge_port->port->tty;
+ if ((!tty) ||
+ (!tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+
+ config = kmalloc (sizeof (*config), GFP_KERNEL);
+ if (!config) {
+ err ("%s - out of memory", __FUNCTION__);
+ return;
+ }
+
+ cflag = tty->termios->c_cflag;
+
+ config->wFlags = 0;
+
+ /* These flags must be set */
+ config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT;
+ config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR;
+ config->bUartMode = 0;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ config->bDataBits = UMP_UART_CHAR5BITS;
+ dbg ("%s - data bits = 5", __FUNCTION__);
+ break;
+ case CS6:
+ config->bDataBits = UMP_UART_CHAR6BITS;
+ dbg ("%s - data bits = 6", __FUNCTION__);
+ break;
+ case CS7:
+ config->bDataBits = UMP_UART_CHAR7BITS;
+ dbg ("%s - data bits = 7", __FUNCTION__);
+ break;
+ default:
+ case CS8:
+ config->bDataBits = UMP_UART_CHAR8BITS;
+ dbg ("%s - data bits = 8", __FUNCTION__);
+ break;
+ }
+
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ config->bParity = UMP_UART_ODDPARITY;
+ dbg(__FUNCTION__" - parity = odd");
+ } else {
+ config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ config->bParity = UMP_UART_EVENPARITY;
+ dbg(__FUNCTION__" - parity = even");
+ }
+ } else {
+ config->bParity = UMP_UART_NOPARITY;
+ dbg(__FUNCTION__" - parity = none");
+ }
+
+ if (cflag & CSTOPB) {
+ config->bStopBits = UMP_UART_STOPBIT2;
+ dbg(__FUNCTION__" - stop bits = 2");
+ } else {
+ config->bStopBits = UMP_UART_STOPBIT1;
+ dbg(__FUNCTION__" - stop bits = 1");
+ }
+
+ /* figure out the flow control settings */
+ if (cflag & CRTSCTS) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
+ config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
+ dbg(__FUNCTION__" - RTS/CTS is enabled");
+ } else {
+ dbg(__FUNCTION__" - RTS/CTS is disabled");
+ }
+
+ /* if we are implementing XON/XOFF, set the start and stop character in the device */
+ if (I_IXOFF(tty) || I_IXON(tty)) {
+ config->cXon = START_CHAR(tty);
+ config->cXoff = STOP_CHAR(tty);
+
+ /* if we are implementing INBOUND XON/XOFF */
+ if (I_IXOFF(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
+ dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __FUNCTION__, config->cXon, config->cXoff);
+ } else {
+ dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
+ }
+
+ /* if we are implementing OUTBOUND XON/XOFF */
+ if (I_IXON(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
+ dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __FUNCTION__, config->cXon, config->cXoff);
+ } else {
+ dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
+ }
+ }
+
+ /* Round the baud rate */
+ baud = tty_get_baud_rate(tty);
+ if (!baud) {
+ /* pick a default, any default... */
+ baud = 9600;
+ }
+ config->wBaudRate = (__u16)(461550L / baud);
+ round = 4615500L / baud;
+ if ((round - (config->wBaudRate * 10)) >= 5)
+ config->wBaudRate++;
+
+ dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
+
+ dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate));
+ dbg ("wFlags: 0x%x", config->wFlags);
+ dbg ("bDataBits: %d", config->bDataBits);
+ dbg ("bParity: %d", config->bParity);
+ dbg ("bStopBits: %d", config->bStopBits);
+ dbg ("cXon: %d", config->cXon);
+ dbg ("cXoff: %d", config->cXoff);
+ dbg ("bUartMode: %d", config->bUartMode);
+
+ /* move the word values into big endian mode */
+ cpu_to_be16s (&config->wFlags);
+ cpu_to_be16s (&config->wBaudRate);
+
+ status = TIWriteCommandSync (edge_port->port->serial->dev,
+ UMPC_SET_CONFIG,
+ (__u8)(UMPM_UART1_PORT + port_number),
+ 0,
+ (__u8 *)config,
+ sizeof(*config));
+ if (status) {
+ dbg ("%s - error %d when trying to write config to device",
+ __FUNCTION__, status);
+ }
+
+ kfree (config);
+
+ return;
+}
+
+static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct tty_struct *tty = port->tty;
+ unsigned int cflag;
+
+ if (!port->tty || !port->tty->termios) {
+ dbg ("%s - no tty or termios", __FUNCTION__);
+ return;
+ }
+
+ cflag = tty->termios->c_cflag;
+ /* check that they really want us to change something */
+ if (old_termios) {
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg ("%s - nothing to change", __FUNCTION__);
+ return;
+ }
+ }
+
+ dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+ tty->termios->c_cflag,
+ RELEVANT_IFLAG(tty->termios->c_iflag));
+ if (old_termios) {
+ dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+ old_termios->c_cflag,
+ RELEVANT_IFLAG(old_termios->c_iflag));
+ }
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ /* change the port settings to the new ones specified */
+ change_port_settings (edge_port, old_termios);
+
+ return;
+}
+
+static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value)
+{
+ unsigned int mcr = edge_port->shadow_mcr;
+ unsigned int arg;
+
+ if (copy_from_user(&arg, value, sizeof(int)))
+ return -EFAULT;
+
+ switch (cmd) {
+ case TIOCMBIS:
+ if (arg & TIOCM_RTS)
+ mcr |= MCR_RTS;
+ if (arg & TIOCM_DTR)
+ mcr |= MCR_RTS;
+ if (arg & TIOCM_LOOP)
+ mcr |= MCR_LOOPBACK;
+ break;
+
+ case TIOCMBIC:
+ if (arg & TIOCM_RTS)
+ mcr &= ~MCR_RTS;
+ if (arg & TIOCM_DTR)
+ mcr &= ~MCR_RTS;
+ if (arg & TIOCM_LOOP)
+ mcr &= ~MCR_LOOPBACK;
+ break;
+
+ case TIOCMSET:
+ /* turn off the RTS and DTR and LOOPBACK
+ * and then only turn on what was asked to */
+ mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+ mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+ mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+ mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
+ break;
+ }
+
+ edge_port->shadow_mcr = mcr;
+
+ TIRestoreMCR (edge_port, mcr);
+
+ return 0;
+}
+
+static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value)
+{
+ unsigned int result = 0;
+ unsigned int msr = edge_port->shadow_msr;
+ unsigned int mcr = edge_port->shadow_mcr;
+
+ result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
+ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
+ | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */
+ | ((msr & MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */
+ | ((msr & MSR_RI) ? TIOCM_RI: 0) /* 0x080 */
+ | ((msr & MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+
+
+ dbg(__FUNCTION__" -- %x", result);
+
+ if (copy_to_user(value, &result, sizeof(int)))
+ return -EFAULT;
+ return 0;
+}
+
+static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ tmp.type = PORT_16550A;
+ tmp.line = edge_port->port->serial->minor;
+ tmp.port = edge_port->port->number;
+ tmp.irq = 0;
+ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ tmp.xmit_fifo_size = edge_port->port->bulk_out_size;
+ tmp.baud_base = 9600;
+ tmp.close_delay = 5*HZ;
+ tmp.closing_wait = 30*HZ;
+// tmp.custom_divisor = state->custom_divisor;
+// tmp.hub6 = state->hub6;
+// tmp.io_type = state->io_type;
+
+
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct async_icount cnow;
+ struct async_icount cprev;
+
+ dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);
+
+ switch (cmd) {
+ case TIOCINQ:
+ dbg(__FUNCTION__" (%d) TIOCINQ", port->number);
+// return get_number_bytes_avail(edge_port, (unsigned int *) arg);
+ break;
+
+ case TIOCSERGETLSR:
+ dbg(__FUNCTION__" (%d) TIOCSERGETLSR", port->number);
+// return get_lsr_info(edge_port, (unsigned int *) arg);
+ break;
+
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ dbg(__FUNCTION__" (%d) TIOCMSET/TIOCMBIC/TIOCMSET", port->number);
+ return set_modem_info(edge_port, cmd, (unsigned int *) arg);
+ break;
+
+ case TIOCMGET:
+ dbg(__FUNCTION__" (%d) TIOCMGET", port->number);
+ return get_modem_info(edge_port, (unsigned int *) arg);
+ break;
+
+ case TIOCGSERIAL:
+ dbg(__FUNCTION__" (%d) TIOCGSERIAL", port->number);
+ return get_serial_info(edge_port, (struct serial_struct *) arg);
+ break;
+
+ case TIOCSSERIAL:
+ dbg(__FUNCTION__" (%d) TIOCSSERIAL", port->number);
+ break;
+
+ case TIOCMIWAIT:
+ dbg(__FUNCTION__" (%d) TIOCMIWAIT", port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ interruptible_sleep_on(&edge_port->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = edge_port->icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* not reached */
+ break;
+
+ case TIOCGICOUNT:
+ dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+ port->number, edge_port->icount.rx, edge_port->icount.tx);
+ if (copy_to_user((void *)arg, &edge_port->icount, sizeof(edge_port->icount)))
+ return -EFAULT;
+ return 0;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static void edge_break (struct usb_serial_port *port, int break_state)
+{
+ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ int status;
+
+ dbg ("%s - state = %d", __FUNCTION__, break_state);
+
+ /* chase the port close */
+ TIChasePort (edge_port);
+
+ if (break_state == -1) {
+ status = TISetBreak (edge_port);
+ } else {
+ status = TIClearBreak (edge_port);
+ }
+ if (status) {
+ dbg ("%s - error %d sending break set/clear command.",
+ __FUNCTION__, status);
+ }
+}
+
+static int edge_startup (struct usb_serial *serial)
+{
+ struct edgeport_serial *edge_serial;
+ struct edgeport_port *edge_port;
+ struct usb_device *dev;
+ int status;
+ int i;
+
+ dev = serial->dev;
+
+ /* create our private serial structure */
+ edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
+ if (edge_serial == NULL) {
+ err(__FUNCTION__" - Out of memory");
+ return -ENOMEM;
+ }
+ memset (edge_serial, 0, sizeof(struct edgeport_serial));
+ edge_serial->serial = serial;
+ serial->private = edge_serial;
+
+ status = TIDownloadFirmware (edge_serial);
+ if (status) {
+ kfree (edge_serial);
+ return status;
+ }
+
+ /* set up our port private structures */
+ for (i = 0; i < serial->num_ports; ++i) {
+ edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+ if (edge_port == NULL) {
+ err(__FUNCTION__" - Out of memory");
+ return -ENOMEM;
+ }
+ memset (edge_port, 0, sizeof(struct edgeport_port));
+ edge_port->port = &serial->port[i];
+ edge_port->edge_serial = edge_serial;
+ serial->port[i].private = edge_port;
+ }
+
+ return 0;
+}
+
+static void edge_shutdown (struct usb_serial *serial)
+{
+ int i;
+
+ dbg (__FUNCTION__);
+
+ for (i=0; i < serial->num_ports; ++i) {
+ kfree (serial->port[i].private);
+ serial->port[i].private = NULL;
+ }
+ kfree (serial->private);
+ serial->private = NULL;
+}
+
+
+static struct usb_serial_device_type edgeport_1port_device = {
+ owner: THIS_MODULE,
+ name: "Edgeport TI 1 port adapter",
+ id_table: edgeport_1port_id_table,
+ num_interrupt_in: 1,
+ num_bulk_in: 1,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: edge_open,
+ close: edge_close,
+ throttle: edge_throttle,
+ unthrottle: edge_unthrottle,
+ attach: edge_startup,
+ shutdown: edge_shutdown,
+ ioctl: edge_ioctl,
+ set_termios: edge_set_termios,
+ write: edge_write,
+ write_room: edge_write_room,
+ chars_in_buffer: edge_chars_in_buffer,
+ break_ctl: edge_break,
+};
+
+static struct usb_serial_device_type edgeport_2port_device = {
+ owner: THIS_MODULE,
+ name: "Edgeport TI 2 port adapter",
+ id_table: edgeport_2port_id_table,
+ num_interrupt_in: 1,
+ num_bulk_in: 2,
+ num_bulk_out: 2,
+ num_ports: 2,
+ open: edge_open,
+ close: edge_close,
+ throttle: edge_throttle,
+ unthrottle: edge_unthrottle,
+ attach: edge_startup,
+ shutdown: edge_shutdown,
+ ioctl: edge_ioctl,
+ set_termios: edge_set_termios,
+ write: edge_write,
+ write_room: edge_write_room,
+ chars_in_buffer: edge_chars_in_buffer,
+ break_ctl: edge_break,
+};
+
+
+static int __init edgeport_init(void)
+{
+ usb_serial_register (&edgeport_1port_device);
+ usb_serial_register (&edgeport_2port_device);
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit edgeport_exit (void)
+{
+ usb_serial_deregister (&edgeport_1port_device);
+ usb_serial_deregister (&edgeport_2port_device);
+}
+
+module_init(edgeport_init);
+module_exit(edgeport_exit);
+
+/* Module information */
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_PARM(ignore_cpu_rev, "i");
+MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
+
diff --git a/drivers/usb/serial/io_ti.h b/drivers/usb/serial/io_ti.h
new file mode 100644
index 000000000000..82a06c8b444c
--- /dev/null
+++ b/drivers/usb/serial/io_ti.h
@@ -0,0 +1,180 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 1997-2002 Inside Out Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *
+ * Feb-16-2001 DMI Added I2C structure definitions
+ * May-29-2002 gkh Ported to Linux
+ *
+ *
+ ******************************************************************************/
+
+#ifndef _IO_TI_H_
+#define _IO_TI_H_
+
+/* Address Space */
+#define DTK_ADDR_SPACE_XDATA 0x03 /* Addr is placed in XDATA space */
+#define DTK_ADDR_SPACE_I2C_TYPE_II 0x82 /* Addr is placed in I2C area */
+#define DTK_ADDR_SPACE_I2C_TYPE_III 0x83 /* Addr is placed in I2C area */
+
+// UART Defines
+#define UMPMEM_BASE_UART1 0xFFA0 /* UMP UART1 base address */
+#define UMPMEM_BASE_UART2 0xFFB0 /* UMP UART2 base address */
+#define UMPMEM_OFFS_UART_LSR 0x05 /* UMP UART LSR register offset */
+
+/* Bits per character */
+#define UMP_UART_CHAR5BITS 0x00
+#define UMP_UART_CHAR6BITS 0x01
+#define UMP_UART_CHAR7BITS 0x02
+#define UMP_UART_CHAR8BITS 0x03
+
+/* Parity */
+#define UMP_UART_NOPARITY 0x00
+#define UMP_UART_ODDPARITY 0x01
+#define UMP_UART_EVENPARITY 0x02
+#define UMP_UART_MARKPARITY 0x03
+#define UMP_UART_SPACEPARITY 0x04
+
+/* Stop bits */
+#define UMP_UART_STOPBIT1 0x00
+#define UMP_UART_STOPBIT15 0x01
+#define UMP_UART_STOPBIT2 0x02
+
+/* Line status register masks */
+#define UMP_UART_LSR_OV_MASK 0x01
+#define UMP_UART_LSR_PE_MASK 0x02
+#define UMP_UART_LSR_FE_MASK 0x04
+#define UMP_UART_LSR_BR_MASK 0x08
+#define UMP_UART_LSR_ER_MASK 0x0F
+#define UMP_UART_LSR_RX_MASK 0x10
+#define UMP_UART_LSR_TX_MASK 0x20
+
+#define UMP_UART_LSR_DATA_MASK ( LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK )
+
+/* Port Settings Constants) */
+#define UMP_MASK_UART_FLAGS_RTS_FLOW 0x0001
+#define UMP_MASK_UART_FLAGS_RTS_DISABLE 0x0002
+#define UMP_MASK_UART_FLAGS_PARITY 0x0008
+#define UMP_MASK_UART_FLAGS_OUT_X_DSR_FLOW 0x0010
+#define UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW 0x0020
+#define UMP_MASK_UART_FLAGS_OUT_X 0x0040
+#define UMP_MASK_UART_FLAGS_OUT_XA 0x0080
+#define UMP_MASK_UART_FLAGS_IN_X 0x0100
+#define UMP_MASK_UART_FLAGS_DTR_FLOW 0x0800
+#define UMP_MASK_UART_FLAGS_DTR_DISABLE 0x1000
+#define UMP_MASK_UART_FLAGS_RECEIVE_MS_INT 0x2000
+#define UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR 0x4000
+
+#define UMP_DMA_MODE_CONTINOUS 0x01
+#define UMP_PIPE_TRANS_TIMEOUT_ENA 0x80
+#define UMP_PIPE_TRANSFER_MODE_MASK 0x03
+#define UMP_PIPE_TRANS_TIMEOUT_MASK 0x7C
+
+/* Purge port Direction Mask Bits */
+#define UMP_PORT_DIR_OUT 0x01
+#define UMP_PORT_DIR_IN 0x02
+
+// Address of Port 0
+#define UMPM_UART1_PORT 0x03
+
+// Commands
+#define UMPC_SET_CONFIG 0x05
+#define UMPC_OPEN_PORT 0x06
+#define UMPC_CLOSE_PORT 0x07
+#define UMPC_START_PORT 0x08
+#define UMPC_STOP_PORT 0x09
+#define UMPC_TEST_PORT 0x0A
+#define UMPC_PURGE_PORT 0x0B
+
+#define UMPC_COMPLETE_READ 0x80 // Force the Firmware to complete the current Read
+#define UMPC_HARDWARE_RESET 0x81 // Force UMP back into BOOT Mode
+#define UMPC_COPY_DNLD_TO_I2C 0x82 // Copy current download image to type 0xf2 record in 16k I2C
+ // firmware will change 0xff record to type 2 record when complete
+
+ // Special function register commands
+ // wIndex is register address
+ // wValue is MSB/LSB mask/data
+#define UMPC_WRITE_SFR 0x83 // Write SFR Register
+
+ // wIndex is register address
+#define UMPC_READ_SFR 0x84 // Read SRF Register
+
+ // Set or Clear DTR (wValue bit 0 Set/Clear) wIndex ModuleID (port)
+#define UMPC_SET_CLR_DTR 0x85
+
+ // Set or Clear RTS (wValue bit 0 Set/Clear) wIndex ModuleID (port)
+#define UMPC_SET_CLR_RTS 0x86
+
+ // Set or Clear LOOPBACK (wValue bit 0 Set/Clear) wIndex ModuleID (port)
+#define UMPC_SET_CLR_LOOPBACK 0x87
+
+ // Set or Clear BREAK (wValue bit 0 Set/Clear) wIndex ModuleID (port)
+#define UMPC_SET_CLR_BREAK 0x88
+
+ // Read MSR wIndex ModuleID (port)
+#define UMPC_READ_MSR 0x89
+
+ /* Toolkit commands */
+ /* Read-write group */
+#define UMPC_MEMORY_READ 0x92
+#define UMPC_MEMORY_WRITE 0x93
+
+/*
+ * UMP DMA Definitions
+ */
+#define UMPD_OEDB1_ADDRESS 0xFF08
+#define UMPD_OEDB2_ADDRESS 0xFF10
+
+struct out_endpoint_desc_block
+{
+ __u8 Configuration;
+ __u8 XBufAddr;
+ __u8 XByteCount;
+ __u8 Unused1;
+ __u8 Unused2;
+ __u8 YBufAddr;
+ __u8 YByteCount;
+ __u8 BufferSize;
+} __attribute__((packed));
+
+
+/*
+ * TYPE DEFINITIONS
+ * Structures for Firmware commands
+ */
+struct ump_uart_config /* UART settings */
+{
+ __u16 wBaudRate; /* Baud rate */
+ __u16 wFlags; /* Bitmap mask of flags */
+ __u8 bDataBits; /* 5..8 - data bits per character */
+ __u8 bParity; /* Parity settings */
+ __u8 bStopBits; /* Stop bits settings */
+ char cXon; /* XON character */
+ char cXoff; /* XOFF character */
+ __u8 bUartMode; /* Will be updated when a user */
+ /* interface is defined */
+} __attribute__((packed));
+
+
+/*
+ * TYPE DEFINITIONS
+ * Structures for USB interrupts
+ */
+struct ump_interrupt /* Interrupt packet structure */
+{
+ __u8 bICode; /* Interrupt code (interrupt num) */
+ __u8 bIInfo; /* Interrupt information */
+} __attribute__((packed));
+
+
+#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
+#define TIUMP_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
+#define TIUMP_INTERRUPT_CODE_LSR 0x03
+#define TIUMP_INTERRUPT_CODE_MSR 0x04
+
+#endif
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index 068066e821e8..37fe6744a92c 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -106,11 +106,23 @@
#define ION_DEVICE_ID_BB_EDGEPORT_4_DIN 0x011 // Edgeport/4 RS232 with Apple DIN connector
#define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU 0x012 // Half of an Edgeport/16 (the kind with 2 EP/8s)
#define ION_DEVICE_ID_BB_EDGEPORT_8I 0x014 // Edgeport/8 RS422 (single-CPU)
-// These IDs are used by the Edgeport.exe program for uninstalling.
-//
-#define EDGEPORT_DEVICE_IDS {0x001, 0x003, 0x004, 0x005, 0x006, 0x007, 0x00B, \
- 0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, \
- 0x013, 0x014 }
+
+
+/* Edgeport TI based devices */
+#define ION_DEVICE_ID_TI_EDGEPORT_4 0x0201 /* Edgeport/4 RS232 */
+#define ION_DEVICE_ID_TI_EDGEPORT_2 0x0205 /* Edgeport/2 RS232 */
+#define ION_DEVICE_ID_TI_EDGEPORT_4I 0x0206 /* Edgeport/4i RS422 */
+#define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 /* Edgeport/2i RS422/RS485 */
+#define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C /* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */
+#define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D /* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */
+#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 /* Edgeport/1 RS232 */
+#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 /* Edgeport/42 4 hub 2 RS232 */
+#define ION_DEVICE_ID_TI_EDGEPORT_22 0x021A /* Edgeport/22 Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */
+
+#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT 0x0240 /* Edgeport/421 in boot mode */
+#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN 0x0241 /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
+#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT 0x0242 /* Edgeport/21 in boot mode */
+#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN 0x0243 /*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
#define MAKE_USB_PRODUCT_ID( OemId, DeviceId ) \
@@ -217,7 +229,7 @@
// descriptor format, so that they may be separately retrieved,
// if necessary, with a minimum of work on the 930. This also
// requires them to be in UNICODE format, which, for English at
-// least, simply means extending each UCHAR into a USHORT.
+// least, simply means extending each __u8 into a __u16.
// 3. For all fields, 00 means 'uninitialized'.
// 4. All unused areas should be set to 00 for future expansion.
//
@@ -384,5 +396,92 @@ struct edge_boot_descriptor {
#define BOOT_CAP_RESET_CMD 0x0001 // If set, boot correctly supports ION_RESET_DEVICE
-#endif // if !defined()
+
+/************************************************************************
+ T I U M P D E F I N I T I O N S
+ ***********************************************************************/
+
+//************************************************************************
+// TI I2C Format Definitions
+//************************************************************************
+#define I2C_DESC_TYPE_INFO_BASIC 1
+#define I2C_DESC_TYPE_FIRMWARE_BASIC 2
+#define I2C_DESC_TYPE_DEVICE 3
+#define I2C_DESC_TYPE_CONFIG 4
+#define I2C_DESC_TYPE_STRING 5
+#define I2C_DESC_TYPE_FIRMWARE_BLANK 0xf2
+
+#define I2C_DESC_TYPE_MAX 5
+// 3410 may define types 6, 7 for other firmware downloads
+
+// Special section defined by ION
+#define I2C_DESC_TYPE_ION 0 // Not defined by TI
+
+
+struct ti_i2c_desc
+{
+ __u8 Type; // Type of descriptor
+ __u16 Size; // Size of data only not including header
+ __u8 CheckSum; // Checksum (8 bit sum of data only)
+ __u8 Data[0]; // Data starts here
+}__attribute__((packed));
+
+struct ti_i2c_firmware_rec
+{
+ __u8 Ver_Major; // Firmware Major version number
+ __u8 Ver_Minor; // Firmware Minor version number
+ __u8 Data[0]; // Download starts here
+}__attribute__((packed));
+
+
+// Structure of header of download image in fw_down.h
+struct ti_i2c_image_header
+{
+ __u16 Length;
+ __u8 CheckSum;
+}__attribute__((packed));
+
+struct ti_basic_descriptor
+{
+ __u8 Power; // Self powered
+ // bit 7: 1 - power switching supported
+ // 0 - power switching not supported
+ //
+ // bit 0: 1 - self powered
+ // 0 - bus powered
+ //
+ //
+ __u16 HubVid; // VID HUB
+ __u16 HubPid; // PID HUB
+ __u16 DevPid; // PID Edgeport
+ __u8 HubTime; // Time for power on to power good
+ __u8 HubCurrent; // HUB Current = 100ma
+} __attribute__((packed));
+
+
+#define TI_GET_CPU_REVISION(x) (__u8)((((x)>>4)&0x0f))
+#define TI_GET_BOARD_REVISION(x) (__u8)(((x)&0x0f))
+
+#define TI_I2C_SIZE_MASK 0x1f // 5 bits
+#define TI_GET_I2C_SIZE(x) ((((x) & TI_I2C_SIZE_MASK)+1)*256)
+
+#define TI_MAX_I2C_SIZE ( 16 * 1024 )
+
+/* TI USB 5052 definitions */
+struct edge_ti_manuf_descriptor
+{
+ __u8 IonConfig; // Config byte for ION manufacturing use
+ __u8 IonConfig2; // Expansion
+ __u8 Version; // Verqsion
+ __u8 CpuRev_BoardRev; // CPU revision level (0xF0) and Board Rev Level (0x0F)
+ __u8 NumPorts; // Number of ports for this UMP
+ __u8 NumVirtualPorts; // Number of Virtual ports
+ __u8 HubConfig1; // Used to configure the Hub
+ __u8 HubConfig2; // Used to configure the Hub
+ __u8 TotalPorts; // Total Number of Com Ports for the entire device (All UMPs)
+ __u8 Reserved;
+}__attribute__((packed));
+
+
+#endif // if !defined()
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index ae7f1f3da7a5..c232a4ec3010 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -15,6 +15,11 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (06/05/2002) gkh
+ * moved location of startup() call in serial_probe() until after all
+ * of the port information and endpoints are initialized. This makes
+ * things easier for some drivers.
+ *
* (04/10/2002) gkh
* added serial_read_proc function which creates a
* /proc/tty/driver/usb-serial file.
@@ -341,7 +346,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.5"
+#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
#define DRIVER_DESC "USB Serial Driver core"
diff --git a/drivers/usb/storage/Config.help b/drivers/usb/storage/Config.help
index 4acef81f9879..81131aef0bce 100644
--- a/drivers/usb/storage/Config.help
+++ b/drivers/usb/storage/Config.help
@@ -1,6 +1,9 @@
CONFIG_USB_STORAGE
Say Y here if you want to connect USB mass storage devices to your
- computer's USB port.
+ computer's USB port. This is the driver you need for USB floppy drives,
+ USB hard disks, USB tape drives and USB CD-ROMs, along with
+ similar devices. This driver may also be used for some cameras and
+ card readers.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
@@ -44,3 +47,11 @@ CONFIG_USB_STORAGE_SDDR09
CONFIG_USB_STORAGE_SDDR55
Say Y here to include additional code to support the Sandisk SDDR-55
SmartMedia reader in the USB Mass Storage driver.
+
+CONFIG_USB_STORAGE_HP8200e
+ Say Y here to include additional code to support Hewlett-Packard
+ 8200e/8210e/8230e CD-Writer Plus drives.
+
+CONFIG_USB_STORAGE_JUMPSHOT
+ Say Y here to include additional code to support the Lexar Jumpshot
+ USB CompactFlash reader.
diff --git a/drivers/usb/storage/Config.in b/drivers/usb/storage/Config.in
index 7f630fb6d53d..6b67604160ca 100644
--- a/drivers/usb/storage/Config.in
+++ b/drivers/usb/storage/Config.in
@@ -6,11 +6,11 @@ if [ "$CONFIG_SCSI" = "n" ]; then
fi
dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
- dep_mbool ' Datafab Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' Datafab Compact Flash Reader support (EXPERIMENTAL)' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE
dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
- dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' SanDisk SDDR-55 SmartMedia support' CONFIG_USB_STORAGE_SDDR55 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' HP CD-Writer 82xx support (EXPERIMENTAL)' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' SanDisk SDDR-55 SmartMedia support (EXPERIMENTAL)' CONFIG_USB_STORAGE_SDDR55 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' Lexar Jumpshot Compact Flash Reader (EXPERIMENTAL)' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index c0bdea0c4e6e..e68801addae4 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -182,46 +182,46 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
# include "unusual_devs.h"
# undef UNUSUAL_DEV
/* Control/Bulk transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_CB},
+ { .useProtocol = US_SC_RBC,
+ .useTransport = US_PR_CB},
+ { .useProtocol = US_SC_8020,
+ .useTransport = US_PR_CB},
+ { .useProtocol = US_SC_QIC,
+ .useTransport = US_PR_CB},
+ { .useProtocol = US_SC_UFI,
+ .useTransport = US_PR_CB},
+ { .useProtocol = US_SC_8070,
+ .useTransport = US_PR_CB},
+ { .useProtocol = US_SC_SCSI,
+ .useTransport = US_PR_CB},
/* Control/Bulk/Interrupt transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_CBI},
+ { .useProtocol = US_SC_RBC,
+ .useTransport = US_PR_CBI},
+ { .useProtocol = US_SC_8020,
+ .useTransport = US_PR_CBI},
+ { .useProtocol = US_SC_QIC,
+ .useTransport = US_PR_CBI},
+ { .useProtocol = US_SC_UFI,
+ .useTransport = US_PR_CBI},
+ { .useProtocol = US_SC_8070,
+ .useTransport = US_PR_CBI},
+ { .useProtocol = US_SC_SCSI,
+ .useTransport = US_PR_CBI},
/* Bulk-only transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_BULK},
+ { .useProtocol = US_SC_RBC,
+ .useTransport = US_PR_BULK},
+ { .useProtocol = US_SC_8020,
+ .useTransport = US_PR_BULK},
+ { .useProtocol = US_SC_QIC,
+ .useTransport = US_PR_BULK},
+ { .useProtocol = US_SC_UFI,
+ .useTransport = US_PR_BULK},
+ { .useProtocol = US_SC_8070,
+ .useTransport = US_PR_BULK},
+ { .useProtocol = US_SC_SCSI,
+ .useTransport = US_PR_BULK},
/* Terminating entry */
{ 0 }
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index 997787786344..56c037a3385a 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -51,7 +50,6 @@
static struct super_operations driverfs_ops;
static struct file_operations driverfs_file_operations;
static struct inode_operations driverfs_dir_inode_operations;
-static struct dentry_operations driverfs_dentry_dir_ops;
static struct dentry_operations driverfs_dentry_file_ops;
static struct address_space_operations driverfs_aops;
@@ -136,6 +134,9 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in
struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev);
int error = -EPERM;
+ if (dentry->d_inode)
+ return -EEXIST;
+
/* only allow create if ->d_fsdata is not NULL (so we can assume it
* comes from the driverfs API below. */
if (dentry->d_fsdata && inode) {
@@ -149,22 +150,19 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in
static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
- lock_kernel();
- dentry->d_op = &driverfs_dentry_dir_ops;
- res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0);
+ mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
+ res = driverfs_mknod(dir, dentry, mode, 0);
if (!res)
dir->i_nlink++;
- unlock_kernel();
return res;
}
static int driverfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
- lock_kernel();
+ mode = (mode & S_IALLUGO) | S_IFREG;
dentry->d_op = &driverfs_dentry_file_ops;
- res = driverfs_mknod(dir, dentry, mode | S_IFREG, 0);
- unlock_kernel();
+ res = driverfs_mknod(dir, dentry, mode, 0);
return res;
}
@@ -173,6 +171,9 @@ static int driverfs_symlink(struct inode * dir, struct dentry *dentry, const cha
struct inode *inode;
int error = -ENOSPC;
+ if (dentry->d_inode)
+ return -EEXIST;
+
inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
@@ -212,24 +213,49 @@ static int driverfs_empty(struct dentry *dentry)
static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
-
- lock_kernel();
- inode->i_nlink--;
- unlock_kernel();
+ down(&inode->i_sem);
+ dentry->d_inode->i_nlink--;
dput(dentry);
+ up(&inode->i_sem);
+ d_delete(dentry);
return 0;
}
+static void d_unhash(struct dentry *dentry)
+{
+ dget(dentry);
+ spin_lock(&dcache_lock);
+ switch (atomic_read(&dentry->d_count)) {
+ default:
+ spin_unlock(&dcache_lock);
+ shrink_dcache_parent(dentry);
+ spin_lock(&dcache_lock);
+ if (atomic_read(&dentry->d_count) != 2)
+ break;
+ case 2:
+ list_del_init(&dentry->d_hash);
+ }
+ spin_unlock(&dcache_lock);
+}
+
static int driverfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error = -ENOTEMPTY;
+ struct inode * inode = dentry->d_inode;
+ down(&inode->i_sem);
+ d_unhash(dentry);
if (driverfs_empty(dentry)) {
- dentry->d_inode->i_nlink--;
- driverfs_unlink(dir, dentry);
+ dentry->d_inode->i_nlink -= 2;
+ dput(dentry);
+ inode->i_flags |= S_DEAD;
dir->i_nlink--;
error = 0;
}
+ up(&inode->i_sem);
+ if (!error)
+ d_delete(dentry);
+ dput(dentry);
return error;
}
@@ -365,7 +391,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
{
loff_t retval = -EINVAL;
- lock_kernel();
+ down(&file->f_dentry->d_inode->i_sem);
switch(orig) {
case 0:
if (offset > 0) {
@@ -382,7 +408,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
default:
break;
}
- unlock_kernel();
+ up(&file->f_dentry->d_inode->i_sem);
return retval;
}
@@ -424,36 +450,31 @@ static int driverfs_d_delete_file (struct dentry * dentry)
}
static struct file_operations driverfs_file_operations = {
- read: driverfs_read_file,
- write: driverfs_write_file,
- llseek: driverfs_file_lseek,
- open: driverfs_open_file,
- release: driverfs_release,
+ .read = driverfs_read_file,
+ .write = driverfs_write_file,
+ .llseek = driverfs_file_lseek,
+ .open = driverfs_open_file,
+ .release = driverfs_release,
};
static struct inode_operations driverfs_dir_inode_operations = {
- create: driverfs_create,
- lookup: simple_lookup,
- unlink: driverfs_unlink,
- symlink: driverfs_symlink,
- mkdir: driverfs_mkdir,
- rmdir: driverfs_rmdir,
+ .lookup = simple_lookup,
};
static struct address_space_operations driverfs_aops = {
- readpage: driverfs_readpage,
- writepage: fail_writepage,
- prepare_write: driverfs_prepare_write,
- commit_write: driverfs_commit_write
+ .readpage = driverfs_readpage,
+ .writepage = fail_writepage,
+ .prepare_write = driverfs_prepare_write,
+ .commit_write = driverfs_commit_write
};
static struct dentry_operations driverfs_dentry_file_ops = {
- d_delete: driverfs_d_delete_file,
+ .d_delete = driverfs_d_delete_file,
};
static struct super_operations driverfs_ops = {
- statfs: simple_statfs,
- drop_inode: generic_delete_inode,
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
};
static int driverfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -489,10 +510,10 @@ static struct super_block *driverfs_get_sb(struct file_system_type *fs_type,
}
static struct file_system_type driverfs_fs_type = {
- owner: THIS_MODULE,
- name: "driverfs",
- get_sb: driverfs_get_sb,
- kill_sb: kill_litter_super,
+ .owner = THIS_MODULE,
+ .name = "driverfs",
+ .get_sb = driverfs_get_sb,
+ .kill_sb = kill_litter_super,
};
static int get_mount(void)
@@ -589,7 +610,7 @@ driverfs_create_dir(struct driver_dir_entry * entry,
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *) entry;
entry->dentry = dentry;
- error = vfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
+ error = driverfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
} else
error = PTR_ERR(dentry);
up(&parent_dentry->d_inode->i_sem);
@@ -630,7 +651,7 @@ driverfs_create_file(struct driver_file_entry * entry,
dentry = lookup_hash(&qstr,parent->dentry);
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)entry;
- error = vfs_create(parent->dentry->d_inode,dentry,entry->mode);
+ error = driverfs_create(parent->dentry->d_inode,dentry,entry->mode);
/* Still good? Ok, then fill in the blanks: */
if (!error) {
@@ -678,7 +699,7 @@ int driverfs_create_symlink(struct driver_dir_entry * parent,
dentry = lookup_hash(&qstr,parent->dentry);
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)entry;
- error = vfs_symlink(parent->dentry->d_inode,dentry,target);
+ error = driverfs_symlink(parent->dentry->d_inode,dentry,target);
if (!error) {
dentry->d_inode->u.generic_ip = (void *)entry;
entry->dentry = dentry;
@@ -717,7 +738,7 @@ void driverfs_remove_file(struct driver_dir_entry * dir, const char * name)
entry = list_entry(node,struct driver_file_entry,node);
if (!strcmp(entry->name,name)) {
list_del_init(node);
- vfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry);
+ driverfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry);
dput(entry->dentry);
put_mount();
break;
@@ -752,14 +773,14 @@ void driverfs_remove_dir(struct driver_dir_entry * dir)
entry = list_entry(node,struct driver_file_entry,node);
list_del_init(node);
- vfs_unlink(dentry->d_inode,entry->dentry);
+ driverfs_unlink(dentry->d_inode,entry->dentry);
dput(entry->dentry);
put_mount();
node = dir->files.next;
}
up(&dentry->d_inode->i_sem);
- vfs_rmdir(dentry->d_parent->d_inode,dentry);
+ driverfs_rmdir(dentry->d_parent->d_inode,dentry);
up(&dentry->d_parent->d_inode->i_sem);
dput(dentry);
done:
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 2a0b795c3afc..c03054d0e721 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -430,16 +430,9 @@ static inline void nfs_renew_times(struct dentry * dentry)
}
static inline
-int nfs_lookup_verify_inode(struct inode *inode, int flags)
+int nfs_lookup_verify_inode(struct inode *inode)
{
- struct nfs_server *server = NFS_SERVER(inode);
- /*
- * If we're interested in close-to-open cache consistency,
- * then we revalidate the inode upon lookup.
- */
- if (!(server->flags & NFS_MOUNT_NOCTO) && !(flags & LOOKUP_CONTINUE))
- NFS_CACHEINV(inode);
- return nfs_revalidate_inode(server, inode);
+ return nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
/*
@@ -497,7 +490,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
/* Force a full look up iff the parent directory has changed */
if (nfs_check_verifier(dir, dentry)) {
- if (nfs_lookup_verify_inode(inode, flags))
+ if (nfs_lookup_verify_inode(inode))
goto out_bad;
goto out_valid;
}
@@ -1087,38 +1080,70 @@ out:
int
nfs_permission(struct inode *inode, int mask)
{
- int error = vfs_permission(inode, mask);
+ struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
+ struct rpc_cred *cred;
+ int mode = inode->i_mode;
+ int res;
- if (!NFS_PROTO(inode)->access)
- goto out;
-
- if (error == -EROFS)
- goto out;
+ if (mask & MAY_WRITE) {
+ /*
+ *
+ * Nobody gets write access to a read-only fs.
+ *
+ */
+ if (IS_RDONLY(inode) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+ return -EROFS;
- /*
- * Trust UNIX mode bits except:
- *
- * 1) When override capabilities may have been invoked
- * 2) When root squashing may be involved
- * 3) When ACLs may overturn a negative answer */
- if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)
- && (current->fsuid != 0) && (current->fsgid != 0)
- && error != -EACCES)
- goto out;
+ /*
+ *
+ * Nobody gets write access to an immutable file.
+ *
+ */
+ if (IS_IMMUTABLE(inode))
+ return -EACCES;
+ }
lock_kernel();
- error = NFS_PROTO(inode)->access(inode, mask, 0);
-
- if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
- current->uid != 0 && current->gid != 0 &&
- (current->fsuid != current->uid || current->fsgid != current->gid))
- error = NFS_PROTO(inode)->access(inode, mask, 1);
+ if (!NFS_PROTO(inode)->access)
+ goto out_notsup;
+
+ cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+ if (cache->cred == cred
+ && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) {
+ if (!(res = cache->err)) {
+ /* Is the mask a subset of an accepted mask? */
+ if ((cache->mask & mask) == mask)
+ goto out;
+ } else {
+ /* ...or is it a superset of a rejected mask? */
+ if ((cache->mask & mask) == cache->mask)
+ goto out;
+ }
+ }
+ res = NFS_PROTO(inode)->access(inode, cred, mask);
+ if (!res || res == -EACCES)
+ goto add_cache;
+out:
+ put_rpccred(cred);
unlock_kernel();
-
- out:
- return error;
+ return res;
+out_notsup:
+ nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ res = vfs_permission(inode, mask);
+ unlock_kernel();
+ return res;
+add_cache:
+ cache->jiffies = jiffies;
+ if (cache->cred)
+ put_rpccred(cache->cred);
+ cache->cred = cred;
+ cache->mask = mask;
+ cache->err = res;
+ unlock_kernel();
+ return res;
}
/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 40ad8333e475..12985cb77ede 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -125,10 +125,14 @@ nfs_delete_inode(struct inode * inode)
static void
nfs_clear_inode(struct inode *inode)
{
- struct rpc_cred *cred = NFS_I(inode)->mm_cred;
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct rpc_cred *cred = nfsi->mm_cred;
if (cred)
put_rpccred(cred);
+ cred = nfsi->cache_access.cred;
+ if (cred)
+ put_rpccred(cred);
}
void
@@ -425,7 +429,8 @@ int nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int sile
goto failure_kill_reqlist;
}
- /* We're airborne */
+ /* We're airborne Set socket buffersize */
+ rpc_setbufsize(clnt, server->wsize + 100, server->rsize + 100);
/* Check whether to start the lockd process */
if (!(server->flags & NFS_MOUNT_NONLM))
@@ -721,6 +726,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+ NFS_I(inode)->cache_access.cred = NULL;
unlock_new_inode(inode);
} else
@@ -854,15 +860,23 @@ int nfs_open(struct inode *inode, struct file *filp)
{
struct rpc_auth *auth;
struct rpc_cred *cred;
+ int err = 0;
lock_kernel();
+ /* Ensure that we revalidate the data cache */
+ if (NFS_SERVER(inode)->flags & NFS_MOUNT_NOCTO) {
+ err = __nfs_revalidate_inode(NFS_SERVER(inode),inode);
+ if (err)
+ goto out;
+ }
auth = NFS_CLIENT(inode)->cl_auth;
cred = rpcauth_lookupcred(auth, 0);
filp->private_data = cred;
if (filp->f_mode & FMODE_WRITE)
nfs_set_mmcred(inode, cred);
+out:
unlock_kernel();
- return 0;
+ return err;
}
int nfs_release(struct inode *inode, struct file *filp)
@@ -1076,6 +1090,16 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
NFS_CACHE_ISIZE(inode) = new_size;
inode->i_size = new_isize;
+ if (inode->i_mode != fattr->mode ||
+ inode->i_uid != fattr->uid ||
+ inode->i_gid != fattr->gid) {
+ struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;
+ if (*cred) {
+ put_rpccred(*cred);
+ *cred = NULL;
+ }
+ }
+
inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index bf24dabd2984..1f4610d1405d 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -133,16 +133,22 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
}
static int
-nfs3_proc_access(struct inode *inode, int mode, int ruid)
+nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
{
struct nfs_fattr fattr;
struct nfs3_accessargs arg = {
- fh: NFS_FH(inode),
+ .fh = NFS_FH(inode),
};
struct nfs3_accessres res = {
- fattr: &fattr,
+ .fattr = &fattr,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = NFS3PROC_ACCESS,
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ .rpc_cred = cred
};
- int status, flags;
+ int status;
dprintk("NFS call access\n");
fattr.valid = 0;
@@ -160,8 +166,7 @@ nfs3_proc_access(struct inode *inode, int mode, int ruid)
if (mode & MAY_EXEC)
arg.access |= NFS3_ACCESS_EXECUTE;
}
- flags = (ruid) ? RPC_CALL_REALUID : 0;
- status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply access\n");
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index f06e68e07cce..5d0bb6074fe4 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -23,6 +23,7 @@
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#ifdef CONFIG_BLK_DEV_IDE
+#include <linux/hdreg.h>
#include <linux/ide.h> /* IDE xlate */
#elif defined(CONFIG_BLK_DEV_IDE_MODULE)
#include <linux/module.h>
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
new file mode 100644
index 000000000000..fe290e3349be
--- /dev/null
+++ b/include/asm-generic/sections.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_GENERIC_SECTIONS_H_
+#define _ASM_GENERIC_SECTIONS_H_
+
+/* References to section boundaries */
+
+extern char _text, _etext;
+extern char _data, _edata;
+extern char __bss_start;
+extern char __init_begin, __init_end;
+
+#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index d36b2f10f731..3947866376d1 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -76,7 +76,8 @@ extern void init_bsp_APIC (void);
extern void setup_local_APIC (void);
extern void init_apic_mappings (void);
extern void smp_local_timer_interrupt (struct pt_regs * regs);
-extern void setup_APIC_clocks (void);
+extern void setup_boot_APIC_clock (void);
+extern void setup_secondary_APIC_clock (void);
extern void setup_apic_nmi_watchdog (void);
extern inline void nmi_watchdog_tick (struct pt_regs * regs);
extern int APIC_init_uniprocessor (void);
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 197ffcc2dd2f..e1b2f75538f8 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -4,72 +4,59 @@
#include <asm/ldt.h>
/*
- * The layout of the GDT under Linux:
+ * The layout of the per-CPU GDT under Linux:
*
* 0 - null
- * 1 - not used
+ * 1 - Thread-Local Storage (TLS) segment
* 2 - kernel code segment
* 3 - kernel data segment
- * 4 - user code segment <-- new cacheline
+ * 4 - user code segment <==== new cacheline
* 5 - user data segment
- * 6 - not used
- * 7 - not used
- * 8 - APM BIOS support <-- new cacheline
+ * 6 - TSS
+ * 7 - LDT
+ * 8 - APM BIOS support <==== new cacheline
* 9 - APM BIOS support
* 10 - APM BIOS support
* 11 - APM BIOS support
- * 12 - PNPBIOS support
+ * 12 - PNPBIOS support <==== new cacheline
* 13 - PNPBIOS support
* 14 - PNPBIOS support
* 15 - PNPBIOS support
- * 16 - PNPBIOS support
+ * 16 - PNPBIOS support <==== new cacheline
* 17 - not used
* 18 - not used
* 19 - not used
+ */
+#define TLS_ENTRY 1
+#define TSS_ENTRY 6
+#define LDT_ENTRY 7
+/*
+ * The interrupt descriptor table has room for 256 idt's,
+ * the global descriptor table is dependent on the number
+ * of tasks we can have..
*
- * The TSS+LDT descriptors are spread out a bit so that every CPU
- * has an exclusive cacheline for the per-CPU TSS and LDT:
- *
- * 20 - CPU#0 TSS <-- new cacheline
- * 21 - CPU#0 LDT
- * 22 - not used
- * 23 - not used
- * 24 - CPU#1 TSS <-- new cacheline
- * 25 - CPU#1 LDT
- * 26 - not used
- * 27 - not used
- * ... NR_CPUS per-CPU TSS+LDT's if on SMP
- *
- * Entry into gdt where to find first TSS.
+ * We pad the GDT to cacheline boundary.
*/
-#define __FIRST_TSS_ENTRY 20
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1)
-
-#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
-#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
+#define IDT_ENTRIES 256
+#define GDT_ENTRIES 20
#ifndef __ASSEMBLY__
#include <asm/mmu.h>
-struct desc_struct {
- unsigned long a,b;
-};
+#define GDT_SIZE (GDT_ENTRIES*sizeof(struct desc_struct))
-extern struct desc_struct gdt_table[];
-extern struct desc_struct *idt, *gdt;
+extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
struct Xgt_desc_struct {
unsigned short size;
unsigned long address __attribute__((packed));
-};
+} __attribute__ ((packed));
-#define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2))
-#define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2))
+extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
-#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3))
-
-#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3))
+#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (TSS_ENTRY<<3))
+#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (LDT_ENTRY<<3))
/*
* This is the ldt that every process will get unless we need
@@ -77,14 +64,43 @@ struct Xgt_desc_struct {
*/
extern struct desc_struct default_ldt[];
extern void set_intr_gate(unsigned int irq, void * addr);
-extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size);
-extern void set_tss_desc(unsigned int n, void *addr);
+
+#define _set_tssldt_desc(n,addr,limit,type) \
+__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
+ "movw %%ax,2(%2)\n\t" \
+ "rorl $16,%%eax\n\t" \
+ "movb %%al,4(%2)\n\t" \
+ "movb %4,5(%2)\n\t" \
+ "movb $0,6(%2)\n\t" \
+ "movb %%ah,7(%2)\n\t" \
+ "rorl $16,%%eax" \
+ : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
+
+static inline void set_tss_desc(unsigned int cpu, void *addr)
+{
+ _set_tssldt_desc(&cpu_gdt_table[cpu][TSS_ENTRY], (int)addr, 235, 0x89);
+}
+
+static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
+{
+ _set_tssldt_desc(&cpu_gdt_table[cpu][LDT_ENTRY], (int)addr, ((size << 3)-1), 0x82);
+}
+
+#define TLS_FLAGS_MASK 0x00000007
+
+#define TLS_FLAG_LIMIT_IN_PAGES 0x00000001
+#define TLS_FLAG_WRITABLE 0x00000002
+#define TLS_FLAG_CLEAR 0x00000004
+
+static inline void load_TLS_desc(struct thread_struct *t, unsigned int cpu)
+{
+ cpu_gdt_table[cpu][TLS_ENTRY] = t->tls_desc;
+}
static inline void clear_LDT(void)
{
- int cpu = smp_processor_id();
- set_ldt_desc(cpu, &default_ldt[0], 5);
- __load_LDT(cpu);
+ set_ldt_desc(smp_processor_id(), &default_ldt[0], 5);
+ load_LDT_desc();
}
/*
@@ -92,17 +108,16 @@ static inline void clear_LDT(void)
*/
static inline void load_LDT (mm_context_t *pc)
{
- int cpu = smp_processor_id();
void *segments = pc->ldt;
int count = pc->size;
- if (!count) {
+ if (likely(!count)) {
segments = &default_ldt[0];
count = 5;
}
- set_ldt_desc(cpu, segments, count);
- __load_LDT(cpu);
+ set_ldt_desc(smp_processor_id(), segments, count);
+ load_LDT_desc();
}
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index 417f2378659d..0da1f3a11983 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -17,7 +17,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{
- if(cpu_tlbstate[cpu].state == TLBSTATE_OK)
+ if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
cpu_tlbstate[cpu].state = TLBSTATE_LAZY;
}
#else
@@ -40,18 +40,18 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
/* Re-load page tables */
load_cr3(next->pgd);
- /* load_LDT, if either the previous or next thread
- * has a non-default LDT.
+ /*
+ * load the LDT, if the LDT is different:
*/
- if (next->context.size+prev->context.size)
+ if (unlikely(prev->context.ldt != next->context.ldt))
load_LDT(&next->context);
}
#ifdef CONFIG_SMP
else {
cpu_tlbstate[cpu].state = TLBSTATE_OK;
- if(cpu_tlbstate[cpu].active_mm != next)
+ if (cpu_tlbstate[cpu].active_mm != next)
BUG();
- if(!test_and_set_bit(cpu, &next->cpu_vm_mask)) {
+ if (!test_and_set_bit(cpu, &next->cpu_vm_mask)) {
/* We were in lazy tlb mode and leave_mm disabled
* tlb flush IPI delivery. We must reload %cr3.
*/
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index beb0c1bc3d30..a69e4be257fc 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -106,4 +106,6 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
return __pmd(((unsigned long long)page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
}
+extern struct kmem_cache_s *pae_pgd_cachep;
+
#endif /* _I386_PGTABLE_3LEVEL_H */
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index e9e980d0c93a..9d407b2c088b 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -18,6 +18,10 @@
#include <linux/config.h>
#include <linux/threads.h>
+struct desc_struct {
+ unsigned long a,b;
+};
+
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
@@ -372,6 +376,9 @@ struct thread_struct {
unsigned long v86flags, v86mask, v86mode, saved_esp0;
/* IO permissions */
unsigned long *ts_io_bitmap;
+/* TLS info and cached descriptor */
+ unsigned int tls_base, tls_limit, tls_flags;
+ struct desc_struct tls_desc;
};
#define INIT_THREAD { \
@@ -395,7 +402,7 @@ struct thread_struct {
0,0,0,0, /* esp,ebp,esi,edi */ \
0,0,0,0,0,0, /* es,cs,ss */ \
0,0,0,0,0,0, /* ds,fs,gs */ \
- __LDT(0),0, /* ldt */ \
+ LDT_ENTRY,0, /* ldt */ \
0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \
{~0, } /* ioperm */ \
}
diff --git a/include/asm-i386/sections.h b/include/asm-i386/sections.h
new file mode 100644
index 000000000000..2dcbb92918b2
--- /dev/null
+++ b/include/asm-i386/sections.h
@@ -0,0 +1,7 @@
+#ifndef _I386_SECTIONS_H
+#define _I386_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 69c872158b54..6b116b38a4e2 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -79,19 +79,13 @@ extern volatile int cpu_to_logical_apicid[NR_CPUS];
extern volatile int logical_apicid_to_cpu[MAX_APICID];
/*
- * General functions that each host system must provide.
- */
-
-extern void smp_boot_cpus(void);
-extern void smp_store_cpu_info(int id); /* Store per CPU info (like the initial udelay numbers */
-
-/*
* This function is needed by all SMP systems. It must _always_ be valid
* from the initial startup. We map APIC_BASE very early in page_setup(),
* so this is correct in the x86 case.
*/
#define smp_processor_id() (current_thread_info()->cpu)
+#define cpu_possible(cpu) (phys_cpu_present_map & (1<<(cpu)))
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
extern inline unsigned int num_online_cpus(void)
@@ -119,6 +113,13 @@ static __inline int logical_smp_processor_id(void)
return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
}
+extern volatile unsigned long cpu_callout_map;
+/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+static inline int num_booting_cpus(void)
+{
+ return hweight32(cpu_callout_map);
+}
+
#endif /* !__ASSEMBLY__ */
#define NO_PROC_ID 0xFF /* No processor magic marker */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index f5218fdb73c2..2c32dc7aa949 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -6,6 +6,7 @@
#define _PPC_MACHDEP_H
#include <linux/config.h>
+#include <linux/init.h>
#ifdef CONFIG_APUS
#include <asm-m68k/machdep.h>
@@ -129,7 +130,14 @@ struct smp_ops_t {
int (*probe)(void);
void (*kick_cpu)(int nr);
void (*setup_cpu)(int nr);
+ void (*space_timers)(int nr);
+ void (*take_timebase)(void);
+ void (*give_timebase)(void);
};
+
+/* Poor default implementations */
+extern void __devinit smp_generic_give_timebase(void);
+extern void __devinit smp_generic_take_timebase(void);
#endif /* CONFIG_SMP */
#endif /* _PPC_MACHDEP_H */
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index 6c58f14684a1..f5e99d565d32 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
+#include <linux/errno.h>
#ifdef CONFIG_SMP
@@ -31,11 +32,11 @@ struct cpuinfo_PPC {
extern struct cpuinfo_PPC cpu_data[];
extern unsigned long cpu_online_map;
+extern unsigned long cpu_possible_map;
extern unsigned long smp_proc_in_lock[];
extern volatile unsigned long cpu_callin_map[];
extern int smp_tb_synchronized;
-extern void smp_store_cpu_info(int id);
extern void smp_send_tlb_invalidate(int);
extern void smp_send_xmon_break(int cpu);
struct pt_regs;
@@ -48,6 +49,7 @@ extern void smp_local_timer_interrupt(struct pt_regs *);
#define smp_processor_id() (current_thread_info()->cpu)
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
+#define cpu_possible(cpu) (cpu_possible_map & (1<<(cpu)))
extern inline unsigned int num_online_cpus(void)
{
@@ -62,6 +64,8 @@ extern inline int any_online_cpu(unsigned int mask)
return -1;
}
+extern int __cpu_up(unsigned int cpu);
+
extern int smp_hw_index[];
#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
diff --git a/include/asm-s390/hdreg.h b/include/asm-s390/hdreg.h
deleted file mode 100644
index 20061819d77a..000000000000
--- a/include/asm-s390/hdreg.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/include/asm-arm/hdreg.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-#ifndef __ASMS390_HDREG_H
-#define __ASMS390_HDREG_H
-
-typedef unsigned long ide_ioreg_t;
-
-#endif /* __ASMS390_HDREG_H */
-
diff --git a/include/asm-s390/ide.h b/include/asm-s390/ide.h
deleted file mode 100644
index 01d7765f7ef4..000000000000
--- a/include/asm-s390/ide.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-s390/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/* s390 does not have IDE */
-
-#ifndef __ASMS390_IDE_H
-#define __ASMS390_IDE_H
-
-#ifdef __KERNEL__
-
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 0
-#endif
-
-/*
- * We always use the new IDE port registering,
- * so these are fixed here.
- */
-#define ide_default_io_base(i) ((ide_ioreg_t)0)
-#define ide_default_irq(b) (0)
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMS390_IDE_H */
diff --git a/include/asm-s390x/hdreg.h b/include/asm-s390x/hdreg.h
deleted file mode 100644
index 20061819d77a..000000000000
--- a/include/asm-s390x/hdreg.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/include/asm-arm/hdreg.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-#ifndef __ASMS390_HDREG_H
-#define __ASMS390_HDREG_H
-
-typedef unsigned long ide_ioreg_t;
-
-#endif /* __ASMS390_HDREG_H */
-
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 726492d4c45a..f83c52f82ab0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -281,12 +281,13 @@ extern int wipe_partitions(kdev_t dev);
extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
extern void generic_make_request(struct bio *bio);
extern inline request_queue_t *bdev_get_queue(struct block_device *bdev);
-extern void blkdev_release_request(struct request *);
+extern void blk_put_request(struct request *);
extern void blk_attempt_remerge(request_queue_t *, struct request *);
extern void __blk_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
extern struct request *__blk_get_request(request_queue_t *, int);
extern void blk_put_request(struct request *);
+extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
extern void blk_plug_device(request_queue_t *);
extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
@@ -309,20 +310,21 @@ extern int blk_init_queue(request_queue_t *, request_fn_proc *, spinlock_t *);
extern void blk_cleanup_queue(request_queue_t *);
extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
extern void blk_queue_bounce_limit(request_queue_t *, u64);
-extern void blk_queue_max_sectors(request_queue_t *q, unsigned short);
-extern void blk_queue_max_phys_segments(request_queue_t *q, unsigned short);
-extern void blk_queue_max_hw_segments(request_queue_t *q, unsigned short);
-extern void blk_queue_max_segment_size(request_queue_t *q, unsigned int);
-extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short);
-extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long);
-extern void blk_queue_assign_lock(request_queue_t *q, spinlock_t *);
-extern void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn);
+extern void blk_queue_max_sectors(request_queue_t *, unsigned short);
+extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short);
+extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short);
+extern void blk_queue_max_segment_size(request_queue_t *, unsigned int);
+extern void blk_queue_hardsect_size(request_queue_t *, unsigned short);
+extern void blk_queue_segment_boundary(request_queue_t *, unsigned long);
+extern void blk_queue_assign_lock(request_queue_t *, spinlock_t *);
+extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn);
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
extern void blk_dump_rq_flags(struct request *, char *);
extern void generic_unplug_device(void *);
+
/*
* tag stuff
*/
@@ -348,15 +350,12 @@ extern int * blk_size[MAX_BLKDEV]; /* in units of 1024 bytes */
extern void drive_stat_acct(struct request *, int, int);
-extern inline void blk_clear(int major)
+static inline void blk_clear(int major)
{
blk_size[major] = NULL;
-#if 0
- blk_size_in_bytes[major] = NULL;
-#endif
}
-extern inline int queue_hardsect_size(request_queue_t *q)
+static inline int queue_hardsect_size(request_queue_t *q)
{
int retval = 512;
@@ -366,7 +365,7 @@ extern inline int queue_hardsect_size(request_queue_t *q)
return retval;
}
-extern inline int bdev_hardsect_size(struct block_device *bdev)
+static inline int bdev_hardsect_size(struct block_device *bdev)
{
return queue_hardsect_size(bdev_get_queue(bdev));
}
@@ -375,7 +374,7 @@ extern inline int bdev_hardsect_size(struct block_device *bdev)
#define blk_started_io(nsects) do { } while (0)
/* assumes size > 256 */
-extern inline unsigned int blksize_bits(unsigned int size)
+static inline unsigned int blksize_bits(unsigned int size)
{
unsigned int bits = 8;
do {
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index 6f1fd4aae99a..dcedacb849ea 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -261,17 +261,17 @@ struct hd_drive_task_hdr {
#define SECURITY_DISABLE_PASSWORD 0xBF
struct hd_geometry {
- unsigned char heads;
- unsigned char sectors;
- unsigned short cylinders;
+ u8 heads;
+ u8 sectors;
+ u16 cylinders;
unsigned long start;
};
/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
struct hd_big_geometry {
- unsigned char heads;
- unsigned char sectors;
- unsigned int cylinders;
+ u8 heads;
+ u8 sectors;
+ u32 cylinders;
unsigned long start;
};
@@ -326,249 +326,243 @@ enum {
* ide/probe.c.
*/
struct hd_driveid {
- unsigned short config; /* lots of obsolete bit flags */
- unsigned short cyls; /* Obsolete, "physical" cyls */
- unsigned short reserved2; /* reserved (word 2) */
- unsigned short heads; /* Obsolete, "physical" heads */
- unsigned short track_bytes; /* unformatted bytes per track */
- unsigned short sector_bytes; /* unformatted bytes per sector */
- unsigned short sectors; /* Obsolete, "physical" sectors per track */
- unsigned short vendor0; /* vendor unique */
- unsigned short vendor1; /* vendor unique */
- unsigned short vendor2; /* Retired vendor unique */
- unsigned char serial_no[20]; /* 0 = not_specified */
- unsigned short buf_type; /* Retired */
- unsigned short buf_size; /* Retired, 512 byte increments
- * 0 = not_specified
- */
- unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */
- unsigned char fw_rev[8]; /* 0 = not_specified */
- unsigned char model[40]; /* 0 = not_specified */
- unsigned char max_multsect; /* 0=not_implemented */
- unsigned char vendor3; /* vendor unique */
- unsigned short dword_io; /* 0=not_implemented; 1=implemented */
- unsigned char vendor4; /* vendor unique */
- unsigned char capability; /* (upper byte of word 49)
- * 3: IORDYsup
- * 2: IORDYsw
- * 1: LBA
- * 0: DMA
- */
- unsigned short reserved50; /* reserved (word 50) */
- unsigned char vendor5; /* Obsolete, vendor unique */
- unsigned char tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
- unsigned char vendor6; /* Obsolete, vendor unique */
- unsigned char tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
- unsigned short field_valid; /* (word 53)
- * 2: ultra_ok word 88
- * 1: eide_ok words 64-70
- * 0: cur_ok words 54-58
- */
- unsigned short cur_cyls; /* Obsolete, logical cylinders */
- unsigned short cur_heads; /* Obsolete, l heads */
- unsigned short cur_sectors; /* Obsolete, l sectors per track */
- unsigned short cur_capacity0; /* Obsolete, l total sectors on drive */
- unsigned short cur_capacity1; /* Obsolete, (2 words, misaligned int) */
- unsigned char multsect; /* current multiple sector count */
- unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
- unsigned int lba_capacity; /* Obsolete, total number of sectors */
- unsigned short dma_1word; /* Obsolete, single-word dma info */
- unsigned short dma_mword; /* multiple-word dma info */
- unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
- unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
- unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */
- unsigned short eide_pio; /* min cycle time (ns), no IORDY */
- unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
- unsigned short words69_70[2]; /* reserved words 69-70
- * future command overlap and queuing
- */
+ u16 config; /* lots of obsolete bit flags */
+ u16 cyls; /* Obsolete, "physical" cyls */
+ u16 reserved2; /* reserved (word 2) */
+ u16 heads; /* Obsolete, "physical" heads */
+ u16 track_bytes; /* unformatted bytes per track */
+ u16 sector_bytes; /* unformatted bytes per sector */
+ u16 sectors; /* Obsolete, "physical" sectors per track */
+ u16 vendor0; /* vendor unique */
+ u16 vendor1; /* vendor unique */
+ u16 vendor2; /* Retired vendor unique */
+ u8 serial_no[20]; /* 0 = not_specified */
+ u16 buf_type; /* Retired */
+ u16 buf_size; /* Retired, 512 byte increments
+ * 0 = not_specified
+ */
+ u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */
+ u8 fw_rev[8]; /* 0 = not_specified */
+ char model[40]; /* 0 = not_specified */
+ u8 max_multsect; /* 0=not_implemented */
+ u8 vendor3; /* vendor unique */
+ u16 dword_io; /* 0=not_implemented; 1=implemented */
+ u8 vendor4; /* vendor unique */
+ u8 capability; /* (upper byte of word 49)
+ * 3: IORDYsup
+ * 2: IORDYsw
+ * 1: LBA
+ * 0: DMA
+ */
+ u16 reserved50; /* reserved (word 50) */
+ u8 vendor5; /* Obsolete, vendor unique */
+ u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ u8 vendor6; /* Obsolete, vendor unique */
+ u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ u16 field_valid; /* (word 53)
+ * 2: ultra_ok word 88
+ * 1: eide_ok words 64-70
+ * 0: cur_ok words 54-58
+ */
+ u16 cur_cyls; /* Obsolete, logical cylinders */
+ u16 cur_heads; /* Obsolete, l heads */
+ u16 cur_sectors; /* Obsolete, l sectors per track */
+ u16 cur_capacity0; /* Obsolete, l total sectors on drive */
+ u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */
+ u8 multsect; /* current multiple sector count */
+ u8 multsect_valid; /* when (bit0==1) multsect is ok */
+ u32 lba_capacity; /* Obsolete, total number of sectors */
+ u16 dma_1word; /* Obsolete, single-word dma info */
+ u16 dma_mword; /* multiple-word dma info */
+ u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */
+ u16 eide_dma_min; /* min mword dma cycle time (ns) */
+ u16 eide_dma_time; /* recommended mword dma cycle time (ns) */
+ u16 eide_pio; /* min cycle time (ns), no IORDY */
+ u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */
+ u16 words69_70[2]; /* reserved words 69-70
+ * future command overlap and queuing
+ */
/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
- unsigned short words71_74[4]; /* reserved words 71-74
- * for IDENTIFY PACKET DEVICE command
- */
- unsigned short queue_depth; /* (word 75)
- * 15:5 reserved
- * 4:0 Maximum queue depth -1
- */
- unsigned short words76_79[4]; /* reserved words 76-79 */
- unsigned short major_rev_num; /* (word 80) */
- unsigned short minor_rev_num; /* (word 81) */
- unsigned short command_set_1; /* (word 82) supported
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- unsigned short command_set_2; /* (word 83)
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- unsigned short cfsse; /* (word 84)
- * cmd set-feature supported extensions
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:3 reserved
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- unsigned short cfs_enable_1; /* (word 85)
- * command set-feature enabled
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- unsigned short cfs_enable_2; /* (word 86)
- * command set-feature enabled
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- unsigned short csf_default; /* (word 87)
- * command set-feature default
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:3 reserved
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- unsigned short dma_ultra; /* (word 88) */
- unsigned short word89; /* reserved (word 89) */
- unsigned short word90; /* reserved (word 90) */
- unsigned short CurAPMvalues; /* current APM values */
- unsigned short word92; /* reserved (word 92) */
- unsigned short hw_config; /* hardware config (word 93)
- * 15:
- * 14:
- * 13:
- * 12:
- * 11:
- * 10:
- * 9:
- * 8:
- * 7:
- * 6:
- * 5:
- * 4:
- * 3:
- * 2:
- * 1:
- * 0:
- */
- unsigned short acoustic; /* (word 94)
- * 15:8 Vendor's recommended value
- * 7:0 current value
- */
- unsigned short words95_99[5]; /* reserved words 95-99 */
- unsigned long long lba_capacity_2;/* 48-bit total number of sectors */
- unsigned short words104_125[22];/* reserved words 104-125 */
- unsigned short last_lun; /* (word 126) */
- unsigned short word127; /* (word 127) Feature Set
- * Removable Media Notification
- * 15:2 reserved
- * 1:0 00 = not supported
- * 01 = supported
- * 10 = reserved
- * 11 = reserved
- */
- unsigned short dlf; /* (word 128)
- * device lock function
- * 15:9 reserved
- * 8 security level 1:max 0:high
- * 7:6 reserved
- * 5 enhanced erase
- * 4 expire
- * 3 frozen
- * 2 locked
- * 1 en/disabled
- * 0 capability
- */
- unsigned short csfo; /* (word 129)
- * current set features options
- * 15:4 reserved
- * 3: auto reassign
- * 2: reverting
- * 1: read-look-ahead
- * 0: write cache
- */
- unsigned short words130_155[26];/* reserved vendor words 130-155 */
- unsigned short word156; /* reserved vendor word 156 */
- unsigned short words157_159[3];/* reserved vendor words 157-159 */
- unsigned short cfa_power; /* (word 160) CFA Power Mode
- * 15 word 160 supported
- * 14 reserved
- * 13
- * 12
- * 11:0
- */
- unsigned short words161_175[14];/* Reserved for CFA */
- unsigned short words176_205[31];/* Current Media Serial Number */
- unsigned short words206_254[48];/* reserved words 206-254 */
- unsigned short integrity_word; /* (word 255)
- * 15:8 Checksum
- * 7:0 Signature
- */
+ u16 words71_74[4]; /* reserved words 71-74
+ * for IDENTIFY PACKET DEVICE command
+ */
+ u16 queue_depth; /* (word 75)
+ * 15:5 reserved
+ * 4:0 Maximum queue depth -1
+ */
+ u16 words76_79[4]; /* reserved words 76-79 */
+ u16 major_rev_num; /* (word 80) */
+ u16 minor_rev_num; /* (word 81) */
+ u16 command_set_1; /* (word 82) supported
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ u16 command_set_2; /* (word 83)
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ u16 cfsse; /* (word 84)
+ * cmd set-feature supported extensions
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:3 reserved
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ u16 cfs_enable_1; /* (word 85)
+ * command set-feature enabled
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ u16 cfs_enable_2; /* (word 86)
+ * command set-feature enabled
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ u16 csf_default; /* (word 87)
+ * command set-feature default
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:3 reserved
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ u16 dma_ultra; /* (word 88) */
+ u16 word89; /* reserved (word 89) */
+ u16 word90; /* reserved (word 90) */
+ u16 CurAPMvalues; /* current APM values */
+ u16 word92; /* reserved (word 92) */
+ u16 hw_config; /* hardware config (word 93)
+ * 15:
+ * 14:
+ * 13:
+ * 12:
+ * 11:
+ * 10:
+ * 9:
+ * 8:
+ * 7:
+ * 6:
+ * 5:
+ * 4:
+ * 3:
+ * 2:
+ * 1:
+ * 0:
+ */
+ u16 acoustic; /* (word 94)
+ * 15:8 Vendor's recommended value
+ * 7:0 current value
+ */
+ u16 words95_99[5]; /* reserved words 95-99 */
+ u64 lba_capacity_2; /* 48-bit total number of sectors */
+ u16 words104_125[22];/* reserved words 104-125 */
+ u16 last_lun; /* (word 126) */
+ u16 word127; /* (word 127) Feature Set
+ * Removable Media Notification
+ * 15:2 reserved
+ * 1:0 00 = not supported
+ * 01 = supported
+ * 10 = reserved
+ * 11 = reserved
+ */
+ u16 dlf; /* (word 128)
+ * device lock function
+ * 15:9 reserved
+ * 8 security level 1:max 0:high
+ * 7:6 reserved
+ * 5 enhanced erase
+ * 4 expire
+ * 3 frozen
+ * 2 locked
+ * 1 en/disabled
+ * 0 capability
+ */
+ u16 csfo; /* (word 129)
+ * current set features options
+ * 15:4 reserved
+ * 3: auto reassign
+ * 2: reverting
+ * 1: read-look-ahead
+ * 0: write cache
+ */
+ u16 words130_155[26];/* reserved vendor words 130-155 */
+ u16 word156; /* reserved vendor word 156 */
+ u16 words157_159[3];/* reserved vendor words 157-159 */
+ u16 cfa_power; /* (word 160) CFA Power Mode
+ * 15 word 160 supported
+ * 14 reserved
+ * 13
+ * 12
+ * 11:0
+ */
+ u16 words161_175[14];/* Reserved for CFA */
+ u16 words176_205[31];/* Current Media Serial Number */
+ u16 words206_254[48];/* reserved words 206-254 */
+ u16 integrity_word; /* (word 255)
+ * 15:8 Checksum
+ * 7:0 Signature
+ */
} __attribute__((packed));
-/*
- * IDE "nice" flags. These are used on a per drive basis to determine
- * when to be nice and give more bandwidth to the other devices which
- * share the same IDE bus.
- */
#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */
-#define IDE_NICE_ATAPI_OVERLAP (1) /* not supported yet */
-#endif /* _LINUX_HDREG_H */
+#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 7b9c5cce01cf..8a41b3b2e74a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -285,8 +285,8 @@ struct ata_device {
unsigned long sleep; /* sleep until this time */
- byte retry_pio; /* retrying dma capable host in pio */
- byte state; /* retry state */
+ u8 retry_pio; /* retrying dma capable host in pio */
+ u8 state; /* retry state */
unsigned using_dma : 1; /* disk is using dma for read/write */
unsigned using_tcq : 1; /* disk is using queueing */
@@ -307,20 +307,20 @@ struct ata_device {
unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */
unsigned ata_flash : 1; /* 1=present, 0=default */
unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */
- byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
+ u8 scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
select_t select; /* basic drive/head select reg value */
u8 status; /* last retrived status value for device */
- byte ready_stat; /* min status value for drive ready */
- byte mult_count; /* current multiple sector setting */
- byte bad_wstat; /* used for ignoring WRERR_STAT */
- byte nowerr; /* used for ignoring WRERR_STAT */
- byte sect0; /* offset of first sector for DM6:DDO */
- byte head; /* "real" number of heads */
- byte sect; /* "real" sectors per track */
- byte bios_head; /* BIOS/fdisk/LILO number of heads */
- byte bios_sect; /* BIOS/fdisk/LILO sectors per track */
+ u8 ready_stat; /* min status value for drive ready */
+ u8 mult_count; /* current multiple sector setting */
+ u8 bad_wstat; /* used for ignoring WRERR_STAT */
+ u8 nowerr; /* used for ignoring WRERR_STAT */
+ u8 sect0; /* offset of first sector for DM6:DDO */
+ u8 head; /* "real" number of heads */
+ u8 sect; /* "real" sectors per track */
+ u8 bios_head; /* BIOS/fdisk/LILO number of heads */
+ u8 bios_sect; /* BIOS/fdisk/LILO sectors per track */
unsigned int bios_cyl; /* BIOS/fdisk/LILO number of cyls */
unsigned int cyl; /* "real" number of cyls */
u64 capacity; /* total number of sectors */
@@ -343,13 +343,12 @@ struct ata_device {
int lun; /* logical unit */
int crc_count; /* crc counter to reduce drive speed */
- byte quirk_list; /* drive is considered quirky if set for a specific host */
- byte suspend_reset; /* drive suspend mode flag, soft-reset recovers */
- byte current_speed; /* current transfer rate set */
- byte dn; /* now wide spread use */
- byte wcache; /* status of write cache */
- byte acoustic; /* acoustic management */
- byte queue_depth; /* max queue depth */
+ int quirk_list; /* drive is considered quirky if set for a specific host */
+ u8 current_speed; /* current transfer rate set */
+ u8 dn; /* now wide spread use */
+ u8 wcache; /* status of write cache */
+ u8 acoustic; /* acoustic management */
+ unsigned int queue_depth; /* max queue depth */
unsigned int failures; /* current failure count */
unsigned int max_failures; /* maximum allowed failure count */
struct device dev; /* global device tree handle */
@@ -370,7 +369,7 @@ typedef enum {
ATA_OP_FINISHED, /* no drive operation was started */
ATA_OP_CONTINUES, /* a drive operation was started, and a handler was set */
ATA_OP_RELEASED, /* started and released bus */
- ATA_OP_READY, /* indicate status poll finished fine */
+ ATA_OP_READY /* indicate status poll finished fine */
} ide_startstop_t;
/*
@@ -428,10 +427,10 @@ struct ata_channel {
*/
/* setup disk on a channel for a particular PIO transfer mode */
- void (*tuneproc) (struct ata_device *, byte pio);
+ void (*tuneproc) (struct ata_device *, u8 pio);
/* setup the chipset timing for a particular transfer mode */
- int (*speedproc) (struct ata_device *, byte pio);
+ int (*speedproc) (struct ata_device *, u8 pio);
/* tweaks hardware to select drive */
void (*selectproc) (struct ata_device *);
@@ -640,10 +639,8 @@ extern void ata_read(struct ata_device *, void *, unsigned int);
extern void ata_write(struct ata_device *, void *, unsigned int);
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *);
-extern int ide_config_drive_speed(struct ata_device *, byte);
-extern byte eighty_ninty_three(struct ata_device *);
-
-extern void ide_stall_queue(struct ata_device *, unsigned long);
+extern int ide_config_drive_speed(struct ata_device *, u8);
+extern int eighty_ninty_three(struct ata_device *);
extern int system_bus_speed;
@@ -656,11 +653,11 @@ extern int system_bus_speed;
extern int drive_is_flashcard(struct ata_device *);
-int ide_spin_wait_hwgroup(struct ata_device *);
-void ide_timer_expiry (unsigned long data);
+extern int ide_spin_wait_hwgroup(struct ata_device *);
+extern void ide_timer_expiry(unsigned long data);
extern void ata_irq_request(int irq, void *data, struct pt_regs *regs);
-void do_ide_request (request_queue_t * q);
-void ide_init_subdrivers (void);
+extern void do_ide_request(request_queue_t * q);
+extern void ide_init_subdrivers(void);
extern struct block_device_operations ide_fops[];
@@ -742,12 +739,12 @@ static inline int udma_irq_status(struct ata_device *drive)
static inline void udma_timeout(struct ata_device *drive)
{
- return drive->channel->udma_timeout(drive);
+ drive->channel->udma_timeout(drive);
}
static inline void udma_irq_lost(struct ata_device *drive)
{
- return drive->channel->udma_irq_lost(drive);
+ drive->channel->udma_irq_lost(drive);
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/include/linux/nbd.h b/include/linux/nbd.h
index eae4f5bbb65a..e2c507ba6b08 100644
--- a/include/linux/nbd.h
+++ b/include/linux/nbd.h
@@ -61,7 +61,7 @@ nbd_end_request(struct request *req)
bio->bi_next = NULL;
bio_endio(bio, uptodate);
}
- blkdev_release_request(req);
+ blk_put_request(req);
spin_unlock_irqrestore(q->queue_lock, flags);
}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index f45c35f298e6..02ef81aee197 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -90,6 +90,16 @@
#ifdef __KERNEL__
/*
+ * NFSv3 Access mode cache
+ */
+struct nfs_access_cache {
+ unsigned long jiffies;
+ struct rpc_cred * cred;
+ int mask;
+ int err;
+};
+
+/*
* nfs fs inode data in memory
*/
struct nfs_inode {
@@ -138,6 +148,8 @@ struct nfs_inode {
*/
unsigned long cache_mtime_jiffies;
+ struct nfs_access_cache cache_access;
+
/*
* This is the cookie verifier used for NFSv3 readdir
* operations
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 110e5b661b58..53ec9c0b94d0 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -300,7 +300,7 @@ struct nfs_rpc_ops {
struct iattr *);
int (*lookup) (struct inode *, struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
- int (*access) (struct inode *, int , int);
+ int (*access) (struct inode *, struct rpc_cred *, int);
int (*readlink)(struct inode *, struct page *);
int (*read) (struct inode *, struct rpc_cred *,
struct nfs_fattr *,
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 0db9736c1166..05d2e7968646 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -60,5 +60,7 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
#define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released */
+#define CPU_ONLINE 0x0002 /* CPU (unsigned)v coming up */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6dd4746e58cd..1ee746b656cf 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -150,7 +150,6 @@ extern void update_process_times(int user);
extern void update_one_process(struct task_struct *p, unsigned long user,
unsigned long system, int cpu);
extern void scheduler_tick(int user_tick, int system);
-extern void migration_init(void);
extern unsigned long cache_decay_ticks;
diff --git a/include/linux/smp.h b/include/linux/smp.h
index d6857a229d5d..454fdcdf14d2 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -32,19 +32,19 @@ extern void FASTCALL(smp_send_reschedule(int cpu));
/*
- * Boot processor call to load the other CPU's
+ * Prepare machine for booting other CPUs.
*/
-extern void smp_boot_cpus(void);
+extern void smp_prepare_cpus(unsigned int max_cpus);
/*
- * Processor call in. Must hold processors until ..
+ * Bring a CPU up
*/
-extern void smp_callin(void);
+extern int __cpu_up(unsigned int cpunum);
/*
- * Multiprocessors may now schedule
+ * Final polishing of CPUs
*/
-extern void smp_commence(void);
+extern void smp_cpus_done(unsigned int max_cpus);
/*
* Call a function on all other processors
@@ -71,6 +71,13 @@ extern volatile int smp_msg_id;
#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/
#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */
+struct notifier_block;
+
+/* Need to know about CPUs going up/down? */
+extern int register_cpu_notifier(struct notifier_block *nb);
+extern void unregister_cpu_notifier(struct notifier_block *nb);
+
+int cpu_up(unsigned int cpu);
#else /* !SMP */
/*
@@ -93,6 +100,10 @@ static inline void smp_send_reschedule_all(void) { }
#define per_cpu(var, cpu) var
#define this_cpu(var) var
+/* Need to know about CPUs going up/down? */
+#define register_cpu_notifier(nb) 0
+#define unregister_cpu_notifier(nb) do { } while(0)
+
#endif /* !SMP */
#define get_cpu() ({ preempt_disable(); smp_processor_id(); })
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index d278df00ecb9..92fa9755592e 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -127,6 +127,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
void rpc_restart_call(struct rpc_task *);
void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
+void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
static __inline__
int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index eca42599039f..c9b93c6a7a27 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -122,6 +122,9 @@ struct rpc_xprt {
unsigned long cong; /* current congestion */
unsigned long cwnd; /* congestion window */
+ unsigned int rcvsize, /* socket receive buffer size */
+ sndsize; /* socket send buffer size */
+
struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue resend; /* requests waiting to resend */
struct rpc_wait_queue pending; /* requests in flight */
@@ -177,13 +180,9 @@ int xprt_adjust_timeout(struct rpc_timeout *);
void xprt_release(struct rpc_task *);
void xprt_reconnect(struct rpc_task *);
int xprt_clear_backlog(struct rpc_xprt *);
+void xprt_sock_setbufsize(struct rpc_xprt *);
-#define XPRT_WSPACE 0
-#define XPRT_CONNECT 1
-
-#define xprt_wspace(xp) (test_bit(XPRT_WSPACE, &(xp)->sockstate))
-#define xprt_test_and_set_wspace(xp) (test_and_set_bit(XPRT_WSPACE, &(xp)->sockstate))
-#define xprt_clear_wspace(xp) (clear_bit(XPRT_WSPACE, &(xp)->sockstate))
+#define XPRT_CONNECT 0
#define xprt_connected(xp) (!(xp)->stream || test_bit(XPRT_CONNECT, &(xp)->sockstate))
#define xprt_set_connected(xp) (set_bit(XPRT_CONNECT, &(xp)->sockstate))
diff --git a/init/main.c b/init/main.c
index 3a50b7b197a6..ab46d162736d 100644
--- a/init/main.c
+++ b/init/main.c
@@ -95,6 +95,35 @@ int rows, cols;
char *execute_command;
+/* Setup configured maximum number of CPUs to activate */
+static unsigned int max_cpus = UINT_MAX;
+
+/*
+ * Setup routine for controlling SMP activation
+ *
+ * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
+ * activation entirely (the MPS table probe still happens, though).
+ *
+ * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
+ * greater than 0, limits the maximum number of CPUs activated in
+ * SMP mode to <NUM>.
+ */
+static int __init nosmp(char *str)
+{
+ max_cpus = 0;
+ return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+ get_option(&str, &max_cpus);
+ return 1;
+}
+
+__setup("maxcpus=", maxcpus);
+
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
@@ -275,6 +304,7 @@ static void __init smp_init(void)
#endif
static inline void setup_per_cpu_areas(void) { }
+static inline void smp_prepare_cpus(unsigned int maxcpus) { }
#else
@@ -305,11 +335,27 @@ static void __init setup_per_cpu_areas(void)
/* Called by boot processor to activate the rest. */
static void __init smp_init(void)
{
+ unsigned int i;
+
+ /* FIXME: This should be done in userspace --RR */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (num_online_cpus() >= max_cpus)
+ break;
+ if (cpu_possible(i) && !cpu_online(i)) {
+ printk("Bringing up %i\n", i);
+ cpu_up(i);
+ }
+ }
+
+ /* Any cleanup work */
+ printk("CPUS done %u\n", max_cpus);
+ smp_cpus_done(max_cpus);
+#if 0
/* Get other processors into their bootup holding patterns. */
- smp_boot_cpus();
smp_threads_ready=1;
smp_commence();
+#endif
}
#endif
@@ -405,14 +451,12 @@ asmlinkage void __init start_kernel(void)
check_bugs();
printk("POSIX conformance testing by UNIFIX\n");
- init_idle(current, smp_processor_id());
-
/*
* We count on the initial thread going ok
* Like idlers init is an unlocked kernel thread, which will
* make syscalls (and thus be locked).
*/
- smp_init();
+ init_idle(current, smp_processor_id());
/* Do the rest non-__init'ed, we're now alive */
rest_init();
@@ -444,12 +488,6 @@ static void __init do_initcalls(void)
static void __init do_basic_setup(void)
{
/*
- * Let the per-CPU migration threads start up:
- */
-#if CONFIG_SMP
- migration_init();
-#endif
- /*
* Tell the world that we're going to be the grim
* reaper of innocent orphaned children.
*
@@ -493,7 +531,10 @@ static int init(void * unused)
static char * argv_sh[] = { "sh", NULL, };
lock_kernel();
+ /* Sets up cpus_possible() */
+ smp_prepare_cpus(max_cpus);
do_basic_setup();
+ smp_init();
prepare_namespace();
diff --git a/kernel/Makefile b/kernel/Makefile
index d0cad7d5115c..4834fc454271 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -17,6 +17,7 @@ obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o context.o futex.o platform.o
+obj-$(CONFIG_SMP) += cpu.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += ksyms.o
obj-$(CONFIG_PM) += pm.o
diff --git a/kernel/cpu.c b/kernel/cpu.c
new file mode 100644
index 000000000000..b1820a5536d6
--- /dev/null
+++ b/kernel/cpu.c
@@ -0,0 +1,54 @@
+/* CPU control.
+ * (C) 2001 Rusty Russell
+ * This code is licenced under the GPL.
+ */
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
+#include <asm/semaphore.h>
+
+/* This protects CPUs going up and down... */
+DECLARE_MUTEX(cpucontrol);
+
+static struct notifier_block *cpu_chain = NULL;
+
+/* Need to know about CPUs going up/down? */
+int register_cpu_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&cpu_chain, nb);
+}
+
+void unregister_cpu_notifier(struct notifier_block *nb)
+{
+ notifier_chain_unregister(&cpu_chain,nb);
+}
+
+int __devinit cpu_up(unsigned int cpu)
+{
+ int ret;
+
+ if ((ret = down_interruptible(&cpucontrol)) != 0)
+ return ret;
+
+ if (cpu_online(cpu)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Arch-specific enabling code. */
+ ret = __cpu_up(cpu);
+ if (ret != 0) goto out;
+ if (!cpu_online(cpu))
+ BUG();
+
+ /* Now call notifier in preparation. */
+ printk("CPU %u IS NOW UP!\n", cpu);
+ notifier_call_chain(&cpu_chain, CPU_ONLINE, (void *)cpu);
+
+ out:
+ up(&cpucontrol);
+ return ret;
+}
diff --git a/kernel/sched.c b/kernel/sched.c
index a54ee5a0356c..67ac32a24c1f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -27,6 +27,8 @@
#include <linux/completion.h>
#include <linux/kernel_stat.h>
#include <linux/security.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
@@ -1777,9 +1779,11 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask)
migration_req_t req;
runqueue_t *rq;
+#if 0 /* FIXME: Grab cpu_lock, return error on this case. --RR */
new_mask &= cpu_online_map;
if (!new_mask)
BUG();
+#endif
preempt_disable();
rq = task_rq_lock(p, &flags);
@@ -1812,8 +1816,6 @@ out:
preempt_enable();
}
-static __initdata int master_migration_thread;
-
static int migration_thread(void * bind_cpu)
{
int cpu = (int) (long) bind_cpu;
@@ -1825,15 +1827,7 @@ static int migration_thread(void * bind_cpu)
sigfillset(&current->blocked);
set_fs(KERNEL_DS);
- /*
- * The first migration thread is started on the boot CPU, it
- * migrates the other migration threads to their destination CPUs.
- */
- if (cpu != master_migration_thread) {
- while (!cpu_rq(master_migration_thread)->migration_thread)
- yield();
- set_cpus_allowed(current, 1UL << cpu);
- }
+ set_cpus_allowed(current, 1UL << cpu);
printk("migration_task %d on cpu=%d\n", cpu, smp_processor_id());
ret = setscheduler(0, SCHED_FIFO, &param);
@@ -1890,29 +1884,33 @@ repeat:
}
}
-void __init migration_init(void)
+static int migration_call(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
{
- int cpu;
-
- master_migration_thread = smp_processor_id();
- current->cpus_allowed = 1UL << master_migration_thread;
-
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- if (!cpu_online(cpu))
- continue;
- if (kernel_thread(migration_thread, (void *) (long) cpu,
- CLONE_FS | CLONE_FILES | CLONE_SIGNAL) < 0)
- BUG();
+ switch (action) {
+ case CPU_ONLINE:
+ printk("Starting migration thread for cpu %li\n",
+ (long)hcpu);
+ kernel_thread(migration_thread, hcpu,
+ CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+ break;
}
- current->cpus_allowed = -1L;
+ return NOTIFY_OK;
+}
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- if (!cpu_online(cpu))
- continue;
- while (!cpu_rq(cpu)->migration_thread)
- schedule_timeout(2);
- }
+static struct notifier_block migration_notifier = { &migration_call, NULL, 0 };
+
+int __init migration_init(void)
+{
+ /* Start one for boot CPU. */
+ migration_call(&migration_notifier, CPU_ONLINE,
+ (void *)smp_processor_id());
+ register_cpu_notifier(&migration_notifier);
+ return 0;
}
+
+__initcall(migration_init);
#endif
extern void init_timervecs(void);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 135106c390c4..38ae82b344c0 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/tqueue.h>
#include <linux/percpu.h>
+#include <linux/notifier.h>
/*
- No shared variables, all the data are CPU local.
@@ -387,20 +388,32 @@ static int ksoftirqd(void * __bind_cpu)
}
}
-static __init int spawn_ksoftirqd(void)
+static int __devinit cpu_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
{
- int cpu;
+ int hotcpu = (unsigned long)hcpu;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- if (!cpu_online(cpu))
- continue;
- if (kernel_thread(ksoftirqd, (void *) (long) cpu,
- CLONE_FS | CLONE_FILES | CLONE_SIGNAL) < 0)
- printk("spawn_ksoftirqd() failed for cpu %d\n", cpu);
- else
- while (!ksoftirqd_task(cpu))
- yield();
- }
+ if (action == CPU_ONLINE) {
+ if (kernel_thread(ksoftirqd, hcpu,
+ CLONE_FS | CLONE_FILES | CLONE_SIGNAL) < 0) {
+ printk("ksoftirqd for %i failed\n", hotcpu);
+ return NOTIFY_BAD;
+ }
+
+ while (!ksoftirqd_task(hotcpu))
+ yield();
+ return NOTIFY_OK;
+ }
+ return NOTIFY_BAD;
+}
+
+static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 };
+
+static __init int spawn_ksoftirqd(void)
+{
+ cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)smp_processor_id());
+ register_cpu_notifier(&cpu_nfb);
return 0;
}
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4d98ac870e85..001c2253ec8f 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -335,6 +335,20 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
rpcproc_count(task->tk_client, task->tk_msg.rpc_proc)++;
}
+void
+rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
+{
+ struct rpc_xprt *xprt = clnt->cl_xprt;
+
+ xprt->sndsize = 0;
+ if (sndsize)
+ xprt->sndsize = sndsize + RPC_SLACK_SPACE;
+ xprt->rcvsize = 0;
+ if (rcvsize)
+ xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
+ xprt_sock_setbufsize(xprt);
+}
+
/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index d6bdb4630d2d..2b41eb87de5d 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -50,6 +50,7 @@ EXPORT_SYMBOL(rpc_clnt_sigmask);
EXPORT_SYMBOL(rpc_clnt_sigunmask);
EXPORT_SYMBOL(rpc_delay);
EXPORT_SYMBOL(rpc_restart_call);
+EXPORT_SYMBOL(rpc_setbufsize);
/* Client transport */
EXPORT_SYMBOL(xprt_create_proto);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 559cbd03e9cc..3d4ba37b48e1 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -233,6 +233,7 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
msg.msg_controllen = 0;
oldfs = get_fs(); set_fs(get_ds());
+ clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
result = sock_sendmsg(sock, &msg, slen);
set_fs(oldfs);
@@ -248,10 +249,7 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
/* When the server has died, an ICMP port unreachable message
* prompts ECONNREFUSED.
*/
- break;
case -EAGAIN:
- if (test_bit(SOCK_NOSPACE, &sock->flags))
- result = -ENOMEM;
break;
case -ENOTCONN:
case -EPIPE:
@@ -965,19 +963,15 @@ xprt_write_space(struct sock *sk)
if (!sock_writeable(sk))
return;
- if (!xprt_test_and_set_wspace(xprt)) {
- spin_lock_bh(&xprt->sock_lock);
- if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending)
- rpc_wake_up_task(xprt->snd_task);
- spin_unlock_bh(&xprt->sock_lock);
- }
+ if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
+ return;
- if (test_bit(SOCK_NOSPACE, &sock->flags)) {
- if (sk->sleep && waitqueue_active(sk->sleep)) {
- clear_bit(SOCK_NOSPACE, &sock->flags);
- wake_up_interruptible(sk->sleep);
- }
- }
+ spin_lock_bh(&xprt->sock_lock);
+ if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending)
+ rpc_wake_up_task(xprt->snd_task);
+ spin_unlock_bh(&xprt->sock_lock);
+ if (sk->sleep && waitqueue_active(sk->sleep))
+ wake_up_interruptible(sk->sleep);
}
/*
@@ -1083,7 +1077,6 @@ do_xprt_transmit(struct rpc_task *task)
* called xprt_sendmsg().
*/
while (1) {
- xprt_clear_wspace(xprt);
req->rq_xtime = jiffies;
status = xprt_sendmsg(xprt, req);
@@ -1098,7 +1091,7 @@ do_xprt_transmit(struct rpc_task *task)
} else {
if (status >= req->rq_slen)
goto out_receive;
- status = -ENOMEM;
+ status = -EAGAIN;
break;
}
@@ -1121,16 +1114,17 @@ do_xprt_transmit(struct rpc_task *task)
task->tk_status = status;
switch (status) {
- case -ENOMEM:
- /* Protect against (udp|tcp)_write_space */
- spin_lock_bh(&xprt->sock_lock);
- if (!xprt_wspace(xprt)) {
- task->tk_timeout = req->rq_timeout.to_current;
- rpc_sleep_on(&xprt->pending, task, NULL, NULL);
- }
- spin_unlock_bh(&xprt->sock_lock);
- return;
case -EAGAIN:
+ if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+ /* Protect against races with xprt_write_space */
+ spin_lock_bh(&xprt->sock_lock);
+ if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
+ task->tk_timeout = req->rq_timeout.to_current;
+ rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+ }
+ spin_unlock_bh(&xprt->sock_lock);
+ return;
+ }
/* Keep holding the socket if it is blocked */
rpc_delay(task, HZ>>4);
return;
@@ -1427,6 +1421,27 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
}
/*
+ * Set socket buffer length
+ */
+void
+xprt_sock_setbufsize(struct rpc_xprt *xprt)
+{
+ struct sock *sk = xprt->inet;
+
+ if (xprt->stream)
+ return;
+ if (xprt->rcvsize) {
+ sk->userlocks |= SOCK_RCVBUF_LOCK;
+ sk->rcvbuf = xprt->rcvsize * RPC_MAXCONG * 2;
+ }
+ if (xprt->sndsize) {
+ sk->userlocks |= SOCK_SNDBUF_LOCK;
+ sk->sndbuf = xprt->sndsize * RPC_MAXCONG * 2;
+ sk->write_space(sk);
+ }
+}
+
+/*
* Create a client socket given the protocol and peer address.
*/
static struct socket *
diff --git a/scripts/Makefile b/scripts/Makefile
index ea426beb6011..1efc9dc8ba49 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -5,7 +5,7 @@
# The following temporary rule will make sure that people's
# trees get updated to the right permissions, since patch(1)
# can't do it
-CHMOD_FILES := docgen gen-all-syms kernel-doc mkcompile_h makelst
+CHMOD_FILES := kernel-doc mkcompile_h makelst
all: fixdep split-include docproc $(CHMOD_FILES)