diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/Documentation/Configure.help linux2.4.21_itanium/Documentation/Configure.help --- linux2.4.21_itanium.org/Documentation/Configure.help Wed Jul 23 18:21:06 2003 +++ linux2.4.21_itanium/Documentation/Configure.help Wed Jul 23 21:14:26 2003 @@ -11018,6 +11018,16 @@ say M here and read . The module will be called sungem.o. +Broadcom NetXtreme BCM5700 Gigabit Ethernet support +CONFIG_NET_BROADCOM + Say Y here if you have a Broadcom BCM570x, or 3Com + 3C996/3C997/3C1000/3C940 PCI/PCIX Gigabit Ethernet adapter. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called bcm5700.o. + Broadcom Tigon3 support CONFIG_TIGON3 This driver supports Broadcom Tigon3 based gigabit Ethernet cards. @@ -18572,70 +18582,64 @@ will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. -ACPI support -CONFIG_ACPI - ACPI/OSPM support for Linux is currently under development. As such, - this support is preliminary and EXPERIMENTAL. Configuring ACPI - support enables kernel interfaces that allow higher level software - (OSPM) to manipulate ACPI defined hardware and software interfaces, - including the evaluation of ACPI control methods. If unsure, choose - N here. Note, this option will enlarge your kernel by about 120K. - - This support requires an ACPI compliant platform (hardware/firmware). - If both ACPI and Advanced Power Management (APM) support are - configured, whichever is loaded first shall be used. - - This code DOES NOT currently provide a complete OSPM implementation - -- it has not yet reached APM's level of functionality. When fully - implemented, Linux ACPI/OSPM will provide a more robust functional - replacement for legacy configuration and power management - interfaces, including the Plug-and-Play BIOS specification (PnP - BIOS), the Multi-Processor Specification (MPS), and the Advanced - Power Management specification (APM). - - Linux support for ACPI/OSPM is based on Intel Corporation's ACPI - Component Architecture (ACPI CA). The latest ACPI CA source code, - documentation, debug builds, and implementation status information - can be downloaded from: - . - - The ACPI Sourceforge project may also be of interest: - - -Enable ACPI 2.0 with errata 1.3 -CONFIG_ACPI20 - Enable support for the 2.0 version of the ACPI interpreter. See the - help for ACPI for caveats and discussion. - -ACPI kernel configuration manager -CONFIG_ACPI_KERNEL_CONFIG - If you say `Y' here, Linux's ACPI support will use the - hardware-level system descriptions found on IA64 machines. - -ACPI Debug Statements -CONFIG_ACPI_DEBUG - The ACPI driver can optionally report errors with a great deal - of verbosity. Saying Y enables these statements. This will increase - your kernel size by around 50K. +ACPI Support +CONFIG_ACPI_ENABLE + Advanced Configuration and Power Interface (ACPI) support for + Linux requires an ACPI compliant platform (hardware/firmware), + and assumes the presence of OS-directed configuration and power + management (OSPM) software. This option will enlarge your + kernel by about 70K. + + Linux ACPI provides a robust functional replacement for several + legacy configuration and power management intefaces, including + the Plug-and-Play BIOS specification (PnP BIOS), the + MultiProcessor Specification (MPS), and the Advanced Power + Management (APM) specification. If both ACPI and APM support + are configured, whichever is loaded first shall be used. + + Add "acpi=off" to the kernel command line to disable this feature. + (Try "man bootparam" or see the documentation of your boot loader + about how to pass options to the kernel at boot time.) + + Add "acpi=ht-only" to the kernel command line to limit ACPI + support to processor enumeration only (see CONFIG_ACPI_HT_ONLY). + + ---------- + + The ACPI SourceForge project contains the latest source code, + documentation, tools, mailing list subscription, and other + information. This project is available at: + + + Linux support for ACPI is based on Intel Corporation's ACPI + Component Architecture (ACPI CA). For more information see: + + + ACPI is an open industry specification co-developed by Compaq, + Intel, Microsoft, Phoenix, and Toshiba. The specification is + available at: + + +CONFIG_ACPI_HT_ONLY + This option enables limited ACPI support -- just enough to + enumerate processors from the ACPI Multiple APIC Description + Table (MADT). Note that ACPI supports both logical (e.g. Hyper- + Threading) and physical processors, where the MultiProcessor + Specification (MPS) table only supports physical processors. -ACPI Bus Manager -CONFIG_ACPI_BUSMGR - The ACPI Bus Manager enumerates devices in the ACPI namespace, and - handles PnP messages. All ACPI devices use its services, so using - them requires saying Y here. + Full ACPI support (CONFIG_ACPI) is preferred. Use this option + only if you wish to limit ACPI's role to processor enumeration. -ACPI System Driver -CONFIG_ACPI_SYS - This driver will enable your system to shut down using ACPI, and - dump your ACPI DSDT table using /proc/acpi/dsdt. +CONFIG_ACPI_AC + This driver adds support for the AC Adapter object, which indicates + whether a system is on AC, or not. Typically, only mobile systems + have this object, since desktops are always on AC. -ACPI Processor Driver -CONFIG_ACPI_CPU - This driver installs ACPI as the idle handler for Linux, and uses - ACPI C2 and C3 processor states to save power, on systems that - support it. +CONFIG_ACPI_BATTERY + This driver adds support for battery information through + /proc/acpi/battery. If you have a mobile system with a battery, + say Y. -ACPI Button CONFIG_ACPI_BUTTON This driver registers for events based on buttons, such as the power, sleep, and lid switch. In the future, a daemon will read @@ -18643,27 +18647,34 @@ down the system. Until then, you can cat it, and see output when a button is pressed. -ACPI AC Adapter -CONFIG_ACPI_AC - This driver adds support for the AC Adapter object, which indicates - whether a system is on AC, or not. Typically, only laptops have - this object, since desktops are always on AC. - -ACPI Embedded Controller CONFIG_ACPI_EC This driver is required on some systems for the proper operation of - the battery and thermal drivers. If you are compiling for a laptop, - say Y. + the battery and thermal drivers. If you are compiling for a + mobile system, say Y. -ACPI Control Method Battery -CONFIG_ACPI_CMBATT - This driver adds support for battery information through - /proc/acpi/battery. If you have a laptop with a battery, say Y. +CONFIG_ACPI_PROCESSOR + This driver installs ACPI as the idle handler for Linux, and uses + ACPI C2 and C3 processor states to save power, on systems that + support it. -ACPI Thermal CONFIG_ACPI_THERMAL - This driver handles overheating conditions on laptops. It is HIGHLY - recommended, as your laptop CPU may be damaged without it. + This driver adds support for ACPI thermal zones. Most mobile and + some desktop systems support ACPI thermal zones. It is HIGHLY + recommended that this option be enabled, as your processor(s) + may be damaged without it. + +CONFIG_ACPI_FAN + This driver adds support for ACPI fan devices, allowing user-mode + applications to perform basic fan control (on, off, status). + +CONFIG_ACPI_SYSTEM + This driver will enable your system to shut down using ACPI, and + dump your ACPI DSDT table using /proc/acpi/dsdt. + +CONFIG_ACPI_DEBUG + The ACPI driver can optionally report errors with a great deal + of verbosity. Saying Y enables these statements. This will increase + your kernel size by around 50K. Advanced Power Management BIOS support CONFIG_APM @@ -25740,11 +25751,13 @@ # Choice: ia64type Itanium CONFIG_ITANIUM - Select your IA64 processor type. The default is Intel Itanium. + Select your IA-64 processor type. The default is Intel Itanium. + This choice is safe for all IA-64 systems, but may not perform + optimally on systems with, say, Itanium 2 or newer processors. -McKinley +Itanium 2 CONFIG_MCKINLEY - Select this to configure for a McKinley processor. + Select this to configure for an Itanium 2 (McKinley) processor. # Choice: ia64system IA-64 system type @@ -25821,12 +25834,31 @@ and restore instructions. It's useful for tracking down spinlock problems, but slow! If you're unsure, select N. -Early printk support (requires VGA!) +Early printk support CONFIG_IA64_EARLY_PRINTK - Selecting this option uses the VGA screen for printk() output before - the consoles are initialised. It is useful for debugging problems - early in the boot process, but only if you have a VGA screen - attached. If you're unsure, select N. + Selecting this option uses a UART or VGA screen (or both) for + printk() output before the consoles are initialised. It is useful + for debugging problems early in the boot process, but only if you + have a serial terminal or a VGA screen attached. If you're unsure, + select N. + +Early printk on serial port +CONFIG_IA64_EARLY_PRINTK_UART + Select this option to use a serial port for early printk() output. + You must also select either CONFIG_IA64_EARLY_PRINTK_UART_BASE or + CONFIG_SERIAL_HCDP. If you select CONFIG_SERIAL_HCDP, early + printk() output will appear on the first console device described by + the HCDP. If you set CONFIG_IA64_EARLY_PRINTK_UART_BASE, the HCDP + will be ignored. + +UART base address +CONFIG_IA64_EARLY_PRINTK_UART_BASE + The physical MMIO address of the UART to use for early printk(). + This overrides any UART located using the EFI HCDP table. + +Early printk on VGA +CONFIG_IA64_EARLY_PRINTK_VGA + Select this option to use VGA for early printk() output. Print possible IA64 hazards to console CONFIG_IA64_PRINT_HAZARDS diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/Documentation/vm/hugetlbpage.txt linux2.4.21_itanium/Documentation/vm/hugetlbpage.txt --- linux2.4.21_itanium.org/Documentation/vm/hugetlbpage.txt Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/Documentation/vm/hugetlbpage.txt Wed Jul 23 18:29:11 2003 @@ -0,0 +1,217 @@ + +The intent of this file is to give a brief summary of hugetlbpage support in +the Linux kernel. This support is built on top of multiple page size support +that is provided by most of modern architectures. For example, IA-32 +architecture supports 4K and 4M (2M in PAE mode) page sizes, IA-64 +architecture supports multiple page sizes 4K, 8K, 64K, 256K, 1M, 4M, 16M, +256M. A TLB is a cache of virtual-to-physical translations. Typically this +is a very scarce resource on processor. Operating systems try to make best +use of limited number of TLB resources. This optimization is more critical +now as bigger and bigger physical memories (several GBs) are more readily +available. + +Users can use the huge page support in Linux kernel by either using the mmap +system call or standard SYSv shared memory system calls (shmget, shmat). + +First the Linux kernel needs to be built with CONFIG_HUGETLB_PAGE (present +under Processor types and feature) and CONFIG_HUGETLBFS (present under file +system option on config menu) config options. + +The kernel built with hugepage support should show the number of configured +hugepages in the system by running the "cat /proc/meminfo" command. + +/proc/meminfo also provides information about the total number of hugetlb +pages configured in the kernel. It also displays information about the +number of free hugetlb pages at any time. It also displays information about +the configured hugepage size - this is needed for generating the proper +alignment and size of the arguments to the above system calls. + +The output of "cat /proc/meminfo" will have output like: + +..... +HugePages_Total: xxx +HugePages_Free: yyy +Hugepagesize: zzz KB + +/proc/filesystems should also show a filesystem of type "hugetlbfs" configured +in the kernel. + +/proc/sys/vm/nr_hugepages indicates the current number of configured hugetlb +pages in the kernel. Super user can dynamically request more (or free some +pre-configured) hugepages. +The allocation( or deallocation) of hugetlb pages is posible only if there are +enough physically contiguous free pages in system (freeing of hugepages is +possible only if there are enough hugetlb pages free that can be transfered +back to regular memory pool). + +Pages that are used as hugetlb pages are reserved inside the kernel and can +not be used for other purposes. + +Once the kernel with Hugetlb page support is built and running, a user can +use either the mmap system call or shared memory system calls to start using +the huge pages. It is required that the system administrator preallocate +enough memory for huge page purposes. + +Use the following command to dynamically allocate/deallocate hugepages: + + echo 20 > /proc/sys/vm/nr_hugepages + +This command will try to configure 20 hugepages in the system. The success +or failure of allocation depends on the amount of physically contiguous +memory that is preset in system at this time. System administrators may want +to put this command in one of the local rc init file. This will enable the +kernel to request huge pages early in the boot process (when the possibility +of getting physical contiguous pages is still very high). + +If the user applications are going to request hugepages using mmap system +call, then it is required that system administrator mount a file system of +type hugetlbfs: + + mount none /mnt/huge -t hugetlbfs + + +This command mounts a (pseudo) filesystem of type hugetlbfs on the directory +/mnt/huge. Any files created on /mnt/huge use hugepages. The uid and gid +options set the owner and group of the root of the file system. By default +the uid and gid of the current process are taken. The mode option sets the +mode of root of file system to value & 0777. This value is given in octal. +By default the value 0755 is picked. The size option sets the maximum value of +memory (huge pages) allowed for that filesystem (/mnt/huge). The size is +rounded down to HPAGE_SIZE. The option nr_inode sets the maximum number of +inodes that /mnt/huge can use. If the size or nr_inode options are not +provided on command line then no limits are set. For option size and option +nr_inodes, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For +example, size=2K has the same meaning as size=2048. An example is given at +the end of this document. + +read and write system calls are not supported on files that reside on hugetlb +file systems. + +Regular chown, chgrp and chmod commands can be used to change the file +attributes on hugetlbfs. + +Also, it is important to note that no such mount command is required if the +applications are going to use only shmat/shmget system calls. It is possible +for same or different applications to use any combination of mmaps and shm* +calls. Though the mount of filesystem will be required for using mmaps. + +/* Example of using hugepage in user application using Sys V shared memory + * system calls. In this example, app is requesting memory of size 256MB that + * is backed by huge pages. Application uses the flag SHM_HUGETLB in shmget + * system call to informt the kernel that it is requesting hugepages. For + * IA-64 architecture, Linux kernel reserves Region number 4 for hugepages. + * That means the addresses starting with 0x800000....will need to be + * specified. + */ +#include +#include +#include +#include + +extern int errno; +#define SHM_HUGETLB 04000 +#define LPAGE_SIZE (256UL*1024UL*1024UL) +#define dprintf(x) printf(x) +#define ADDR (0x8000000000000000UL) +main() +{ + int shmid; + int i, j, k; + volatile char *shmaddr; + + if ((shmid =shmget(2, LPAGE_SIZE, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W )) +< 0) { + perror("Failure:"); + exit(1); + } + printf("shmid: 0x%x\n", shmid); + shmaddr = shmat(shmid, (void *)ADDR, SHM_RND) ; + if (errno != 0) { + perror("Shared Memory Attach Failure:"); + exit(2); + } + printf("shmaddr: %p\n", shmaddr); + + dprintf("Starting the writes:\n"); + for (i=0;i +#include +#include +#include + +#define FILE_NAME "/mnt/hugepagefile" +#define LENGTH (256*1024*1024) +#define PROTECTION (PROT_READ | PROT_WRITE) +#define FLAGS MAP_SHARED |MAP_FIXED +#define ADDRESS (char *)(0x60000000UL + 0x8000000000000000UL) + +extern errno; + +check_bytes(char *addr) +{ + printf("First hex is %x\n", *((unsigned int *)addr)); +} + +write_bytes(char *addr) +{ + int i; + for (i=0;i + * Copyright (C) 2001 Jun Nakajima + * Copyright (C) 2001 Patrick Mochel + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PREFIX "ACPI: " + + +/* -------------------------------------------------------------------------- + Boot-time Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +enum acpi_irq_model_id acpi_irq_model; + + +/* + * Use reserved fixmap pages for physical-to-virtual mappings of ACPI tables. + * Note that the same range is used for each table, so tables that need to + * persist should be memcpy'd. + */ +char * +__acpi_map_table ( + unsigned long phys_addr, + unsigned long size) +{ + unsigned long base = 0; + unsigned long mapped_phys = phys_addr; + unsigned long offset = phys_addr & (PAGE_SIZE - 1); + unsigned long mapped_size = PAGE_SIZE - offset; + unsigned long avail_size = mapped_size + (PAGE_SIZE * FIX_ACPI_PAGES); + int idx = FIX_ACPI_BEGIN; + + if (!phys_addr || !size) + return NULL; + + base = fix_to_virt(FIX_ACPI_BEGIN); + + set_fixmap(idx, mapped_phys); + + if (size > avail_size) + return NULL; + + /* If the table doesn't map completely into the fist page... */ + if (size > mapped_size) { + do { + /* Make sure we don't go past our range */ + if (idx++ == FIX_ACPI_END) + return NULL; + mapped_phys = mapped_phys + PAGE_SIZE; + set_fixmap(idx, mapped_phys); + mapped_size = mapped_size + PAGE_SIZE; + } while (mapped_size < size); + } + + return ((unsigned char *) base + offset); +} + + +#ifdef CONFIG_X86_LOCAL_APIC + +int acpi_lapic; + +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; + + +static int __init +acpi_parse_madt ( + unsigned long phys_addr, + unsigned long size) +{ + struct acpi_table_madt *madt = NULL; + + if (!phys_addr || !size) + return -EINVAL; + + madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); + return -ENODEV; + } + + if (madt->lapic_address) + acpi_lapic_addr = (u64) madt->lapic_address; + + printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); + + return 0; +} + + +static int __init +acpi_parse_lapic ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic *processor = NULL; + + processor = (struct acpi_table_lapic*) header; + if (!processor) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_lapic ( + processor->id, /* APIC ID */ + processor->flags.enabled); /* Enabled? */ + + return 0; +} + + +static int __init +acpi_parse_lapic_addr_ovr ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; + + lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; + if (!lapic_addr_ovr) + return -EINVAL; + + acpi_lapic_addr = lapic_addr_ovr->address; + + return 0; +} + + +static int __init +acpi_parse_lapic_nmi ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic_nmi *lapic_nmi = NULL; + + lapic_nmi = (struct acpi_table_lapic_nmi*) header; + if (!lapic_nmi) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + if (lapic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); + + return 0; +} + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#ifdef CONFIG_X86_IO_APIC + +int acpi_ioapic; + +static int __init +acpi_parse_ioapic ( + acpi_table_entry_header *header) +{ + struct acpi_table_ioapic *ioapic = NULL; + + ioapic = (struct acpi_table_ioapic*) header; + if (!ioapic) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_ioapic ( + ioapic->id, + ioapic->address, + ioapic->global_irq_base); + + return 0; +} + + +static int __init +acpi_parse_int_src_ovr ( + acpi_table_entry_header *header) +{ + struct acpi_table_int_src_ovr *intsrc = NULL; + + intsrc = (struct acpi_table_int_src_ovr*) header; + if (!intsrc) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, + intsrc->flags.trigger, + intsrc->global_irq); + + return 0; +} + + +static int __init +acpi_parse_nmi_src ( + acpi_table_entry_header *header) +{ + struct acpi_table_nmi_src *nmi_src = NULL; + + nmi_src = (struct acpi_table_nmi_src*) header; + if (!nmi_src) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* TBD: Support nimsrc entries? */ + + return 0; +} + +#endif /*CONFIG_X86_IO_APIC*/ + + +static unsigned long __init +acpi_scan_rsdp ( + unsigned long start, + unsigned long length) +{ + unsigned long offset = 0; + unsigned long sig_len = sizeof("RSD PTR ") - 1; + + /* + * Scan all 16-byte boundaries of the physical memory region for the + * RSDP signature. + */ + for (offset = 0; offset < length; offset += 16) { + if (0 != strncmp((char *) (start + offset), "RSD PTR ", sig_len)) + continue; + return (start + offset); + } + + return 0; +} + + +unsigned long __init +acpi_find_rsdp (void) +{ + unsigned long rsdp_phys = 0; + + /* + * Scan memory looking for the RSDP signature. First search EBDA (low + * memory) paragraphs and then search upper memory (E0000-FFFFF). + */ + rsdp_phys = acpi_scan_rsdp (0, 0x400); + if (!rsdp_phys) + rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); + + return rsdp_phys; +} + + +int __init +acpi_boot_init ( + char *cmdline) +{ + int result = 0; + + /* + * The default interrupt routing model is PIC (8259). This gets + * overriden if IOAPICs are enumerated (below). + */ + acpi_irq_model = ACPI_IRQ_MODEL_PIC; + + /* + * Initialize the ACPI boot-time table parser. + */ + result = acpi_table_init(cmdline); + if (0 != result) + return result; + +#ifdef CONFIG_X86_LOCAL_APIC + + /* + * MADT + * ---- + * Parse the Multiple APIC Description Table (MADT), if exists. + * Note that this table provides platform SMP configuration + * information -- the successor to MPS tables. + */ + + result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); + if (0 == result) { + printk(KERN_WARNING PREFIX "MADT not present\n"); + return 0; + } + else if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing MADT\n"); + return result; + } + else if (1 < result) + printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); + + /* + * Local APIC + * ---------- + * Note that the LAPIC address is obtained from the MADT (32-bit value) + * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). + */ + + result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); + if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); + return result; + } + + mp_register_lapic_address(acpi_lapic_addr); + + result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); + if (0 == result) { + printk(KERN_ERR PREFIX "No LAPIC entries present\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return -ENODEV; + } + else if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return result; + } + + result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); + if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return result; + } + + acpi_lapic = 1; + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#ifdef CONFIG_X86_IO_APIC + + /* + * I/O APIC + * -------- + */ + + result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); + if (0 == result) { + printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); + return -ENODEV; + } + else if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); + return result; + } + + /* Build a default routing table for legacy (ISA) interrupts. */ + mp_config_acpi_legacy_irqs(); + + result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); + if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return result; + } + + result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); + if (0 > result) { + printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return result; + } + + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + + acpi_ioapic = 1; + +#endif /*CONFIG_X86_IO_APIC*/ + +#ifdef CONFIG_X86_LOCAL_APIC + if (acpi_lapic && acpi_ioapic) + smp_found_config = 1; +#endif + + return 0; +} + +int +acpi_register_irq ( + u32 gsi, + u32 polarity, + u32 mode) +{ + return gsi; +} + +#endif /*CONFIG_ACPI_BOOT*/ + + +/* -------------------------------------------------------------------------- + Low-Level Sleep Support + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_SLEEP + +#define DEBUG + +#ifdef DEBUG +#include +#endif + +/* address in low memory of the wakeup routine. */ +unsigned long acpi_wakeup_address = 0; + +/* new page directory that we will be using */ +static pmd_t *pmd; + +/* saved page directory */ +static pmd_t saved_pmd; + +/* page which we'll use for the new page directory */ +static pte_t *ptep; + +extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); + +/* + * acpi_create_identity_pmd + * + * Create a new, identity mapped pmd. + * + * Do this by creating new page directory, and marking all the pages as R/W + * Then set it as the new Page Middle Directory. + * And, of course, flush the TLB so it takes effect. + * + * We save the address of the old one, for later restoration. + */ +static void acpi_create_identity_pmd (void) +{ + pgd_t *pgd; + int i; + + ptep = (pte_t*)__get_free_page(GFP_KERNEL); + + /* fill page with low mapping */ + for (i = 0; i < PTRS_PER_PTE; i++) + set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED)); + + pgd = pgd_offset(current->active_mm, 0); + pmd = pmd_alloc(current->mm,pgd, 0); + + /* save the old pmd */ + saved_pmd = *pmd; + + /* set the new one */ + set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep))); + + /* flush the TLB */ + local_flush_tlb(); +} + +/* + * acpi_restore_pmd + * + * Restore the old pmd saved by acpi_create_identity_pmd and + * free the page that said function alloc'd + */ +static void acpi_restore_pmd (void) +{ + set_pmd(pmd, saved_pmd); + local_flush_tlb(); + free_page((unsigned long)ptep); +} + +/** + * acpi_save_state_mem - save kernel state + * + * Create an identity mapped page table and copy the wakeup routine to + * low memory. + */ +int acpi_save_state_mem (void) +{ + acpi_create_identity_pmd(); + acpi_copy_wakeup_routine(acpi_wakeup_address); + + return 0; +} + +/** + * acpi_save_state_disk - save kernel state to disk + * + */ +int acpi_save_state_disk (void) +{ + return 1; +} + +/* + * acpi_restore_state + */ +void acpi_restore_state_mem (void) +{ + acpi_restore_pmd(); +} + +/** + * acpi_reserve_bootmem - do _very_ early ACPI initialisation + * + * We allocate a page in low memory for the wakeup + * routine for when we come back from a sleep state. The + * runtime allocator allows specification of <16M pages, but not + * <1M pages. + */ +void __init acpi_reserve_bootmem(void) +{ + acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); + printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address); +} + +#endif /*CONFIG_ACPI_SLEEP*/ + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/acpi_wakeup.S linux2.4.21_itanium/arch/i386/kernel/acpi_wakeup.S --- linux2.4.21_itanium.org/arch/i386/kernel/acpi_wakeup.S Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/i386/kernel/acpi_wakeup.S Wed Jul 23 18:28:23 2003 @@ -0,0 +1,139 @@ + +.text +#include +#include + + +ALIGN +wakeup_start: +wakeup_code: + wakeup_code_start = . + .code16 + + cli + cld + + # setup data segment + movw %cs, %ax + + addw $(wakeup_data - wakeup_code) >> 4, %ax + movw %ax, %ds + movw %ax, %ss + mov $(wakeup_stack - wakeup_data), %sp # Private stack is needed for ASUS board + + # set up page table + movl (real_save_cr3 - wakeup_data), %eax + movl %eax, %cr3 + + # make sure %cr4 is set correctly (features, etc) + movl (real_save_cr4 - wakeup_data), %eax + movl %eax, %cr4 + + # need a gdt + lgdt real_save_gdt - wakeup_data + + movl %cr0, %eax + orl $0x80000001, %eax + movl %eax, %cr0 + + ljmpl $__KERNEL_CS,$SYMBOL_NAME(wakeup_pmode_return) + + .code32 + ALIGN + +.org 0x100 +wakeup_data: + .word 0 +real_save_gdt: .word 0 + .long 0 +real_save_cr3: .long 0 +real_save_cr4: .long 0 + +.org 0x300 +wakeup_stack: +wakeup_end: + +wakeup_pmode_return: + # restore data segment + movl $__KERNEL_DS, %eax + movw %ax, %ds + movw %ax, %es + + # and restore the stack + movw %ax, %ss + movl saved_esp, %esp + + # restore other segment registers + xorl %eax, %eax + movw %ax, %fs + movw %ax, %gs + + # reload the gdt, as we need the full 32 bit address + lgdt saved_gdt + lidt saved_idt + lldt saved_ldt + + # restore the other general registers + movl saved_ebx, %ebx + movl saved_edi, %edi + movl saved_esi, %esi + movl saved_ebp, %ebp + + # jump to place where we left off + movl saved_eip,%eax + jmp *%eax + +## +# acpi_copy_wakeup_routine +# +# Copy the above routine to low memory. +# +# Parameters: +# %eax: place to copy wakeup routine to +# +# Returned address is location of code in low memory (past data and stack) +# +ENTRY(acpi_copy_wakeup_routine) + + pushl %esi + pushl %edi + + sgdt saved_gdt + sidt saved_idt + sldt saved_ldt + str saved_tss + + movl %eax, %edi + leal wakeup_start, %esi + movl $(wakeup_end - wakeup_start) >> 2, %ecx + + rep ; movsl + + movl %cr3, %edx + movl %edx, real_save_cr3 - wakeup_start (%eax) + movl %cr4, %edx + movl %edx, real_save_cr4 - wakeup_start (%eax) + sgdt real_save_gdt - wakeup_start (%eax) + + # restore the regs we used + popl %edi + popl %esi + ret + + +.data +ALIGN +# saved registers +saved_gdt: .long 0,0 +saved_idt: .long 0,0 +saved_ldt: .long 0 +saved_tss: .long 0 +saved_cr0: .long 0 + +ENTRY(saved_ebp) .long 0 +ENTRY(saved_esi) .long 0 +ENTRY(saved_edi) .long 0 +ENTRY(saved_ebx) .long 0 + +ENTRY(saved_eip) .long 0 +ENTRY(saved_esp) .long 0 diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/io_apic.c linux2.4.21_itanium/arch/i386/kernel/io_apic.c --- linux2.4.21_itanium.org/arch/i386/kernel/io_apic.c Wed Jul 23 18:20:47 2003 +++ linux2.4.21_itanium/arch/i386/kernel/io_apic.c Wed Jul 23 18:28:23 2003 @@ -17,6 +17,7 @@ * thanks to Eric Gilmore * and Rolf G. Tews * for testing these extensively + * Paul Diefenbaugh : Added full ACPI support */ #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -1057,6 +1059,10 @@ unsigned char old_id; unsigned long flags; + if (acpi_ioapic) + /* This gets done during IOAPIC enumeration for ACPI. */ + return; + if (clustered_apic_mode) /* We don't have a good way to do this yet - hack */ phys_id_present_map = (u_long) 0xf; @@ -1657,8 +1663,7 @@ printk("ENABLING IO-APIC IRQs\n"); /* - * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS - * mptable: + * Set up IO-APIC IRQ routing. */ setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); @@ -1667,3 +1672,159 @@ check_timer(); print_IO_APIC(); } + + +/* -------------------------------------------------------------------------- + ACPI-based IOAPIC Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +#define IO_APIC_MAX_ID 15 + +int __init io_apic_get_unique_id (int ioapic, int apic_id) +{ + struct IO_APIC_reg_00 reg_00; + static unsigned long apic_id_map = 0; + unsigned long flags; + int i = 0; + + /* + * The P4 platform supports up to 256 APIC IDs on two separate APIC + * buses (one for LAPICs, one for IOAPICs), where predecessors only + * supports up to 16 on one shared APIC bus. + * + * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full + * advantage of new APIC bus architecture. + */ + + if (!apic_id_map) + apic_id_map = phys_cpu_present_map; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + if (apic_id >= IO_APIC_MAX_ID) { + printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " + "%d\n", ioapic, apic_id, reg_00.ID); + apic_id = reg_00.ID; + } + + /* + * Every APIC in a system must have a unique ID or we get lots of nice + * 'stuck on smp_invalidate_needed IPI wait' messages. + */ + if (apic_id_map & (1 << apic_id)) { + + for (i = 0; i < IO_APIC_MAX_ID; i++) { + if (!(apic_id_map & (1 << i))) + break; + } + + if (i == IO_APIC_MAX_ID) + panic("Max apic_id exceeded!\n"); + + printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " + "trying %d\n", ioapic, apic_id, i); + + apic_id = i; + } + + apic_id_map |= (1 << apic_id); + + if (reg_00.ID != apic_id) { + reg_00.ID = apic_id; + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0, *(int *)®_00); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + /* Sanity check */ + if (reg_00.ID != apic_id) + panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + } + + printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + + return apic_id; +} + + +int __init io_apic_get_version (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.version; +} + + +int __init io_apic_get_redir_entries (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.entries; +} + + +int io_apic_set_pci_routing (int ioapic, int pin, int irq) +{ + struct IO_APIC_route_entry entry; + unsigned long flags; + + if (!IO_APIC_IRQ(irq)) { + printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0/n", + ioapic); + return -EINVAL; + } + + /* + * Generate a PCI IRQ routing entry and program the IOAPIC accordingly. + * Note that we mask (disable) IRQs now -- these get enabled when the + * corresponding device driver registers for this IRQ. + */ + + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = dest_LowestPrio; + entry.dest_mode = INT_DELIVERY_MODE; + entry.dest.logical.logical_dest = TARGET_CPUS; + entry.mask = 1; /* Disabled (masked) */ + entry.trigger = 1; /* Level sensitive */ + entry.polarity = 1; /* Low active */ + + add_pin_to_irq(irq, ioapic, pin); + + entry.vector = assign_irq_vector(irq); + + printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " + "IRQ %d)\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq); + + irq_desc[irq].handler = &ioapic_level_irq_type; + + set_intr_gate(entry.vector, interrupt[irq]); + + if (!ioapic && (irq < 16)) + disable_8259A_irq(irq); + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return entry.vector; +} + +#endif /*CONFIG_ACPI_BOOT*/ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/mpparse.c linux2.4.21_itanium/arch/i386/kernel/mpparse.c --- linux2.4.21_itanium.org/arch/i386/kernel/mpparse.c Wed Jul 23 18:20:47 2003 +++ linux2.4.21_itanium/arch/i386/kernel/mpparse.c Wed Jul 23 18:28:23 2003 @@ -9,12 +9,14 @@ * Erich Boleyn : MP v1.4 and additional changes. * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites - * Maciej W. Rozycki : Bits for default MP configurations + * Maciej W. Rozycki: Bits for default MP configurations + * Paul Diefenbaugh: Added full ACPI support */ #include #include #include +#include #include #include #include @@ -23,9 +25,11 @@ #include #include +#include #include #include #include +#include #include /* Have we found an MP table */ @@ -137,12 +141,6 @@ return n; } -#ifdef CONFIG_X86_IO_APIC -extern int have_acpi_tables; /* set by acpitable.c */ -#else -#define have_acpi_tables (0) -#endif - /* * Have to match translation table entries to main table entries by counter * hence the mpc_record variable .... can't see a less disgusting way of @@ -447,10 +445,11 @@ printk("APIC at: 0x%lX\n",mpc->mpc_lapic); - /* save the local APIC address, it might be non-default, - * but only if we're not using the ACPI tables + /* + * Save the local APIC address (it might be non-default) -- but only + * if we're not using ACPI. */ - if (!have_acpi_tables) + if (!acpi_lapic) mp_lapic_addr = mpc->mpc_lapic; if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && mpc->mpc_oemptr) { @@ -530,9 +529,8 @@ { struct mpc_config_processor *m= (struct mpc_config_processor *)mpt; - - /* ACPI may already have provided this one for us */ - if (!have_acpi_tables) + /* ACPI may have already provided this data */ + if (!acpi_lapic) MP_processor_info(m); mpt += sizeof(*m); count += sizeof(*m); @@ -761,7 +759,6 @@ } static struct intel_mp_floating *mpf_found; -extern void config_acpi_tables(void); /* * Scan the memory blocks for an SMP configuration block. @@ -770,17 +767,19 @@ { struct intel_mp_floating *mpf = mpf_found; -#ifdef CONFIG_X86_IO_APIC /* - * Check if the ACPI tables are provided. Use them only to get - * the processor information, mainly because it provides - * the info on the logical processor(s), rather than the physical - * processor(s) that are provided by the MPS. We attempt to - * check only if the user provided a commandline override + * ACPI may be used to obtain the entire SMP configuration or just to + * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that + * ACPI supports both logical (e.g. Hyper-Threading) and physical + * processors, where MPS only supports physical. */ - config_acpi_tables(); -#endif - + if (acpi_lapic && acpi_ioapic) { + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); + return; + } + else if (acpi_lapic) + printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); + printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { printk(" IMCR and PIC compatibility mode.\n"); @@ -902,7 +901,7 @@ address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; - smp_scan_config(address, 0x1000); + smp_scan_config(address, 0x400); } #else @@ -939,3 +938,315 @@ #endif } + +/* -------------------------------------------------------------------------- + ACPI-based MP Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +void __init mp_register_lapic_address ( + u64 address) +{ + mp_lapic_addr = (unsigned long) address; + + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); + + if (boot_cpu_physical_apicid == -1U) + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); + + Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); +} + + +void __init mp_register_lapic ( + u8 id, + u8 enabled) +{ + struct mpc_config_processor processor; + int boot_cpu = 0; + + if (id >= MAX_APICS) { + printk(KERN_WARNING "Processor #%d invalid (max %d)\n", + id, MAX_APICS); + return; + } + + if (id == boot_cpu_physical_apicid) + boot_cpu = 1; + + processor.mpc_type = MP_PROCESSOR; + processor.mpc_apicid = id; + processor.mpc_apicver = 0x10; /* TBD: lapic version */ + processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); + processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); + processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | + (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; + processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; + processor.mpc_reserved[0] = 0; + processor.mpc_reserved[1] = 0; + + MP_processor_info(&processor); +} + +#ifdef CONFIG_X86_IO_APIC + +#define MP_ISA_BUS 0 +#define MP_MAX_IOAPIC_PIN 127 + +struct mp_ioapic_routing { + int apic_id; + int irq_start; + int irq_end; + u32 pin_programmed[4]; +} mp_ioapic_routing[MAX_IO_APICS]; + + +static int __init mp_find_ioapic ( + int irq) +{ + int i = 0; + + /* Find the IOAPIC that manages this IRQ. */ + for (i = 0; i < nr_ioapics; i++) { + if ((irq >= mp_ioapic_routing[i].irq_start) + && (irq <= mp_ioapic_routing[i].irq_end)) + return i; + } + + printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d/n", irq); + + return -1; +} + + +void __init mp_register_ioapic ( + u8 id, + u32 address, + u32 irq_base) +{ + int idx = 0; + + if (nr_ioapics >= MAX_IO_APICS) { + printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " + "(found %d)\n", MAX_IO_APICS, nr_ioapics); + panic("Recompile kernel with bigger MAX_IO_APICS!\n"); + } + if (!address) { + printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" + " found in MADT table, skipping!\n"); + return; + } + + idx = nr_ioapics++; + + mp_ioapics[idx].mpc_type = MP_IOAPIC; + mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; + mp_ioapics[idx].mpc_apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); + mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); + + /* + * Build basic IRQ lookup table to facilitate irq->io_apic lookups + * and to prevent reprogramming of IOAPIC pins (PCI IRQs). + */ + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; + mp_ioapic_routing[idx].irq_start = irq_base; + mp_ioapic_routing[idx].irq_end = irq_base + + io_apic_get_redir_entries(idx); + + printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " + "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, + mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, + mp_ioapic_routing[idx].irq_start, + mp_ioapic_routing[idx].irq_end); + + return; +} + + +void __init mp_override_legacy_irq ( + u8 bus_irq, + u8 polarity, + u8 trigger, + u32 global_irq) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int found = 0; + int ioapic = -1; + int pin = -1; + + /* + * Convert 'global_irq' to 'ioapic.pin'. + */ + ioapic = mp_find_ioapic(global_irq); + if (ioapic < 0) + return; + pin = global_irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * TBD: This check is for faulty timer entries, where the override + * erroneously sets the trigger to level, resulting in a HUGE + * increase of timer interrupts! + */ + if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3)) + trigger = 1; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqtype = mp_INT; + intsrc.mpc_irqflag = (trigger << 2) | polarity; + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ + intsrc.mpc_dstirq = pin; /* INTIN# */ + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", + intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); + + /* + * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it. + * Otherwise create a new entry (e.g. global_irq == 2). + */ + for (i = 0; i < mp_irq_entries; i++) { + if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) + && (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) { + mp_irqs[i] = intsrc; + found = 1; + break; + } + } + if (!found) { + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } + + return; +} + + +void __init mp_config_acpi_legacy_irqs (void) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int ioapic = -1; + + /* + * Fabricate the legacy ISA bus (bus #31). + */ + mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; + Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); + + /* + * Locate the IOAPIC that manages the ISA IRQs (0-15). + */ + ioapic = mp_find_ioapic(0); + if (ioapic < 0) + return; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqflag = 0; /* Conforming */ + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; + + /* + * Use the default configuration for the IRQs 0-15. These may be + * overriden by (MADT) interrupt source override entries. + */ + for (i = 0; i < 16; i++) { + + if (i == 2) continue; /* Don't connect IRQ2 */ + + intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT; /* 8259A to #0 */ + intsrc.mpc_srcbusirq = i; /* Identity mapped */ + intsrc.mpc_dstirq = i; + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " + "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, + intsrc.mpc_dstirq); + + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } + + return; +} + +#endif /*CONFIG_X86_IO_APIC*/ + +#ifdef CONFIG_ACPI_PCI + +void __init mp_parse_prt (void) +{ + struct list_head *node = NULL; + struct acpi_prt_entry *entry = NULL; + int vector = 0; + int ioapic = -1; + int ioapic_pin = 0; + int irq = 0; + int idx, bit = 0; + + /* + * Parsing through the PCI Interrupt Routing Table (PRT) and program + * routing for all static (IOAPIC-direct) entries. + */ + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + + /* We're only interested in static (non-link) entries. */ + if (entry->link.handle) + continue; + + irq = entry->link.index; + ioapic = mp_find_ioapic(irq); + if (ioapic < 0) + continue; + ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->irq mappings (but unique PCI devices); + * we only only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + continue; + } + if ((1<irq = irq; + continue; + } + + mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq = irq; + + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> vector 0x%02x" + " -> IRQ %d\n", entry->id.segment, entry->id.bus, + entry->id.device, ('A' + entry->pin), + mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, + entry->irq); + } + + return; +} + +#endif /*CONFIG_ACPI_PCI*/ + +#endif /*CONFIG_ACPI_BOOT*/ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/pci-irq.c linux2.4.21_itanium/arch/i386/kernel/pci-irq.c --- linux2.4.21_itanium.org/arch/i386/kernel/pci-irq.c Wed Jul 23 18:20:47 2003 +++ linux2.4.21_itanium/arch/i386/kernel/pci-irq.c Wed Jul 23 18:28:20 2003 @@ -116,7 +116,7 @@ * Code for querying and setting of IRQ routes on various interrupt routers. */ -static void eisa_set_level_irq(unsigned int irq) +void eisa_set_level_irq(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/pci-pc.c linux2.4.21_itanium/arch/i386/kernel/pci-pc.c --- linux2.4.21_itanium.org/arch/i386/kernel/pci-pc.c Wed Jul 23 18:20:47 2003 +++ linux2.4.21_itanium/arch/i386/kernel/pci-pc.c Wed Jul 23 18:28:23 2003 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,8 @@ #define QUADLOCAL2BUS(quad,local) (local) #endif +static int pci_using_acpi_prt = 0; + /* * This interrupt-safe spinlock protects all accesses to PCI * configuration space. @@ -1353,6 +1356,23 @@ pci_read_bridge_bases(b); } +struct pci_bus * __devinit pcibios_scan_root(int busnum) +{ + struct list_head *list; + struct pci_bus *bus; + + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + if (bus->number == busnum) { + /* Already scanned */ + return bus; + } + } + + printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); + + return pci_scan_bus(busnum, pci_root_ops, NULL); +} void __devinit pcibios_config_init(void) { @@ -1405,20 +1425,26 @@ return; } - printk(KERN_INFO "PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); - if (clustered_apic_mode && (numnodes > 1)) { - for (quad = 1; quad < numnodes; ++quad) { - printk("Scanning PCI bus %d for quad %d\n", - QUADLOCAL2BUS(quad,0), quad); - pci_scan_bus(QUADLOCAL2BUS(quad,0), - pci_root_ops, NULL); +#ifdef CONFIG_ACPI_PCI + if (acpi_pci_irq_init() > 0) + pci_using_acpi_prt = 1; +#endif + if (!pci_using_acpi_prt) { + pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); + if (clustered_apic_mode && (numnodes > 1)) { + for (quad = 1; quad < numnodes; ++quad) { + printk("Scanning PCI bus %d for quad %d\n", + QUADLOCAL2BUS(quad,0), quad); + pci_scan_bus(QUADLOCAL2BUS(quad,0), + pci_root_ops, NULL); + } } + + pcibios_irq_init(); + pcibios_fixup_peer_bridges(); + pcibios_fixup_irqs(); } - pcibios_irq_init(); - pcibios_fixup_peer_bridges(); - pcibios_fixup_irqs(); pcibios_resource_survey(); #ifdef CONFIG_PCI_BIOS @@ -1485,6 +1511,15 @@ if ((err = pcibios_enable_resources(dev, mask)) < 0) return err; + +#ifdef CONFIG_ACPI_PCI + if (pci_using_acpi_prt) { + acpi_pci_irq_enable(dev); + return 0; + } +#endif + pcibios_enable_irq(dev); + return 0; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/i386/kernel/setup.c linux2.4.21_itanium/arch/i386/kernel/setup.c --- linux2.4.21_itanium.org/arch/i386/kernel/setup.c Wed Jul 23 18:20:47 2003 +++ linux2.4.21_itanium/arch/i386/kernel/setup.c Wed Jul 23 18:28:20 2003 @@ -95,6 +95,7 @@ #include #include #include +#include #include #ifdef CONFIG_BLK_DEV_RAM #include @@ -1007,10 +1008,15 @@ */ reserve_bootmem(PAGE_SIZE, PAGE_SIZE); #endif - +#ifdef CONFIG_ACPI_SLEEP + /* + * Reserve low memory region for sleep support. + */ + acpi_reserve_bootmem(); +#endif #ifdef CONFIG_X86_LOCAL_APIC /* - * Find and reserve possible boot-time SMP configuration: + * Find and reserve possible boot-time SMP configuration. */ find_smp_config(); #endif @@ -1154,12 +1160,23 @@ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); + +#ifdef CONFIG_ACPI_BOOT + /* + * Parse the ACPI tables for possible boot-time SMP configuration. + */ + acpi_boot_init(*cmdline_p); +#endif #ifdef CONFIG_X86_LOCAL_APIC /* * get boot-time SMP configuration: */ if (smp_found_config) get_smp_config(); + /* + * Validate APIC configuration and map into corresponding fixmap pages. + */ + init_apic_mappings(); #endif register_memory(max_low_pfn); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/Makefile linux2.4.21_itanium/arch/ia64/Makefile --- linux2.4.21_itanium.org/arch/ia64/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/Makefile Wed Jul 23 18:28:55 2003 @@ -132,6 +132,9 @@ archclean: @$(MAKEBOOT) clean +check: vmlinux + arch/ia64/scripts/unwcheck.sh vmlinux + archmrproper: rm -f arch/$(ARCH)/vmlinux.lds @$(MAKE) -C arch/$(ARCH)/tools mrproper diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/config.in linux2.4.21_itanium/arch/ia64/config.in --- linux2.4.21_itanium.org/arch/ia64/config.in Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/config.in Wed Jul 23 18:28:55 2003 @@ -23,8 +23,8 @@ define_bool CONFIG_EISA n define_bool CONFIG_MCA n define_bool CONFIG_SBUS n -define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y -define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n +define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n +define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y choice 'IA-64 processor type' \ "Itanium CONFIG_ITANIUM \ @@ -86,6 +86,32 @@ define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore. +define_int CONFIG_FORCE_MAX_ZONEORDER 19 + +bool 'IA-64 Huge TLB Page Support' CONFIG_HUGETLB_PAGE + +if [ "$CONFIG_HUGETLB_PAGE" = "y" ]; then + if [ "$CONFIG_MCKINLEY" = "y" ]; then + choice ' IA-64 Huge TLB Page Size' \ + "4GB CONFIG_HUGETLB_PAGE_SIZE_4GB \ + 1GB CONFIG_HUGETLB_PAGE_SIZE_1GB \ + 256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \ + 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \ + 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \ + 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \ + 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \ + 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB + else + choice ' IA-64 Huge TLB Page Size' \ + "256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \ + 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \ + 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \ + 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \ + 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \ + 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB + fi +fi + bool 'SMP support' CONFIG_SMP tristate 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT bool 'Performance monitor support' CONFIG_PERFMON diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/configs/dig linux2.4.21_itanium/arch/ia64/configs/dig --- linux2.4.21_itanium.org/arch/ia64/configs/dig Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/configs/dig Wed Jul 23 18:28:55 2003 @@ -22,8 +22,8 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_ITANIUM=y # CONFIG_MCKINLEY is not set # CONFIG_IA64_GENERIC is not set @@ -41,6 +41,14 @@ CONFIG_IA64_MCA=y CONFIG_PM=y CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y @@ -243,7 +251,7 @@ # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_ADMA100 is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set @@ -257,7 +265,6 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -322,6 +329,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -623,6 +631,7 @@ # # Video Adapters # +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_CPIA is not set # CONFIG_VIDEO_SAA5249 is not set @@ -672,6 +681,7 @@ # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y +CONFIG_HUGETLBFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set @@ -874,6 +884,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/configs/generic linux2.4.21_itanium/arch/ia64/configs/generic --- linux2.4.21_itanium.org/arch/ia64/configs/generic Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/configs/generic Wed Jul 23 18:28:55 2003 @@ -22,8 +22,8 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_ITANIUM=y # CONFIG_MCKINLEY is not set CONFIG_IA64_GENERIC=y @@ -41,6 +41,14 @@ CONFIG_IA64_MCA=y CONFIG_PM=y CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y @@ -243,13 +251,13 @@ # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_ADMA100 is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set # CONFIG_AMD74XX_OVERRIDE is not set -# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_TRIFLEX is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -257,7 +265,6 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -322,6 +329,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -628,6 +636,7 @@ # # Video Adapters # +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_CPIA is not set # CONFIG_VIDEO_SAA5249 is not set @@ -677,6 +686,7 @@ # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y +CONFIG_HUGETLBFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set @@ -879,6 +889,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/configs/ski linux2.4.21_itanium/arch/ia64/configs/ski --- linux2.4.21_itanium.org/arch/ia64/configs/ski Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/configs/ski Wed Jul 23 18:28:55 2003 @@ -22,8 +22,8 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_ITANIUM=y # CONFIG_MCKINLEY is not set # CONFIG_IA64_GENERIC is not set @@ -39,6 +39,14 @@ # CONFIG_ITANIUM_BSTEP_SPECIFIC is not set CONFIG_IA64_L1_CACHE_SHIFT=6 CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y @@ -149,6 +157,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -274,6 +283,7 @@ # # Video Adapters # +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_BWQCAM is not set # CONFIG_VIDEO_CQCAM is not set @@ -326,6 +336,7 @@ # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y +CONFIG_HUGETLBFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/configs/zx1 linux2.4.21_itanium/arch/ia64/configs/zx1 --- linux2.4.21_itanium.org/arch/ia64/configs/zx1 Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/configs/zx1 Wed Jul 23 18:28:55 2003 @@ -22,8 +22,8 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ITANIUM is not set CONFIG_MCKINLEY=y # CONFIG_IA64_GENERIC is not set @@ -40,6 +40,16 @@ CONFIG_IA64_MCA=y CONFIG_PM=y CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y @@ -242,7 +252,7 @@ # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_ADMA100 is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set @@ -256,7 +266,6 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -321,6 +330,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -622,6 +632,7 @@ # # Video Adapters # +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_CPIA is not set # CONFIG_VIDEO_SAA5249 is not set @@ -671,6 +682,7 @@ # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y +CONFIG_HUGETLBFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set @@ -873,6 +885,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/defconfig linux2.4.21_itanium/arch/ia64/defconfig --- linux2.4.21_itanium.org/arch/ia64/defconfig Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/defconfig Wed Jul 23 18:28:55 2003 @@ -22,8 +22,8 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_ITANIUM=y # CONFIG_MCKINLEY is not set CONFIG_IA64_GENERIC=y @@ -41,6 +41,14 @@ CONFIG_IA64_MCA=y CONFIG_PM=y CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set CONFIG_SMP=y CONFIG_IA32_SUPPORT=y CONFIG_PERFMON=y @@ -243,13 +251,13 @@ # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_ADMA100 is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set # CONFIG_AMD74XX_OVERRIDE is not set -# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_TRIFLEX is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -257,7 +265,6 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -322,6 +329,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -628,6 +636,7 @@ # # Video Adapters # +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_CPIA is not set # CONFIG_VIDEO_SAA5249 is not set @@ -677,6 +686,7 @@ # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set CONFIG_RAMFS=y +CONFIG_HUGETLBFS=y CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set @@ -879,6 +889,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/dig/machvec.c linux2.4.21_itanium/arch/ia64/dig/machvec.c --- linux2.4.21_itanium.org/arch/ia64/dig/machvec.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/dig/machvec.c Wed Jul 23 18:28:55 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_HEADER #include diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/dig/setup.c linux2.4.21_itanium/arch/ia64/dig/setup.c --- linux2.4.21_itanium.org/arch/ia64/dig/setup.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/dig/setup.c Wed Jul 23 18:28:55 2003 @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Intel Corp. * Copyright (C) 1999, 2001 Hewlett-Packard Co - * Copyright (C) 1999, 2001 David Mosberger-Tang + * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond * Copyright (C) 1999 Vijay Chander @@ -56,7 +56,7 @@ if (!ia64_boot_param->console_info.num_rows || !ia64_boot_param->console_info.num_cols) { - printk("dig_setup: warning: invalid screen-info, guessing 80x25\n"); + printk(KERN_WARNING "dig_setup: warning: invalid screen-info, guessing 80x25\n"); orig_x = 0; orig_y = 0; num_cols = 80; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/hp/common/sba_iommu.c linux2.4.21_itanium/arch/ia64/hp/common/sba_iommu.c --- linux2.4.21_itanium.org/arch/ia64/hp/common/sba_iommu.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/hp/common/sba_iommu.c Wed Jul 23 18:28:56 2003 @@ -1,8 +1,9 @@ /* ** IA64 System Bus Adapter (SBA) I/O MMU manager ** -** (c) Copyright 2002 Alex Williamson -** (c) Copyright 2002 Hewlett-Packard Company +** (c) Copyright 2002-2003 Alex Williamson +** (c) Copyright 2002-2003 Grant Grundler +** (c) Copyright 2002-2003 Hewlett-Packard Company ** ** Portions (c) 2000 Grant Grundler (from parisc I/O MMU code) ** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) @@ -29,12 +30,14 @@ #include #include #include +#include #include #include #include /* ia64_get_itc() */ #include #include /* PAGE_OFFSET */ +#include /* wmb() */ #define PFX "IOC: " @@ -130,6 +133,7 @@ #define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP) #define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP) +#define SX1000_IOC_ID ((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP) #define ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */ @@ -206,7 +210,7 @@ /* Stuff we don't need in performance path */ struct ioc *next; /* list of IOC's in system */ acpi_handle handle; /* for multiple IOC's */ - const char *name; + char *name; unsigned int func_id; unsigned int rev; /* HW revision of chip */ u32 iov_size; @@ -217,11 +221,15 @@ static struct ioc *ioc_list; static int reserve_sba_gart = 1; -#define sba_sg_address(sg) (sg->address ? sg->address : \ - page_address((sg)->page) + (sg)->offset) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) +#else +#define sba_sg_address(sg) ((sg)->address ? (sg)->address : \ + page_address((sg)->page) + (sg)->offset) +#endif #ifdef FULL_VALID_PDIR -static void* prefetch_spill_page; +static u64 prefetch_spill_page; #endif #define GET_IOC(dev) ((struct ioc *) PCI_CONTROLLER(dev)->iommu) @@ -282,24 +290,23 @@ sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide) { /* start printing from lowest pde in rval */ - u64 *ptr = &(ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]); - unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]); + u64 *ptr = &ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]; + unsigned long *rptr = (unsigned long *) &ioc->res_map[(pide >>3) & -sizeof(unsigned long)]; uint rcnt; - /* printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n", */ - printk("SBA: %s rp %p bit %d rval 0x%lx\n", + printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n", msg, rptr, pide & (BITS_PER_LONG - 1), *rptr); rcnt = 0; while (rcnt < BITS_PER_LONG) { - printk("%s %2d %p %016Lx\n", - (rcnt == (pide & (BITS_PER_LONG - 1))) - ? " -->" : " ", - rcnt, ptr, *ptr ); + printk(KERN_DEBUG "%s %2d %p %016Lx\n", + (rcnt == (pide & (BITS_PER_LONG - 1))) + ? " -->" : " ", + rcnt, ptr, (unsigned long long) *ptr ); rcnt++; ptr++; } - printk("%s", msg); + printk(KERN_DEBUG "%s", msg); } @@ -361,12 +368,13 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { while (nents-- > 0) { - printk(" %d : %08lx/%05x %p\n", - nents, startsg->dma_address, - startsg->dma_length, sba_sg_address(startsg)); + printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents, + startsg->dma_address, startsg->dma_length, + sba_sg_address(startsg)); startsg++; } } + static void sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { @@ -397,7 +405,8 @@ #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir))) +#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | \ + ((hint_reg)<<(ioc->hint_shift_pdir))) #define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase)) /* FIXME : review these macros to verify correctness and usage */ @@ -520,7 +529,8 @@ if (pide >= (ioc->res_size << 3)) { pide = sba_search_bitmap(ioc, pages_needed); if (pide >= (ioc->res_size << 3)) - panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", + ioc->ioc_hpa); } #ifdef ASSERT_PDIR_SANITY @@ -625,7 +635,8 @@ */ #if 1 -#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x8000000000000000ULL) +#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) \ + | 0x8000000000000000ULL) #else void SBA_INLINE sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba) @@ -709,7 +720,7 @@ ** the spill page so devices prefetching won't ** cause a hard fail. */ - ioc->pdir_base[off] = (0x80000000000000FFULL | (u64)prefetch_spill_page); + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); #endif } else { u32 t = get_order(byte_cnt) + PAGE_SHIFT; @@ -724,7 +735,7 @@ /* clear I/O Pdir entry "valid" bit first */ ioc->pdir_base[off] &= ~(0x80000000000000FFULL); #else - ioc->pdir_base[off] = (0x80000000000000FFULL | (u64)prefetch_spill_page); + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); #endif off++; byte_cnt -= IOVP_SIZE; @@ -747,7 +758,7 @@ sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) { struct ioc *ioc; - unsigned long flags; + unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; @@ -816,6 +827,9 @@ size -= IOVP_SIZE; pdir_start++; } + /* force pdir update */ + wmb(); + /* form complete address */ #ifdef ASSERT_PDIR_SANITY sba_check_pdir(ioc,"Check after sba_map_single()"); @@ -840,7 +854,7 @@ #if DELAYED_RESOURCE_CNT > 0 struct sba_dma_pair *d; #endif - unsigned long flags; + unsigned long flags; dma_addr_t offset; ioc = GET_IOC(dev); @@ -932,7 +946,7 @@ ** we don't need the syncdma. The issue here is I/O MMU cachelines ** are *not* coherent in all cases. May be hwrev dependent. ** Need to investigate more. - asm volatile("syncdma"); + asm volatile("syncdma"); */ } @@ -1078,6 +1092,9 @@ } startsg++; } + /* force pdir update */ + wmb(); + #ifdef DEBUG_LARGE_SG_ENTRIES dump_run_sg = 0; #endif @@ -1122,7 +1139,7 @@ int n_mappings = 0; while (nents > 0) { - unsigned long vaddr = (unsigned long) sba_sg_address(startsg); + unsigned long vaddr = (unsigned long) sba_sg_address(startsg); /* ** Prepare for first/next DMA stream @@ -1155,7 +1172,8 @@ ** exceed DMA_CHUNK_SIZE if we coalesce the ** next entry. */ - if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) > DMA_CHUNK_SIZE) + if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) + > DMA_CHUNK_SIZE) break; /* @@ -1214,7 +1232,7 @@ vcontig_sg->dma_length = vcontig_len; dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; ASSERT(dma_len <= DMA_CHUNK_SIZE); - dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG + dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) | dma_offset); n_mappings++; @@ -1233,8 +1251,7 @@ * * See Documentation/DMA-mapping.txt */ -int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, - int direction) +int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) { struct ioc *ioc; int coalesced, filled = 0; @@ -1299,13 +1316,13 @@ ** Access to the virtual address is what forces a two pass algorithm. */ coalesced = sba_coalesce_chunks(ioc, sglist, nents); - + /* ** Program the I/O Pdir ** ** map the virtual addresses to the I/O Pdir ** o dma_address will contain the pdir index - ** o dma_len will contain the number of bytes to map + ** o dma_len will contain the number of bytes to map ** o address contains the virtual address. */ filled = sba_fill_pdir(ioc, sglist, nents); @@ -1371,7 +1388,8 @@ ** were coalesced to a single entry. The stats are fun, ** but speed is more important. */ - ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length + IOVP_SIZE - 1) >> PAGE_SHIFT; + ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length + + IOVP_SIZE - 1) >> PAGE_SHIFT; #endif sglist++; nents--; @@ -1387,12 +1405,6 @@ } -int -sba_dma_supported (struct pci_dev *dev, u64 mask) -{ - return 1; -} - /************************************************************** * * Initialization and claim @@ -1418,19 +1430,6 @@ ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL; ioc->iov_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; - if (ioc->ibase == 0) { - if (((unsigned long) ioc->ioc_hpa & 0x3000UL) == 0x2000) - ioc->ibase = 0xc0000000; - else - ioc->ibase = 0x80000000; - printk("WARNING: IBASE is zero; setting to 0x%lx\n", ioc->ibase); - } - - if (ioc->ibase < 0xfed00000UL && ioc->ibase + ioc->iov_size >= 0xfee00000UL) { - printk("WARNING: IOV space overlaps local config and interrupt message, truncating\n"); - ioc->iov_size /= 2; - } - /* ** iov_order is always based on a 1GB IOVA space since we want to ** turn on the other half for AGP GART. @@ -1438,9 +1437,9 @@ iov_order = get_order(ioc->iov_size >> (IOVP_SHIFT - PAGE_SHIFT)); ioc->pdir_size = (ioc->iov_size / IOVP_SIZE) * sizeof(u64); - DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits) PDIR size 0x%0x\n", - __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20, - iov_order + PAGE_SHIFT, ioc->pdir_size); + DBG_INIT("%s() hpa %p IOV %dMB (%d bits) PDIR size 0x%x\n", + __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20, + iov_order + PAGE_SHIFT, ioc->pdir_size); /* FIXME : DMA HINTs not used */ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; @@ -1520,7 +1519,8 @@ agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); if (agp_found && reserve_sba_gart) { - DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n", __FUNCTION__); + DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n", + __FUNCTION__); ioc->pdir_size /= 2; ((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE; } @@ -1532,26 +1532,27 @@ if (!prefetch_spill_page) { char *spill_poison = "SBAIOMMU POISON"; int poison_size = 16; - void *poison_addr; - - prefetch_spill_page = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE)); - if (!prefetch_spill_page) + void *poison_addr, *addr; + + addr = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE)); + if (!addr) panic(PFX "Couldn't allocate PDIR spill page\n"); - poison_addr = prefetch_spill_page; - for (; (u64)poison_addr < (u64)prefetch_spill_page + IOVP_SIZE ; poison_addr += poison_size) - (void)memcpy(poison_addr,spill_poison,poison_size); + poison_addr = addr; + for ( ; (u64) poison_addr < addr + IOVP_SIZE; poison_addr += poison_size) + memcpy(poison_addr, spill_poison, poison_size); - prefetch_spill_page = (void *)virt_to_phys(prefetch_spill_page); + prefetch_spill_page = virt_to_phys(addr); - DBG_INIT("%s() prefetch spill addr: %p\n", __FUNCTION__, prefetch_spill_page); + DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __FUNCTION__, prefetch_spill_page); } /* ** Set all the PDIR entries valid w/ the spill page as the target */ for (index = 0 ; index < (ioc->pdir_size / sizeof(u64)) ; index++) - ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FFULL | (u64)prefetch_spill_page); + ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page); #endif + } static void __init @@ -1581,7 +1582,8 @@ #ifdef FULL_VALID_PDIR /* Mark the last resource used so we don't prefetch beyond IOVA space */ ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */ - ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FFULL | (u64)prefetch_spill_page); + ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FF + | prefetch_spill_page); #endif DBG_INIT("%s() res_map %x %p\n", __FUNCTION__, @@ -1635,6 +1637,7 @@ static struct ioc_iommu ioc_iommu_info[] __initdata = { { ZX1_IOC_ID, "zx1", ioc_zx1_init }, { REO_IOC_ID, "REO" }, + { SX1000_IOC_ID, "sx1000" }, }; static struct ioc * __init @@ -1701,25 +1704,52 @@ **************************************************************************/ #ifdef CONFIG_PROC_FS +static void * +ioc_start(struct seq_file *s, loff_t *pos) +{ + struct ioc *ioc; + loff_t n = *pos; + + for (ioc = ioc_list; ioc; ioc = ioc->next) + if (!n--) + return ioc; + + return NULL; +} + +static void * +ioc_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct ioc *ioc = v; + + ++*pos; + return ioc->next; +} + +static void +ioc_stop(struct seq_file *s, void *v) +{ +} + static int -sba_proc_info_one(char *buf, struct ioc *ioc) +ioc_show(struct seq_file *s, void *v) { + struct ioc *ioc = v; int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ unsigned long i = 0, avg = 0, min, max; - sprintf(buf, "Hewlett Packard %s IOC rev %d.%d\n", + seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); - sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", - buf, + seq_printf(s, "IO PDIR size : %d bytes (%d entries)\n", (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); - sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, + seq_printf(s, "IO PDIR entries : %ld free %ld used (%d%%)\n", total_pages - ioc->used_pages, ioc->used_pages, (int) (ioc->used_pages * 100 / total_pages)); - - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + + seq_printf(s, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ min = max = ioc->avg_search[0]; for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { @@ -1728,81 +1758,106 @@ if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; } avg /= SBA_SEARCH_SAMPLE; - sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - buf, min, avg, max); + seq_printf(s, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); - sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msingle_calls, ioc->msingle_pages, + seq_printf(s, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_single(): %12ld bypasses\n", - buf, ioc->msingle_bypass); + seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass); #endif - sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usingle_calls, ioc->usingle_pages, + seq_printf(s, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usingle_calls, ioc->usingle_pages, (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_unmap_single: %12ld bypasses\n", - buf, ioc->usingle_bypass); + seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass); #endif - sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msg_calls, ioc->msg_pages, + seq_printf(s, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_sg() : %12ld bypasses\n", - buf, ioc->msg_bypass); + seq_printf(s, "pci_map_sg() : %12ld bypasses\n", ioc->msg_bypass); #endif - sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usg_calls, ioc->usg_pages, + seq_printf(s, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); - return strlen(buf); + return 0; } +static struct seq_operations ioc_seq_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_show +}; + static int -sba_proc_info(char *buf, char **start, off_t offset, int len) +ioc_open(struct inode *inode, struct file *file) { - struct ioc *ioc; - char *base = buf; - - for (ioc = ioc_list; ioc; ioc = ioc->next) { - buf += sba_proc_info_one(buf, ioc); - } - - return strlen(base); + return seq_open(file, &ioc_seq_ops); } +static struct file_operations ioc_fops = { + .open = ioc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + static int -sba_resource_map_one(char *buf, struct ioc *ioc) +ioc_map_show(struct seq_file *s, void *v) { + struct ioc *ioc = v; unsigned int *res_ptr = (unsigned int *)ioc->res_map; int i; - buf[0] = '\0'; - for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { - if ((i & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); - } - strcat(buf, "\n"); + for (i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) + seq_printf(s, "%s%08x", (i & 7) ? " " : "\n ", *res_ptr); + seq_printf(s, "\n"); - return strlen(buf); + return 0; } +static struct seq_operations ioc_map_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_map_show +}; + static int -sba_resource_map(char *buf, char **start, off_t offset, int len) +ioc_map_open(struct inode *inode, struct file *file) { - struct ioc *ioc; - char *base = buf; + return seq_open(file, &ioc_map_ops); +} - for (ioc = ioc_list; ioc; ioc = ioc->next) { - buf += sba_resource_map_one(buf, ioc); - } +static struct file_operations ioc_map_fops = { + .open = ioc_map_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; - return strlen(base); +static void __init +ioc_proc_init(void) +{ + if (ioc_list) { + struct proc_dir_entry *dir, *entry; + + dir = proc_mkdir("bus/mckinley", 0); + entry = create_proc_entry(ioc_list->name, 0, dir); + if (entry) + entry->proc_fops = &ioc_fops; + + entry = create_proc_entry("bitmap", 0, dir); + if (entry) + entry->proc_fops = &ioc_map_fops; + } } #endif @@ -1833,7 +1888,7 @@ handle = parent; } while (ACPI_SUCCESS(status)); - printk("No IOC for %s in ACPI\n", dev->slot_name); + printk(KERN_WARNING "No IOC for %s in ACPI\n", dev->slot_name); } static int __init @@ -1842,31 +1897,23 @@ struct ioc *ioc; acpi_status status; u64 hpa, length; + acpi_device_info dev_info; - /* - * Only SBA appears in ACPI namespace. It encloses the PCI - * root bridges, and its CSR space includes the IOC function. - */ status = acpi_hp_csr_space(device->handle, &hpa, &length); if (ACPI_FAILURE(status)) return 1; - ioc = ioc_init(hpa + ZX1_IOC_OFFSET, device->handle); - if (!ioc) - return 1; - - return 0; -} - -static int __init -acpi_ioc_add(struct acpi_device *device) -{ - struct ioc *ioc; - acpi_status status; - u64 hpa, length; - status = acpi_hp_csr_space(device->handle, &hpa, &length); + status = acpi_get_object_info(device->handle, &dev_info); if (ACPI_FAILURE(status)) return 1; + + /* + * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI + * root bridges, and its CSR space includes the IOC function. + */ + if (strncmp("HWP0001", dev_info.hardware_id, 7) == 0) + hpa += ZX1_IOC_OFFSET; + ioc = ioc_init(hpa, device->handle); if (!ioc) return 1; @@ -1876,40 +1923,19 @@ static struct acpi_driver acpi_sba_ioc_driver = { name: "IOC IOMMU Driver", - ids: "HWP0001", + ids: "HWP0001,HWP0004", ops: { add: acpi_sba_ioc_add, }, }; -static struct acpi_driver acpi_ioc_driver = { - name: "IOC IOMMU Driver", - ids: "HWP0004", - ops: { - add: acpi_ioc_add, - }, -}; - -void __init -ioc_acpi_init(void) -{ - acpi_bus_register_driver(&acpi_sba_ioc_driver); - acpi_bus_register_driver(&acpi_ioc_driver); -} - void __init sba_init(void) { - ioc_acpi_init(); + acpi_bus_register_driver(&acpi_sba_ioc_driver); #ifdef CONFIG_PROC_FS - if (ioc_list) { - struct proc_dir_entry * proc_mckinley_root; - - proc_mckinley_root = proc_mkdir("bus/mckinley",0); - create_proc_info_entry(ioc_list->name, 0, proc_mckinley_root, sba_proc_info); - create_proc_info_entry("bitmap", 0, proc_mckinley_root, sba_resource_map); - } + ioc_proc_init(); #endif } @@ -1920,6 +1946,13 @@ return 1; } +int +sba_dma_supported (struct pci_dev *dev, u64 mask) +{ + /* make sure it's at least 32bit capable */ + return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL); +} + __setup("nosbagart", nosbagart); EXPORT_SYMBOL(sba_init); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_console.c linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_console.c --- linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_console.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_console.c Wed Jul 23 18:28:55 2003 @@ -28,12 +28,12 @@ static kdev_t simcons_console_device (struct console *); struct console hpsim_cons = { - name: "simcons", - write: simcons_write, - device: simcons_console_device, - setup: simcons_init, - flags: CON_PRINTBUFFER, - index: -1, + .name = "simcons", + .write = simcons_write, + .device = simcons_console_device, + .setup = simcons_init, + .flags = CON_PRINTBUFFER, + .index = -1, }; static int diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_irq.c linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_irq.c --- linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_irq.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_irq.c Wed Jul 23 18:28:55 2003 @@ -22,14 +22,14 @@ } static struct hw_interrupt_type irq_type_hp_sim = { - typename: "hpsim", - startup: hpsim_irq_startup, - shutdown: hpsim_irq_noop, - enable: hpsim_irq_noop, - disable: hpsim_irq_noop, - ack: hpsim_irq_noop, - end: hpsim_irq_noop, - set_affinity: (void (*)(unsigned int, unsigned long)) hpsim_irq_noop, + .typename = "hpsim", + .startup = hpsim_irq_startup, + .shutdown = hpsim_irq_noop, + .enable = hpsim_irq_noop, + .disable = hpsim_irq_noop, + .ack = hpsim_irq_noop, + .end = hpsim_irq_noop, + .set_affinity = (void (*)(unsigned int, unsigned long)) hpsim_irq_noop, }; void __init diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_machvec.c linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_machvec.c --- linux2.4.21_itanium.org/arch/ia64/hp/sim/hpsim_machvec.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/hp/sim/hpsim_machvec.c Wed Jul 23 18:28:55 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_HEADER #include diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/hp/zx1/hpzx1_machvec.c linux2.4.21_itanium/arch/ia64/hp/zx1/hpzx1_machvec.c --- linux2.4.21_itanium.org/arch/ia64/hp/zx1/hpzx1_machvec.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/hp/zx1/hpzx1_machvec.c Wed Jul 23 18:28:55 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_HEADER #include diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/ia32/binfmt_elf32.c linux2.4.21_itanium/arch/ia64/ia32/binfmt_elf32.c --- linux2.4.21_itanium.org/arch/ia64/ia32/binfmt_elf32.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/ia32/binfmt_elf32.c Wed Jul 23 18:28:56 2003 @@ -67,7 +67,7 @@ } static struct vm_operations_struct ia32_shared_page_vm_ops = { - nopage: ia32_install_shared_page + .nopage =ia32_install_shared_page }; void diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/ia32/ia32_entry.S linux2.4.21_itanium/arch/ia64/ia32/ia32_entry.S --- linux2.4.21_itanium.org/arch/ia64/ia32/ia32_entry.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/ia32/ia32_entry.S Wed Jul 23 18:28:56 2003 @@ -87,12 +87,19 @@ GLOBAL_ENTRY(ia32_ret_from_clone) PT_REGS_UNWIND_INFO(0) +{ /* + * Some versions of gas generate bad unwind info if the first instruction of a + * procedure doesn't go into the first slot of a bundle. This is a workaround. + */ + nop.m 0 + nop.i 0 /* * We need to call schedule_tail() to complete the scheduling process. * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the * address of the previously executing task. */ br.call.sptk.many rp=ia64_invoke_schedule_tail +} .ret1: adds r2=IA64_TASK_PTRACE_OFFSET,r13 ;; ld8 r2=[r2] diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/ia32/ia32_ioctl.c linux2.4.21_itanium/arch/ia64/ia32/ia32_ioctl.c --- linux2.4.21_itanium.org/arch/ia64/ia32/ia32_ioctl.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/ia32/ia32_ioctl.c Wed Jul 23 18:28:57 2003 @@ -268,6 +268,6 @@ return sys_ioctl(fd, cmd, (unsigned long)arg); } - printk("%x:unimplemented IA32 ioctl system call\n", cmd); + printk(KERN_ERR "%x:unimplemented IA32 ioctl system call\n", cmd); return -EINVAL; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/ia32/sys_ia32.c linux2.4.21_itanium/arch/ia64/ia32/sys_ia32.c --- linux2.4.21_itanium.org/arch/ia64/ia32/sys_ia32.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/ia32/sys_ia32.c Wed Jul 23 18:28:56 2003 @@ -250,9 +250,8 @@ static int -get_page_prot (unsigned long addr) +get_page_prot (struct vm_area_struct *vma, unsigned long addr) { - struct vm_area_struct *vma = find_vma(current->mm, addr); int prot = 0; if (!vma || vma->vm_start > addr) @@ -275,14 +274,26 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int prot, int flags, loff_t off) { - void *page = (void *) get_zeroed_page(GFP_KERNEL); + void *page = NULL; struct inode *inode; - unsigned long ret; - int old_prot = get_page_prot(start); + unsigned long ret = 0; + struct vm_area_struct *vma = find_vma(current->mm, start); + int old_prot = get_page_prot(vma, start); DBG("mmap_subpage(file=%p,start=0x%lx,end=0x%lx,prot=%x,flags=%x,off=0x%llx)\n", file, start, end, prot, flags, off); + + /* Optimize the case where the old mmap and the new mmap are both anonymous */ + if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) { + if (clear_user((void *) start, end - start)) { + ret = -EFAULT; + goto out; + } + goto skip_mmap; + } + + page = (void *) get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; @@ -307,6 +318,7 @@ copy_to_user((void *) end, page + PAGE_OFF(end), PAGE_SIZE - PAGE_OFF(end)); } + if (!(flags & MAP_ANONYMOUS)) { /* read the file contents */ inode = file->f_dentry->d_inode; @@ -317,10 +329,13 @@ goto out; } } + + skip_mmap: if (!(prot & PROT_WRITE)) ret = sys_mprotect(PAGE_START(start), PAGE_SIZE, prot | old_prot); out: - free_page((unsigned long) page); + if (page) + free_page((unsigned long) page); return ret; } @@ -448,7 +463,12 @@ return addr; if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len) + { + if (flags & MAP_FIXED) + return -ENOMEM; + else return -EINVAL; + } if (OFFSET4K(offset)) return -EINVAL; @@ -547,7 +567,7 @@ #if PAGE_SHIFT <= IA32_PAGE_SHIFT ret = sys_munmap(start, end - start); #else - if (start > end) + if (start >= end) return -EINVAL; start = PAGE_ALIGN(start); @@ -576,11 +596,12 @@ mprotect_subpage (unsigned long address, int new_prot) { int old_prot; + struct vm_area_struct *vma; if (new_prot == PROT_NONE) return 0; /* optimize case where nothing changes... */ - - old_prot = get_page_prot(address); + vma = find_vma(current->mm, address); + old_prot = get_page_prot(vma, address); return sys_mprotect(address, PAGE_SIZE, new_prot | old_prot); } @@ -1230,8 +1251,8 @@ #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) struct rlimit32 { - int rlim_cur; - int rlim_max; + unsigned int rlim_cur; + unsigned int rlim_max; }; extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim); @@ -2085,7 +2106,7 @@ }; struct shmid64_ds32 { - struct ipc64_perm shm_perm; + struct ipc64_perm32 shm_perm; __kernel_size_t32 shm_segsz; __kernel_time_t32 shm_atime; unsigned int __unused1; @@ -2167,6 +2188,10 @@ else fourth.__pad = (void *)A(pad); switch (third) { + default: + err = -EINVAL; + break; + case IPC_INFO: case IPC_RMID: case IPC_SET: @@ -2234,7 +2259,7 @@ static int do_sys32_msgsnd (int first, int second, int third, void *uptr) { - struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER); + struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf), GFP_USER); struct msgbuf32 *up = (struct msgbuf32 *)uptr; mm_segment_t old_fs; int err; @@ -2276,12 +2301,12 @@ msgtyp = ipck.msgtyp; } err = -ENOMEM; - p = kmalloc(second + sizeof(struct msgbuf) + 4, GFP_USER); + p = kmalloc(second + sizeof(struct msgbuf), GFP_USER); if (!p) goto out; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_msgrcv(first, p, second + 4, msgtyp, third); + err = sys_msgrcv(first, p, second, msgtyp, third); set_fs(old_fs); if (err < 0) goto free_then_out; @@ -2314,21 +2339,21 @@ case IPC_SET: if (version == IPC_64) { - err = get_user(m.msg_perm.uid, &up64->msg_perm.uid); - err |= get_user(m.msg_perm.gid, &up64->msg_perm.gid); - err |= get_user(m.msg_perm.mode, &up64->msg_perm.mode); - err |= get_user(m.msg_qbytes, &up64->msg_qbytes); + err = get_user(m64.msg_perm.uid, &up64->msg_perm.uid); + err |= get_user(m64.msg_perm.gid, &up64->msg_perm.gid); + err |= get_user(m64.msg_perm.mode, &up64->msg_perm.mode); + err |= get_user(m64.msg_qbytes, &up64->msg_qbytes); } else { - err = get_user(m.msg_perm.uid, &up32->msg_perm.uid); - err |= get_user(m.msg_perm.gid, &up32->msg_perm.gid); - err |= get_user(m.msg_perm.mode, &up32->msg_perm.mode); - err |= get_user(m.msg_qbytes, &up32->msg_qbytes); + err = get_user(m64.msg_perm.uid, &up32->msg_perm.uid); + err |= get_user(m64.msg_perm.gid, &up32->msg_perm.gid); + err |= get_user(m64.msg_perm.mode, &up32->msg_perm.mode); + err |= get_user(m64.msg_qbytes, &up32->msg_qbytes); } if (err) break; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_msgctl(first, second, &m); + err = sys_msgctl(first, second, &m64); set_fs(old_fs); break; @@ -2408,7 +2433,7 @@ shmctl32 (int first, int second, void *uptr) { int err = -EFAULT, err2; - struct shmid_ds s; + struct shmid64_ds s64; struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; @@ -2460,19 +2485,19 @@ case IPC_SET: if (version == IPC_64) { - err = get_user(s.shm_perm.uid, &up64->shm_perm.uid); - err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid); - err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode); + err = get_user(s64.shm_perm.uid, &up64->shm_perm.uid); + err |= get_user(s64.shm_perm.gid, &up64->shm_perm.gid); + err |= get_user(s64.shm_perm.mode, &up64->shm_perm.mode); } else { - err = get_user(s.shm_perm.uid, &up32->shm_perm.uid); - err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid); - err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode); + err = get_user(s64.shm_perm.uid, &up32->shm_perm.uid); + err |= get_user(s64.shm_perm.gid, &up32->shm_perm.gid); + err |= get_user(s64.shm_perm.mode, &up32->shm_perm.mode); } if (err) break; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_shmctl(first, second, &s); + err = sys_shmctl(first, second, &s64); set_fs(old_fs); break; @@ -2590,7 +2615,7 @@ return shmctl32(first, second, (void *)AA(ptr)); default: - return -EINVAL; + return -ENOSYS; } return -EINVAL; } @@ -2924,7 +2949,7 @@ ptp = ia64_task_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) - put_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos); + put_fpreg(i, &save->st_space[i], ptp, swp, tos); return 0; } @@ -2957,7 +2982,7 @@ ptp = ia64_task_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) - get_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos); + get_fpreg(i, &save->st_space[i], ptp, swp, tos); return 0; } @@ -3076,26 +3101,23 @@ ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); + if (child) + get_task_struct(child); read_unlock(&tasklist_lock); if (!child) goto out; ret = -EPERM; if (pid == 1) /* no messing around with init! */ - goto out; + goto out_tsk; if (request == PTRACE_ATTACH) { ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack); - goto out; + goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out; - } - if (child->p_pptr != current) - goto out; + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_tsk; switch (request) { case PTRACE_PEEKTEXT: @@ -3105,12 +3127,12 @@ ret = put_user(value, (unsigned int *) A(data)); else ret = -EIO; - goto out; + goto out_tsk; case PTRACE_POKETEXT: case PTRACE_POKEDATA: /* write the word at location addr */ ret = ia32_poke(regs, child, addr, data); - goto out; + goto out_tsk; case PTRACE_PEEKUSR: /* read word at addr in USER area */ ret = -EIO; @@ -3185,6 +3207,8 @@ break; } + out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; @@ -3407,6 +3431,7 @@ asmlinkage long sys32_sysctl (struct sysctl32 *args) { +#ifdef CONFIG_SYSCTL struct sysctl32 a32; mm_segment_t old_fs = get_fs (); void *oldvalp, *newvalp; @@ -3444,6 +3469,9 @@ return -EFAULT; return ret; +#else + return -ENOSYS; +#endif } asmlinkage long @@ -3707,21 +3735,43 @@ u32 bufferram; u32 totalswap; u32 freeswap; - unsigned short procs; - char _f[22]; + u16 procs; + u16 pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[8]; }; asmlinkage long sys32_sysinfo (struct sysinfo32 *info) { extern asmlinkage long sys_sysinfo (struct sysinfo *); - mm_segment_t old_fs = get_fs(); struct sysinfo s; long ret, err; + int bitcount = 0; + mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_sysinfo(&s); set_fs(old_fs); + /* Check to see if any memory value is too large for 32-bit and + * scale down if needed. + */ + if ((s.totalram >> 32) || (s.totalswap >> 32)) { + while (s.mem_unit < PAGE_SIZE) { + s.mem_unit <<= 1; + bitcount++; + } + s.totalram >>= bitcount; + s.freeram >>= bitcount; + s.sharedram >>= bitcount; + s.bufferram >>= bitcount; + s.totalswap >>= bitcount; + s.freeswap >>= bitcount; + s.totalhigh >>= bitcount; + s.freehigh >>= bitcount; + } if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) return -EFAULT; @@ -3737,6 +3787,9 @@ err |= __put_user(s.totalswap, &info->totalswap); err |= __put_user(s.freeswap, &info->freeswap); err |= __put_user(s.procs, &info->procs); + err |= __put_user(s.totalhigh, &info->totalhigh); + err |= __put_user(s.freehigh, &info->freehigh); + err |= __put_user(s.mem_unit, &info->mem_unit); if (err) return -EFAULT; return ret; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/acpi.c linux2.4.21_itanium/arch/ia64/kernel/acpi.c --- linux2.4.21_itanium.org/arch/ia64/kernel/acpi.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/acpi.c Wed Jul 23 18:28:58 2003 @@ -3,7 +3,7 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999,2000 Walt Drummond - * Copyright (C) 2000, 2002 Hewlett-Packard Co. + * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co. * David Mosberger-Tang * Copyright (C) 2000 Intel Corp. * Copyright (C) 2000,2001 J.I. Lee @@ -51,6 +51,7 @@ asm (".weak iosapic_override_isa_irq"); asm (".weak iosapic_register_platform_intr"); asm (".weak iosapic_init"); +asm (".weak iosapic_system_init"); asm (".weak iosapic_version"); void (*pm_idle) (void); @@ -69,20 +70,20 @@ rsdp_phys = acpi_find_rsdp(); if (!rsdp_phys) { - printk("ACPI 2.0 RSDP not found, default to \"dig\"\n"); + printk(KERN_ERR "ACPI 2.0 RSDP not found, default to \"dig\"\n"); return "dig"; } rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys); if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) { - printk("ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n"); + printk(KERN_ERR "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n"); return "dig"; } xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address); hdr = &xsdt->header; if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) { - printk("ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n"); + printk(KERN_ERR "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n"); return "dig"; } @@ -110,165 +111,88 @@ #ifdef CONFIG_ACPI -static acpi_resource * -acpi_get_crs_next (acpi_buffer *buf, int *offset) -{ - acpi_resource *res; - - if (*offset >= buf->length) - return NULL; +struct acpi_vendor_descriptor { + u8 guid_id; + efi_guid_t guid; +}; + +struct acpi_vendor_info { + struct acpi_vendor_descriptor *descriptor; + u8 *data; + u32 length; +}; - res = (acpi_resource *)((char *) buf->pointer + *offset); - *offset += res->length; - return res; -} - -static acpi_resource_data * -acpi_get_crs_type (acpi_buffer *buf, int *offset, int type) -{ - for (;;) { - acpi_resource *res = acpi_get_crs_next(buf, offset); - if (!res) - return NULL; - if (res->id == type) - return &res->data; - } -} - -static void -acpi_get_crs_addr (acpi_buffer *buf, int type, u64 *base, u64 *length, u64 *tra) -{ - int offset = 0; - acpi_resource_address16 *addr16; - acpi_resource_address32 *addr32; - acpi_resource_address64 *addr64; - - for (;;) { - acpi_resource *res = acpi_get_crs_next(buf, &offset); - if (!res) - return; - switch (res->id) { - case ACPI_RSTYPE_ADDRESS16: - addr16 = (acpi_resource_address16 *) &res->data; - - if (type == addr16->resource_type) { - *base = addr16->min_address_range; - *length = addr16->address_length; - *tra = addr16->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS32: - addr32 = (acpi_resource_address32 *) &res->data; - if (type == addr32->resource_type) { - *base = addr32->min_address_range; - *length = addr32->address_length; - *tra = addr32->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS64: - addr64 = (acpi_resource_address64 *) &res->data; - if (type == addr64->resource_type) { - *base = addr64->min_address_range; - *length = addr64->address_length; - *tra = addr64->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_END_TAG: - return; - break; - } - } +acpi_status +acpi_vendor_resource_match(acpi_resource *resource, void *context) +{ + struct acpi_vendor_info *info = (struct acpi_vendor_info *) context; + acpi_resource_vendor *vendor; + struct acpi_vendor_descriptor *descriptor; + u32 length; + + if (resource->id != ACPI_RSTYPE_VENDOR) + return AE_OK; + + vendor = (acpi_resource_vendor *) &resource->data; + descriptor = (struct acpi_vendor_descriptor *) vendor->reserved; + if (vendor->length <= sizeof(*info->descriptor) || + descriptor->guid_id != info->descriptor->guid_id || + efi_guidcmp(descriptor->guid, info->descriptor->guid)) + return AE_OK; + + length = vendor->length - sizeof(struct acpi_vendor_descriptor); + info->data = acpi_os_allocate(length); + if (!info->data) + return AE_NO_MEMORY; + + memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length); + info->length = length; + return AE_CTRL_TERMINATE; } acpi_status -acpi_get_addr_space(acpi_handle obj, u8 type, u64 *base, u64 *length, u64 *tra) +acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id, + u8 **data, u32 *length) { - acpi_status status; - acpi_buffer buf = { .length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL }; + struct acpi_vendor_info info; - *base = 0; - *length = 0; - *tra = 0; - - status = acpi_get_current_resources(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } + info.descriptor = id; + info.data = 0; - acpi_get_crs_addr(&buf, type, base, length, tra); - - acpi_os_free(buf.pointer); + acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info); + if (!info.data) + return AE_NOT_FOUND; + *data = info.data; + *length = info.length; return AE_OK; } -typedef struct { - u8 guid_id; - u8 guid[16]; - u8 csr_base[8]; - u8 csr_length[8]; -} acpi_hp_vendor_long; - -#define HP_CCSR_LENGTH 0x21 -#define HP_CCSR_TYPE 0x2 -#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ - 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) +struct acpi_vendor_descriptor hp_ccsr_descriptor = { + .guid_id = 2, + .guid = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) +}; acpi_status acpi_hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) { - int i, offset = 0; acpi_status status; - acpi_buffer buf = { .length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL }; - acpi_resource_vendor *res; - acpi_hp_vendor_long *hp_res; - efi_guid_t vendor_guid; - - *csr_base = 0; - *csr_length = 0; - - status = acpi_get_current_resources(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } - - status = AE_NOT_FOUND; - res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); - if (!res) { - printk(KERN_ERR PREFIX "Failed to find config space for device\n"); - goto out; - } - - status = AE_TYPE; /* Revisit error? */ - hp_res = (acpi_hp_vendor_long *)(res->reserved); + u8 *data; + u32 length; + int i; + + status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length); + + if (ACPI_FAILURE(status) || length != 16) + return AE_NOT_FOUND; + + memcpy(csr_base, data, sizeof(*csr_base)); + memcpy(csr_length, data + 8, sizeof(*csr_length)); + acpi_os_free(data); - if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { - printk(KERN_ERR PREFIX "Unknown Vendor data\n"); - goto out; - } - - memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); - if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { - printk(KERN_ERR PREFIX "Vendor GUID does not match\n"); - goto out; - } - - /* It's probably unaligned, so use memcpy */ - memcpy(csr_base, hp_res->csr_base, 8); - memcpy(csr_length, hp_res->csr_length, 8); - status = AE_OK; - - out: - acpi_os_free(buf.pointer); - return status; + return AE_OK; } + #endif /* CONFIG_ACPI */ #ifdef CONFIG_ACPI_BOOT @@ -293,8 +217,7 @@ /* correctable platform error interrupt */ vector = platform_intr_list[int_type]; } else - printk("acpi_request_vector(): invalid interrupt type\n"); - + printk(KERN_ERR "acpi_request_vector(): invalid interrupt type\n"); return vector; } @@ -354,7 +277,7 @@ return 0; } - printk("CPU %d (0x%04x)", total_cpus, phys_id); + printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, phys_id); if (lsapic->flags.enabled) { available_cpus++; @@ -397,40 +320,6 @@ static int __init -acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address) -{ - struct acpi_table_iosapic *iosapic; - int ver; - int max_pin; - char *p; - char *end; - - if (!gsi_base || !iosapic_address) - return -ENODEV; - - p = (char *) (acpi_madt + 1); - end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt)); - - while (p < end) { - if (*p == ACPI_MADT_IOSAPIC) { - iosapic = (struct acpi_table_iosapic *) p; - - *gsi_base = iosapic->global_irq_base; - *iosapic_address = ioremap(iosapic->address, 0); - - ver = iosapic_version(*iosapic_address); - max_pin = (ver >> 16) & 0xff; - - if ((gsi - *gsi_base) <= max_pin) - return 0; /* Found it! */ - } - p += p[1]; - } - return -ENODEV; -} - - -static int __init acpi_parse_iosapic (acpi_table_entry_header *header) { struct acpi_table_iosapic *iosapic; @@ -441,15 +330,9 @@ acpi_table_print_madt_entry(header); - if (iosapic_init) { -#ifndef CONFIG_ITANIUM - iosapic_init(iosapic->address, iosapic->global_irq_base, - has_8259); -#else - /* Firmware on old Itanium systems is broken */ - iosapic_init(iosapic->address, iosapic->global_irq_base, 1); -#endif - } + if (iosapic_init) + iosapic_init(iosapic->address, iosapic->global_irq_base); + return 0; } @@ -459,8 +342,6 @@ { struct acpi_table_plat_int_src *plintsrc; int vector; - u32 gsi_base; - char *iosapic_address; plintsrc = (struct acpi_table_plat_int_src *) header; if (!plintsrc) @@ -473,11 +354,6 @@ return -ENODEV; } - if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) { - printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); - return -ENODEV; - } - /* * Get vector assignment for this interrupt, set attributes, * and program the IOSAPIC routing table. @@ -487,10 +363,8 @@ plintsrc->iosapic_vector, plintsrc->eid, plintsrc->id, - (plintsrc->flags.polarity == 1) ? 1 : 0, - (plintsrc->flags.trigger == 1) ? 1 : 0, - gsi_base, - iosapic_address); + (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; return 0; @@ -513,9 +387,8 @@ return 0; iosapic_override_isa_irq(p->bus_irq, p->global_irq, - (p->flags.polarity == 1) ? 1 : 0, - (p->flags.trigger == 1) ? 1 : 0); - + (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return 0; } @@ -546,7 +419,13 @@ acpi_madt = (struct acpi_table_madt *) __va(phys_addr); /* remember the value for reference after free_initmem() */ +#ifdef CONFIG_ITANIUM + has_8259 = 1; /* Firmware on old Itanium systems is broken */ +#else has_8259 = acpi_madt->flags.pcat_compat; +#endif + if (iosapic_system_init) + iosapic_system_init(has_8259); /* Get base address of IPI Message Block */ @@ -563,8 +442,7 @@ { struct acpi_table_header *fadt_header; fadt_descriptor_rev2 *fadt; - u32 sci_irq, gsi_base; - char *iosapic_address; + u32 sci_irq; if (!phys_addr || !size) return -EINVAL; @@ -587,9 +465,7 @@ if (!iosapic_register_intr) return -ENODEV; - if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address)) - iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address); - + iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); return 0; } @@ -676,13 +552,13 @@ #ifdef CONFIG_SMP if (available_cpus == 0) { - printk("ACPI: Found 0 CPUS; assuming 1\n"); + printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); available_cpus = 1; /* We've got at least one of these, no? */ } smp_boot_data.cpu_count = total_cpus; #endif /* Make boot-up look pretty */ - printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); + printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); return 0; } @@ -690,6 +566,7 @@ /* -------------------------------------------------------------------------- PCI Interrupt Routing -------------------------------------------------------------------------- */ +#ifdef CONFIG_PCI int __init acpi_get_prt (struct pci_vector_struct **vectors, int *count) @@ -732,7 +609,7 @@ *count = acpi_prt.count; return 0; } - +#endif /* Assume IA64 always use I/O SAPIC */ int __init @@ -754,4 +631,21 @@ return gsi_to_vector(irq); } +int +acpi_register_irq (u32 gsi, u32 polarity, u32 mode) +{ + int vector = 0; + + if (has_8259 && gsi < 16) + return isa_irq_to_vector(gsi); + + if (!iosapic_register_intr) + return 0; + + /* Turn it on */ + vector = iosapic_register_intr(gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + mode ? IOSAPIC_EDGE : IOSAPIC_LEVEL); + return vector; +} + #endif /* CONFIG_ACPI_BOOT */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/brl_emu.c linux2.4.21_itanium/arch/ia64/kernel/brl_emu.c --- linux2.4.21_itanium.org/arch/ia64/kernel/brl_emu.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/brl_emu.c Wed Jul 23 18:28:58 2003 @@ -55,11 +55,11 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec) { unsigned long bundle[2]; - unsigned long opcode, btype, qp, offset; + unsigned long opcode, btype, qp, offset, cpl; unsigned long next_ip; struct siginfo siginfo; struct illegal_op_return rv; - int tmp_taken, unimplemented_address; + long tmp_taken, unimplemented_address; rv.fkt = (unsigned long) -1; @@ -158,9 +158,9 @@ * AR[PFS].pec = AR[EC] * AR[PFS].ppl = PSR.cpl */ + cpl = ia64_psr(regs)->cpl; regs->ar_pfs = ((regs->cr_ifs & 0x3fffffffff) - | (ar_ec << 52) - | ((unsigned long) ia64_psr(regs)->cpl << 62)); + | (ar_ec << 52) | (cpl << 62)); /* * CFM.sof -= CFM.sol @@ -195,7 +195,7 @@ /* * The target address contains unimplemented bits. */ - printk("Woah! Unimplemented Instruction Address Trap!\n"); + printk(KERN_DEBUG "Woah! Unimplemented Instruction Address Trap!\n"); siginfo.si_signo = SIGILL; siginfo.si_errno = 0; siginfo.si_flags = 0; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/efi.c linux2.4.21_itanium/arch/ia64/kernel/efi.c --- linux2.4.21_itanium.org/arch/ia64/kernel/efi.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/efi.c Wed Jul 23 18:28:58 2003 @@ -5,7 +5,7 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond - * Copyright (C) 1999-2002 Hewlett-Packard Co. + * Copyright (C) 1999-2003 Hewlett-Packard Co. * David Mosberger-Tang * Stephane Eranian * @@ -365,7 +365,7 @@ prev_valid = 1; } else { if (curr.start < prev.start) - printk("Oops: EFI memory table not ordered!\n"); + printk(KERN_ERR "Oops: EFI memory table not ordered!\n"); if (prev.end == curr.start) { /* merge two consecutive memory ranges */ @@ -437,7 +437,8 @@ * dedicated ITR for the PAL code. */ if ((vaddr & mask) == (KERNEL_START & mask)) { - printk("%s: no need to install ITR for PAL code\n", __FUNCTION__); + printk(KERN_INFO "%s: no need to install ITR for PAL code\n", + __FUNCTION__); continue; } @@ -445,7 +446,7 @@ panic("Woah! PAL code size bigger than a granule!"); mask = ~((1 << IA64_GRANULE_SHIFT) - 1); - printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", + printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", smp_processor_id(), md->phys_addr, md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); @@ -488,7 +489,7 @@ } } if (mem_limit != ~0UL) - printk("Ignoring memory above %luMB\n", mem_limit >> 20); + printk(KERN_INFO "Ignoring memory above %luMB\n", mem_limit >> 20); efi.systab = __va(ia64_boot_param->efi_systab); @@ -500,7 +501,7 @@ if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) panic("Woah! EFI system table signature incorrect\n"); if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0) - printk("Warning: EFI system table major version mismatch: " + printk(KERN_WARNING "Warning: EFI system table major version mismatch: " "got %d.%02d, expected %d.%02d\n", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff); @@ -515,7 +516,7 @@ vendor[i] = '\0'; } - printk("EFI v%u.%.02u by %s:", + printk(KERN_INFO "EFI v%u.%.02u by %s:", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); for (i = 0; i < efi.systab->nr_tables; i++) { @@ -607,7 +608,7 @@ | _PAGE_PL_0 | _PAGE_AR_RW)); #else - printk("EFI_MEMORY_WC mapping\n"); + printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); md->virt_addr = (u64) ioremap(md->phys_addr, 0); #endif } else if (md->attribute & EFI_MEMORY_WT) { @@ -617,7 +618,7 @@ | _PAGE_PL_0 | _PAGE_AR_RW)); #else - printk("EFI_MEMORY_WT mapping\n"); + printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); md->virt_addr = (u64) ioremap(md->phys_addr, 0); #endif } @@ -629,7 +630,7 @@ efi_desc_size, ia64_boot_param->efi_memdesc_version, ia64_boot_param->efi_memmap); if (status != EFI_SUCCESS) { - printk("Warning: unable to switch EFI into virtual mode (status=0x%lx)\n", status); + printk(KERN_WARNING "warning: unable to switch EFI into virtual mode (status=0x%lx)\n", status); return; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/efivars.c linux2.4.21_itanium/arch/ia64/kernel/efivars.c --- linux2.4.21_itanium.org/arch/ia64/kernel/efivars.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/efivars.c Wed Jul 23 18:28:58 2003 @@ -29,6 +29,9 @@ * * Changelog: * + * 10 Dec 2002 - Matt Domsch + * fix locking per Peter Chubb's findings + * * 25 Mar 2002 - Matt Domsch * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse() * @@ -73,7 +76,7 @@ MODULE_DESCRIPTION("/proc interface to EFI Variables"); MODULE_LICENSE("GPL"); -#define EFIVARS_VERSION "0.05 2002-Mar-26" +#define EFIVARS_VERSION "0.06 2002-Dec-10" static int efivar_read(char *page, char **start, off_t off, @@ -106,6 +109,14 @@ struct list_head list; } efivar_entry_t; +/* + efivars_lock protects two things: + 1) efivar_list - adds, removals, reads, writes + 2) efi.[gs]et_variable() calls. + It must not be held when creating proc entries or calling kmalloc. + efi.get_next_variable() is only called from efivars_init(), + which is protected by the BKL, so that path is safe. +*/ static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(efivar_list); static struct proc_dir_entry *efi_vars_dir = NULL; @@ -150,6 +161,7 @@ * variable_name_size = number of bytes required to hold * variable_name (not counting the NULL * character at the end. + * efivars_lock is not held on entry or exit. * Returns 1 on failure, 0 on success */ static int @@ -157,13 +169,14 @@ efi_char16_t *variable_name, efi_guid_t *vendor_guid) { - int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; - char *short_name = kmalloc(short_name_size+1, - GFP_KERNEL); - efivar_entry_t *new_efivar = kmalloc(sizeof(efivar_entry_t), - GFP_KERNEL); + char *short_name; + efivar_entry_t *new_efivar; + + short_name = kmalloc(short_name_size+1, GFP_KERNEL); + new_efivar = kmalloc(sizeof(efivar_entry_t), GFP_KERNEL); + if (!short_name || !new_efivar) { if (short_name) kfree(short_name); if (new_efivar) kfree(new_efivar); @@ -188,19 +201,18 @@ *(short_name + strlen(short_name)) = '-'; efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); - /* Create the entry in proc */ new_efivar->entry = create_proc_entry(short_name, 0600, efi_vars_dir); kfree(short_name); short_name = NULL; if (!new_efivar->entry) return 1; - new_efivar->entry->data = new_efivar; new_efivar->entry->read_proc = efivar_read; new_efivar->entry->write_proc = efivar_write; + spin_lock(&efivars_lock); list_add(&new_efivar->list, &efivar_list); - + spin_unlock(&efivars_lock); return 0; } @@ -326,6 +338,8 @@ kfree(efivar); } + spin_unlock(&efivars_lock); + /* If this is a new variable, set up the proc entry for it. */ if (!found) { efivar_create_proc_entry(utf8_strsize(var_data->VariableName, @@ -336,36 +350,96 @@ kfree(var_data); MOD_DEC_USE_COUNT; - spin_unlock(&efivars_lock); return size; } +/* + * The EFI system table contains pointers to the SAL system table, + * HCDP, ACPI, SMBIOS, etc, that may be useful to applications. + */ +static ssize_t +efi_systab_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + void *data; + u8 *proc_buffer; + ssize_t size, length; + int ret; + const int max_nr_entries = 7; /* num ptrs to tables we could expose */ + const int max_line_len = 80; + + if (!efi.systab) + return 0; + + proc_buffer = kmalloc(max_nr_entries * max_line_len, GFP_KERNEL); + if (!proc_buffer) + return -ENOMEM; + + length = 0; + if (efi.mps) + length += sprintf(proc_buffer + length, "MPS=0x%lx\n", __pa(efi.mps)); + if (efi.acpi20) + length += sprintf(proc_buffer + length, "ACPI20=0x%lx\n", __pa(efi.acpi20)); + if (efi.acpi) + length += sprintf(proc_buffer + length, "ACPI=0x%lx\n", __pa(efi.acpi)); + if (efi.smbios) + length += sprintf(proc_buffer + length, "SMBIOS=0x%lx\n", __pa(efi.smbios)); + if (efi.sal_systab) + length += sprintf(proc_buffer + length, "SAL=0x%lx\n", __pa(efi.sal_systab)); + if (efi.hcdp) + length += sprintf(proc_buffer + length, "HCDP=0x%lx\n", __pa(efi.hcdp)); + if (efi.boot_info) + length += sprintf(proc_buffer + length, "BOOTINFO=0x%lx\n", __pa(efi.boot_info)); + + if (*ppos >= length) { + ret = 0; + goto out; + } + data = proc_buffer + file->f_pos; + size = length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, data, size)) { + ret = -EFAULT; + goto out; + } + + *ppos += size; + ret = size; + +out: + kfree(proc_buffer); + return ret; +} + +static struct proc_dir_entry *efi_systab_entry; +static struct file_operations efi_systab_fops = { + .read = efi_systab_read, +}; static int __init efivars_init(void) { - efi_status_t status; efi_guid_t vendor_guid; efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL); unsigned long variable_name_size = 1024; - spin_lock(&efivars_lock); - printk(KERN_INFO "EFI Variables Facility v%s\n", EFIVARS_VERSION); - /* Since efi.c happens before procfs is available, - we create the directory here if it doesn't - already exist. There's probably a better way - to do this. - */ - if (!efi_dir) + /* Since efi.c happens before procfs is available, + we create the directory here if it doesn't + already exist. There's probably a better way + to do this. + */ + if (!efi_dir) efi_dir = proc_mkdir("efi", NULL); - efi_vars_dir = proc_mkdir("vars", efi_dir); - + efi_systab_entry = create_proc_entry("systab", S_IRUSR | S_IRGRP, efi_dir); + if (efi_systab_entry) + efi_systab_entry->proc_fops = &efi_systab_fops; + efi_vars_dir = proc_mkdir("vars", efi_dir); /* Per EFI spec, the maximum storage allocated for both the variable name and variable data is 1024 bytes. @@ -398,7 +472,6 @@ } while (status != EFI_NOT_FOUND); kfree(variable_name); - spin_unlock(&efivars_lock); return 0; } @@ -409,16 +482,17 @@ efivar_entry_t *efivar; spin_lock(&efivars_lock); - + if (efi_systab_entry) + remove_proc_entry(efi_systab_entry->name, efi_dir); list_for_each_safe(pos, n, &efivar_list) { efivar = efivar_entry(pos); remove_proc_entry(efivar->entry->name, efi_vars_dir); list_del(&efivar->list); kfree(efivar); } - remove_proc_entry(efi_vars_dir->name, efi_dir); spin_unlock(&efivars_lock); + remove_proc_entry(efi_vars_dir->name, efi_dir); } module_init(efivars_init); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/entry.S linux2.4.21_itanium/arch/ia64/kernel/entry.S --- linux2.4.21_itanium.org/arch/ia64/kernel/entry.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/entry.S Wed Jul 23 18:28:58 2003 @@ -161,7 +161,7 @@ mov r8=r13 // return pointer to previously running task mov r13=in0 // set "current" pointer ;; -(p6) ssm psr.i // renable psr.i AFTER the ic bit is serialized + ssm psr.i // renable psr.i AFTER the ic bit is serialized DO_LOAD_SWITCH_STACK #ifdef CONFIG_SMP @@ -454,7 +454,14 @@ GLOBAL_ENTRY(ia64_trace_syscall) PT_REGS_UNWIND_INFO(0) +{ /* + * Some versions of gas generate bad unwind info if the first instruction of a + * procedure doesn't go into the first slot of a bundle. This is a workaround. + */ + nop.m 0 + nop.i 0 br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args +} .ret6: br.call.sptk.many rp=b6 // do the syscall strace_check_retval: cmp.lt p6,p0=r8,r0 // syscall failed? @@ -484,12 +491,19 @@ GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0) +{ /* + * Some versions of gas generate bad unwind info if the first instruction of a + * procedure doesn't go into the first slot of a bundle. This is a workaround. + */ + nop.m 0 + nop.i 0 /* * We need to call schedule_tail() to complete the scheduling process. * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the * address of the previously executing task. */ br.call.sptk.many rp=ia64_invoke_schedule_tail +} .ret8: adds r2=IA64_TASK_PTRACE_OFFSET,r13 ;; @@ -652,7 +666,7 @@ * NOTE: alloc, loadrs, and cover can't be predicated. */ (pNonSys) br.cond.dpnt dont_preserve_current_frame - cover // add current frame into dirty partition + cover // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointer sub r16=r16,r18 // krbs = old bsp - size of dirty partition @@ -678,24 +692,12 @@ # define Nregs 14 #endif alloc loc0=ar.pfs,2,Nregs-2,2,0 - shr.u loc1=r18,9 // RNaTslots <= dirtySize / (64*8) + 1 + shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize ;; -#if 1 - .align 32 // see comment below about gas bug... -#endif mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" shladd in0=loc1,3,r17 mov in1=0 -#if 0 - // gas-2.11.90 is unable to generate a stop bit after .align, which is bad, - // because alloc must be at the beginning of an insn-group. - .align 32 -#else - nop 0 - nop 0 - nop 0 -#endif ;; rse_clear_invalid: #ifdef CONFIG_ITANIUM @@ -737,13 +739,13 @@ ;; mov loc3=0 mov loc4=0 - mov loc9=0 mov loc5=0 mov loc6=0 + mov loc7=0 (pRecurse) br.call.sptk.many b6=rse_clear_invalid ;; - mov loc7=0 mov loc8=0 + mov loc9=0 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret mov loc10=0 mov loc11=0 @@ -848,13 +850,14 @@ mov r9=ar.unat mov loc0=rp // save return address mov out0=0 // there is no "oldset" - adds out1=0,sp // out1=&sigscratch + adds out1=8,sp // out1=&sigscratch->ar_pfs (pSys) mov out2=1 // out2==1 => we're in a syscall ;; (pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch .body br.call.sptk.many rp=ia64_do_signal .ret15: .restore sp @@ -875,11 +878,12 @@ mov loc0=rp // save return address mov out0=in0 // mask mov out1=in1 // sigsetsize - adds out2=0,sp // out2=&sigscratch + adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch .body br.call.sptk.many rp=ia64_rt_sigsuspend .ret17: .restore sp @@ -915,17 +919,16 @@ END(sys_rt_sigreturn) GLOBAL_ENTRY(ia64_prepare_handle_unaligned) - // - // r16 = fake ar.pfs, we simply need to make sure - // privilege is still 0 - // - mov r16=r0 .prologue + /* + * r16 = fake ar.pfs, we simply need to make sure privilege is still 0 + */ + mov r16=r0 DO_SAVE_SWITCH_STACK - br.call.sptk.many rp=ia64_handle_unaligned // stack frame setup in ivt + br.call.sptk.many rp=ia64_handle_unaligned // stack frame setup in ivt .ret21: .body DO_LOAD_SWITCH_STACK - br.cond.sptk.many rp // goes to ia64_leave_kernel + br.cond.sptk.many rp // goes to ia64_leave_kernel END(ia64_prepare_handle_unaligned) // diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/gate.S linux2.4.21_itanium/arch/ia64/kernel/gate.S --- linux2.4.21_itanium.org/arch/ia64/kernel/gate.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/gate.S Wed Jul 23 18:28:57 2003 @@ -63,15 +63,19 @@ * call stack. */ +#define SIGTRAMP_SAVES \ + .unwabi @svr4, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \ + .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \ + .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \ + .savesp pr, PR_OFF+SIGCONTEXT_OFF; \ + .savesp rp, RP_OFF+SIGCONTEXT_OFF; \ + .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \ + .vframesp SP_OFF+SIGCONTEXT_OFF + GLOBAL_ENTRY(ia64_sigtramp) // describe the state that is active when we get here: .prologue - .unwabi @svr4, 's' // mark this as a sigtramp handler (saves scratch regs) - .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF - .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF - .savesp pr, PR_OFF+SIGCONTEXT_OFF - .savesp rp, RP_OFF+SIGCONTEXT_OFF - .vframesp SP_OFF+SIGCONTEXT_OFF + SIGTRAMP_SAVES .body .label_state 1 @@ -89,9 +93,7 @@ .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF (p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16) back_from_setup_rbs: - - .spillreg ar.pfs, r8 - alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8 + alloc r8=ar.pfs,0,0,3,0 ld8 out0=[base0],16 // load arg0 (signum) adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1 ;; @@ -100,17 +102,12 @@ ;; ld8 out2=[base0] // load arg2 (sigcontextp) ld8 gp=[r17] // get signal handler's global pointer - adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF - st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp - dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits - adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp - ;; - .spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF - st8 [base0]=r8 // save CFM0 + st8 [base0]=r9 // save sc_ar_bsp adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp + adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp ;; stf.spill [base0]=f6,32 stf.spill [base1]=f7,32 @@ -133,7 +130,6 @@ ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp ;; - ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0 cmp.ne p8,p0=r14,r15 // do we need to restore the rbs? (p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) ;; @@ -156,10 +152,11 @@ ldf.fill f14=[base0],32 ldf.fill f15=[base1],32 mov r15=__NR_rt_sigreturn + .restore sp // pop .prologue break __BREAK_SYSCALL - .body - .copy_state 1 + .prologue + SIGTRAMP_SAVES setup_rbs: mov ar.rsc=0 // put RSE into enforced lazy mode ;; @@ -171,6 +168,7 @@ ;; .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF st8 [r14]=r16 // save sc_ar_rnat + .body adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp mov.m r16=ar.bsp // sc_loadrs <- (new bsp - new bspstore) << 16 @@ -182,10 +180,11 @@ ;; st8 [r14]=r15 // save sc_loadrs mov ar.rsc=0xf // set RSE into eager mode, pl 3 + .restore sp // pop .prologue br.cond.sptk back_from_setup_rbs .prologue - .copy_state 1 + SIGTRAMP_SAVES .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF .body restore_rbs: diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/ia64_ksyms.c linux2.4.21_itanium/arch/ia64/kernel/ia64_ksyms.c --- linux2.4.21_itanium.org/arch/ia64/kernel/ia64_ksyms.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/ia64_ksyms.c Wed Jul 23 21:14:27 2003 @@ -4,6 +4,9 @@ #include #include +#include +EXPORT_SYMBOL(pm_idle); + #include EXPORT_SYMBOL_NOVERS(memset); @@ -47,6 +50,7 @@ EXPORT_SYMBOL(__ia64_memcpy_fromio); EXPORT_SYMBOL(__ia64_memcpy_toio); EXPORT_SYMBOL(__ia64_memset_c_io); +EXPORT_SYMBOL(io_space); #include EXPORT_SYMBOL_NOVERS(__down); @@ -165,3 +169,21 @@ EXPORT_SYMBOL(pfm_install_alternate_syswide_subsystem); EXPORT_SYMBOL(pfm_remove_alternate_syswide_subsystem); #endif + +#if defined(CONFIG_ETHERPM_RWCP) || defined(CONFIG_ETHERPM_RWCP_MODULE) +EXPORT_SYMBOL(__pmd_alloc); +EXPORT_SYMBOL(ia64_ctx); +EXPORT_SYMBOL(wrap_mmu_context); +#endif +#if defined(CONFIG_PM_MEMORY) || defined(CONFIG_PM_MEMORY_MODULE) +#ifdef CONFIG_SMP +EXPORT_SYMBOL(smp_flush_tlb_mm); +#endif +#endif +#if defined(CONFIG_ETHERPM_RWCP) || defined(CONFIG_ETHERPM_RWCP_MODULE) || defined(CONFIG_PM_MEMORY) || defined(CONFIG_PM_MEMORY_MODULE) +extern unsigned int +csum_partial_copy_from_user(const char *src, char *dst, int len, + unsigned int sum, int *errp); + +EXPORT_SYMBOL(csum_partial_copy_from_user); +#endif diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/iosapic.c linux2.4.21_itanium/arch/ia64/kernel/iosapic.c --- linux2.4.21_itanium.org/arch/ia64/kernel/iosapic.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/iosapic.c Wed Jul 23 18:28:57 2003 @@ -4,7 +4,7 @@ * Copyright (C) 1999 Intel Corp. * Copyright (C) 1999 Asit Mallick * Copyright (C) 2000-2002 J.I. Lee - * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co. + * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co. * David Mosberger-Tang * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999,2000 Walt Drummond @@ -28,6 +28,9 @@ * 02/07/29 T. Kochi Allocate interrupt vectors dynamically * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) * 02/08/13 B. Helgaas Support PCI segments + * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. + * Remove iosapic_address & gsi_base from external interfaces. + * Rationalize __init/__devinit attributes. */ /* * Here is what the interrupt logic between a PCI device and the CPU looks like: @@ -63,14 +66,14 @@ */ #include -#include +#include #include +#include +#include #include #include #include #include -#include -#include #include #include @@ -83,7 +86,6 @@ #undef DEBUG_INTERRUPT_ROUTING -#undef OVERRIDE_DEBUG #ifdef DEBUG_INTERRUPT_ROUTING #define DBG(fmt...) printk(fmt) @@ -115,23 +117,26 @@ char *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */ - unsigned char pcat_compat; /* 8259 compatibility flag */ -} iosapic_lists[256] __devinitdata; +} iosapic_lists[256]; -static int __devinitdata num_iosapic = 0; +static int num_iosapic; + +static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ /* * Find an IOSAPIC associated with a GSI */ -static inline int __devinit +static inline int find_iosapic (unsigned int gsi) { int i; - for (i = 0; i < num_iosapic; i++) + for (i = 0; i < num_iosapic; i++) { if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte) return i; + } + return -1; } @@ -159,6 +164,8 @@ int rte_index; char redir; + DBG(KERN_DEBUG "IOSAPIC: routing vector %d to 0x%x\n", vector, dest); + rte_index = iosapic_intr_info[vector].rte_index; if (rte_index < 0) return; /* not an IOSAPIC interrupt */ @@ -171,7 +178,7 @@ redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; #ifdef CONFIG_SMP { - int irq; + unsigned int irq; for (irq = 0; irq < NR_IRQS; ++irq) if (irq_to_vector(irq) == vector) { @@ -333,14 +340,14 @@ #define iosapic_ack_level_irq nop struct hw_interrupt_type irq_type_iosapic_level = { - typename: "IO-SAPIC-level", - startup: iosapic_startup_level_irq, - shutdown: iosapic_shutdown_level_irq, - enable: iosapic_enable_level_irq, - disable: iosapic_disable_level_irq, - ack: iosapic_ack_level_irq, - end: iosapic_end_level_irq, - set_affinity: iosapic_set_affinity + .typename = "IO-SAPIC-level", + .startup = iosapic_startup_level_irq, + .shutdown = iosapic_shutdown_level_irq, + .enable = iosapic_enable_level_irq, + .disable = iosapic_disable_level_irq, + .ack = iosapic_ack_level_irq, + .end = iosapic_end_level_irq, + .set_affinity = iosapic_set_affinity }; /* @@ -377,14 +384,14 @@ #define iosapic_end_edge_irq nop struct hw_interrupt_type irq_type_iosapic_edge = { - typename: "IO-SAPIC-edge", - startup: iosapic_startup_edge_irq, - shutdown: iosapic_disable_edge_irq, - enable: iosapic_enable_edge_irq, - disable: iosapic_disable_edge_irq, - ack: iosapic_ack_edge_irq, - end: iosapic_end_edge_irq, - set_affinity: iosapic_set_affinity + .typename = "IO-SAPIC-edge", + .startup = iosapic_startup_edge_irq, + .shutdown = iosapic_disable_edge_irq, + .enable = iosapic_enable_edge_irq, + .disable = iosapic_disable_edge_irq, + .ack = iosapic_ack_edge_irq, + .end = iosapic_end_edge_irq, + .set_affinity = iosapic_set_affinity }; unsigned int @@ -407,7 +414,7 @@ * if the given vector is already owned by other, * assign a new vector for the other and make the vector available */ -static void +static void __init iosapic_reassign_vector (int vector) { int new_vector; @@ -417,67 +424,52 @@ || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger) { new_vector = ia64_alloc_vector(); - printk("Reassigning Vector %d to %d\n", vector, new_vector); - memcpy (&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], - sizeof(struct iosapic_intr_info)); - memset (&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); + printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); + memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], + sizeof(struct iosapic_intr_info)); + memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); iosapic_intr_info[vector].rte_index = -1; } } static void register_intr (unsigned int gsi, int vector, unsigned char delivery, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { irq_desc_t *idesc; struct hw_interrupt_type *irq_type; int rte_index; + int index; + unsigned long gsi_base; + char *iosapic_address; + + index = find_iosapic(gsi); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi); + return; + } + + iosapic_address = iosapic_lists[index].addr; + gsi_base = iosapic_lists[index].gsi_base; rte_index = gsi - gsi_base; iosapic_intr_info[vector].rte_index = rte_index; - iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; + iosapic_intr_info[vector].polarity = polarity; iosapic_intr_info[vector].dmode = delivery; + iosapic_intr_info[vector].addr = iosapic_address; + iosapic_intr_info[vector].gsi_base = gsi_base; + iosapic_intr_info[vector].trigger = trigger; - /* - * In override, it may not provide addr/gsi_base. GSI is enough to - * locate iosapic addr, gsi_base and rte_index by examining - * gsi_base and num_rte of registered iosapics (tbd) - */ -#ifndef OVERRIDE_DEBUG - if (iosapic_address) { - iosapic_intr_info[vector].addr = iosapic_address; - iosapic_intr_info[vector].gsi_base = gsi_base; - } -#else - if (iosapic_address) { - if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address)) - printk("WARN: %s: diff IOSAPIC ADDRESS for GSI 0x%x, vector %d\n", - __FUNCTION__, gsi, vector); - iosapic_intr_info[vector].addr = iosapic_address; - if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) { - printk("WARN: %s: diff GSI base 0x%x for GSI 0x%x, vector %d\n", - __FUNCTION__, gsi_base, gsi, vector); - } - iosapic_intr_info[vector].gsi_base = gsi_base; - } else if (!iosapic_intr_info[vector].addr) - printk("WARN: %s: invalid override for GSI 0x%x, vector %d\n", - __FUNCTION__, gsi, vector); -#endif - if (edge_triggered) { - iosapic_intr_info[vector].trigger = IOSAPIC_EDGE; + if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; - } else { - iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL; + else irq_type = &irq_type_iosapic_level; - } idesc = irq_desc(vector); if (idesc->handler != irq_type) { if (idesc->handler != &no_irq_type) - printk("%s: changing vector %d from %s to %s\n", - __FUNCTION__, vector, idesc->handler->typename, - irq_type->typename); + printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", + __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); idesc->handler = irq_type; } } @@ -489,8 +481,7 @@ */ int iosapic_register_intr (unsigned int gsi, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; @@ -500,11 +491,11 @@ vector = ia64_alloc_vector(); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, edge_triggered, gsi_base, iosapic_address); + polarity, trigger); - printk("GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", + gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -515,11 +506,10 @@ * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */ -int +int __init iosapic_register_platform_intr (u32 int_type, unsigned int gsi, int iosapic_vector, u16 eid, u16 id, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { unsigned char delivery; int vector; @@ -544,17 +534,16 @@ delivery = IOSAPIC_LOWEST_PRIORITY; break; default: - printk("%s: invalid interrupt type (%d)\n", __FUNCTION__, + printk(KERN_ERR "%s: invalid interrupt type (%d)\n", __FUNCTION__, int_type); return -1; } - register_intr(gsi, vector, delivery, polarity, - edge_triggered, gsi_base, iosapic_address); + register_intr(gsi, vector, delivery, polarity, trigger); - printk("PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - int_type, gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", + int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -566,32 +555,20 @@ * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */ -void +void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, - unsigned long polarity, unsigned long edge_triggered) + unsigned long polarity, unsigned long trigger) { - int index, vector; - unsigned int gsi_base; - char *addr; + int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; - index = find_iosapic(gsi); - - if (index < 0) { - printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi); - return; - } - vector = isa_irq_to_vector(isa_irq); - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered, - gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); - DBG("ISA: IRQ %u -> GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", + DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", isa_irq, gsi, - polarity ? "high" : "low", edge_triggered ? "edge" : "level", + polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); /* program the IOSAPIC routing table */ @@ -624,13 +601,11 @@ static int pci_pin_to_vector (int segment, int bus, int slot, int pci_pin) { - int index, vector; - int gsi_base, pcat_compat; - char *addr; + int vector; unsigned int gsi; if (pci_pin_to_gsi(segment, bus, slot, pci_pin, &gsi) < 0) { - printk("PCI: no interrupt route for %02x:%02x:%02x pin %c\n", + printk(KERN_ERR "PCI: no interrupt route for %02x:%02x:%02x pin %c\n", segment, bus, slot, 'A' + pci_pin); return -1; } @@ -638,19 +613,7 @@ vector = gsi_to_vector(gsi); if (vector < 0) { - /* we should allocate a vector for this interrupt line */ - - index = find_iosapic(gsi); - - if (index < 0) { - printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi); - return -1; - } - - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - pcat_compat = iosapic_lists[index].pcat_compat; - + /* allocate a vector for this interrupt line */ if (pcat_compat && (gsi < 16)) vector = isa_irq_to_vector(gsi); else { @@ -658,8 +621,7 @@ vector = ia64_alloc_vector(); } - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - 0, 0, gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); DBG("PCI: (%02x:%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n", segment, bus, slot, 'A' + pci_pin, gsi, vector); @@ -668,29 +630,32 @@ return vector; } -void __devinit -iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat) +void __init +iosapic_system_init (int system_pcat_compat) { - int num_rte, vector; - unsigned int isa_irq, ver; - char *addr; - static int first_time = 1; + int vector; - if (first_time) { - first_time = 0; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) - iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ - } + for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) + iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ + pcat_compat = system_pcat_compat; if (pcat_compat) { /* * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support * enabled. */ - printk("%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__); + printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__); outb(0xff, 0xA1); outb(0xff, 0x21); } +} + +void __init +iosapic_init (unsigned long phys_addr, unsigned int gsi_base) +{ + int num_rte; + unsigned int isa_irq, ver; + char *addr; addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); @@ -703,35 +668,22 @@ num_rte = ((ver >> 16) & 0xff) + 1; iosapic_lists[num_iosapic].addr = addr; - iosapic_lists[num_iosapic].pcat_compat = pcat_compat; iosapic_lists[num_iosapic].gsi_base = gsi_base; iosapic_lists[num_iosapic].num_rte = num_rte; num_iosapic++; - printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n", + printk(KERN_INFO " IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n", (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { - unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may * get reprogrammed later on with data from the ACPI Interrupt Source * Override table. */ - for (isa_irq = 0; isa_irq < 16; ++isa_irq) { - vector = isa_irq_to_vector(isa_irq); - - register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY, - /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */ - 1, 1, gsi_base, addr); - - DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n", - isa_irq, isa_irq, dest, vector); - - /* program the IOSAPIC routing table: */ - set_rte(vector, dest); - } + for (isa_irq = 0; isa_irq < 16; ++isa_irq) + iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } @@ -790,7 +742,7 @@ idesc = irq_desc(vector); if (idesc->handler != irq_type) { if (idesc->handler != &no_irq_type) - printk("%s: changing vector %d from %s to %s\n", + printk(KERN_INFO "%s: changing vector %d from %s to %s\n", __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); @@ -822,7 +774,7 @@ dest = (ia64_get_lid() >> 16) & 0xffff; #endif - printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n", + printk(KERN_INFO "PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n", dev->slot_name, 'A' + pci_pin, dest, vector); set_rte(vector, dest); } @@ -837,7 +789,7 @@ if (phase == 0) { if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) { - printk("%s: acpi_get_prt failed\n", __FUNCTION__); + printk(KERN_ERR "%s: acpi_get_prt failed\n", __FUNCTION__); } return; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/irq.c linux2.4.21_itanium/arch/ia64/kernel/irq.c --- linux2.4.21_itanium.org/arch/ia64/kernel/irq.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/irq.c Wed Jul 23 18:28:57 2003 @@ -111,7 +111,7 @@ * a generic callback i think. */ #if CONFIG_X86 - printk("unexpected IRQ trap at vector %02x\n", irq); + printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); #ifdef CONFIG_X86_LOCAL_APIC /* * Currently unexpected vectors happen only on SMP and APIC. @@ -125,7 +125,7 @@ #endif #endif #if CONFIG_IA64 - printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id()); + printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id()); #endif } @@ -591,7 +591,7 @@ desc->depth--; break; case 0: - printk("enable_irq(%u) unbalanced from %p\n", + printk(KERN_ERR "enable_irq(%u) unbalanced from %p\n", irq, (void *) __builtin_return_address(0)); } spin_unlock_irqrestore(&desc->lock, flags); @@ -738,7 +738,7 @@ */ if (irqflags & SA_SHIRQ) { if (!dev_id) - printk("Bad boy: %s called us without a dev_id!\n", devname); + printk(KERN_ERR "Bad boy: %s called us without a dev_id!\n", devname); } #endif @@ -819,7 +819,7 @@ kfree(action); return; } - printk("Trying to free free IRQ%d\n",irq); + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); spin_unlock_irqrestore(&desc->lock,flags); return; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/irq_ia64.c linux2.4.21_itanium/arch/ia64/kernel/irq_ia64.c --- linux2.4.21_itanium.org/arch/ia64/kernel/irq_ia64.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/irq_ia64.c Wed Jul 23 18:28:57 2003 @@ -148,9 +148,9 @@ extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); static struct irqaction ipi_irqaction = { - handler: handle_IPI, - flags: SA_INTERRUPT, - name: "IPI" + .handler = handle_IPI, + .flags = SA_INTERRUPT, + .name = "IPI" }; #endif diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/irq_lsapic.c linux2.4.21_itanium/arch/ia64/kernel/irq_lsapic.c --- linux2.4.21_itanium.org/arch/ia64/kernel/irq_lsapic.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/irq_lsapic.c Wed Jul 23 18:28:58 2003 @@ -27,12 +27,12 @@ } struct hw_interrupt_type irq_type_ia64_lsapic = { - typename: "LSAPIC", - startup: lsapic_noop_startup, - shutdown: lsapic_noop, - enable: lsapic_noop, - disable: lsapic_noop, - ack: lsapic_noop, - end: lsapic_noop, - set_affinity: (void (*)(unsigned int, unsigned long)) lsapic_noop + .typename = "LSAPIC", + .startup = lsapic_noop_startup, + .shutdown = lsapic_noop, + .enable = lsapic_noop, + .disable = lsapic_noop, + .ack = lsapic_noop, + .end = lsapic_noop, + .set_affinity = (void (*)(unsigned int, unsigned long)) lsapic_noop }; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/ivt.S linux2.4.21_itanium/arch/ia64/kernel/ivt.S --- linux2.4.21_itanium.org/arch/ia64/kernel/ivt.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/ivt.S Wed Jul 23 18:28:58 2003 @@ -114,6 +114,10 @@ * - the faulting virtual address has no L1, L2, or L3 mapping */ mov r16=cr.ifa // get address that caused the TLB miss +#ifdef CONFIG_HUGETLB_PAGE + movl r18=PAGE_SHIFT + mov r25=cr.itir +#endif ;; rsm psr.dt // use physical addressing for data mov r31=pr // save the predicate registers @@ -121,8 +125,18 @@ shl r21=r16,3 // shift bit 60 into sign bit shr.u r17=r16,61 // get the region number into r17 ;; + shr r22=r21,3 +#ifdef CONFIG_HUGETLB_PAGE + extr.u r26=r25,2,6 + ;; + cmp.eq p8,p0=HPAGE_SHIFT,r26 + ;; +(p8) dep r25=r18,r25,2,6 +(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT +#endif + ;; cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? - shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of the faulting address + shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address ;; (p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d // ensure "rsm psr.dt" has taken effect @@ -133,7 +147,7 @@ (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) cmp.eq p7,p6=0,r21 // unused address bits all zeroes? - shr.u r18=r16,PMD_SHIFT // shift L2 index into position + shr.u r18=r22,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; @@ -141,7 +155,7 @@ dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry ;; (p7) ld8 r20=[r17] // fetch the L2 entry (may be 0) - shr.u r19=r16,PAGE_SHIFT // shift L3 index into position + shr.u r19=r22,PAGE_SHIFT // shift L3 index into position ;; (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL? dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry @@ -160,6 +174,10 @@ (p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) mov cr.ifa=r22 +#ifdef CONFIG_HUGETLB_PAGE +(p8) mov cr.itir=r25 // change to default page-size for VHPT +#endif + /* * Now compute and insert the TLB entry for the virtual page table. We never * execute in a page table page so there is no need to set the exception deferral diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/machvec.c linux2.4.21_itanium/arch/ia64/kernel/machvec.c --- linux2.4.21_itanium.org/arch/ia64/kernel/machvec.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/machvec.c Wed Jul 23 18:28:57 2003 @@ -44,7 +44,7 @@ panic("generic kernel failed to find machine vector for platform %s!", name); } ia64_mv = *mv; - printk("booting generic kernel on platform %s\n", name); + printk(KERN_INFO "booting generic kernel on platform %s\n", name); } #endif /* CONFIG_IA64_GENERIC */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/mca.c linux2.4.21_itanium/arch/ia64/kernel/mca.c --- linux2.4.21_itanium.org/arch/ia64/kernel/mca.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/mca.c Wed Jul 23 18:28:57 2003 @@ -3,6 +3,9 @@ * Purpose: Generic MCA handling layer * * Updated for latest kernel + * Copyright (C) 2003 Hewlett-Packard Co + * David Mosberger-Tang + * * Copyright (C) 2002 Dell Computer Corporation * Copyright (C) Matt Domsch (Matt_Domsch@dell.com) * @@ -18,6 +21,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * + * 03/04/15 D. Mosberger Added INIT backtrace support. * 02/03/25 M. Domsch GUID cleanups * * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU @@ -45,7 +49,9 @@ #include #include #include +#include +#include #include #include #include @@ -53,11 +59,14 @@ #include #include +#include #include #include #undef MCA_PRT_XTRA_DATA +#define print_symbol(fmt, addr) printk(fmt, ""); + typedef struct ia64_fptr { unsigned long fp; unsigned long gp; @@ -70,7 +79,7 @@ u64 ia64_mca_stack[1024] __attribute__((aligned(16))); u64 ia64_mca_stackframe[32]; u64 ia64_mca_bspstore[1024]; -u64 ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16))); +u64 ia64_init_stack[INIT_TASK_SIZE/8] __attribute__((aligned(16))); u64 ia64_mca_sal_data_area[1356]; u64 ia64_tlb_functional; u64 ia64_os_mca_recovery_successful; @@ -85,40 +94,50 @@ extern struct hw_interrupt_type irq_type_iosapic_level; static struct irqaction cmci_irqaction = { - handler: ia64_mca_cmc_int_handler, - flags: SA_INTERRUPT, - name: "cmc_hndlr" + .handler = ia64_mca_cmc_int_handler, + .flags = SA_INTERRUPT, + .name = "cmc_hndlr" }; static struct irqaction mca_rdzv_irqaction = { - handler: ia64_mca_rendez_int_handler, - flags: SA_INTERRUPT, - name: "mca_rdzv" + .handler = ia64_mca_rendez_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_rdzv" }; static struct irqaction mca_wkup_irqaction = { - handler: ia64_mca_wakeup_int_handler, - flags: SA_INTERRUPT, - name: "mca_wkup" + .handler = ia64_mca_wakeup_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_wkup" }; static struct irqaction mca_cpe_irqaction = { - handler: ia64_mca_cpe_int_handler, - flags: SA_INTERRUPT, - name: "cpe_hndlr" + .handler = ia64_mca_cpe_int_handler, + .flags = SA_INTERRUPT, + .name = "cpe_hndlr" }; #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ +#define CMC_POLL_INTERVAL (1*60*HZ) /* 1 minute */ +#define CMC_HISTORY_LENGTH 5 static struct timer_list cpe_poll_timer; +static struct timer_list cmc_poll_timer; +/* + * Start with this in the wrong state so we won't play w/ timers + * before the system is ready. + */ +static int cmc_polling_enabled = 1; + +extern void salinfo_log_wakeup(int); /* * ia64_mca_log_sal_error_record * - * This function retrieves a specified error record type from SAL, sends it to - * the system log, and notifies SALs to clear the record from its non-volatile - * memory. + * This function retrieves a specified error record type from SAL, + * wakes up any processes waiting for error records, and sends it to + * the system log. * * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT) * Outputs : platform error status @@ -130,7 +149,7 @@ /* Get the MCA error record */ if (!ia64_log_get(sal_info_type, (prfunc_t)printk)) - return platform_err; // no record retrieved + return platform_err; /* no record retrieved */ /* TODO: * 1. analyze error logs to determine recoverability @@ -138,11 +157,8 @@ * 3. set ia64_os_mca_recovery_successful flag, if applicable */ + salinfo_log_wakeup(sal_info_type); platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk); - /* temporary: only clear SAL logs on hardware-corrected errors - or if we're logging an error after an MCA-initiated reboot */ - if ((sal_info_type > 1) || (called_from_init)) - ia64_sal_clear_state_info(sal_info_type); return platform_err; } @@ -160,24 +176,174 @@ void ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { - IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. vector = %#x\n", cpe_irq); + IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n", + smp_processor_id(), cpe_irq); /* Get the CMC error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0); } -/* - * This routine will be used to deal with platform specific handling - * of the init, i.e. drop into the kernel debugger on server machine, - * or if the processor is part of some parallel machine without a - * console, then we would call the appropriate debug hooks here. - */ +static void +show_min_state (pal_min_state_area_t *minstate) +{ + u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri; + u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri; + + printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits); + printk("pr\t\t%016lx\n", minstate->pmsa_pr); + printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0); + printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc); + printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip); + printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr); + printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs); + printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip); + printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr); + printk("xfs\t\t%016lx\n", minstate->pmsa_xfs); + printk("b1\t\t%016lx ", minstate->pmsa_br1); + print_symbol("%s\n", minstate->pmsa_br1); + + printk("\nstatic registers r0-r15:\n"); + printk(" r0- 3 %016lx %016lx %016lx %016lx\n", + 0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]); + printk(" r4- 7 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[3], minstate->pmsa_gr[4], + minstate->pmsa_gr[5], minstate->pmsa_gr[6]); + printk(" r8-11 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[7], minstate->pmsa_gr[8], + minstate->pmsa_gr[9], minstate->pmsa_gr[10]); + printk("r12-15 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[11], minstate->pmsa_gr[12], + minstate->pmsa_gr[13], minstate->pmsa_gr[14]); + + printk("\nbank 0:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1], + minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5], + minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9], + minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13], + minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]); + + printk("\nbank 1:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1], + minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5], + minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9], + minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13], + minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]); +} + +static void +fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw) +{ + u64 *dst_banked, *src_banked, bit, shift, nat_bits; + int i; + + /* + * First, update the pt-regs and switch-stack structures with the contents stored + * in the min-state area: + */ + if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) { + pt->cr_ipsr = ms->pmsa_xpsr; + pt->cr_iip = ms->pmsa_xip; + pt->cr_ifs = ms->pmsa_xfs; + } else { + pt->cr_ipsr = ms->pmsa_ipsr; + pt->cr_iip = ms->pmsa_iip; + pt->cr_ifs = ms->pmsa_ifs; + } + pt->ar_rsc = ms->pmsa_rsc; + pt->pr = ms->pmsa_pr; + pt->r1 = ms->pmsa_gr[0]; + pt->r2 = ms->pmsa_gr[1]; + pt->r3 = ms->pmsa_gr[2]; + sw->r4 = ms->pmsa_gr[3]; + sw->r5 = ms->pmsa_gr[4]; + sw->r6 = ms->pmsa_gr[5]; + sw->r7 = ms->pmsa_gr[6]; + pt->r8 = ms->pmsa_gr[7]; + pt->r9 = ms->pmsa_gr[8]; + pt->r10 = ms->pmsa_gr[9]; + pt->r11 = ms->pmsa_gr[10]; + pt->r12 = ms->pmsa_gr[11]; + pt->r13 = ms->pmsa_gr[12]; + pt->r14 = ms->pmsa_gr[13]; + pt->r15 = ms->pmsa_gr[14]; + dst_banked = &pt->r16; /* r16-r31 are contiguous in struct pt_regs */ + src_banked = ms->pmsa_bank1_gr; + for (i = 0; i < 16; ++i) + dst_banked[i] = src_banked[i]; + pt->b0 = ms->pmsa_br0; + sw->b1 = ms->pmsa_br1; + + /* construct the NaT bits for the pt-regs structure: */ +# define PUT_NAT_BIT(dst, addr) \ + do { \ + bit = nat_bits & 1; nat_bits >>= 1; \ + shift = ((unsigned long) addr >> 3) & 0x3f; \ + dst = ((dst) & ~(1UL << shift)) | (bit << shift); \ + } while (0) + + /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */ + shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f; + nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift)); + + PUT_NAT_BIT(sw->caller_unat, &pt->r1); + PUT_NAT_BIT(sw->caller_unat, &pt->r2); + PUT_NAT_BIT(sw->caller_unat, &pt->r3); + PUT_NAT_BIT(sw->ar_unat, &sw->r4); + PUT_NAT_BIT(sw->ar_unat, &sw->r5); + PUT_NAT_BIT(sw->ar_unat, &sw->r6); + PUT_NAT_BIT(sw->ar_unat, &sw->r7); + PUT_NAT_BIT(sw->caller_unat, &pt->r8); PUT_NAT_BIT(sw->caller_unat, &pt->r9); + PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11); + PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13); + PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15); + nat_bits >>= 16; /* skip over bank0 NaT bits */ + PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17); + PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19); + PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21); + PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23); + PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25); + PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27); + PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29); + PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31); +} + void -init_handler_platform (struct pt_regs *regs) +init_handler_platform (sal_log_processor_info_t *proc_ptr, + struct pt_regs *pt, struct switch_stack *sw) { + struct unw_frame_info info; + /* if a kernel debugger is available call it here else just dump the registers */ - show_regs(regs); /* dump the state info */ + /* + * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be + * generated via the BMC's command-line interface, but since the console is on the + * same serial line, the user will need some time to switch out of the BMC before + * the dump begins. + */ + printk("Delaying for 5 seconds...\n"); + udelay(5*1000000); + show_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); + + fetch_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area, pt, sw); + unw_init_from_interruption(&info, current, pt, sw); + ia64_do_show_stack(&info, NULL); + + printk("\nINIT dump complete. Please reboot now.\n"); while (1); /* hang city if no debugger */ } @@ -202,21 +368,22 @@ * ia64_mca_check_errors * * External entry to check for error records which may have been posted by SAL - * for a prior failure which resulted in a machine shutdown before an the - * error could be logged. This function must be called after the filesystem - * is initialized. + * for a prior failure. * * Inputs : None * * Outputs : None */ -void +int ia64_mca_check_errors (void) { /* * If there is an MCA error record pending, get it and log it. */ + printk("CPU %d: checking for saved MCA error records\n", smp_processor_id()); ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 1); + + return 0; } /* @@ -234,8 +401,11 @@ ia64_mca_register_cpev (int cpev) { /* Register the CPE interrupt vector with SAL */ - if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) { - printk("ia64_mca_platform_init: failed to register Corrected " + struct ia64_sal_retval isrv; + + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0); + if (isrv.status) { + printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected " "Platform Error interrupt vector with SAL.\n"); return; } @@ -246,26 +416,9 @@ #endif /* PLATFORM_MCA_HANDLERS */ -static char *min_state_labels[] = { - "nat", - "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", - "r9", "r10","r11", "r12","r13","r14", "r15", - "b0r16","b0r17", "b0r18", "b0r19", "b0r20", - "b0r21", "b0r22","b0r23", "b0r24", "b0r25", - "b0r26", "b0r27", "b0r28","b0r29", "b0r30", "b0r31", - "r16", "r17", "r18","r19", "r20", "r21","r22", - "r23", "r24","r25", "r26", "r27","r28", "r29", "r30","r31", - "preds", "br0", "rsc", - "iip", "ipsr", "ifs", - "xip", "xpsr", "xfs" -}; - -int ia64_pmss_dump_bank0=0; /* dump bank 0 ? */ - /* * routine to process and prepare to dump min_state_save * information for debugging purposes. - * */ void ia64_process_min_state_save (pal_min_state_area_t *pmss) @@ -274,30 +427,12 @@ u64 *tpmss_ptr = (u64 *)pmss; u64 *return_min_state_ptr = ia64_mca_min_state_save_info; - /* dump out the min_state_area information */ - for (i=0;i= CMC_HISTORY_LENGTH) { + /* + * CMC threshold exceeded, clear the history + * so we have a fresh start when we return + */ + for (index = 0 ; index < CMC_HISTORY_LENGTH; index++) + cmc_history[index] = 0; + index = 0; + + /* Switch to polling mode */ + cmc_polling_enabled = 1; + + /* + * Unlock & enable interrupts before + * smp_call_function or risk deadlock + */ + spin_unlock(&cmc_history_lock); + ia64_mca_cmc_vector_disable(NULL); + + local_irq_enable(); + smp_call_function(ia64_mca_cmc_vector_disable, NULL, 1, 1); + + /* + * Corrected errors will still be corrected, but + * make sure there's a log somewhere that indicates + * something is generating more than we can handle. + */ + printk(KERN_WARNING "ia64_mca_cmc_int_handler: WARNING: Switching to polling CMC handler, error records may be lost\n"); + + + mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL); + + /* lock already released, get out now */ + return; + } else { + cmc_history[index++] = now; + if (index == CMC_HISTORY_LENGTH) + index = 0; + } + } + spin_unlock(&cmc_history_lock); } /* @@ -797,6 +1054,7 @@ { spinlock_t isl_lock; int isl_index; + unsigned long isl_count; ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ } ia64_state_log_t; @@ -813,11 +1071,78 @@ #define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index #define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index #define IA64_LOG_INDEX_INC(it) \ - ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index + {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \ + ia64_state_log[it].isl_count++;} #define IA64_LOG_INDEX_DEC(it) \ ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index #define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])) #define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) +#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count + +/* + * ia64_mca_cmc_int_caller + * + * Call CMC interrupt handler, only purpose is to have a + * smp_call_function callable entry. + * + * Inputs : dummy(unused) + * Outputs : None + * */ +static void +ia64_mca_cmc_int_caller(void *dummy) +{ + ia64_mca_cmc_int_handler(0, NULL, NULL); +} + +/* + * ia64_mca_cmc_poll + * + * Poll for Corrected Machine Checks (CMCs) + * + * Inputs : dummy(unused) + * Outputs : None + * + */ +static void +ia64_mca_cmc_poll (unsigned long dummy) +{ + int start_count; + + start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC); + + /* Call the interrupt handler */ + smp_call_function(ia64_mca_cmc_int_caller, NULL, 1, 1); + local_irq_disable(); + ia64_mca_cmc_int_caller(NULL); + local_irq_enable(); + + /* + * If no log recored, switch out of polling mode. + */ + if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) { + printk(KERN_WARNING "ia64_mca_cmc_poll: Returning to interrupt driven CMC handler\n"); + cmc_polling_enabled = 0; + smp_call_function(ia64_mca_cmc_vector_enable, NULL, 1, 1); + ia64_mca_cmc_vector_enable(NULL); + } else { + mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL); + } +} + +/* + * ia64_mca_cpe_int_caller + * + * Call CPE interrupt handler, only purpose is to have a + * smp_call_function callable entry. + * + * Inputs : dummy(unused) + * Outputs : None + * */ +static void +ia64_mca_cpe_int_caller(void *dummy) +{ + ia64_mca_cpe_int_handler(0, NULL, NULL); +} /* * ia64_mca_cpe_poll @@ -832,19 +1157,22 @@ static void ia64_mca_cpe_poll (unsigned long dummy) { - int start_index; + int start_count; static int poll_time = MAX_CPE_POLL_INTERVAL; - start_index = IA64_LOG_CURR_INDEX(SAL_INFO_TYPE_CPE); + start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE); /* Call the interrupt handler */ - ia64_mca_cpe_int_handler(0, NULL, NULL); + smp_call_function(ia64_mca_cpe_int_caller, NULL, 1, 1); + local_irq_disable(); + ia64_mca_cpe_int_caller(NULL); + local_irq_enable(); /* * If a log was recorded, increase our polling frequency, * otherwise, backoff. */ - if (start_index != IA64_LOG_CURR_INDEX(SAL_INFO_TYPE_CPE)) { + if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) { poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time/2); } else { poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2); @@ -865,11 +1193,19 @@ static int __init ia64_mca_late_init(void) { - if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0) { - init_timer(&cpe_poll_timer); - cpe_poll_timer.function = ia64_mca_cpe_poll; - ia64_mca_cpe_poll(0); - } + init_timer(&cmc_poll_timer); + cmc_poll_timer.function = ia64_mca_cmc_poll; + + /* Reset to the correct state */ + cmc_polling_enabled = 0; + + init_timer(&cpe_poll_timer); + cpe_poll_timer.function = ia64_mca_cpe_poll; + + /* If platform doesn't support CPEI, get the timer going. */ + if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0) + ia64_mca_cpe_poll(0UL); + return 0; } @@ -888,12 +1224,12 @@ * */ void -ia64_init_handler (struct pt_regs *regs) +ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw) { sal_log_processor_info_t *proc_ptr; ia64_err_rec_t *plog_ptr; - printk("Entered OS INIT handler\n"); + printk(KERN_INFO "Entered OS INIT handler\n"); /* Get the INIT processor log */ if (!ia64_log_get(SAL_INFO_TYPE_INIT, (prfunc_t)printk)) @@ -910,12 +1246,9 @@ plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT); proc_ptr = &plog_ptr->proc_err; - ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area); - - /* Clear the INIT SAL logs now that they have been saved in the OS buffer */ - ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT); + ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); - init_handler_platform(regs); /* call platform specific routines */ + init_handler_platform(proc_ptr, pt, sw); /* call platform specific routines */ } /* @@ -1076,12 +1409,12 @@ ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) { prfunc("+Err Record ID: %d SAL Rev: %2x.%02x\n", lh->id, - lh->revision.major, lh->revision.minor); - prfunc("+Time: %02x/%02x/%02x%02x %02d:%02d:%02d Severity %d\n", - lh->timestamp.slh_month, lh->timestamp.slh_day, - lh->timestamp.slh_century, lh->timestamp.slh_year, - lh->timestamp.slh_hour, lh->timestamp.slh_minute, - lh->timestamp.slh_second, lh->severity); + lh->revision.major, lh->revision.minor); + prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n", + lh->timestamp.slh_month, lh->timestamp.slh_day, + lh->timestamp.slh_century, lh->timestamp.slh_year, + lh->timestamp.slh_hour, lh->timestamp.slh_minute, + lh->timestamp.slh_second, lh->severity); } /* @@ -1704,7 +2037,7 @@ * absent. Also, current implementations only allocate space for number of * elements used. So we walk the data pointer from here on. */ - p_data = &slpi->cache_check_info[0]; + p_data = &slpi->info[0]; /* Print the cache check information if any*/ for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++) @@ -1821,8 +2154,7 @@ /* * Now process processor device error record section */ - ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, - printk); + ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, printk); } IA64_MCA_DEBUG("ia64_mca_log_print: " @@ -1965,9 +2297,8 @@ switch(sal_info_type) { case SAL_INFO_TYPE_MCA: - prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n"); - platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - prfunc("+END HARDWARE ERROR STATE AT MCA\n"); + prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id()); + ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); break; case SAL_INFO_TYPE_INIT: prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n"); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/mca_asm.S linux2.4.21_itanium/arch/ia64/kernel/mca_asm.S --- linux2.4.21_itanium.org/arch/ia64/kernel/mca_asm.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/mca_asm.S Wed Jul 23 18:28:58 2003 @@ -766,8 +766,6 @@ // stash the information the SAL passed to os SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) ;; - -// now we want to save information so we can dump registers SAVE_MIN_WITH_COVER ;; mov r8=cr.ifa @@ -798,10 +796,12 @@ // // Let's call the C handler to get the rest of the state info // - alloc r14=ar.pfs,0,0,1,0 // now it's safe (must be first in insn group!) - ;; // + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + ;; adds out0=16,sp // out0 = pointer to pt_regs ;; + DO_SAVE_SWITCH_STACK + adds out1=16,sp // out0 = pointer to switch_stack br.call.sptk.many rp=ia64_init_handler .ret1: diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/palinfo.c linux2.4.21_itanium/arch/ia64/kernel/palinfo.c --- linux2.4.21_itanium.org/arch/ia64/kernel/palinfo.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/palinfo.c Wed Jul 23 18:28:58 2003 @@ -6,7 +6,7 @@ * Intel IA-64 Architecture Software Developer's Manual v1.0. * * - * Copyright (C) 2000-2001 Hewlett-Packard Co + * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co * Stephane Eranian * * 05/26/2000 S.Eranian initial release @@ -27,9 +27,7 @@ #include #include #include -#ifdef CONFIG_SMP #include -#endif MODULE_AUTHOR("Stephane Eranian "); MODULE_DESCRIPTION("/proc interface to IA-64 PAL"); @@ -37,12 +35,6 @@ #define PALINFO_VERSION "0.5" -#ifdef CONFIG_SMP -#define cpu_is_online(i) (cpu_online_map & (1UL << i)) -#else -#define cpu_is_online(i) 1 -#endif - typedef int (*palinfo_func_t)(char*); typedef struct { @@ -101,26 +93,15 @@ #define RSE_HINTS_COUNT (sizeof(rse_hints)/sizeof(const char *)) -/* - * The current revision of the Volume 2 (July 2000) of - * IA-64 Architecture Software Developer's Manual is wrong. - * Table 4-10 has invalid information concerning the ma field: - * Correct table is: - * bit 0 - 001 - UC - * bit 4 - 100 - UC - * bit 5 - 101 - UCE - * bit 6 - 110 - WC - * bit 7 - 111 - NatPage - */ static const char *mem_attrib[]={ - "Write Back (WB)", /* 000 */ - "Uncacheable (UC)", /* 001 */ - "Reserved", /* 010 */ - "Reserved", /* 011 */ - "Uncacheable (UC)", /* 100 */ - "Uncacheable Exported (UCE)", /* 101 */ - "Write Coalescing (WC)", /* 110 */ - "NaTPage" /* 111 */ + "WB", /* 000 */ + "SW", /* 001 */ + "010", /* 010 */ + "011", /* 011 */ + "UC", /* 100 */ + "UCE", /* 101 */ + "WC", /* 110 */ + "NaTPage" /* 111 */ }; /* @@ -236,15 +217,12 @@ int i,j, k; s64 status; - if ((status=ia64_pal_cache_summary(&levels, &unique_caches)) != 0) { - printk("ia64_pal_cache_summary=%ld\n", status); - return 0; + if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) { + printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status); + return 0; } - p += sprintf(p, "Cache levels : %ld\n" \ - "Unique caches : %ld\n\n", - levels, - unique_caches); + p += sprintf(p, "Cache levels : %ld\nUnique caches : %ld\n\n", levels, unique_caches); for (i=0; i < levels; i++) { @@ -315,11 +293,12 @@ pal_vm_info_2_u_t vm_info_2; pal_tc_info_u_t tc_info; ia64_ptce_info_t ptce; + const char *sep; int i, j; s64 status; - if ((status=ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) { - printk("ia64_pal_vm_summary=%ld\n", status); + if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) { + printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status); return 0; } @@ -339,18 +318,26 @@ if (ia64_pal_mem_attrib(&attrib) != 0) return 0; - p += sprintf(p, "Supported memory attributes : %s\n", mem_attrib[attrib&0x7]); + p += sprintf(p, "Supported memory attributes : "); + sep = ""; + for (i = 0; i < 8; i++) { + if (attrib & (1 << i)) { + p += sprintf(p, "%s%s", sep, mem_attrib[i]); + sep = ", "; + } + } + p += sprintf(p, "\n"); - if ((status=ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) { - printk("ia64_pal_vm_page_size=%ld\n", status); + if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) { + printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status); return 0; } - p += sprintf(p, "\nTLB walker : %s implemented\n" \ + p += sprintf(p, "\nTLB walker : %simplemented\n" \ "Number of DTR : %d\n" \ "Number of ITR : %d\n" \ "TLB insertable page sizes : ", - vm_info_1.pal_vm_info_1_s.vw ? "\b":"not", + vm_info_1.pal_vm_info_1_s.vw ? "" : "not ", vm_info_1.pal_vm_info_1_s.max_dtr_entry+1, vm_info_1.pal_vm_info_1_s.max_itr_entry+1); @@ -362,7 +349,7 @@ p = bitvector_process(p, vw_pages); if ((status=ia64_get_ptce(&ptce)) != 0) { - printk("ia64_get_ptce=%ld\n",status); + printk(KERN_ERR "ia64_get_ptce=%ld\n", status); return 0; } @@ -712,8 +699,8 @@ u64 rv2:32; } *rid_reg; - if ((status=ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) { - printk("ia64_pal_vm_summary=%ld\n", status); + if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) { + printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status); return 0; } max[0] = vm_info_1.pal_vm_info_1_s.max_itr_entry+1; @@ -724,7 +711,8 @@ status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid); if (status != 0) { - printk("palinfo: pal call failed on tr[%d:%d]=%ld\n", i, j, status); + printk(KERN_ERR "palinfo: pal call failed on tr[%d:%d]=%ld\n", + i, j, status); continue; } @@ -843,7 +831,7 @@ { palinfo_smp_data_t *data = (palinfo_smp_data_t *)info; if (data == NULL) { - printk("%s palinfo: data pointer is NULL\n", KERN_ERR); + printk(KERN_ERR "palinfo: data pointer is NULL\n"); data->ret = 0; /* no output */ return; } @@ -870,7 +858,8 @@ /* will send IPI to other CPU and wait for completion of remote call */ if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 0, 1))) { - printk("palinfo: remote CPU call from %d to %d on function %d: error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret); + printk(KERN_ERR "palinfo: remote CPU call from %d to %d on function %d: " + "error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret); return 0; } return ptr.ret; @@ -879,7 +868,7 @@ static int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page) { - printk("palinfo: should not be called with non SMP kernel\n"); + printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n"); return 0; } #endif /* CONFIG_SMP */ @@ -937,7 +926,7 @@ */ for (i=0; i < NR_CPUS; i++) { - if (!cpu_is_online(i)) continue; + if (!cpu_online(i)) continue; sprintf(cpustr,CPUSTR, i); @@ -947,8 +936,10 @@ for (j=0; j < NR_PALINFO_ENTRIES; j++) { f.func_id = j; - *pdir++ = create_proc_read_entry (palinfo_entries[j].name, 0, cpu_dir, - palinfo_read_entry, (void *)f.value); + *pdir = create_proc_read_entry( + palinfo_entries[j].name, 0, cpu_dir, + palinfo_read_entry, (void *)f.value); + pdir++; } *pdir++ = cpu_dir; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/pci.c linux2.4.21_itanium/arch/ia64/kernel/pci.c --- linux2.4.21_itanium.org/arch/ia64/kernel/pci.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/pci.c Wed Jul 23 18:28:57 2003 @@ -2,9 +2,15 @@ * pci.c - Low-Level PCI Access in IA-64 * * Derived from bios32.c of i386 tree. + * Copyright (C) 2002, 2003 Hewlett-Packard Co + * David Mosberger-Tang + * Bjorn Helgaas + * + * Note: Above list of copyright holders is incomplete... */ #include +#include #include #include #include @@ -13,9 +19,9 @@ #include #include #include -#include #include +#include #include #include #include @@ -39,12 +45,6 @@ #define DBG(x...) #endif -#ifdef CONFIG_IA64_MCA -extern void ia64_mca_check_errors( void ); -#endif - -static unsigned int acpi_root_bridges; - struct pci_fixup pcibios_fixups[1]; struct pci_ops *pci_root_ops; @@ -213,14 +213,14 @@ return b; } -static void +static int alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags) { struct resource *res; res = kmalloc(sizeof(*res), GFP_KERNEL); if (!res) - return; + return -ENOMEM; memset(res, 0, sizeof(*res)); res->name = name; @@ -228,7 +228,10 @@ res->end = end; res->flags = flags; - request_resource(root, res); + if (request_resource(root, res)) + return -EBUSY; + + return 0; } static u64 @@ -308,14 +311,24 @@ } else return AE_OK; + if (addr.min_address_range == addr.max_address_range) { + printk(KERN_INFO "ACPI reports bogus %s %s range 0x%lx-0x%lx; ignoring it\n", + info->name, root->name, addr.min_address_range + offset, + addr.max_address_range + offset); + return AE_OK; + } + window = &info->controller->window[info->controller->windows++]; window->resource.flags |= flags; window->resource.start = addr.min_address_range; window->resource.end = addr.max_address_range; window->offset = offset; - alloc_resource(info->name, root, addr.min_address_range + offset, - addr.max_address_range + offset, flags); + if (alloc_resource(info->name, root, addr.min_address_range + offset, + addr.max_address_range + offset, flags)) + printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", + addr.min_address_range + offset, addr.max_address_range + offset, + root->name, info->name); } return AE_OK; @@ -329,8 +342,6 @@ unsigned int windows = 0; char *name; - acpi_root_bridges++; - controller = alloc_pci_controller(seg); if (!controller) goto out1; @@ -379,7 +390,6 @@ void __init pcibios_init (void) { -# define PCI_BUSES_TO_SCAN 256 int i = 0; struct pci_controller *controller; @@ -391,15 +401,6 @@ platform_pci_fixup(0); /* phase 0 fixups (before buses scanned) */ - /* Only probe blindly if ACPI didn't tell us about root bridges */ - if (!acpi_root_bridges) { - printk("PCI: Probing PCI hardware\n"); - controller = alloc_pci_controller(0); - if (controller) - for (i = 0; i < PCI_BUSES_TO_SCAN; i++) - pci_scan_bus(i, pci_root_ops, controller); - } - platform_pci_fixup(1); /* phase 1 fixups (after buses scanned) */ return; @@ -576,9 +577,81 @@ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) + vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; } + +/** + * pci_cacheline_size - determine cacheline size for PCI devices + * @dev: void + * + * We want to use the line-size of the outer-most cache. We assume + * that this line-size is the same for all CPUs. + * + * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +static unsigned long +pci_cacheline_size (void) +{ + u64 levels, unique_caches; + s64 status; + pal_cache_config_info_t cci; + static u8 cacheline_size; + + if (cacheline_size) + return cacheline_size; + + status = ia64_pal_cache_summary(&levels, &unique_caches); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + + status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, + &cci); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + cacheline_size = 1 << cci.pcci_line_size; + return cacheline_size; +} + +/** + * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi() + * @dev: the PCI device for which MWI is enabled + * + * For ia64, we can get the cacheline sizes from PAL. + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +int +pcibios_set_mwi (struct pci_dev *dev) +{ + unsigned long desired_linesize, current_linesize; + int rc = 0; + u8 pci_linesize; + + desired_linesize = pci_cacheline_size(); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize); + current_linesize = 4 * pci_linesize; + if (desired_linesize != current_linesize) { + printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,", + dev->slot_name, current_linesize); + if (current_linesize > desired_linesize) { + printk(" expected %lu bytes instead\n", desired_linesize); + rc = -EINVAL; + } else { + printk(" correcting to %lu\n", desired_linesize); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4); + } + } + return rc; +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/perfmon.c linux2.4.21_itanium/arch/ia64/kernel/perfmon.c --- linux2.4.21_itanium.org/arch/ia64/kernel/perfmon.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/perfmon.c Wed Jul 23 18:28:57 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -120,8 +121,22 @@ #define CTX_USED_DBR(ctx,n) (ctx)->ctx_used_dbrs[(n)>>6] |= 1UL<< ((n) % 64) #define CTX_USES_DBREGS(ctx) (((pfm_context_t *)(ctx))->ctx_fl_using_dbreg==1) -#define LOCK_CTX(ctx) spin_lock(&(ctx)->ctx_lock) -#define UNLOCK_CTX(ctx) spin_unlock(&(ctx)->ctx_lock) +#ifdef CONFIG_SMP +#define GET_ACTIVATION() pmu_owners[smp_processor_id()].activation_number +#define INC_ACTIVATION() pmu_owners[smp_processor_id()].activation_number++ +#define SET_ACTIVATION(c) (c)->ctx_last_activation = GET_ACTIVATION() +#define SET_LAST_CPU(ctx, v) (ctx)->ctx_last_cpu = (v) +#define GET_LAST_CPU(ctx) (ctx)->ctx_last_cpu +#else /* !CONFIG_SMP */ +#define SET_ACTIVATION(t) do {} while(0) +#define GET_ACTIVATION(t) do {} while(0) +#define INC_ACTIVATION(t) do {} while(0) +#define SET_LAST_CPU(ctx, v) do {} while(0) +#define GET_LAST_CPU(ctx) do {} while(0) +#endif /* CONFIG_SMP */ + + +#define PFM_INVALID_ACTIVATION (~0UL) #define SET_PMU_OWNER(t) do { pmu_owners[smp_processor_id()].owner = (t); } while(0) #define PMU_OWNER() pmu_owners[smp_processor_id()].owner @@ -131,14 +146,13 @@ #define PFM_REG_RETFLAG_SET(flags, val) do { flags &= ~PFM_REG_RETFL_MASK; flags |= (val); } while(0) -#define PFM_CPUINFO_CLEAR(v) local_cpu_data->pfm_syst_info &= ~(v) -#define PFM_CPUINFO_SET(v) local_cpu_data->pfm_syst_info |= (v) +#define TASK_PTREGS(t) (((struct pt_regs *)((unsigned long) (t) + IA64_STK_OFFSET))-1) + +/* + * cmp0 must be the value of pmc0 + */ +#define PMC0_HAS_OVFL(cmp0) (cmp0 & ~0x1UL) -#ifdef CONFIG_SMP -#define cpu_is_online(i) (cpu_online_map & (1UL << i)) -#else -#define cpu_is_online(i) (i==0) -#endif /* * debugging @@ -230,7 +244,8 @@ unsigned int protected:1; /* allow access to creator of context only */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ - unsigned int reserved:23; + unsigned int unsecure:1; /* sp = 0 for non self-monitored task */ + unsigned int reserved:22; } pfm_context_flags_t; /* @@ -265,13 +280,17 @@ u64 ctx_saved_psr; /* copy of psr used for lazy ctxsw */ unsigned long ctx_saved_cpus_allowed; /* copy of the task cpus_allowed (system wide) */ + unsigned long ctx_last_activation; /* context last activation number for last_cpu */ + unsigned int ctx_last_cpu; /* CPU id of current or last CPU used (SMP only) */ unsigned int ctx_cpu; /* cpu to which perfmon is applied (system wide) */ - atomic_t ctx_saving_in_progress; /* flag indicating actual save in progress */ - atomic_t ctx_is_busy; /* context accessed by overflow handler */ - atomic_t ctx_last_cpu; /* CPU id of current or last CPU used */ + struct tasklet_struct ctx_tasklet; /* used for sending signal-based notifications */ } pfm_context_t; +#define PFM_GET_CTX(t) ((pfm_context_t *)(t)->thread.pfm_context) +#define LOCK_CTX(ctx) spin_lock(&(ctx)->ctx_lock) +#define UNLOCK_CTX(ctx) spin_unlock(&(ctx)->ctx_lock) + #define ctx_fl_inherit ctx_flags.inherit #define ctx_fl_block ctx_flags.block #define ctx_fl_system ctx_flags.system @@ -279,6 +298,7 @@ #define ctx_fl_protected ctx_flags.protected #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_excl_idle ctx_flags.excl_idle +#define ctx_fl_unsecure ctx_flags.unsecure /* * global information about all sessions @@ -335,17 +355,6 @@ } pmu_config_t; /* - * structure used to pass argument to/from remote CPU - * using IPI to check and possibly save the PMU context on SMP systems. - * - * not used in UP kernels - */ -typedef struct { - struct task_struct *task; /* which task we are interested in */ - int retval; /* return value of the call: 0=you can proceed, 1=need to wait for completion */ -} pfm_smp_ipi_arg_t; - -/* * perfmon command descriptions */ typedef struct { @@ -428,7 +437,8 @@ */ static struct { struct task_struct *owner; - char pad[SMP_CACHE_BYTES] ____cacheline_aligned; + unsigned long activation_number; + char pad[SMP_CACHE_BYTES] ____cacheline_aligned; } pmu_owners[NR_CPUS]; @@ -437,10 +447,7 @@ * forward declarations */ static void pfm_reset_pmu(struct task_struct *); -#ifdef CONFIG_SMP -static void pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx); -#endif -static void pfm_lazy_save_regs (struct task_struct *ta); +static unsigned long pfm_lazy_save_regs (struct task_struct *ta); #if defined(CONFIG_ITANIUM) #include "perfmon_itanium.h" @@ -504,6 +511,69 @@ ia64_srlz_d(); } +static inline void +pfm_restore_ibrs(unsigned long *ibrs, unsigned int nibrs) +{ + int i; + + for (i=0; i < nibrs; i++) { + ia64_set_ibr(i, ibrs[i]); + } + ia64_srlz_i(); +} + +static inline void +pfm_restore_dbrs(unsigned long *dbrs, unsigned int ndbrs) +{ + int i; + + for (i=0; i < ndbrs; i++) { + ia64_set_dbr(i, dbrs[i]); + } + ia64_srlz_d(); +} + +static inline void +pfm_restore_pmcs(unsigned long *pmcs, unsigned long mask) +{ + int i; + + DBprintk(("mask=0x%lx\n", mask)); + for (i=0; mask; i++, mask>>=1) { + if ((mask & 0x1) == 0) continue; + ia64_set_pmc(i, pmcs[i]); + DBprintk(("pmc[%d]=0x%lx\n", i, pmcs[i])); + } + ia64_srlz_d(); +} + +static inline void +pfm_restore_pmds(unsigned long *pmds, unsigned long mask) +{ + int i; + unsigned long val, ovfl_val = pmu_conf.ovfl_val; + + DBprintk(("mask=0x%lx\n", mask)); + for (i=0; mask; i++, mask>>=1) { + if ((mask & 0x1) == 0) continue; + val = PMD_IS_COUNTING(i) ? pmds[i] & ovfl_val : pmds[i]; + ia64_set_pmd(i, val); + DBprintk(("pmd[%d]=0x%lx\n", i, val)); + } + ia64_srlz_d(); +} + +static inline void +pfm_save_pmds(unsigned long *pmds, unsigned long mask) +{ + int i; + + ia64_srlz_d(); + + for (i=0; mask; i++, mask>>=1) { + if (mask & 0x1) pmds[i] = ia64_get_pmd(i); + } +} static inline unsigned long pfm_read_soft_counter(pfm_context_t *ctx, int i) @@ -600,7 +670,7 @@ pfm_smpl_buffer_desc_t *psb = (pfm_smpl_buffer_desc_t *)vma->vm_private_data; if (psb == NULL) { - printk("perfmon: psb is null in [%d]\n", current->pid); + printk(KERN_DEBUG "perfmon: psb is null in [%d]\n", current->pid); return; } /* @@ -665,7 +735,7 @@ * some sanity checks first */ if (ctx == NULL || task->mm == NULL || ctx->ctx_smpl_vaddr == 0 || ctx->ctx_psb == NULL) { - printk("perfmon: invalid context mm=%p\n", task->mm); + printk(KERN_DEBUG "perfmon: invalid context mm=%p\n", task->mm); return -1; } psb = ctx->ctx_psb; @@ -676,11 +746,11 @@ up_write(&task->mm->mmap_sem); if (r !=0) { - printk("perfmon: pid %d unable to unmap sampling buffer @0x%lx size=%ld\n", - task->pid, ctx->ctx_smpl_vaddr, psb->psb_size); + printk(KERN_DEBUG "perfmon: pid %d unable to unmap sampling buffer " + "@0x%lx size=%ld\n", task->pid, ctx->ctx_smpl_vaddr, psb->psb_size); } - DBprintk(("[%d] do_unmap(0x%lx, %ld)=%d refcnt=%lu psb_flags=0x%x\n", + DBprintk(("[%d] do_unmap(0x%lx, %ld)=%d refcnt=%lu psb_flags=0x%x\n", task->pid, ctx->ctx_smpl_vaddr, psb->psb_size, r, psb->psb_refcnt, psb->psb_flags)); return 0; @@ -701,7 +771,14 @@ static void pfm_context_free(pfm_context_t *ctx) { - if (ctx) kfree(ctx); + if (ctx) { + DBprintk(("kill tasklet for ctx %p\n", ctx)); + + tasklet_kill(&ctx->ctx_tasklet); + + DBprintk(("free ctx @%p\n", ctx)); + kfree(ctx); + } } static int @@ -715,7 +792,7 @@ page = pfm_kvirt_to_pa(buf); if (remap_page_range(addr, page, PAGE_SIZE, PAGE_READONLY)) return -ENOMEM; - + addr += PAGE_SIZE; buf += PAGE_SIZE; size -= PAGE_SIZE; @@ -873,7 +950,7 @@ vma->vm_end = vma->vm_start + size; DBprintk(("entries=%ld aligned size=%ld, unmapped @0x%lx\n", entries, size, vma->vm_start)); - + /* can only be applied to current, need to have the mm semaphore held when called */ if (pfm_remap_buffer((unsigned long)smpl_buf, vma->vm_start, size)) { DBprintk(("Can't remap buffer\n")); @@ -991,7 +1068,7 @@ pfm_sessions.pfs_sys_use_dbregs, is_syswide, cpu_mask)); - + if (is_syswide) { m = cpu_mask; n = 0; @@ -1005,7 +1082,8 @@ */ if (ctx && ctx->ctx_fl_using_dbreg) { if (pfm_sessions.pfs_sys_use_dbregs == 0) { - printk("perfmon: invalid release for [%d] sys_use_dbregs=0\n", task->pid); + printk(KERN_DEBUG "perfmon: invalid release for [%d] " + "sys_use_dbregs=0\n", task->pid); } else { pfm_sessions.pfs_sys_use_dbregs--; } @@ -1025,7 +1103,44 @@ return 0; } +static void +pfm_send_notification_signal(unsigned long data) +{ + pfm_context_t *ctx = (pfm_context_t *)data; + struct siginfo si; + int ret; + + DBprintk(("[%d] tasklet called\n", current->pid)); + + LOCK_CTX(ctx); + + if (ctx->ctx_notify_task == NULL) { + printk(KERN_INFO "perfmon: tasklet lost notify_task\n"); + goto nothing_to_do; + } + /* no leak */ + memset(&si,0, sizeof(si)); + si.si_addr = NULL; + si.si_pid = current->pid; /* irrelevant */ + si.si_signo = SIGPROF; + si.si_code = PROF_OVFL; /* indicates a perfmon SIGPROF signal */ + si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0]; + + if (ctx->ctx_notify_task != current) read_lock(&tasklist_lock); + + DBprintk_ovfl(("[%d] tasklet sending notification to [%d]\n", current->pid, ctx->ctx_notify_task->pid)); + + ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); + if (ret != 0) printk(KERN_ERR "send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_task->pid, ret); + + /* + * now undo the protections in order + */ + if (ctx->ctx_notify_task != current) read_unlock(&tasklist_lock); +nothing_to_do: + UNLOCK_CTX(ctx); +} /* * XXX: do something better here @@ -1080,7 +1195,7 @@ * and it must be a valid CPU */ cpu = ffz(~pfx->ctx_cpu_mask); - if (cpu_is_online(cpu) == 0) { + if (cpu_online(cpu) == 0) { DBprintk(("CPU%d is not online\n", cpu)); return -EINVAL; } @@ -1229,6 +1344,7 @@ ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; + ctx->ctx_fl_unsecure = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0; ctx->ctx_fl_frozen = 0; /* * setting this flag to 0 here means, that the creator or the task that the @@ -1242,14 +1358,20 @@ ctx->ctx_cpu = ffz(~tmp.ctx_cpu_mask); /* SMP only, means no CPU */ - atomic_set(&ctx->ctx_last_cpu,-1); - - /* may be redudant with memset() but at least it's easier to remember */ - atomic_set(&ctx->ctx_saving_in_progress, 0); - atomic_set(&ctx->ctx_is_busy, 0); + ctx->ctx_last_activation = PFM_INVALID_ACTIVATION; + SET_LAST_CPU(ctx, -1); sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */ + /* + * initialize tasklet for signal notifications + * + * ALL signal-based (or any notification using data structures + * external to perfmon) MUST use tasklets to avoid lock contentions + * when a signal has to be sent for overflow interrupt handler. + */ + tasklet_init(&ctx->ctx_tasklet, pfm_send_notification_signal, (unsigned long)ctx); + if (__copy_to_user(req, &tmp, sizeof(tmp))) { ret = -EFAULT; goto buffer_error; @@ -1258,9 +1380,11 @@ DBprintk(("context=%p, pid=%d notify_task=%p\n", (void *)ctx, task->pid, ctx->ctx_notify_task)); - DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d\n", + DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d unsecure=%d\n", (void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, - ctx->ctx_fl_block, ctx->ctx_fl_system, ctx->ctx_fl_excl_idle)); + ctx->ctx_fl_block, ctx->ctx_fl_system, + ctx->ctx_fl_excl_idle, + ctx->ctx_fl_unsecure)); /* * when no notification is required, we can make this visible at the last moment @@ -1362,8 +1486,9 @@ pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; unsigned long value, reset_pmds; unsigned int cnum, reg_flags, flags; - int i; - int ret = -EINVAL; + int is_monitor, is_counting; + int i, ret = -EINVAL; +#define PFM_CHECK_PMC_PM(x, y, z) ((x)->ctx_fl_system ^ PMC_PM(y, z)) /* we don't quite support this right now */ if (task != current) return -EINVAL; @@ -1383,6 +1508,9 @@ reset_pmds = tmp.reg_reset_pmds[0]; flags = 0; + is_counting = PMC_IS_COUNTING(cnum); + is_monitor = PMC_IS_MONITOR(cnum); + /* * we reject all non implemented PMC as well * as attempts to modify PMC[0-3] which are used @@ -1393,21 +1521,19 @@ goto error; } /* - * A PMC used to configure monitors must be: - * - system-wide session: privileged monitor - * - per-task : user monitor - * any other configuration is rejected. - */ - if (PMC_IS_MONITOR(cnum) || PMC_IS_COUNTING(cnum)) { - DBprintk(("pmc[%u].pm=%ld\n", cnum, PMC_PM(cnum, value))); - - if (ctx->ctx_fl_system ^ PMC_PM(cnum, value)) { - DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, value), ctx->ctx_fl_system)); - goto error; - } + * If the PMC is a monitor, then if the value is not the default: + * - system-wide session: PMCx.pm=1 (privileged monitor) + * - per-task : PMCx.pm=0 (user monitor) + */ + if ((is_monitor || is_counting) && value != PMC_DFL_VAL(i) && PFM_CHECK_PMC_PM(ctx, cnum, value)) { + DBprintk(("pmc%u pmc_pm=%ld fl_system=%d\n", + cnum, + PMC_PM(cnum, value), + ctx->ctx_fl_system)); + goto error; } - if (PMC_IS_COUNTING(cnum)) { + if (is_counting) { pfm_monitor_t *p = (pfm_monitor_t *)&value; /* * enforce generation of overflow interrupt. Necessary on all @@ -1470,7 +1596,7 @@ */ ctx->ctx_soft_pmds[cnum].flags = flags; - if (PMC_IS_COUNTING(cnum)) { + if (is_counting) { ctx->ctx_soft_pmds[cnum].reset_pmds[0] = reset_pmds; /* mark all PMDS to be accessed as used */ @@ -1591,7 +1717,7 @@ ia64_srlz_d(); DBprintk(("[%d] pmd[%u]: value=0x%lx hw_value=0x%lx soft_pmd=0x%lx short_reset=0x%lx " - "long_reset=0x%lx hw_pmd=%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx\n", + "long_reset=0x%lx hw_pmd=%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx psr=%d\n", task->pid, cnum, value, hw_value, ctx->ctx_soft_pmds[cnum].val, @@ -1600,7 +1726,7 @@ ia64_get_pmd(cnum) & pmu_conf.ovfl_val, PMC_OVFL_NOTIFY(ctx, cnum) ? 'Y':'N', ctx->ctx_used_pmds[0], - ctx->ctx_soft_pmds[cnum].reset_pmds[0])); + ctx->ctx_soft_pmds[cnum].reset_pmds[0], ia64_psr(regs)->sp)); } return 0; @@ -1635,7 +1761,10 @@ int foo; #endif - if (!CTX_IS_ENABLED(ctx)) return -EINVAL; + if (!CTX_IS_ENABLED(ctx)) { + DBprintk(("context for [%d] is disabled\n", task->pid)); + return -EINVAL; + } /* * XXX: MUST MAKE SURE WE DON"T HAVE ANY PENDING OVERFLOW BEFORE READING @@ -1646,7 +1775,10 @@ /* XXX: ctx locking may be required here */ - DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); + /* + * should we need to access the PMU, serialization is needed + */ + ia64_srlz_d(); for (i = 0; i < count; i++, req++) { @@ -1673,36 +1805,20 @@ if (!CTX_IS_USED_PMD(ctx, cnum)) goto abort_mission; /* - * If the task is not the current one, then we check if the - * PMU state is still in the local live register due to lazy ctxsw. - * If true, then we read directly from the registers. + * we can access the registers directly only when task + * is the OWNER of the local PMU. In SMP, this can + * happen only when task == current. In addition + * this can happen when task != currrent but + * only in UP mode. */ - if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){ - ia64_srlz_d(); + if (task == PMU_OWNER()) { val = ia64_get_pmd(cnum); DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val)); } else { -#ifdef CONFIG_SMP - int cpu; - /* - * for SMP system, the context may still be live on another - * CPU so we need to fetch it before proceeding with the read - * This call we only be made once for the whole loop because - * of ctx_last_cpu becoming == -1. - * - * We cannot reuse ctx_last_cpu as it may change before we get to the - * actual IPI call. In this case, we will do the call for nothing but - * there is no way around it. The receiving side will simply do nothing. - */ - cpu = atomic_read(&ctx->ctx_last_cpu); - if (cpu != -1) { - DBprintk(("must fetch on CPU%d for [%d]\n", cpu, task->pid)); - pfm_fetch_regs(cpu, task, ctx); - } -#endif /* context has been saved */ val = th->pmd[cnum]; } + if (PMD_IS_COUNTING(cnum)) { /* * XXX: need to check for overflow @@ -1814,7 +1930,8 @@ LOCK_PFS(); if (pfm_sessions.pfs_ptrace_use_dbregs == 0) { - printk("perfmon: invalid release for [%d] ptrace_use_dbregs=0\n", task->pid); + printk(KERN_DEBUG "perfmon: invalid release for [%d] ptrace_use_dbregs=0\n", + task->pid); ret = -1; } else { pfm_sessions.pfs_ptrace_use_dbregs--; @@ -2051,7 +2168,6 @@ pfm_protect_context(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { - DBprintk(("context from [%d] is protected\n", task->pid)); /* * from now on, only the creator of the context has access to it */ @@ -2060,7 +2176,9 @@ /* * reinforce secure monitoring: cannot toggle psr.up */ - ia64_psr(regs)->sp = 1; + if (ctx->ctx_fl_unsecure == 0) ia64_psr(regs)->sp = 1; + + DBprintk(("[%d] protected psr.sp=%d\n", task->pid, ia64_psr(regs)->sp)); return 0; } @@ -2073,7 +2191,7 @@ pfm_sysctl.debug = mode == 0 ? 0 : 1; - printk("perfmon debugging %s\n", pfm_sysctl.debug ? "on" : "off"); + printk(KERN_INFO "perfmon debugging %s\n", pfm_sysctl.debug ? "on" : "off"); return 0; } @@ -2338,7 +2456,7 @@ current)); if (PMU_OWNER() != task) { - printk("perfmon: pfm_start task [%d] not pmu owner\n", task->pid); + printk(KERN_DEBUG "perfmon: pfm_start task [%d] not pmu owner\n", task->pid); return -EINVAL; } @@ -2359,7 +2477,8 @@ } else { if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) { - printk("perfmon: pfm_start task flag not set for [%d]\n", task->pid); + printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n", + task->pid); return -EINVAL; } /* set user level psr.up */ @@ -2384,8 +2503,10 @@ return -EINVAL; } +#ifndef CONFIG_SMP if (ctx->ctx_fl_system == 0 && PMU_OWNER() && PMU_OWNER() != current) pfm_lazy_save_regs(PMU_OWNER()); +#endif /* reset all registers to stable quiet state */ pfm_reset_pmu(task); @@ -2427,7 +2548,9 @@ SET_PMU_OWNER(task); ctx->ctx_flags.state = PFM_CTX_ENABLED; - atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); + SET_LAST_CPU(ctx, smp_processor_id()); + INC_ACTIVATION(); + SET_ACTIVATION(ctx); /* simply unfreeze */ pfm_unfreeze_pmu(); @@ -2599,12 +2722,15 @@ if (PFM_CMD_CHK(cmd)) { ret = check_task_state(task); - if (ret != 0) goto abort_call; + if (ret != 0) { + DBprintk(("check_task_state=%ld for [%d]\n", ret, task->pid)); + goto abort_call; + } } } } - ctx = task->thread.pfm_context; + ctx = PFM_GET_CTX(task); if (PFM_CMD_USE_CTX(cmd)) { ret = -EINVAL; @@ -2612,6 +2738,8 @@ DBprintk(("no context for task %d\n", task->pid)); goto abort_call; } + + ret = -EPERM; /* * we only grant access to the context if: @@ -2651,7 +2779,7 @@ * do some sanity checks first */ if (!ctx) { - printk("perfmon: [%d] has no PFM context\n", current->pid); + printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); return; } @@ -2701,6 +2829,8 @@ /* * This function will record an entry in the sampling if it is not full already. + * Input: + * ovfl_mask: mask of overflowed PMD. MUST NEVER be 0. * Return: * 0 : buffer is not full (did not BECOME full: still space or was already full) * 1 : buffer is full (recorded the last entry) @@ -2713,8 +2843,6 @@ perfmon_smpl_entry_t *h; int j; - - idx = ia64_fetch_and_add(1, &psb->psb_index); DBprintk_ovfl(("recording index=%ld entries=%ld\n", idx-1, psb->psb_entries)); @@ -2736,7 +2864,7 @@ /* * initialize entry header */ - h->pid = current->pid; + h->pid = ctx->ctx_fl_system ? current->pid : task->pid; h->cpu = smp_processor_id(); h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL; h->ip = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL; @@ -2802,7 +2930,6 @@ unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; int i; int ret = 1; - struct siginfo si; /* * It is never safe to access the task for which the overflow interrupt is destinated * using the current variable as the interrupt may occur in the middle of a context switch @@ -2823,16 +2950,16 @@ * Don't think this could happen given upfront tests */ if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) { - printk("perfmon: Spurious overflow interrupt: process %d not using perfmon\n", - task->pid); + printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not " + "using perfmon\n", task->pid); return 0x1; } /* * sanity test. Should never happen */ if ((pmc0 & 0x1) == 0) { - printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", - task->pid, pmc0); + printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", + task->pid, pmc0); return 0x0; } @@ -2863,7 +2990,7 @@ * taken into consideration here but will be with any read of the pmd via * pfm_read_pmds(). */ - old_val = ctx->ctx_soft_pmds[i].val; + old_val = ctx->ctx_soft_pmds[i].val; ctx->ctx_soft_pmds[i].val += 1 + pmu_conf.ovfl_val; /* @@ -2876,6 +3003,11 @@ if (PMC_OVFL_NOTIFY(ctx, i)) { ovfl_notify |= 1UL << i; } + } else { + /* + * clear top bits (maintain counts in lower part, may not always be zero) + */ + ia64_set_pmd(i, ia64_get_pmd(i) & pmu_conf.ovfl_val); } DBprintk_ovfl(("soft_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n", i, ctx->ctx_soft_pmds[i].val, old_val, @@ -2885,10 +3017,10 @@ /* * check for sampling buffer * - * if present, record sample. We propagate notification ONLY when buffer - * becomes full. + * if present, record sample only when a 64-bit counter has overflowed. + * We propagate notification ONLY when buffer becomes full. */ - if(CTX_HAS_SMPL(ctx)) { + if(CTX_HAS_SMPL(ctx) && ovfl_pmds) { ret = pfm_record_sample(task, ctx, ovfl_pmds, regs); if (ret == 1) { /* @@ -2924,136 +3056,40 @@ ctx->ctx_ovfl_regs[0] = ovfl_pmds; /* + * As a consequence of the overflow, we always resume + * with monitoring turned off. pfm_restart() will + * reactivate. + */ + ctx->ctx_fl_frozen = 1; + + /* * we have come to this point because there was an overflow and that notification * was requested. The notify_task may have disappeared, in which case notify_task * is NULL. */ - if (ctx->ctx_notify_task) { - - si.si_errno = 0; - si.si_addr = NULL; - si.si_pid = task->pid; /* who is sending */ - - si.si_signo = SIGPROF; - si.si_code = PROF_OVFL; /* indicates a perfmon SIGPROF signal */ - /* - * Shift the bitvector such that the user sees bit 4 for PMD4 and so on. - * We only use smpl_ovfl[0] for now. It should be fine for quite a while - * until we have more than 61 PMD available. - */ - si.si_pfm_ovfl[0] = ovfl_notify; - - /* - * when the target of the signal is not ourself, we have to be more - * careful. The notify_task may being cleared by the target task itself - * in release_thread(). We must ensure mutual exclusion here such that - * the signal is delivered (even to a dying task) safely. - */ - - if (ctx->ctx_notify_task != current) { - /* - * grab the notification lock for this task - * This guarantees that the sequence: test + send_signal - * is atomic with regards to the ctx_notify_task field. - * - * We need a spinlock and not just an atomic variable for this. - * - */ - spin_lock(&ctx->ctx_lock); - - /* - * now notify_task cannot be modified until we're done - * if NULL, they it got modified while we were in the handler - */ - if (ctx->ctx_notify_task == NULL) { - - spin_unlock(&ctx->ctx_lock); + LOCK_CTX(ctx); - /* - * If we've lost the notified task, then we will run - * to completion wbut keep the PMU frozen. Results - * will be incorrect anyway. We do not kill task - * to leave it possible to attach perfmon context - * to already running task. - */ - goto lost_notify; - } - /* - * required by send_sig_info() to make sure the target - * task does not disappear on us. - */ - read_lock(&tasklist_lock); + if (ctx->ctx_notify_task) { + if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { + t->pfm_ovfl_block_reset = 1; /* will cause blocking */ + } else { + t->pfm_ovfl_block_reset = 0; } - /* - * in this case, we don't stop the task, we let it go on. It will - * necessarily go to the signal handler (if any) when it goes back to - * user mode. - */ - DBprintk_ovfl(("[%d] sending notification to [%d]\n", - task->pid, ctx->ctx_notify_task->pid)); - - /* - * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock - */ - ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); - if (ret != 0) - printk("send_sig_info(process %d, SIGPROF)=%d\n", - ctx->ctx_notify_task->pid, ret); - /* - * now undo the protections in order - */ - if (ctx->ctx_notify_task != current) { - read_unlock(&tasklist_lock); - spin_unlock(&ctx->ctx_lock); - } + DBprintk_ovfl(("[%d] scheduling tasklet\n", current->pid)); /* - * if we block set the pfm_must_block bit - * when in block mode, we can effectively block only when the notified - * task is not self, otherwise we would deadlock. - * in this configuration, the notification is sent, the task will not - * block on the way back to user mode, but the PMU will be kept frozen - * until PFM_RESTART. - * Note that here there is still a race condition with notify_task - * possibly being nullified behind our back, but this is fine because - * it can only be changed to NULL which by construction, can only be - * done when notify_task != current. So if it was already different - * before, changing it to NULL will still maintain this invariant. - * Of course, when it is equal to current it cannot change at this point. - */ - DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", - ctx->ctx_fl_block, - ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, - current->pid )); + * the tasklet is responsible for sending the notification + * not the PMU owner nor the current task. + */ + tasklet_schedule(&ctx->ctx_tasklet); - if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ - } } else { -lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */ - DBprintk_ovfl(("notification task has disappeared !\n")); - /* - * for a non-blocking context, we make sure we do not fall into the - * pfm_overflow_notify() trap. Also in the case of a blocking context with lost - * notify process, then we do not want to block either (even though it is - * interruptible). In this case, the PMU will be kept frozen and the process will - * run to completion without monitoring enabled. - * - * Of course, we cannot loose notify process when self-monitoring. - */ - t->pfm_ovfl_block_reset = 0; - + t->pfm_ovfl_block_reset = 0; } - /* - * If notification was successful, then we rely on the pfm_restart() - * call to unfreeze and reset (in both blocking or non-blocking mode). - * - * If notification failed, then we will keep the PMU frozen and run - * the task to completion - */ - ctx->ctx_fl_frozen = 1; + + UNLOCK_CTX(ctx); DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n", ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset)); @@ -3084,37 +3120,23 @@ * This is slow */ pmc0 = ia64_get_pmc(0); - + task = PMU_OWNER(); /* * if we have some pending bits set * assumes : if any PM[0].bit[63-1] is set, then PMC[0].fr = 1 */ - if ((pmc0 & ~0x1UL)!=0UL && (task=PMU_OWNER())!= NULL) { + if (PMC0_HAS_OVFL(pmc0) && task) { /* * we assume that pmc0.fr is always set here */ - ctx = task->thread.pfm_context; + ctx = PFM_GET_CTX(task); /* sanity check */ if (!ctx) { - printk("perfmon: Spurious overflow interrupt: process %d has no PFM context\n", - task->pid); + printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has " + "no PFM context\n", task->pid); return; } -#ifdef CONFIG_SMP - /* - * Because an IPI has higher priority than the PMU overflow interrupt, it is - * possible that the handler be interrupted by a request from another CPU to fetch - * the PMU state of the currently active context. The task may have just been - * migrated to another CPU which is trying to restore the context. If there was - * a pending overflow interrupt when the task left this CPU, it is possible for - * the handler to get interrupt by the IPI. In which case, we fetch request - * MUST be postponed until the interrupt handler is done. The ctx_is_busy - * flag indicates such a condition. The other CPU must busy wait until it's cleared. - */ - atomic_set(&ctx->ctx_is_busy, 1); -#endif - /* * assume PMC[0].fr = 1 at this point */ @@ -3122,26 +3144,21 @@ /* * we can only update pmc0 when the overflow - * is for the current context. In UP the current - * task may not be the one owning the PMU + * is for the current context or we are in system + * wide mode. In UP (per-task) the current + * task may not be the one owning the PMU, + * same thing for system-wide. */ - if (task == current) { + if (task == current || ctx->ctx_fl_system) { /* - * We always clear the overflow status bits and either unfreeze - * or keep the PMU frozen. - */ + * We always clear the overflow status bits and either unfreeze + * or keep the PMU frozen. + */ ia64_set_pmc(0, pmc0); ia64_srlz_d(); } else { task->thread.pmc[0] = pmc0; } - -#ifdef CONFIG_SMP - /* - * announce that we are doing with the context - */ - atomic_set(&ctx->ctx_is_busy, 0); -#endif } else { pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } @@ -3158,7 +3175,7 @@ p += sprintf(p, "ovfl_mask : 0x%lx\n", pmu_conf.ovfl_val); for(i=0; i < NR_CPUS; i++) { - if (cpu_is_online(i) == 0) continue; + if (cpu_online(i) == 0) continue; p += sprintf(p, "CPU%-2d overflow intrs : %lu\n", i, pfm_stats[i].pfm_ovfl_intr_count); p += sprintf(p, "CPU%-2d spurious intrs : %lu\n", i, pfm_stats[i].pfm_spurious_ovfl_intr_count); p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count); @@ -3167,6 +3184,7 @@ p += sprintf(p, "CPU%-2d dcr_pp : %d\n", i, cpu_data(i)->pfm_syst_info & PFM_CPUINFO_DCR_PP ? 1 : 0); p += sprintf(p, "CPU%-2d exclude idle : %d\n", i, cpu_data(i)->pfm_syst_info & PFM_CPUINFO_EXCL_IDLE ? 1 : 0); p += sprintf(p, "CPU%-2d owner : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1); + p += sprintf(p, "CPU%-2d activations : %lu\n", i, pmu_owners[i].activation_number); } LOCK_PFS(); @@ -3257,13 +3275,26 @@ } } +#ifdef CONFIG_SMP void -pfm_save_regs (struct task_struct *task) +pfm_save_regs(struct task_struct *task) { pfm_context_t *ctx; + struct thread_struct *t; u64 psr; - ctx = task->thread.pfm_context; + ctx = PFM_GET_CTX(task); + if (ctx == NULL) goto save_error; + t = &task->thread; + + /* + * sanity check + */ + if (ctx->ctx_last_activation != GET_ACTIVATION()) { + DBprintk(("ctx_activation=%lu activation=%lu: no save\n", + ctx->ctx_last_activation, GET_ACTIVATION())); + return; + } /* * save current PSR: needed because we modify it @@ -3272,229 +3303,258 @@ /* * stop monitoring: - * This is the last instruction which can generate an overflow + * This is the last instruction which may generate an overflow * * We do not need to set psr.sp because, it is irrelevant in kernel. * It will be restored from ipsr when going back to user level */ pfm_clear_psr_up(); - ia64_srlz_i(); + /* + * keep a copy of the saved psr (for reload) + */ ctx->ctx_saved_psr = psr; - //ctx->ctx_last_cpu = smp_processor_id(); + /* + * release ownership of this PMU. + */ + SET_PMU_OWNER(NULL); + + /* + * we systematically save the PMD as we have no + * guarantee we will be schedule at that same + * CPU again. + */ + pfm_save_pmds(t->pmd, ctx->ctx_used_pmds[0]); + + /* + * save pmc0 ia64_srlz_d() done in pfm_save_pmds() + * we will need it on the restore path to check + * for pending overflow. + */ + t->pmc[0] = ia64_get_pmc(0); + + return; +save_error: + printk(KERN_ERR "perfmon: pfm_save_regs CPU%d [%d] NULL context PM_VALID=%ld\n", + smp_processor_id(), task->pid, + task->thread.flags & IA64_THREAD_PM_VALID); } -static void -pfm_lazy_save_regs (struct task_struct *task) +#else /* !CONFIG_SMP */ + +void +pfm_save_regs(struct task_struct *task) { pfm_context_t *ctx; - struct thread_struct *t; - unsigned long mask; - int i; - - DBprintk(("on [%d] by [%d]\n", task->pid, current->pid)); + u64 psr; - t = &task->thread; - ctx = task->thread.pfm_context; + ctx = PFM_GET_CTX(task); + if (ctx == NULL) goto save_error; + /* + * save current PSR: needed because we modify it + */ + psr = pfm_get_psr(); -#ifdef CONFIG_SMP - /* - * announce we are saving this PMU state - * This will cause other CPU, to wait until we're done - * before using the context.h + /* + * stop monitoring: + * This is the last instruction which may generate an overflow * - * must be an atomic operation + * We do not need to set psr.sp because, it is irrelevant in kernel. + * It will be restored from ipsr when going back to user level */ - atomic_set(&ctx->ctx_saving_in_progress, 1); - - /* - * if owner is NULL, it means that the other CPU won the race - * and the IPI has caused the context to be saved in pfm_handle_fectch_regs() - * instead of here. We have nothing to do - * - * note that this is safe, because the other CPU NEVER modifies saving_in_progress. - */ - if (PMU_OWNER() == NULL) goto do_nothing; -#endif + pfm_clear_psr_up(); /* - * do not own the PMU + * keep a copy of the saved psr (for reload) */ - SET_PMU_OWNER(NULL); + ctx->ctx_saved_psr = psr; - ia64_srlz_d(); + return; +save_error: + printk(KERN_ERR "perfmon: pfm_save_regs CPU%d [%d] NULL context PM_VALID=%ld\n", + smp_processor_id(), task->pid, + task->thread.flags & IA64_THREAD_PM_VALID); +} - /* - * XXX needs further optimization. - * Also must take holes into account - */ - mask = ctx->ctx_used_pmds[0]; - for (i=0; mask; i++, mask>>=1) { - if (mask & 0x1) t->pmd[i] =ia64_get_pmd(i); - } +static unsigned long +pfm_lazy_save_regs (struct task_struct *task) +{ + pfm_context_t *ctx; + struct thread_struct *t; - /* save pmc0 */ - t->pmc[0] = ia64_get_pmc(0); + ctx = PFM_GET_CTX(task); + t = &task->thread; - /* not owned by this CPU */ - atomic_set(&ctx->ctx_last_cpu, -1); + DBprintk(("on [%d] used_pmds=0x%lx\n", task->pid, ctx->ctx_used_pmds[0])); -#ifdef CONFIG_SMP -do_nothing: -#endif /* - * declare we are done saving this context + * release ownership of this PMU. + * must be done before we save the registers. * - * must be an atomic operation + * after this call any PMU interrupt is treated + * as spurious. */ - atomic_set(&ctx->ctx_saving_in_progress,0); + SET_PMU_OWNER(NULL); + /* + * save all the pmds we use + */ + pfm_save_pmds(t->pmd, ctx->ctx_used_pmds[0]); + + /* + * save pmc0 ia64_srlz_d() done in pfm_save_pmds() + * it is needed to check for pended overflow + * on the restore path + */ + t->pmc[0] = ia64_get_pmc(0); + + return t->pmc[0]; } +#endif /* CONFIG_SMP */ #ifdef CONFIG_SMP -/* - * Handles request coming from other CPUs - */ -static void -pfm_handle_fetch_regs(void *info) +void +pfm_load_regs (struct task_struct *task) { - pfm_smp_ipi_arg_t *arg = info; - struct thread_struct *t; pfm_context_t *ctx; - unsigned long mask; - int i; - - ctx = arg->task->thread.pfm_context; - t = &arg->task->thread; + struct thread_struct *t; + struct task_struct *owner; + unsigned long pmc_mask = 0UL, pmd_mask = 0UL; + u64 psr; - DBprintk(("task=%d owner=%d saving=%d\n", - arg->task->pid, - PMU_OWNER() ? PMU_OWNER()->pid: -1, - atomic_read(&ctx->ctx_saving_in_progress))); - - /* must wait until not busy before retrying whole request */ - if (atomic_read(&ctx->ctx_is_busy)) { - arg->retval = 2; + ctx = PFM_GET_CTX(task); + if (unlikely(ctx == NULL)) { + printk(KERN_ERR "perfmon: pfm_load_regs() null context\n"); return; } - /* must wait if saving was interrupted */ - if (atomic_read(&ctx->ctx_saving_in_progress)) { - arg->retval = 1; - return; - } + owner = PMU_OWNER(); + t = &task->thread; - /* can proceed, done with context */ - if (PMU_OWNER() != arg->task) { - arg->retval = 0; + /* + * possible on unload + */ + if ((t->flags & IA64_THREAD_PM_VALID) == 0) { + DBprintk(("[%d] PM_VALID=0, nothing to do\n", task->pid)); return; } - DBprintk(("saving state for [%d] used_pmcs=0x%lx reload_pmcs=0x%lx used_pmds=0x%lx\n", - arg->task->pid, - ctx->ctx_used_pmcs[0], - ctx->ctx_reload_pmcs[0], - ctx->ctx_used_pmds[0])); - /* - * XXX: will be replaced with pure assembly call + * we restore ALL the debug registers to avoid picking up + * stale state. + * + * This must be done even when the task is still the owner + * as the registers may have been modified via ptrace() + * (not perfmon) by the previous task. */ - SET_PMU_OWNER(NULL); - - ia64_srlz_d(); + if (ctx->ctx_fl_using_dbreg) { + pfm_restore_ibrs(t->ibr, pmu_conf.num_ibrs); + pfm_restore_dbrs(t->dbr, pmu_conf.num_dbrs); + } /* - * XXX needs further optimization. + * retrieve saved psr */ - mask = ctx->ctx_used_pmds[0]; - for (i=0; mask; i++, mask>>=1) { - if (mask & 0x1) t->pmd[i] = ia64_get_pmd(i); - } - - /* save pmc0 */ - t->pmc[0] = ia64_get_pmc(0); - - /* not owned by this CPU */ - atomic_set(&ctx->ctx_last_cpu, -1); + psr = ctx->ctx_saved_psr; - /* can proceed */ - arg->retval = 0; -} + /* + * if we were the last user of the PMU on that CPU, + * then nothing to do except restore psr + */ + if (GET_LAST_CPU(ctx) == smp_processor_id() && ctx->ctx_last_activation == GET_ACTIVATION()) { + /* + * retrieve partial reload masks (due to user modifications) + */ + pmc_mask = 0UL; + pmd_mask = 0UL; -/* - * Function call to fetch PMU state from another CPU identified by 'cpu'. - * If the context is being saved on the remote CPU, then we busy wait until - * the saving is done and then we return. In this case, non IPI is sent. - * Otherwise, we send an IPI to the remote CPU, potentially interrupting - * pfm_lazy_save_regs() over there. - * - * If the retval==1, then it means that we interrupted remote save and that we must - * wait until the saving is over before proceeding. - * Otherwise, we did the saving on the remote CPU, and it was done by the time we got there. - * in either case, we can proceed. - */ -static void -pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx) -{ - pfm_smp_ipi_arg_t arg; - int ret; + if (pmc_mask || pmd_mask) DBprintk(("partial reload [%d] pmd_mask=0x%lx pmc_mask=0x%lx\n", task->pid, pmd_mask, pmc_mask)); + } else { + /* + * To avoid leaking information to the user level when psr.sp=0, + * we must reload ALL implemented pmds (even the ones we don't use). + * In the kernel we only allow PFM_READ_PMDS on registers which + * we initialized or requested (sampling) so there is no risk there. + */ + pmd_mask = pfm_sysctl.fastctxsw ? ctx->ctx_used_pmds[0] : ctx->ctx_reload_pmds[0]; - arg.task = task; - arg.retval = -1; + /* + * ALL accessible PMCs are systematically reloaded, unused registers + * get their default (from pfm_reset_pmu_state()) values to avoid picking + * up stale configuration. + * + * PMC0 is never in the mask. It is always restored separately. + */ + pmc_mask = ctx->ctx_reload_pmcs[0]; + + DBprintk(("full reload for [%d] owner=%d activation=%lu last_activation=%lu last_cpu=%d pmd_mask=0x%lx pmc_mask=0x%lx\n", + task->pid, owner ? owner->pid : -1, + GET_ACTIVATION(), ctx->ctx_last_activation, + GET_LAST_CPU(ctx), pmd_mask, pmc_mask)); - if (atomic_read(&ctx->ctx_is_busy)) { -must_wait_busy: - while (atomic_read(&ctx->ctx_is_busy)); } + + if (pmd_mask) pfm_restore_pmds(t->pmd, pmd_mask); + if (pmc_mask) pfm_restore_pmcs(t->pmc, pmc_mask); - if (atomic_read(&ctx->ctx_saving_in_progress)) { - DBprintk(("no IPI, must wait for [%d] to be saved on [%d]\n", task->pid, cpu)); -must_wait_saving: - /* busy wait */ - while (atomic_read(&ctx->ctx_saving_in_progress)); - DBprintk(("done saving for [%d] on [%d]\n", task->pid, cpu)); - return; + /* + * check for pending overflow at the time the state + * was saved. + */ + if (PMC0_HAS_OVFL(t->pmc[0])) { + struct pt_regs *regs = TASK_PTREGS(task); + pfm_overflow_handler(task, ctx, t->pmc[0], regs); } - DBprintk(("calling CPU %d from CPU %d\n", cpu, smp_processor_id())); - if (cpu == -1) { - printk("refusing to use -1 for [%d]\n", task->pid); - return; + /* + * fl_frozen==1 when we are in blocking mode waiting for restart + */ + if (ctx->ctx_fl_frozen == 0) { + pfm_unfreeze_pmu(); } - /* will send IPI to other CPU and wait for completion of remote call */ - if ((ret=smp_call_function_single(cpu, pfm_handle_fetch_regs, &arg, 0, 1))) { - printk("perfmon: remote CPU call from %d to %d error %d\n", smp_processor_id(), cpu, ret); - return; - } + SET_LAST_CPU(ctx, smp_processor_id()); + /* - * we must wait until saving is over on the other CPU - * This is the case, where we interrupted the saving which started just at the time we sent the - * IPI. + * dump activation value for this PMU */ - if (arg.retval == 1) goto must_wait_saving; - if (arg.retval == 2) goto must_wait_busy; -} -#endif /* CONFIG_SMP */ + INC_ACTIVATION(); + /* + * record current activation for this context + */ + SET_ACTIVATION(ctx); + /* + * establish new ownership. Interrupts + * are still masked at this point. + */ + SET_PMU_OWNER(task); + + /* + * restore the psr we changed + */ + pfm_set_psr_l(psr); + +} +#else /* !CONFIG_SMP */ +/* + * reload PMU state for UP kernels + */ void pfm_load_regs (struct task_struct *task) { struct thread_struct *t; pfm_context_t *ctx; struct task_struct *owner; - unsigned long mask; + unsigned long pmd_mask, pmc_mask; + unsigned long prev_pmc0 = ~0UL; u64 psr; - int i; -#ifdef CONFIG_SMP - int cpu; -#endif - owner = PMU_OWNER(); - ctx = task->thread.pfm_context; - t = &task->thread; + owner = PMU_OWNER(); + ctx = PFM_GET_CTX(task); + t = &task->thread; /* * we restore ALL the debug registers to avoid picking up @@ -3503,105 +3563,112 @@ * This must be done even when the task is still the owner * as the registers may have been modified via ptrace() * (not perfmon) by the previous task. - * - * XXX: dealing with this in a lazy fashion requires modifications - * to the way the the debug registers are managed. This is will done - * in the next version of perfmon. */ if (ctx->ctx_fl_using_dbreg) { - for (i=0; i < pmu_conf.num_ibrs; i++) { - ia64_set_ibr(i, t->ibr[i]); - } - ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { - ia64_set_dbr(i, t->dbr[i]); - } - ia64_srlz_d(); + pfm_restore_ibrs(t->ibr, pmu_conf.num_ibrs); + pfm_restore_dbrs(t->dbr, pmu_conf.num_dbrs); } /* - * if we were the last user, then nothing to do except restore psr + * retrieved save psr */ - if (owner == task) { - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) - DBprintk(("invalid last_cpu=%d for [%d]\n", - atomic_read(&ctx->ctx_last_cpu), task->pid)); + psr = ctx->ctx_saved_psr; - psr = ctx->ctx_saved_psr; + /* + * short path, our state is still there, just + * need to restore psr and we go + * + * we do not touch either PMC nor PMD. the psr is not touched + * by the overflow_handler. So we are safe w.r.t. to interrupt + * concurrency even without interrupt masking. + */ + if (owner == task) { pfm_set_psr_l(psr); - return; } - DBprintk(("load_regs: must reload for [%d] owner=%d\n", - task->pid, owner ? owner->pid : -1 )); + + DBprintk(("reload for [%d] owner=%d\n", task->pid, owner ? owner->pid : -1)); + /* * someone else is still using the PMU, first push it out and * then we'll be able to install our stuff ! + * + * Upon return, there will be no owner for the current PMU */ - if (owner) pfm_lazy_save_regs(owner); - -#ifdef CONFIG_SMP - /* - * check if context on another CPU (-1 means saved) - * We MUST use the variable, as last_cpu may change behind our - * back. If it changes to -1 (not on a CPU anymore), then in cpu - * we have the last CPU the context was on. We may be sending the - * IPI for nothing, but we have no way of verifying this. - */ - cpu = atomic_read(&ctx->ctx_last_cpu); - if (cpu != -1) { - pfm_fetch_regs(cpu, task, ctx); - } -#endif - + if (owner) prev_pmc0 = pfm_lazy_save_regs(owner); /* * To avoid leaking information to the user level when psr.sp=0, * we must reload ALL implemented pmds (even the ones we don't use). * In the kernel we only allow PFM_READ_PMDS on registers which * we initialized or requested (sampling) so there is no risk there. - * - * As an optimization, we will only reload the PMD that we use when - * the context is in protected mode, i.e. psr.sp=1 because then there - * is no leak possible. */ - mask = pfm_sysctl.fastctxsw || ctx->ctx_fl_protected ? ctx->ctx_used_pmds[0] : ctx->ctx_reload_pmds[0]; - for (i=0; mask; i++, mask>>=1) { - if (mask & 0x1) ia64_set_pmd(i, t->pmd[i] & pmu_conf.ovfl_val); - } - + pmd_mask = pfm_sysctl.fastctxsw ? ctx->ctx_used_pmds[0] : ctx->ctx_reload_pmds[0]; + /* - * PMC0 is never set in the mask because it is always restored - * separately. + * ALL accessible PMCs are systematically reloaded, unused registers + * get their default (from pfm_reset_pmu_state()) values to avoid picking + * up stale configuration. * - * ALL PMCs are systematically reloaded, unused registers - * get their default (PAL reset) values to avoid picking up - * stale configuration. + * PMC0 is never in the mask. It is always restored separately. */ - mask = ctx->ctx_reload_pmcs[0]; - for (i=0; mask; i++, mask>>=1) { - if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]); - } + pmc_mask = ctx->ctx_reload_pmcs[0]; + + pfm_restore_pmds(t->pmd, pmd_mask); + pfm_restore_pmcs(t->pmc, pmc_mask); - if (t->pmc[0] & ~0x1) { - pfm_overflow_handler(task, ctx, t->pmc[0], NULL); + /* + * Check for pending overflow when state was last saved. + * invoked handler is overflow status bits set. + * + * Any PMU overflow in flight at this point, will still + * be treated as spurious because we have no declared + * owner. Note that the first level interrupt handler + * DOES NOT TOUCH any PMC except PMC0 for which we have + * a copy already. + */ + if (PMC0_HAS_OVFL(t->pmc[0])) { + struct pt_regs *regs = TASK_PTREGS(task); + pfm_overflow_handler(task, ctx, t->pmc[0], regs); } + + /* * fl_frozen==1 when we are in blocking mode waiting for restart */ if (ctx->ctx_fl_frozen == 0) { pfm_unfreeze_pmu(); + } else if (prev_pmc0 == 0UL && ctx->ctx_fl_frozen) { + /* + * owner is still NULL at this point. + * + * if the previous owner (from lazy_save_regs()) + * was not in frozen state, then we need to freeze + * the PMU if the new context is frozen. + * + * on McKinley this will generate a spurious interrupt + * but we have no other way. + */ + pfm_freeze_pmu(); } - atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); + /* + * establish new ownership. If there was an in-flight + * overflow interrupt, it will be treated as spurious + * before and after the call, because no overflow + * status bit can possibly be set. No new overflow + * can be generated because, at this point, psr.up + * is still cleared. + */ SET_PMU_OWNER(task); /* - * restore the psr we changed in pfm_save_regs() + * restore the psr. This is the point at which + * new overflow interrupts can be generated again. */ - psr = ctx->ctx_saved_psr; pfm_set_psr_l(psr); } +#endif /* CONFIG_SMP */ /* * XXX: make this routine able to work with non current context @@ -3798,9 +3865,11 @@ * waitpid(). * */ - - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) - printk("perfmon: [%d] last_cpu=%d\n", task->pid, atomic_read(&ctx->ctx_last_cpu)); +#ifdef CONFIG_SMP + if (GET_LAST_CPU(ctx) != smp_processor_id()) + printk(KERN_DEBUG "perfmon: [%d] last_cpu=%d\n", + task->pid, GET_LAST_CPU(ctx)); +#endif /* * we save all the used pmds @@ -3847,11 +3916,7 @@ task->thread.pmd[i] = val; } } - /* - * indicates that context has been saved - */ - atomic_set(&ctx->ctx_last_cpu, -1); - + SET_LAST_CPU(ctx, -1); } @@ -3875,10 +3940,15 @@ thread = &task->thread; /* - * make sure child cannot mess up the monitoring session + * for secure sessions, make sure child cannot mess up + * the monitoring session. */ - ia64_psr(regs)->sp = 1; - DBprintk(("enabling psr.sp for [%d]\n", task->pid)); + if (ctx->ctx_fl_unsecure == 0) { + ia64_psr(regs)->sp = 1; + DBprintk(("enabling psr.sp for [%d]\n", task->pid)); + } else { + DBprintk(("psr.sp=%d [%d]\n", ia64_psr(regs)->sp, task->pid)); + } /* @@ -3938,7 +4008,6 @@ /* copy content */ *nctx = *ctx; - if (CTX_INHERIT_MODE(ctx) == PFM_FL_INHERIT_ONCE) { nctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE; DBprintk(("downgrading to INHERIT_NONE for [%d]\n", task->pid)); @@ -3978,7 +4047,7 @@ nctx->ctx_fl_frozen = 0; nctx->ctx_ovfl_regs[0] = 0UL; - atomic_set(&nctx->ctx_last_cpu, -1); + SET_LAST_CPU(nctx, -1); /* * here nctx->ctx_psb == ctx->ctx_psb @@ -4014,6 +4083,21 @@ */ nctx->ctx_saved_psr = pfm_get_psr(); + /* + * force a full reload on ctxsw in + */ + nctx->ctx_last_activation = PFM_INVALID_ACTIVATION; + SET_LAST_CPU(nctx, -1); + + /* + * initialize tasklet for signal notifications + * + * ALL signal-based (or any notification using data structures + * external to perfmon) MUST use tasklets to avoid lock contentions + * when a signal has to be sent for overflow interrupt handler. + */ + tasklet_init(&nctx->ctx_tasklet, pfm_send_notification_signal, (unsigned long)nctx); + /* link with new task */ thread->pfm_context = nctx; @@ -4027,7 +4111,6 @@ DBprintk(("setting PM_VALID for [%d]\n", task->pid)); thread->flags |= IA64_THREAD_PM_VALID; } - return 0; } @@ -4171,7 +4254,7 @@ pfm_smpl_buffer_desc_t *tmp, *psb = task->thread.pfm_smpl_buf_list; if (psb == NULL) { - printk("perfmon: psb is null in [%d]\n", current->pid); + printk(KERN_DEBUG "perfmon: psb is null in [%d]\n", current->pid); return -1; } /* @@ -4331,7 +4414,8 @@ if (ret) return ret; if (pfm_alternate_intr_handler) { - printk("perfmon: install_alternate, intr_handler not NULL after reserve\n"); + printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL " + "after reserve\n"); return -EINVAL; } @@ -4368,10 +4452,8 @@ pmu_conf.disabled = 1; - printk("perfmon: version %u.%u IRQ %u\n", - PFM_VERSION_MAJ, - PFM_VERSION_MIN, - IA64_PERFMON_VECTOR); + printk(KERN_INFO "perfmon: version %u.%u IRQ %u\n", PFM_VERSION_MAJ, PFM_VERSION_MIN, + IA64_PERFMON_VECTOR); /* * compute the number of implemented PMD/PMC from the @@ -4395,8 +4477,8 @@ pmu_conf.num_pmds = n; pmu_conf.num_counters = n_counters; - printk("perfmon: %u PMCs, %u PMDs, %u counters (%lu bits)\n", - pmu_conf.num_pmcs, + printk(KERN_INFO "perfmon: %u PMCs, %u PMDs, %u counters (%lu bits)\n", + pmu_conf.num_pmcs, pmu_conf.num_pmds, pmu_conf.num_counters, ffz(pmu_conf.ovfl_val)); @@ -4413,7 +4495,7 @@ perfmon_dir = create_proc_read_entry ("perfmon", 0, 0, perfmon_read_entry, NULL); if (perfmon_dir == NULL) { printk(KERN_ERR "perfmon: cannot create /proc entry, perfmon disabled\n"); - return -1; + return -1; } /* diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/perfmon_mckinley.h linux2.4.21_itanium/arch/ia64/kernel/perfmon_mckinley.h --- linux2.4.21_itanium.org/arch/ia64/kernel/perfmon_mckinley.h Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/perfmon_mckinley.h Wed Jul 23 18:28:57 2003 @@ -25,8 +25,8 @@ /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff3ffffffbUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff3ffffffbUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, @@ -143,11 +143,8 @@ case 8: val8 = *val; val13 = th->pmc[13]; val14 = th->pmc[14]; - *val |= 1UL << 2; /* bit 2 must always be 1 */ check_case1 = 1; break; - case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */ - break; case 13: val8 = th->pmc[8]; val13 = *val; val14 = th->pmc[14]; @@ -163,12 +160,12 @@ * i-side events in L1D and L2 caches */ if (check_case1) { - ret = ((val13 >> 45) & 0xf) == 0 + ret = ((val13 >> 45) & 0xf) == 0 && ((val8 & 0x1) == 0) && ((((val14>>1) & 0x3) == 0x2 || ((val14>>1) & 0x3) == 0x0) ||(((val14>>4) & 0x3) == 0x2 || ((val14>>4) & 0x3) == 0x0)); - if (ret) printk("perfmon: failure check_case1\n"); + if (ret) printk(KERN_DEBUG "perfmon: failure check_case1\n"); } return ret ? -EINVAL : 0; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/process.c linux2.4.21_itanium/arch/ia64/kernel/process.c --- linux2.4.21_itanium.org/arch/ia64/kernel/process.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/process.c Wed Jul 23 18:28:57 2003 @@ -33,10 +33,13 @@ #include #endif -static void -do_show_stack (struct unw_frame_info *info, void *arg) +#define print_symbol(fmt, addr) printk(fmt, ""); + +void +ia64_do_show_stack (struct unw_frame_info *info, void *arg) { unsigned long ip, sp, bsp; + char buf[80]; /* don't make it so big that it overflows the stack! */ printk("\nCall Trace: "); do { @@ -46,29 +49,28 @@ unw_get_sp(info, &sp); unw_get_bsp(info, &bsp); - printk("[<%016lx>] sp=0x%016lx bsp=0x%016lx\n", ip, sp, bsp); + snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n", + ip, sp, bsp); + print_symbol(buf, ip); } while (unw_unwind(info) >= 0); } void show_trace_task (struct task_struct *task) { - struct unw_frame_info info; - - unw_init_from_blocked_task(&info, task); - do_show_stack(&info, 0); + show_stack(task); } void show_stack (struct task_struct *task) { if (!task) - unw_init_running(do_show_stack, 0); + unw_init_running(ia64_do_show_stack, 0); else { struct unw_frame_info info; unw_init_from_blocked_task(&info, task); - do_show_stack(&info, 0); + ia64_do_show_stack(&info, 0); } } @@ -119,7 +121,7 @@ } } if (!user_mode(regs)) - show_stack(0); + show_stack(NULL); } void __attribute__((noreturn)) @@ -331,6 +333,7 @@ # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); + ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ #ifdef CONFIG_IA32_SUPPORT /* * If we're cloning an IA32 task then save the IA32 extra @@ -492,6 +495,15 @@ tid = clone(flags | CLONE_VM, 0); if (parent != current) { +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(ia64_task_regs(current))) { + /* A kernel thread is always a 64-bit process. */ + current->thread.map_base = DEFAULT_MAP_BASE; + current->thread.task_size = DEFAULT_TASK_SIZE; + ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); + ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); + } +#endif result = (*fn)(arg); _exit(result); } @@ -506,11 +518,7 @@ { /* drop floating-point and debug-register state if it exists: */ current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); - -#ifndef CONFIG_SMP - if (ia64_get_fpu_owner() == current) - ia64_set_fpu_owner(0); -#endif + ia64_drop_fpu(current); } #ifdef CONFIG_PERFMON @@ -548,10 +556,7 @@ void exit_thread (void) { -#ifndef CONFIG_SMP - if (ia64_get_fpu_owner() == current) - ia64_set_fpu_owner(0); -#endif + ia64_drop_fpu(current); #ifdef CONFIG_PERFMON /* stop monitoring */ if (current->thread.pfm_context) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/ptrace.c linux2.4.21_itanium/arch/ia64/kernel/ptrace.c --- linux2.4.21_itanium.org/arch/ia64/kernel/ptrace.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/ptrace.c Wed Jul 23 18:28:57 2003 @@ -1,7 +1,7 @@ /* * Kernel support for the ptrace() and syscall tracing interfaces. * - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2003 Hewlett-Packard Co * David Mosberger-Tang * * Derived from the x86 and Alpha versions. Most of the code in here @@ -25,7 +25,7 @@ #include #include #ifdef CONFIG_PERFMON -# include +#include #endif /* @@ -198,20 +198,27 @@ * rnat0/rnat1 gets its value from sw->ar_rnat. */ static unsigned long -get_rnat (struct pt_regs *pt, struct switch_stack *sw, - unsigned long *krbs, unsigned long *urnat_addr) +get_rnat (struct task_struct *task, struct switch_stack *sw, + unsigned long *krbs, unsigned long *urnat_addr, unsigned long *urbs_end) { - unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL; + unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0, mask, m; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; - long num_regs; + long num_regs, nbits; + struct pt_regs *pt; + pt = ia64_task_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; + + if (urbs_end < urnat_addr) + nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_end); + else + nbits = 63; + mask = (1UL << nbits) - 1; /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); @@ -221,20 +228,26 @@ if (ubspstore + 63 > urnat_addr) { /* some bits need to be merged in from pt->ar_rnat */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - urnat = (pt->ar_rnat & ~kmask); + umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1) & mask; + urnat = (pt->ar_rnat & umask); + mask &= ~umask; + if (!mask) + return urnat; } - if (rnat0_kaddr >= kbsp) { + + m = mask << shift; + if (rnat0_kaddr >= kbsp) rnat0 = sw->ar_rnat; - } else if (rnat0_kaddr > krbs) { + else if (rnat0_kaddr > krbs) rnat0 = *rnat0_kaddr; - } - if (rnat1_kaddr >= kbsp) { + urnat |= (rnat0 & m) >> shift; + + m = mask >> (63 - shift); + if (rnat1_kaddr >= kbsp) rnat1 = sw->ar_rnat; - } else if (rnat1_kaddr > krbs) { + else if (rnat1_kaddr > krbs) rnat1 = *rnat1_kaddr; - } - urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask; + urnat |= (rnat1 & m) << (63 - shift); return urnat; } @@ -242,22 +255,49 @@ * The reverse of get_rnat. */ static void -put_rnat (struct pt_regs *pt, struct switch_stack *sw, - unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat) +put_rnat (struct task_struct *task, struct switch_stack *sw, + unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat, + unsigned long *urbs_end) { - unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask; + unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; - long num_regs; + long num_regs, nbits; + struct pt_regs *pt; + unsigned long cfm, *urbs_kargs; + struct unw_frame_info info; + pt = ia64_task_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; + + urbs_kargs = urbs_end; + if ((long)pt->cr_ifs >= 0) { + /* + * If entered via syscall, don't allow user to set rnat bits + * for syscall args. + */ + unw_init_from_blocked_task(&info,task); + if (unw_unwind_to_user(&info) == 0) { + unw_get_cfm(&info,&cfm); + urbs_kargs = ia64_rse_skip_regs(urbs_end,-(cfm & 0x7f)); + } + } + + if (urbs_kargs >= urnat_addr) + nbits = 63; + else { + if ((urnat_addr - 63) >= urbs_kargs) + return; + nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_kargs); + } + mask = (1UL << nbits) - 1; + /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ - num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1); + num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); shift = ia64_rse_slot_num(slot0_kaddr); rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr); @@ -265,28 +305,29 @@ if (ubspstore + 63 > urnat_addr) { /* some bits need to be place in pt->ar_rnat: */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask); + umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1) & mask; + pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask); + mask &= ~umask; + if (!mask) + return; } /* * Note: Section 11.1 of the EAS guarantees that bit 63 of an * rnat slot is ignored. so we don't have to clear it here. */ rnat0 = (urnat << shift); - mask = ~0UL << shift; - if (rnat0_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask); - } else if (rnat0_kaddr > krbs) { - *rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask)); - } + m = mask << shift; + if (rnat0_kaddr >= kbsp) + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m); + else if (rnat0_kaddr > krbs) + *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m)); rnat1 = (urnat >> (63 - shift)); - mask = ~0UL >> (63 - shift); - if (rnat1_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask); - } else if (rnat1_kaddr > krbs) { - *rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask)); - } + m = mask >> (63 - shift); + if (rnat1_kaddr >= kbsp) + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m); + else if (rnat1_kaddr > krbs) + *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m)); } /* @@ -319,7 +360,7 @@ * read the corresponding bits in the kernel RBS. */ rnat_addr = ia64_rse_rnat_addr(laddr); - ret = get_rnat(child_regs, child_stack, krbs, rnat_addr); + ret = get_rnat(child, child_stack, krbs, rnat_addr, urbs_end); if (laddr == rnat_addr) { /* return NaT collection word itself */ @@ -370,7 +411,7 @@ * => write the corresponding bits in the kernel RBS. */ if (ia64_rse_is_rnat_slot(laddr)) - put_rnat(child_regs, child_stack, krbs, laddr, val); + put_rnat(child, child_stack, krbs, laddr, val, urbs_end); else { if (laddr < urbs_end) { regnum = ia64_rse_num_regs(bspstore, laddr); @@ -578,16 +619,11 @@ ia64_flush_fph (struct task_struct *task) { struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); -#ifdef CONFIG_SMP - struct task_struct *fpu_owner = current; -#else - struct task_struct *fpu_owner = ia64_get_fpu_owner(); -#endif - if (task == fpu_owner && psr->mfh) { + if (ia64_is_local_fpu_owner(task) && psr->mfh) { psr->mfh = 0; - ia64_save_fpu(&task->thread.fph[0]); task->thread.flags |= IA64_THREAD_FPH_VALID; + ia64_save_fpu(&task->thread.fph[0]); } } @@ -609,10 +645,7 @@ task->thread.flags |= IA64_THREAD_FPH_VALID; memset(&task->thread.fph, 0, sizeof(task->thread.fph)); } -#ifndef CONFIG_SMP - if (ia64_get_fpu_owner() == task) - ia64_set_fpu_owner(0); -#endif + ia64_drop_fpu(task); psr->dfh = 1; } @@ -701,7 +734,9 @@ case PT_R4: case PT_R5: case PT_R6: case PT_R7: if (write_access) { /* read NaT bit first: */ - ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, data, &nat); + unsigned long dummy; + + ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, &dummy, &nat); if (ret < 0) return ret; } @@ -846,8 +881,7 @@ * IA64_THREAD_DBG_VALID. The registers are restored by the PMU context * switch code. */ - if (pfm_use_debug_registers(child)) - return -1; + if (pfm_use_debug_registers(child)) return -1; #endif if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { @@ -1344,10 +1378,11 @@ set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); + /* - * This isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl + * This isn't the same as continuing with a signal, but it will do for normal use. + * strace only continues with a signal if the stopping signal is not SIGTRAP. + * -brl */ if (current->exit_code) { send_sig(current->exit_code, current, 1); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/sal.c linux2.4.21_itanium/arch/ia64/kernel/sal.c --- linux2.4.21_itanium.org/arch/ia64/kernel/sal.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/sal.c Wed Jul 23 18:28:58 2003 @@ -1,7 +1,7 @@ /* * System Abstraction Layer (SAL) interface routines. * - * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co + * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co * David Mosberger-Tang * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond @@ -77,7 +77,7 @@ return str; } -static void __init +void __init ia64_sal_handler_init (void *entry_point, void *gpval) { /* fill in the SAL procedure descriptor and point ia64_sal to it: */ @@ -96,17 +96,17 @@ int i; if (!systab) { - printk("Hmm, no SAL System Table.\n"); + printk(KERN_WARNING "Hmm, no SAL System Table.\n"); return; } if (strncmp(systab->signature, "SST_", 4) != 0) - printk("bad signature in system table!"); + printk(KERN_ERR "bad signature in system table!"); /* * revisions are coded in BCD, so %x does the job for us */ - printk("SAL v%x.%02x: oem=%.32s, product=%.32s\n", + printk(KERN_INFO "SAL v%x.%02x: oem=%.32s, product=%.32s\n", systab->sal_rev_major, systab->sal_rev_minor, systab->oem_id, systab->product_id); @@ -121,7 +121,7 @@ switch (*p) { case SAL_DESC_ENTRY_POINT: ep = (struct ia64_sal_desc_entry_point *) p; - printk("SAL: entry: pal_proc=0x%lx, sal_proc=0x%lx\n", + printk(KERN_INFO "SAL: entry: pal_proc=0x%lx, sal_proc=0x%lx\n", ep->pal_proc, ep->sal_proc); ia64_pal_handler_init(__va(ep->pal_proc)); ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); @@ -139,12 +139,12 @@ switch (ap->mechanism) { case IA64_SAL_AP_EXTERNAL_INT: ap_wakeup_vector = ap->vector; - printk("SAL: AP wakeup using external interrupt " + printk(KERN_INFO "SAL: AP wakeup using external interrupt " "vector 0x%lx\n", ap_wakeup_vector); break; default: - printk("SAL: AP wakeup mechanism unsupported!\n"); + printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n"); break; } break; @@ -154,7 +154,7 @@ { struct ia64_sal_desc_platform_feature *pf = (void *) p; sal_platform_features = pf->feature_mask; - printk("SAL: Platform features "); + printk(KERN_INFO "SAL: Platform features "); if (pf->feature_mask & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK) printk("BusLock "); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/salinfo.c linux2.4.21_itanium/arch/ia64/kernel/salinfo.c --- linux2.4.21_itanium.org/arch/ia64/kernel/salinfo.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/salinfo.c Wed Jul 23 18:28:58 2003 @@ -4,6 +4,8 @@ * Creates entries in /proc/sal for various system features. * * Copyright (c) 2001 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2003 Hewlett-Packard Co + * Bjorn Helgaas * * 10/30/2001 jbarnes@sgi.com copied much of Stephane's palinfo * code to create this file @@ -12,8 +14,10 @@ #include #include #include +#include #include +#include MODULE_AUTHOR("Jesse Barnes "); MODULE_DESCRIPTION("/proc interface to IA-64 SAL features"); @@ -40,25 +44,325 @@ #define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t)) -/* - * One for each feature and one more for the directory entry... - */ -static struct proc_dir_entry *salinfo_proc_entries[NR_SALINFO_ENTRIES + 1]; +static char *salinfo_log_name[] = { + "mca", + "init", + "cmc", + "cpe", +}; + +static struct proc_dir_entry *salinfo_proc_entries[ + ARRAY_SIZE(salinfo_entries) + /* /proc/sal/bus_lock */ + ARRAY_SIZE(salinfo_log_name) + /* /proc/sal/{mca,...} */ + (2 * ARRAY_SIZE(salinfo_log_name)) + /* /proc/sal/mca/{event,data} */ + 1]; /* /proc/sal */ + +struct salinfo_log_data { + int type; + u8 *log_buffer; + u64 log_size; +}; + +struct salinfo_event { + int type; + int cpu; /* next CPU to check */ + volatile unsigned long cpu_mask; + wait_queue_head_t queue; +}; + +static struct salinfo_event *salinfo_event[ARRAY_SIZE(salinfo_log_name)]; + +struct salinfo_data { + int open; /* single-open to prevent races */ + int type; + int cpu; /* "current" cpu for reads */ +}; + +static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)]; + +static spinlock_t data_lock; + +void +salinfo_log_wakeup(int type) +{ + if (type < ARRAY_SIZE(salinfo_log_name)) { + struct salinfo_event *event = salinfo_event[type]; + + if (event) { + set_bit(smp_processor_id(), &event->cpu_mask); + wake_up_interruptible(&event->queue); + } + } +} + +static int +salinfo_event_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_event *event = entry->data; + + if (!suser()) + return -EPERM; + return 0; +} + +static ssize_t +salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_event *event = entry->data; + char cmd[32]; + size_t size; + int i, n, cpu = -1; + +retry: + if (!event->cpu_mask) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + interruptible_sleep_on(&event->queue); + if (signal_pending(current)) + return -EINTR; + } + + n = event->cpu; + for (i = 0; i < NR_CPUS; i++) { + if (event->cpu_mask & 1UL << n) { + cpu = n; + break; + } + if (++n == NR_CPUS) + n = 0; + } + + if (cpu == -1) + goto retry; + + /* for next read, start checking at next CPU */ + event->cpu = cpu; + if (++event->cpu == NR_CPUS) + event->cpu = 0; + + snprintf(cmd, sizeof(cmd), "read %d\n", cpu); + + size = strlen(cmd); + if (size > count) + size = count; + if (copy_to_user(buffer, cmd, size)) + return -EFAULT; + + return size; +} + +static struct file_operations salinfo_event_fops = { + .open = salinfo_event_open, + .read = salinfo_event_read, +}; + +static int +salinfo_log_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_data *data = entry->data; + + if (!suser()) + return -EPERM; + + spin_lock(&data_lock); + if (data->open) { + spin_unlock(&data_lock); + return -EBUSY; + } + data->open = 1; + spin_unlock(&data_lock); + + return 0; +} + +static int +salinfo_log_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_data *data = entry->data; + + spin_lock(&data_lock); + data->open = 0; + spin_unlock(&data_lock); + return 0; +} + +static void +call_on_cpu(int cpu, void (*fn)(void *), void *arg) +{ + if (cpu == smp_processor_id()) + (*fn)(arg); +#ifdef CONFIG_SMP + else if (cpu_online(cpu)) /* cpu may not have been validated */ + smp_call_function_single(cpu, fn, arg, 0, 1); +#endif +} + +static void +salinfo_log_read_cpu(void *context) +{ + struct salinfo_log_data *info = context; + struct salinfo_event *event = salinfo_event[info->type]; + u64 size; + + size = ia64_sal_get_state_info_size(info->type); + info->log_buffer = kmalloc(size, GFP_ATOMIC); + if (!info->log_buffer) + return; + + clear_bit(smp_processor_id(), &event->cpu_mask); + info->log_size = ia64_sal_get_state_info(info->type, (u64 *) info->log_buffer); + if (info->log_size) + salinfo_log_wakeup(info->type); +} + +static ssize_t +salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_data *data = entry->data; + struct salinfo_log_data info; + int ret; + void *saldata; + size_t size; + + info.type = data->type; + info.log_buffer = 0; + call_on_cpu(data->cpu, salinfo_log_read_cpu, &info); + if (!info.log_buffer || *ppos >= info.log_size) { + ret = 0; + goto out; + } + + saldata = info.log_buffer + file->f_pos; + size = info.log_size - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, saldata, size)) { + ret = -EFAULT; + goto out; + } + + *ppos += size; + ret = size; + +out: + kfree(info.log_buffer); + return ret; +} + +static void +salinfo_log_clear_cpu(void *context) +{ + struct salinfo_data *data = context; + struct salinfo_event *event = salinfo_event[data->type]; + struct salinfo_log_data info; + + clear_bit(smp_processor_id(), &event->cpu_mask); + ia64_sal_clear_state_info(data->type); + + /* clearing one record may make another visible */ + info.type = data->type; + salinfo_log_read_cpu(&info); + if (info.log_buffer && info.log_size) + salinfo_log_wakeup(data->type); + + kfree(info.log_buffer); +} + +static ssize_t +salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip; + struct salinfo_data *data = entry->data; + char cmd[32]; + size_t size; + int cpu; + + size = sizeof(cmd); + if (count < size) + size = count; + if (copy_from_user(cmd, buffer, size)) + return -EFAULT; + + if (sscanf(cmd, "read %d", &cpu) == 1) + data->cpu = cpu; + else if (sscanf(cmd, "clear %d", &cpu) == 1) + call_on_cpu(cpu, salinfo_log_clear_cpu, data); + + return count; +} + +static struct file_operations salinfo_data_fops = { + .open = salinfo_log_open, + .release = salinfo_log_release, + .read = salinfo_log_read, + .write = salinfo_log_write, +}; static int __init salinfo_init(void) { struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */ struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ - int i; + struct proc_dir_entry *dir, *entry; + struct salinfo_event *event; + struct salinfo_data *data; + int i, j; salinfo_dir = proc_mkdir("sal", NULL); + if (!salinfo_dir) + return 0; for (i=0; i < NR_SALINFO_ENTRIES; i++) { /* pass the feature bit in question as misc data */ *sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir, salinfo_read, (void *)salinfo_entries[i].feature); } + + for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { + dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); + if (!dir) + continue; + + entry = create_proc_entry("event", S_IRUSR, dir); + if (!entry) + continue; + + event = kmalloc(sizeof(*event), GFP_KERNEL); + if (!event) + continue; + memset(event, 0, sizeof(*event)); + event->type = i; + init_waitqueue_head(&event->queue); + salinfo_event[i] = event; + /* we missed any events before now */ + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + set_bit(j, &event->cpu_mask); + entry->data = event; + entry->proc_fops = &salinfo_event_fops; + *sdir++ = entry; + + entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir); + if (!entry) + continue; + + data = &salinfo_data[i]; + data->type = i; + entry->data = data; + entry->proc_fops = &salinfo_data_fops; + *sdir++ = entry; + + *sdir++ = dir; + } + *sdir++ = salinfo_dir; return 0; @@ -69,7 +373,7 @@ { int i = 0; - for (i = 0; i < NR_SALINFO_ENTRIES ; i++) { + for (i = 0; i < ARRAY_SIZE(salinfo_proc_entries); i++) { if (salinfo_proc_entries[i]) remove_proc_entry (salinfo_proc_entries[i]->name, NULL); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/setup.c linux2.4.21_itanium/arch/ia64/kernel/setup.c --- linux2.4.21_itanium.org/arch/ia64/kernel/setup.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/setup.c Wed Jul 23 18:28:57 2003 @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM # include @@ -58,6 +59,7 @@ struct cpuinfo_ia64 *boot_cpu_data; #else struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section"))); + mmu_gather_t mmu_gathers[NR_CPUS]; #endif unsigned long ia64_cycles_per_usec; @@ -125,7 +127,7 @@ #if IGNORE_PFN0 if (start == PAGE_OFFSET) { - printk("warning: skipping physical page 0\n"); + printk(KERN_WARNING "warning: skipping physical page 0\n"); start += PAGE_SIZE; if (start >= end) return 0; } @@ -278,7 +280,7 @@ initrd_start = (unsigned long)__va(ia64_boot_param->initrd_start); initrd_end = initrd_start+ia64_boot_param->initrd_size; - printk("Initial ramdisk at: 0x%lx (%lu bytes)\n", + printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", initrd_start, ia64_boot_param->initrd_size); } #endif @@ -335,8 +337,9 @@ ia64_set_kr(IA64_KR_IO_BASE, phys_iobase); else { phys_iobase = ia64_get_kr(IA64_KR_IO_BASE); - printk("No I/O port range found in EFI memory map, falling back to AR.KR0\n"); - printk("I/O port base = 0x%lx\n", phys_iobase); + printk(KERN_INFO "No I/O port range found in EFI memory map, falling back " + "to AR.KR0\n"); + printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase); } ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); @@ -470,10 +473,10 @@ } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: show_cpuinfo + .start =c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo }; void @@ -526,7 +529,7 @@ impl_va_msb = vm2.pal_vm_info_2_s.impl_va_msb; phys_addr_size = vm1.pal_vm_info_1_s.phys_add_size; } - printk("CPU %d: %lu virtual and %lu physical address bits\n", + printk(KERN_INFO "CPU %d: %lu virtual and %lu physical address bits\n", smp_processor_id(), impl_va_msb + 1, phys_addr_size); c->unimpl_va_mask = ~((7L<<61) | ((1L << (impl_va_msb + 1)) - 1)); c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); @@ -566,6 +569,8 @@ for (cpu = 1; cpu < NR_CPUS; ++cpu) memcpy(my_cpu_data->cpu_data[cpu]->cpu_data, my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data)); + my_cpu_data->mmu_gathers = alloc_bootmem_pages_node(BOOT_NODE_DATA(boot_get_local_cnodeid()), + sizeof(mmu_gather_t)); } else { order = get_order(sizeof(struct cpuinfo_ia64)); my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order)); @@ -575,9 +580,14 @@ order); for (cpu = 0; cpu < NR_CPUS; ++cpu) boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data; + + my_cpu_data->mmu_gathers = page_address(boot_alloc_pages_node(boot_get_local_cnodeid(), + GFP_KERNEL, + get_order(sizeof(mmu_gather_t))); } #else my_cpu_data = cpu_data(smp_processor_id()); + my_cpu_data->mmu_gathers = &mmu_gathers[smp_processor_id()]; #endif /* @@ -609,6 +619,8 @@ /* Clear the stack memory reserved for pt_regs: */ memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); + ia64_set_kr(IA64_KR_FPU_OWNER, 0); + /* * Initialize default control register to defer all speculative faults. The * kernel MUST NOT depend on a particular setting of these bits (in other words, @@ -619,10 +631,6 @@ */ ia64_set_dcr( IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC); -#ifndef CONFIG_SMP - ia64_set_fpu_owner(0); -#endif - atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; @@ -650,7 +658,7 @@ if (ia64_pal_vm_summary(NULL, &vmi) == 0) max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1; else { - printk("cpu_init: PAL VM summary failed, assuming 18 RID bits\n"); + printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n"); max_ctx = (1U << 15) - 1; /* use architected minimum */ } while (max_ctx < ia64_ctx.max_ctx) { @@ -660,7 +668,7 @@ } if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) { - printk ("cpu_init: PAL RSE info failed, assuming 96 physical stacked regs\n"); + printk(KERN_WARNING "cpu_init: PAL RSE info failed, assuming 96 physical stacked regs\n"); num_phys_stacked = 96; } local_cpu_data->phys_stacked_size_p8 = num_phys_stacked*8 + 8; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/sigframe.h linux2.4.21_itanium/arch/ia64/kernel/sigframe.h --- linux2.4.21_itanium.org/arch/ia64/kernel/sigframe.h Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/sigframe.h Wed Jul 23 18:28:58 2003 @@ -1,6 +1,6 @@ struct sigscratch { unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */ - unsigned long pad; + unsigned long ar_pfs; /* for syscalls, the user-level function-state */ struct pt_regs pt; }; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/signal.c linux2.4.21_itanium/arch/ia64/kernel/signal.c --- linux2.4.21_itanium.org/arch/ia64/kernel/signal.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/signal.c Wed Jul 23 18:28:57 2003 @@ -142,8 +142,13 @@ __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); psr->mfh = 0; /* drop signal handler's fph contents... */ - if (!psr->dfh) + if (psr->dfh) + ia64_drop_fpu(current); + else { + /* We already own the local fph, otherwise psr->dfh wouldn't be 0. */ __ia64_load_fpu(current->thread.fph); + ia64_set_local_fpu_owner(current); + } } return err; } @@ -315,7 +320,7 @@ static long setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) { - unsigned long flags = 0, ifs, nat; + unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; @@ -325,7 +330,9 @@ if ((ifs & (1UL << 63)) == 0) { /* if cr_ifs isn't valid, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; - } + cfm = scr->ar_pfs & ((1UL << 38) - 1); + } else + cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; @@ -344,6 +351,7 @@ err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); + err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); @@ -422,6 +430,15 @@ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ + /* + * Force the interruption function mask to zero. This has no effect when a + * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is + * ignored), but it has the desirable effect of making it possible to deliver a + * signal with an incomplete register frame (which happens when a mandatory RSE + * load faults). Furthermore, it has no negative effect on the getting the user's + * dirty partition preserved, because that's governed by scr->pt.loadrs. + */ + scr->pt.cr_ifs = (1UL << 63); /* * Note: this affects only the NaT bits of the scratch regs (the ones saved in diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/smpboot.c linux2.4.21_itanium/arch/ia64/kernel/smpboot.c --- linux2.4.21_itanium.org/arch/ia64/kernel/smpboot.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/smpboot.c Wed Jul 23 18:28:57 2003 @@ -1,7 +1,8 @@ /* * SMP boot-related support * - * Copyright (C) 2001 David Mosberger-Tang + * Copyright (C) 1998-2003 Hewlett-Packard Co + * David Mosberger-Tang * * 01/05/16 Rohit Seth Moved SMP booting functions from smp.c to here. * 01/04/27 David Mosberger Added ITC synching code. @@ -66,8 +67,8 @@ #define DEBUG_ITC_SYNC 0 -extern void __init calibrate_delay(void); -extern void start_ap(void); +extern void __init calibrate_delay (void); +extern void start_ap (void); extern unsigned long ia64_iobase; int cpucount; @@ -235,7 +236,7 @@ go[MASTER] = 1; if (smp_call_function_single(master, sync_master, NULL, 1, 0) < 0) { - printk("sync_itc: failed to get attention of CPU %u!\n", master); + printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master); return; } @@ -275,8 +276,8 @@ t[i].rt, t[i].master, t[i].diff, t[i].lat); #endif - printk("CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, maxerr %lu cycles)\n", - smp_processor_id(), master, delta, rt); + printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, " + "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt); } /* @@ -328,19 +329,14 @@ phys_id = hard_smp_processor_id(); if (test_and_set_bit(cpuid, &cpu_online_map)) { - printk("huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid); + printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", + phys_id, cpuid); BUG(); } smp_setup_percpu_timer(); /* - * Synchronize the ITC with the BP - */ - Dprintk("Going to syncup ITC with BP.\n"); - - ia64_sync_itc(0); - /* * Get our bogomips. */ ia64_init_itm(); @@ -362,6 +358,27 @@ local_irq_enable(); calibrate_delay(); local_cpu_data->loops_per_jiffy = loops_per_jiffy; + + if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { + /* + * Synchronize the ITC with the BP. Need to do this after irqs are + * enabled because ia64_sync_itc() calls smp_call_function_single(), which + * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls + * local_bh_enable(), which bugs out if irqs are not enabled... + */ + Dprintk("Going to syncup ITC with BP.\n"); + ia64_sync_itc(0); + + /* + * Make sure we didn't sync the itc ahead of the next + * timer interrupt, if so, just reset it. + */ + if (time_after(ia64_get_itc(),local_cpu_data->itm_next)) { + Dprintk("oops, jumped a timer.\n"); + ia64_cpu_local_tick(); + } + } + /* * Allow the master to continue. */ @@ -394,8 +411,8 @@ fork_by_hand (void) { /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. + * don't care about the eip and regs settings since we'll never reschedule the + * forked task. */ return do_fork(CLONE_VM|CLONE_PID, 0, 0, 0); } @@ -430,7 +447,7 @@ unhash_process(idle); init_tasks[cpu] = idle; - Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); + Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); @@ -447,9 +464,7 @@ if (test_bit(cpu, &cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ - printk("CPU%d: ", cpu); - /*print_cpu_info(&cpu_data[cpu]); */ - printk("CPU has booted.\n"); + printk(KERN_INFO "CPU%d: CPU has booted.\n", cpu); } else { printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid); ia64_cpu_to_sapicid[cpu] = -1; @@ -476,15 +491,15 @@ smp_setup_percpu_timer(); /* - * We have the boot CPU online for sure. - */ + * We have the boot CPU online for sure. + */ set_bit(0, &cpu_online_map); set_bit(0, &cpu_callin_map); local_cpu_data->loops_per_jiffy = loops_per_jiffy; ia64_cpu_to_sapicid[0] = boot_cpu_id; - printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id); + printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id); global_irq_holder = 0; current->processor = 0; @@ -500,7 +515,7 @@ goto smp_done; } if (max_cpus != -1) - printk (KERN_INFO "Limiting CPUs to %d\n", max_cpus); + printk(KERN_INFO "Limiting CPUs to %d\n", max_cpus); if (smp_boot_data.cpu_count > 1) { @@ -518,12 +533,6 @@ break; do_boot_cpu(sapicid); - - /* - * Make sure we unmap all failed CPUs - */ - if (ia64_cpu_to_sapicid[cpu] == -1) - printk("phys CPU#%d not responding - cannot use it.\n", cpu); } smp_num_cpus = cpucount + 1; @@ -541,7 +550,7 @@ if (cpu_online_map & (1UL << cpu)) bogosum += cpu_data(cpu)->loops_per_jiffy; - printk(KERN_INFO"Total of %d processors activated (%lu.%02lu BogoMIPS).\n", + printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); } } @@ -550,7 +559,7 @@ } /* - * Assume that CPU's have been discovered by some platform-dependant interface. For + * Assume that CPU's have been discovered by some platform-dependent interface. For * SoftSDV/Lion, that would be ACPI. * * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP(). @@ -569,7 +578,7 @@ sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0); if (sal_ret < 0) { - printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n Forcing UP mode\n", + printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n Forcing UP mode\n", ia64_sal_strerror(sal_ret)); max_cpus = 0; smp_num_cpus = 1; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/sys_ia64.c linux2.4.21_itanium/arch/ia64/kernel/sys_ia64.c --- linux2.4.21_itanium.org/arch/ia64/kernel/sys_ia64.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/sys_ia64.c Wed Jul 23 18:28:57 2003 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,10 @@ if (len > RGN_MAP_LIMIT) return -ENOMEM; +#ifdef CONFIG_HUGETLB_PAGE + if (rgn_index(addr)==REGION_HPAGE) + addr = 0; +#endif if (!addr) addr = TASK_UNMAPPED_BASE; @@ -56,16 +61,14 @@ } asmlinkage long -ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6, - long arg7, long stack) +ia64_getpriority (int which, int who) { - struct pt_regs *regs = (struct pt_regs *) &stack; extern long sys_getpriority (int, int); long prio; prio = sys_getpriority(which, who); if (prio >= 0) { - regs->r8 = 0; /* ensure negative priority is not mistaken as error code */ + force_successful_syscall_return(); prio = 20 - prio; } return prio; @@ -79,11 +82,9 @@ } asmlinkage unsigned long -ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6, - long arg7, long stack) +ia64_shmat (int shmid, void *shmaddr, int shmflg) { extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr); - struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long raddr; int retval; @@ -91,16 +92,14 @@ if (retval < 0) return retval; - regs->r8 = 0; /* ensure negative addresses are not mistaken as an error code */ + force_successful_syscall_return(); return raddr; } asmlinkage unsigned long -ia64_brk (unsigned long brk, long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6, long arg7, long stack) +ia64_brk (unsigned long brk) { extern int vm_enough_memory (long pages); - struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long rlim, retval, newbrk, oldbrk; struct mm_struct *mm = current->mm; @@ -150,7 +149,7 @@ out: retval = mm->brk; up_write(&mm->mmap_sem); - regs->r8 = 0; /* ensure large retval isn't mistaken as error code */ + force_successful_syscall_return(); return retval; } @@ -227,29 +226,23 @@ * of) files that are larger than the address space of the CPU. */ asmlinkage unsigned long -sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff, - long arg6, long arg7, long stack) +sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) { - struct pt_regs *regs = (struct pt_regs *) &stack; - addr = do_mmap2(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) - regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ + force_successful_syscall_return(); return addr; } asmlinkage unsigned long -sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, - int fd, long off, long arg6, long arg7, long stack) +sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off) { - struct pt_regs *regs = (struct pt_regs *) &stack; - if ((off & ~PAGE_MASK) != 0) return -EINVAL; addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); if (!IS_ERR((void *) addr)) - regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ + force_successful_syscall_return(); return addr; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/time.c linux2.4.21_itanium/arch/ia64/kernel/time.c --- linux2.4.21_itanium.org/arch/ia64/kernel/time.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/time.c Wed Jul 23 18:28:58 2003 @@ -73,10 +73,8 @@ now = ia64_get_itc(); if ((long) (now - last_tick) < 0) { -# if 1 - printk("CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", + printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", smp_processor_id(), now, last_tick); -# endif return last_time_offset; } elapsed_cycles = now - last_tick; @@ -154,7 +152,7 @@ new_itm = local_cpu_data->itm_next; if (!time_after(ia64_get_itc(), new_itm)) - printk("Oops: timer tick before it's due (itc=%lx,itm=%lx)\n", + printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n", ia64_get_itc(), new_itm); while (1) { @@ -243,21 +241,22 @@ */ status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &drift); if (status != 0) { - printk("SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); + printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); } else { status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio); if (status != 0) - printk("PAL_FREQ_RATIOS failed with status=%ld\n", status); + printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status); } if (status != 0) { /* invent "random" values */ - printk("SAL/PAL failed to obtain frequency info---inventing reasonably values\n"); + printk(KERN_ERR + "SAL/PAL failed to obtain frequency info---inventing reasonably values\n"); platform_base_freq = 100000000; itc_ratio.num = 3; itc_ratio.den = 1; } if (platform_base_freq < 40000000) { - printk("Platform base frequency %lu bogus---resetting to 75MHz!\n", + printk(KERN_ERR "Platform base frequency %lu bogus---resetting to 75MHz!\n", platform_base_freq); platform_base_freq = 75000000; } @@ -268,8 +267,8 @@ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; - printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n", - smp_processor_id(), + printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " + "ITC freq=%lu.%03luMHz\n", smp_processor_id(), platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); @@ -284,9 +283,9 @@ } static struct irqaction timer_irqaction = { - handler: timer_interrupt, - flags: SA_INTERRUPT, - name: "timer" + .handler = timer_interrupt, + .flags = SA_INTERRUPT, + .name = "timer" }; void __init diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/traps.c linux2.4.21_itanium/arch/ia64/kernel/traps.c --- linux2.4.21_itanium.org/arch/ia64/kernel/traps.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/traps.c Wed Jul 23 18:28:57 2003 @@ -51,12 +51,12 @@ if (ia64_boot_param->fpswa) { /* FPSWA fixup: make the interface pointer a kernel virtual address: */ fpswa_interface = __va(ia64_boot_param->fpswa); - printk("FPSWA interface at 0x%lx, revision %d.%d\n", + printk(KERN_INFO "FPSWA interface at 0x%lx, revision %d.%d\n", ia64_boot_param->fpswa, fpswa_interface->revision >> 16, fpswa_interface->revision & 0xffff); } else - printk("No FPSWA interface\n"); + printk(KERN_INFO "No FPSWA interface\n"); } /* @@ -97,9 +97,9 @@ int lock_owner; int lock_owner_depth; } die = { - lock: SPIN_LOCK_UNLOCKED, - lock_owner: -1, - lock_owner_depth: 0 + .lock = SPIN_LOCK_UNLOCKED, + .lock_owner = -1, + .lock_owner_depth = 0 }; if (die.lock_owner != smp_processor_id()) { @@ -223,7 +223,7 @@ { struct pt_regs *regs = (struct pt_regs *) &stack; - printk("%s(%d): \n", current->comm, current->pid, + printk(KERN_DEBUG "%s(%d): \n", current->comm, current->pid, regs->r15, arg0, arg1, arg2, arg3); return -ENOSYS; } @@ -245,17 +245,17 @@ psr->dfh = 0; #ifndef CONFIG_SMP { - struct task_struct *fpu_owner = ia64_get_fpu_owner(); + struct task_struct *fpu_owner + = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER); - if (fpu_owner == current) + if (ia64_is_local_fpu_owner(current)) return; if (fpu_owner) ia64_flush_fph(fpu_owner); - } #endif /* !CONFIG_SMP */ - ia64_set_fpu_owner(current); + ia64_set_local_fpu_owner(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { __ia64_load_fpu(current->thread.fph); psr->mfh = 0; @@ -337,8 +337,8 @@ fpu_swa_count = 0; if ((++fpu_swa_count < 5) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) { last_time = jiffies; - printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx\n", - current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri); + printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n", + current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr); } exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr, @@ -348,7 +348,7 @@ /* emulation was successful */ ia64_increment_ip(regs); } else if (exception == -1) { - printk("handle_fpu_swa: fp_emulate() returned -1\n"); + printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n"); return -1; } else { /* is next instruction a trap? */ @@ -371,7 +371,7 @@ } } else { if (exception == -1) { - printk("handle_fpu_swa: fp_emulate() returned -1\n"); + printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n"); return -1; } else if (exception != 0) { /* raise exception */ @@ -469,7 +469,9 @@ ? " (RSE access)" : " (data access)") : ""); if (code == 8) { # ifdef CONFIG_IA64_PRINT_HAZARDS - printk("%016lx:possible hazard, pr = %016lx\n", regs->cr_iip, regs->pr); + printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n", + current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, + regs->pr); # endif return; } @@ -485,19 +487,23 @@ case 26: /* NaT Consumption */ if (user_mode(regs)) { + void *addr; + if (((isr >> 4) & 0xf) == 2) { /* NaT page consumption */ sig = SIGSEGV; code = SEGV_ACCERR; + addr = (void *) ifa; } else { /* register NaT consumption */ sig = SIGILL; code = ILL_ILLOPN; + addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); } siginfo.si_signo = sig; siginfo.si_code = code; siginfo.si_errno = 0; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = addr; siginfo.si_imm = vector; siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; @@ -585,8 +591,9 @@ if (ia32_exception(regs, isr) == 0) return; #endif - printk("Unexpected IA-32 exception (Trap 45)\n"); - printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); + printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n"); + printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", + regs->cr_iip, ifa, isr); force_sig(SIGSEGV, current); break; @@ -595,8 +602,8 @@ if (ia32_intercept(regs, isr) == 0) return; #endif - printk("Unexpected IA-32 intercept trap (Trap 46)\n"); - printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", + printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n"); + printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", regs->cr_iip, ifa, isr, iim); force_sig(SIGSEGV, current); return; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/unwind.c linux2.4.21_itanium/arch/ia64/kernel/unwind.c --- linux2.4.21_itanium.org/arch/ia64/kernel/unwind.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/unwind.c Wed Jul 23 18:28:57 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2003 Hewlett-Packard Co * David Mosberger-Tang */ /* @@ -51,18 +51,24 @@ #define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1) #define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE) -#define UNW_DEBUG 0 #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ -#if UNW_DEBUG - static long unw_debug_level = 255; -# define debug(level,format...) if (unw_debug_level > level) printk(format) -# define dprintk(format...) printk(format) -# define inline -#else -# define debug(level,format...) -# define dprintk(format...) -#endif +#ifdef UNW_DEBUG + static unsigned int unw_debug_level = UNW_DEBUG; +# ifdef CONFIG_KDB +# include +# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING()) +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__) +# else /* !CONFIG_KDB */ +# define UNW_DEBUG_ON(n) unw_debug_level >= n + /* Do not code a printk level, not all debug lines end in newline */ +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) +# endif /* CONFIG_KDB */ +# define inline +#else /* !UNW_DEBUG */ +# define UNW_DEBUG_ON(n) 0 +# define UNW_DPRINT(n, ...) +#endif /* UNW_DEBUG */ #if UNW_STATS # define STAT(x...) x @@ -111,7 +117,7 @@ /* script cache: */ struct unw_script cache[UNW_CACHE_SIZE]; -# if UNW_DEBUG +# ifdef UNW_DEBUG const char *preg_name[UNW_NUM_REGS]; # endif # if UNW_STATS @@ -140,13 +146,13 @@ } stat; # endif } unw = { - tables: &unw.kernel_table, - lock: SPIN_LOCK_UNLOCKED, - save_order: { + .tables = &unw.kernel_table, + .lock = SPIN_LOCK_UNLOCKED, + .save_order = { UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR, UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR }, - preg_index: { + .preg_index = { struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */ struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */ struct_offset(struct unw_frame_info, bsp_loc)/8, @@ -189,9 +195,9 @@ struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8, struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, }, - hash : { [0 ... UNW_HASH_SIZE - 1] = -1 }, -#if UNW_DEBUG - preg_name: { + .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 }, +#ifdef UNW_DEBUG + .preg_name = { "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp", "r4", "r5", "r6", "r7", "ar.unat", "pr", "ar.lc", "ar.fpsr", @@ -223,10 +229,25 @@ else if (reg <= 31) off = struct_offset(struct pt_regs, r16) + 8*(reg - 16); else - dprintk("unwind: bad scratch reg r%lu\n", reg); + UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg); return off; } +static inline struct pt_regs * +get_scratch_regs (struct unw_frame_info *info) +{ + if (!info->pt) { + /* This should not happen with valid unwind info. */ + UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__); + if (info->flags & UNW_FLAG_INTERRUPT_FRAME) + info->pt = (unsigned long) ((struct pt_regs *) info->psp - 1); + else + info->pt = info->sp - 16; + } + UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt); + return (struct pt_regs *) info->pt; +} + int unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write) { @@ -235,7 +256,13 @@ struct pt_regs *pt; if ((unsigned) regnum - 1 >= 127) { - dprintk("unwind: trying to access non-existent r%u\n", regnum); + if (regnum == 0 && !write) { + *val = 0; /* read r0 always returns 0 */ + *nat = 0; + return 0; + } + UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n", + __FUNCTION__, regnum); return -1; } @@ -280,8 +307,9 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: %p outside of regstk " - "[0x%lx-0x%lx)\n", (void *) addr, + UNW_DPRINT(0, "unwind.%s: %p outside of regstk " + "[0x%lx-0x%lx)\n", + __FUNCTION__, (void *) addr, info->regstk.limit, info->regstk.top); return -1; @@ -298,11 +326,8 @@ } } else { /* access a scratch register */ - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - addr = (unsigned long *) ((long) pt + pt_regs_off(regnum)); + pt = get_scratch_regs(info); + addr = (unsigned long *) ((unsigned long)pt + pt_regs_off(regnum)); if (info->pri_unat_loc) nat_addr = info->pri_unat_loc; else @@ -316,7 +341,8 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: ignoring attempt to access register outside of rbs\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside " + "of rbs\n", __FUNCTION__); return -1; } if ((unsigned long) nat_addr >= info->regstk.top) @@ -348,15 +374,11 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; switch (regnum) { /* scratch: */ - case 0: addr = &pt->b0; break; - case 6: addr = &pt->b6; break; - case 7: addr = &pt->b7; break; + case 0: pt = get_scratch_regs(info); addr = &pt->b0; break; + case 6: pt = get_scratch_regs(info); addr = &pt->b6; break; + case 7: pt = get_scratch_regs(info); addr = &pt->b7; break; /* preserved: */ case 1: case 2: case 3: case 4: case 5: @@ -366,7 +388,8 @@ break; default: - dprintk("unwind: trying to access non-existent b%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n", + __FUNCTION__, regnum); return -1; } if (write) @@ -383,22 +406,20 @@ struct pt_regs *pt; if ((unsigned) (regnum - 2) >= 126) { - dprintk("unwind: trying to access non-existent f%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n", + __FUNCTION__, regnum); return -1; } - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - if (regnum <= 5) { addr = *(&info->f2_loc + (regnum - 2)); if (!addr) addr = &info->sw->f2 + (regnum - 2); } else if (regnum <= 15) { - if (regnum <= 9) + if (regnum <= 9) { + pt = get_scratch_regs(info); addr = &pt->f6 + (regnum - 6); + } else addr = &info->sw->f10 + (regnum - 10); } else if (regnum <= 31) { @@ -428,11 +449,6 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - switch (regnum) { case UNW_AR_BSP: addr = info->bsp_loc; @@ -487,15 +503,18 @@ break; case UNW_AR_RSC: + pt = get_scratch_regs(info); addr = &pt->ar_rsc; break; case UNW_AR_CCV: + pt = get_scratch_regs(info); addr = &pt->ar_ccv; break; default: - dprintk("unwind: trying to access non-existent ar%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n", + __FUNCTION__, regnum); return -1; } @@ -532,7 +551,7 @@ rs = alloc_reg_state(); if (!rs) { - printk("unwind: cannot stack reg state!\n"); + printk(KERN_ERR "unwind: cannot stack reg state!\n"); return; } memcpy(rs, &sr->curr, sizeof(*rs)); @@ -545,7 +564,7 @@ struct unw_reg_state *rs = sr->curr.next; if (!rs) { - printk("unwind: stack underflow!\n"); + printk(KERN_ERR "unwind: stack underflow!\n"); return; } memcpy(&sr->curr, rs, sizeof(*rs)); @@ -561,7 +580,7 @@ while (rs) { copy = alloc_reg_state(); if (!copy) { - printk ("unwind.dup_state_stack: out of memory\n"); + printk(KERN_ERR "unwind.dup_state_stack: out of memory\n"); return NULL; } memcpy(copy, rs, sizeof(*copy)); @@ -612,7 +631,7 @@ default: break; } - dprintk("unwind: bad abreg=0x%x\n", abreg); + UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg); return UNW_REG_LC; } @@ -652,7 +671,7 @@ return; } } - dprintk("unwind: excess spill!\n"); + UNW_DPRINT(0, "unwind.%s: excess spill!\n", __FUNCTION__); } static inline void @@ -720,7 +739,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave, struct unw_state_record *sr) { - int i; + int i, region_start; if (!(sr->in_body || sr->first_region)) finish_prologue(sr); @@ -732,19 +751,20 @@ return; } + region_start = sr->region_start + sr->region_len; + for (i = 0; i < sr->epilogue_count; ++i) pop(sr); sr->epilogue_count = 0; sr->epilogue_start = UNW_WHEN_NEVER; - if (!body) - push(sr); - - sr->region_start += sr->region_len; + sr->region_start = region_start; sr->region_len = rlen; sr->in_body = body; if (!body) { + push(sr); + for (i = 0; i < 4; ++i) { if (mask & 0x8) set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR, @@ -765,10 +785,13 @@ static inline void desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr) { - if (abi == 0 && context == 'i') + if (abi == 0 && context == 'i') { sr->flags |= UNW_FLAG_INTERRUPT_FRAME; + UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __FUNCTION__); + } else - dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context); + UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n", + __FUNCTION__, abi, context); } static inline void @@ -951,7 +974,7 @@ return; } } - printk("unwind: failed to find state labeled 0x%lx\n", label); + printk(KERN_ERR "unwind: failed to find state labeled 0x%lx\n", label); } static inline void @@ -961,7 +984,7 @@ ls = alloc_labeled_state(); if (!ls) { - printk("unwind.desc_label_state(): out of memory\n"); + printk(KERN_ERR "unwind.desc_label_state(): out of memory\n"); return; } ls->label = label; @@ -1055,7 +1078,8 @@ r->val = 4*spoff; } -#define UNW_DEC_BAD_CODE(code) printk("unwind: unknown code 0x%02x\n", code); +#define UNW_DEC_BAD_CODE(code) printk(KERN_ERR "unwind: unknown code 0x%02x\n", \ + code); /* * region headers: @@ -1135,6 +1159,9 @@ unsigned short index; unsigned long ip, pr; + if (UNW_DEBUG_ON(0)) + return 0; /* Always regenerate scripts in debug mode */ + STAT(++unw.stat.cache.lookups); ip = info->ip; @@ -1259,8 +1286,8 @@ script_emit (struct unw_script *script, struct unw_insn insn) { if (script->count >= UNW_MAX_SCRIPT_LEN) { - dprintk("unwind: script exceeds maximum size of %u instructions!\n", - UNW_MAX_SCRIPT_LEN); + UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n", + __FUNCTION__, UNW_MAX_SCRIPT_LEN); return; } script->insn[script->count++] = insn; @@ -1301,7 +1328,8 @@ break; default: - dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where); + UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n", + __FUNCTION__, r->where); return; } insn.opc = opc; @@ -1338,8 +1366,9 @@ } val = unw.preg_index[UNW_REG_R4 + (rval - 4)]; } else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs) + pt_regs_off(rval); + /* register got spilled to a scratch register */ + opc = UNW_INSN_MOVE_SCRATCH; + val = pt_regs_off(rval); } break; @@ -1349,12 +1378,12 @@ else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval <= 9) - val += struct_offset(struct pt_regs, f6) + 16*(rval - 6); + val = struct_offset(struct pt_regs, f6) + 16*(rval - 6); else - dprintk("unwind: kernel may not touch f%lu\n", rval); + UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n", + __FUNCTION__, rval); } break; @@ -1362,14 +1391,13 @@ if (rval >= 1 && rval <= 5) val = unw.preg_index[UNW_REG_B1 + (rval - 1)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval == 0) - val += struct_offset(struct pt_regs, b0); + val = struct_offset(struct pt_regs, b0); else if (rval == 6) - val += struct_offset(struct pt_regs, b6); + val = struct_offset(struct pt_regs, b6); else - val += struct_offset(struct pt_regs, b7); + val = struct_offset(struct pt_regs, b7); } break; @@ -1382,7 +1410,8 @@ break; default: - dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where); + UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n", + __FUNCTION__, i, r->where); break; } insn.opc = opc; @@ -1455,9 +1484,10 @@ r->when = UNW_WHEN_NEVER; sr.pr_val = info->pr; + UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip); script = script_new(ip); if (!script) { - dprintk("unwind: failed to create unwind script\n"); + UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__); STAT(unw.stat.script.build_time += ia64_get_itc() - start); return 0; } @@ -1475,8 +1505,8 @@ } if (!e) { /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */ - dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip, - unw.cache[info->prev_script].ip); + UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", + __FUNCTION__, ip, unw.cache[info->prev_script].ip); sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = 0; @@ -1524,26 +1554,32 @@ sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg; + UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n", + __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where, + sr.curr.reg[UNW_REG_RP].val); } -#if UNW_DEBUG - printk("unwind: state record for func 0x%lx, t=%u:\n", - table->segment_base + e->start_offset, sr.when_target); +#ifdef UNW_DEBUG + UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n", + __FUNCTION__, table->segment_base + e->start_offset, sr.when_target); for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) { if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) { - printk(" %s <- ", unw.preg_name[r - sr.curr.reg]); + UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]); switch (r->where) { - case UNW_WHERE_GR: printk("r%lu", r->val); break; - case UNW_WHERE_FR: printk("f%lu", r->val); break; - case UNW_WHERE_BR: printk("b%lu", r->val); break; - case UNW_WHERE_SPREL: printk("[sp+0x%lx]", r->val); break; - case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break; + case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break; + case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break; + case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break; + case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break; + case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break; case UNW_WHERE_NONE: - printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + break; + + default: + UNW_DPRINT(1, "BADWHERE(%d)", r->where); break; - default: printk("BADWHERE(%d)", r->where); break; } - printk("\t\t%d\n", r->when); + UNW_DPRINT(1, "\t\t%d\n", r->when); } } #endif @@ -1641,6 +1677,16 @@ s[dst] = s[val]; break; + case UNW_INSN_MOVE_SCRATCH: + if (state->pt) { + s[dst] = (unsigned long) get_scratch_regs(state) + val; + } else { + s[dst] = 0; + UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n", + __FUNCTION__, dst, val); + } + break; + case UNW_INSN_MOVE_STACKED: s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp, val); @@ -1666,11 +1712,12 @@ break; case UNW_INSN_LOAD: -#if UNW_DEBUG +#ifdef UNW_DEBUG if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0 || s[val] < TASK_SIZE) { - debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]); + UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n", + __FUNCTION__, s[val]); break; } #endif @@ -1703,7 +1750,8 @@ if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { /* don't let obviously bad addresses pollute the cache */ - debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip); info->rp_loc = 0; return -1; } @@ -1712,8 +1760,9 @@ if (!scr) { scr = build_script(info); if (!scr) { - dprintk("unwind: failed to locate/build unwind script for ip %lx\n", - info->ip); + UNW_DPRINT(0, + "unwind.%s: failed to locate/build unwind script for ip %lx\n", + __FUNCTION__, info->ip); return -1; } have_write_lock = 1; @@ -1746,7 +1795,9 @@ /* restore the ip */ if (!info->rp_loc) { - debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n", + __FUNCTION__, info->ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1756,14 +1807,14 @@ * We don't have unwind info for the gate page, so we consider that part * of user-space for the purpose of unwinding. */ - debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip); + UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } /* restore the cfm: */ if (!info->pfs_loc) { - dprintk("unwind: failed to locate ar.pfs!\n"); + UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1773,16 +1824,18 @@ pr = info->pr; num_regs = 0; if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) { + info->pt = info->sp + 16; if ((pr & (1UL << pNonSys)) != 0) num_regs = *info->cfm_loc & 0x7f; /* size of frame */ info->pfs_loc = - (unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs)); + (unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs)); + UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt); } else num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */ info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs); if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) { - dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->bsp, info->regstk.limit, info->regstk.top); + UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1790,14 +1843,15 @@ /* restore the sp: */ info->sp = info->psp; if (info->sp < info->memstk.top || info->sp > info->memstk.limit) { - dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->sp, info->memstk.top, info->memstk.limit); + UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->sp, info->memstk.top, info->memstk.limit); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) { - dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1821,7 +1875,8 @@ while (unw_unwind(info) >= 0) { if (unw_get_rp(info, &ip) < 0) { unw_get_ip(info, &ip); - dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n", + __FUNCTION__, ip); return -1; } /* @@ -1832,26 +1887,25 @@ return 0; } unw_get_ip(info, &ip); - dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); return -1; } -void -unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +static void +init_frame_info (struct unw_frame_info *info, struct task_struct *t, + struct switch_stack *sw, unsigned long stktop) { - unsigned long rbslimit, rbstop, stklimit, stktop, sol; + unsigned long rbslimit, rbstop, stklimit; STAT(unsigned long start, flags;) STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc()); /* - * Subtle stuff here: we _could_ unwind through the - * switch_stack frame but we don't want to do that because it - * would be slow as each preserved register would have to be - * processed. Instead, what we do here is zero out the frame - * info and start the unwind process at the function that - * created the switch_stack frame. When a preserved value in - * switch_stack needs to be accessed, run_script() will + * Subtle stuff here: we _could_ unwind through the switch_stack frame but we + * don't want to do that because it would be slow as each preserved register would + * have to be processed. Instead, what we do here is zero out the frame info and + * start the unwind process at the function that created the switch_stack frame. + * When a preserved value in switch_stack needs to be accessed, run_script() will * initialize the appropriate pointer on demand. */ memset(info, 0, sizeof(*info)); @@ -1862,7 +1916,6 @@ rbstop = rbslimit; stklimit = (unsigned long) t + IA64_STK_OFFSET; - stktop = (unsigned long) sw - 16; if (stktop <= rbstop) stktop = rbstop; @@ -1872,15 +1925,56 @@ info->memstk.top = stktop; info->task = t; info->sw = sw; - info->sp = info->psp = (unsigned long) (sw + 1) - 16; + info->sp = info->psp = stktop; + info->pr = sw->pr; + UNW_DPRINT(3, "unwind.%s:\n" + " task 0x%lx\n" + " rbs = [0x%lx-0x%lx)\n" + " stk = [0x%lx-0x%lx)\n" + " pr 0x%lx\n" + " sw 0x%lx\n" + " sp 0x%lx\n", + __FUNCTION__, (unsigned long) task, rbslimit, rbstop, stktop, stklimit, + info->pr, (unsigned long) info->sw, info->sp); + STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); +} + +void +unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t, + struct pt_regs *pt, struct switch_stack *sw) +{ + unsigned long sof; + + init_frame_info(info, t, sw, pt->r12); + info->cfm_loc = &pt->cr_ifs; + sof = *info->cfm_loc & 0x7f; + info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof); + info->ip = pt->cr_iip + ia64_psr(pt)->ri; + info->pt = (unsigned long) pt; + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sof 0x%lx\n" + " ip 0x%lx\n", + info->bsp, sof, info->ip); + find_save_locs(info); +} + +void +unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +{ + unsigned long sol; + + init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16); info->cfm_loc = &sw->ar_pfs; sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; - info->pr = sw->pr; - + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sol 0x%lx\n" + " ip 0x%lx\n", + info->bsp, sol, info->ip); find_save_locs(info); - STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); } void @@ -1888,6 +1982,7 @@ { struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16); + UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__); unw_init_frame_info(info, t, sw); } @@ -1915,7 +2010,8 @@ unsigned long flags; if (end - start <= 0) { - dprintk("unwind: ignoring attempt to insert empty unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n", + __FUNCTION__); return 0; } @@ -1945,13 +2041,15 @@ long index; if (!handle) { - dprintk("unwind: ignoring attempt to remove non-existent unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n", + __FUNCTION__); return; } table = handle; if (table == &unw.kernel_table) { - dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n"); + UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a " + "no-can-do!\n", __FUNCTION__); return; } @@ -1963,7 +2061,8 @@ if (prev->next == table) break; if (!prev) { - dprintk("unwind: failed to find unwind table %p\n", (void *) table); + UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n", + __FUNCTION__, (void *) table); spin_unlock_irqrestore(&unw.lock, flags); return; } @@ -2015,7 +2114,7 @@ unw.gate_table = alloc_bootmem(size); if (!unw.gate_table) { unw.gate_table_size = 0; - printk("unwind: unable to create unwind data for gate page!\n"); + printk(KERN_ERR "unwind: unable to create unwind data for gate page!\n"); return; } unw.gate_table_size = size; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/kernel/unwind_i.h linux2.4.21_itanium/arch/ia64/kernel/unwind_i.h --- linux2.4.21_itanium.org/arch/ia64/kernel/unwind_i.h Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/kernel/unwind_i.h Wed Jul 23 18:28:58 2003 @@ -137,7 +137,8 @@ UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK; s[dst+1].nat.off = *s.pri_unat - s[dst] */ UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */ - UNW_INSN_LOAD /* s[dst] = *s[val] */ + UNW_INSN_LOAD, /* s[dst] = *s[val] */ + UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */ }; struct unw_insn { diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/lib/memcpy_mck.S linux2.4.21_itanium/arch/ia64/lib/memcpy_mck.S --- linux2.4.21_itanium.org/arch/ia64/lib/memcpy_mck.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/lib/memcpy_mck.S Wed Jul 23 18:28:58 2003 @@ -163,7 +163,7 @@ mov ar.ec=2 (p10) br.dpnt.few .aligned_src_tail ;; - .align 32 +// .align 32 1: EX(.ex_handler, (p16) ld8 r34=[src0],16) EK(.ex_handler, (p16) ld8 r38=[src1],16) @@ -320,7 +320,7 @@ (p7) mov ar.lc = r21 (p8) mov ar.lc = r0 ;; - .align 32 +// .align 32 1: lfetch [src_pre_mem], 128 lfetch.excl [dst_pre_mem], 128 br.cloop.dptk.few 1b @@ -526,7 +526,7 @@ shrp r21=r22,r38,shift; /* speculative work */ \ br.sptk.few .unaligned_src_tail /* branch out of jump table */ \ ;; - .align 32 +// .align 32 .jump_table: COPYU(8) // unaligned cases .jmp1: diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/lib/memset.S linux2.4.21_itanium/arch/ia64/lib/memset.S --- linux2.4.21_itanium.org/arch/ia64/lib/memset.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/lib/memset.S Wed Jul 23 18:28:58 2003 @@ -125,7 +125,7 @@ (p_zr) br.cond.dptk.many .l1b // Jump to use stf.spill ;; } - .align 32 // -------------------------- // L1A: store ahead into cache lines; fill later +// .align 32 // -------------------------- // L1A: store ahead into cache lines; fill later { .mmi and tmp = -(LINE_SIZE), cnt // compute end of range mov ptr9 = ptr1 // used for prefetching @@ -194,7 +194,7 @@ br.cond.dpnt.many .move_bytes_from_alignment // Branch no. 3 ;; } - .align 32 +// .align 32 .l1b: // ------------------------------------ // L1B: store ahead into cache lines; fill later { .mmi and tmp = -(LINE_SIZE), cnt // compute end of range @@ -261,7 +261,7 @@ and cnt = 0x1f, cnt // compute the remaining cnt mov.i ar.lc = loopcnt ;; } - .align 32 +// .align 32 .l2: // ------------------------------------ // L2A: store 32B in 2 cycles { .mmb stf8 [ptr1] = fvalue, 8 diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/lib/swiotlb.c linux2.4.21_itanium/arch/ia64/lib/swiotlb.c --- linux2.4.21_itanium.org/arch/ia64/lib/swiotlb.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/lib/swiotlb.c Wed Jul 23 18:28:58 2003 @@ -116,7 +116,7 @@ io_tlb_index = 0; io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); - printk("Placing software IO TLB between 0x%p - 0x%p\n", + printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n", (void *) io_tlb_start, (void *) io_tlb_end); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/Makefile linux2.4.21_itanium/arch/ia64/mm/Makefile --- linux2.4.21_itanium.org/arch/ia64/mm/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/mm/Makefile Wed Jul 23 18:28:58 2003 @@ -12,5 +12,6 @@ export-objs := init.o obj-y := init.o fault.o tlb.o extable.o +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/extable.c linux2.4.21_itanium/arch/ia64/mm/extable.c --- linux2.4.21_itanium.org/arch/ia64/mm/extable.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/mm/extable.c Wed Jul 23 18:28:58 2003 @@ -38,6 +38,8 @@ register unsigned long main_gp __asm__("gp"); #endif +extern spinlock_t modlist_lock; + struct exception_fixup search_exception_table (unsigned long addr) { @@ -52,9 +54,11 @@ return fix; #else struct archdata *archdata; + unsigned long flags; struct module *mp; /* The kernel is the last "module" -- no need to treat it special. */ + spin_lock_irqsave(&modlist_lock, flags); for (mp = module_list; mp; mp = mp->next) { if (!mp->ex_table_start) continue; @@ -65,9 +69,10 @@ addr, (unsigned long) archdata->gp); if (entry) { fix.cont = entry->cont + (unsigned long) archdata->gp; - return fix; + break; } } + spin_unlock_irqrestore(&modlist_lock, flags); #endif return fix; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/fault.c linux2.4.21_itanium/arch/ia64/mm/fault.c --- linux2.4.21_itanium.org/arch/ia64/mm/fault.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/mm/fault.c Wed Jul 23 18:28:58 2003 @@ -43,6 +43,33 @@ return 0; } +/* + * Return TRUE if ADDRESS points at a page in the kernel's mapped segment + * (inside region 5, on ia64) and that page is present. + */ +static int +mapped_kernel_page_is_present (unsigned long address) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *ptep, pte; + + pgd = pgd_offset_k(address); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + pmd = pmd_offset(pgd,address); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return 0; + + ptep = pte_offset(pmd, address); + if (!ptep) + return 0; + + pte = *ptep; + return pte_present(pte); +} + void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { @@ -183,6 +210,16 @@ return; /* + * Since we have no vma's for region 5, we might get here even if the address is + * valid, due to the VHPT walker inserting a non present translation that becomes + * stale. If that happens, the non present fault handler already purged the stale + * translation, which fixed the problem. So, we check to see if the translation is + * valid, and return if it is. + */ + if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address)) + return; + + /* * Oops. The kernel tried to access some bad page. We'll have to terminate things * with extreme prejudice. */ @@ -204,7 +241,7 @@ goto survive; } up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", current->comm); + printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/hugetlbpage.c linux2.4.21_itanium/arch/ia64/mm/hugetlbpage.c --- linux2.4.21_itanium.org/arch/ia64/mm/hugetlbpage.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/mm/hugetlbpage.c Wed Jul 23 18:28:58 2003 @@ -0,0 +1,463 @@ +/* + * IA-64 Huge TLB Page Support for Kernel. + * + * Copyright (C) 2002, Rohit Seth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) + +static long htlbpagemem; +int htlbpage_max; +static long htlbzone_pages; + +struct vm_operations_struct hugetlb_vm_ops; +static LIST_HEAD(htlbpage_freelist); +static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; + +static struct page *alloc_hugetlb_page(void) +{ + int i; + struct page *page; + + spin_lock(&htlbpage_lock); + if (list_empty(&htlbpage_freelist)) { + spin_unlock(&htlbpage_lock); + return NULL; + } + + page = list_entry(htlbpage_freelist.next, struct page, list); + list_del(&page->list); + htlbpagemem--; + spin_unlock(&htlbpage_lock); + set_page_count(page, 1); + for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) + clear_highpage(&page[i]); + return page; +} + +static pte_t * +huge_pte_alloc (struct mm_struct *mm, unsigned long addr) +{ + unsigned long taddr = htlbpage_to_page(addr); + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte = NULL; + + pgd = pgd_offset(mm, taddr); + pmd = pmd_alloc(mm, pgd, taddr); + if (pmd) + pte = pte_alloc(mm, pmd, taddr); + return pte; +} + +static pte_t * +huge_pte_offset (struct mm_struct *mm, unsigned long addr) +{ + unsigned long taddr = htlbpage_to_page(addr); + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte = NULL; + + pgd = pgd_offset(mm, taddr); + pmd = pmd_offset(pgd, taddr); + pte = pte_offset(pmd, taddr); + return pte; +} + +#define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; } + +static void +set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma, + struct page *page, pte_t * page_table, int write_access) +{ + pte_t entry; + + mm->rss += (HPAGE_SIZE / PAGE_SIZE); + if (write_access) { + entry = + pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); + } else + entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot)); + entry = pte_mkyoung(entry); + mk_pte_huge(entry); + set_pte(page_table, entry); + return; +} +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + if (REGION_NUMBER(addr) != REGION_HPAGE) + return -EINVAL; + + return 0; +} +/* This function checks if the address and address+len falls out of HugeTLB region. It + * return -EINVAL if any part of address range falls in HugeTLB region. + */ +int is_invalid_hugepage_range(unsigned long addr, unsigned long len) +{ + if (REGION_NUMBER(addr) == REGION_HPAGE) + return -EINVAL; + if (REGION_NUMBER(addr+len) == REGION_HPAGE) + return -EINVAL; + return 0; +} + +int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + struct vm_area_struct *vma) +{ + pte_t *src_pte, *dst_pte, entry; + struct page *ptepage; + unsigned long addr = vma->vm_start; + unsigned long end = vma->vm_end; + + while (addr < end) { + dst_pte = huge_pte_alloc(dst, addr); + if (!dst_pte) + goto nomem; + src_pte = huge_pte_offset(src, addr); + entry = *src_pte; + ptepage = pte_page(entry); + get_page(ptepage); + set_pte(dst_pte, entry); + dst->rss += (HPAGE_SIZE / PAGE_SIZE); + addr += HPAGE_SIZE; + } + return 0; +nomem: + return -ENOMEM; +} + +int +follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, + struct page **pages, struct vm_area_struct **vmas, + unsigned long *st, int *length, int i) +{ + pte_t *ptep, pte; + unsigned long start = *st; + unsigned long pstart; + int len = *length; + struct page *page; + + do { + pstart = start; + ptep = huge_pte_offset(mm, start); + pte = *ptep; + +back1: + page = pte_page(pte); + if (pages) { + page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); + pages[i] = page; + } + if (vmas) + vmas[i] = vma; + i++; + len--; + start += PAGE_SIZE; + if (((start & HPAGE_MASK) == pstart) && len && + (start < vma->vm_end)) + goto back1; + } while (len && start < vma->vm_end); + *length = len; + *st = start; + return i; +} + +void free_huge_page(struct page *page) +{ + BUG_ON(page_count(page)); + BUG_ON(page->mapping); + + INIT_LIST_HEAD(&page->list); + + spin_lock(&htlbpage_lock); + list_add(&page->list, &htlbpage_freelist); + htlbpagemem++; + spin_unlock(&htlbpage_lock); +} + +void huge_page_release(struct page *page) +{ + if (!put_page_testzero(page)) + return; + + free_huge_page(page); +} + +void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long address; + pte_t *pte; + struct page *page; + + BUG_ON(start & (HPAGE_SIZE - 1)); + BUG_ON(end & (HPAGE_SIZE - 1)); + + for (address = start; address < end; address += HPAGE_SIZE) { + pte = huge_pte_offset(mm, address); + if (pte_none(*pte)) + continue; + page = pte_page(*pte); + huge_page_release(page); + pte_clear(pte); + } + mm->rss -= (end - start) >> PAGE_SHIFT; + flush_tlb_range(mm, start, end); +} + +void zap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long length) +{ + struct mm_struct *mm = vma->vm_mm; + spin_lock(&mm->page_table_lock); + unmap_hugepage_range(vma, start, start + length); + spin_unlock(&mm->page_table_lock); +} + +int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) +{ + struct mm_struct *mm = current->mm; + struct inode *inode = mapping->host; + unsigned long addr; + int ret = 0; + + BUG_ON(vma->vm_start & ~HPAGE_MASK); + BUG_ON(vma->vm_end & ~HPAGE_MASK); + + spin_lock(&mm->page_table_lock); + for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { + unsigned long idx; + pte_t *pte = huge_pte_alloc(mm, addr); + struct page *page; + + if (!pte) { + ret = -ENOMEM; + goto out; + } + if (!pte_none(*pte)) + continue; + + idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) + + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); + page = find_get_page(mapping, idx); + if (!page) { + loff_t i_size; + page = alloc_hugetlb_page(); + if (!page) { + ret = -ENOMEM; + goto out; + } + add_to_page_cache(page, mapping, idx); + unlock_page(page); + i_size = (loff_t)(idx + 1) * HPAGE_SIZE; + if (i_size > inode->i_size) + inode->i_size = i_size; + + } + set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); + } +out: + spin_unlock(&mm->page_table_lock); + return ret; +} + +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct *vmm; + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; + if (len & ~HPAGE_MASK) + return -EINVAL; + /* This code assumes that REGION_HPAGE != 0. */ + if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) + addr = TASK_HPAGE_BASE; + else + addr = COLOR_HALIGN(addr); + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT) + return -ENOMEM; + if (!vmm || (addr + len) <= vmm->vm_start) + return addr; + addr = COLOR_HALIGN(vmm->vm_end); + } +} +void update_and_free_page(struct page *page) +{ + int j; + struct page *map; + + map = page; + htlbzone_pages--; + for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) { + map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | + 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved); + set_page_count(map, 0); + map++; + } + set_page_count(page, 1); + __free_pages(page, HUGETLB_PAGE_ORDER); +} + +int try_to_free_low(int count) +{ + struct list_head *p; + struct page *page, *map; + + map = NULL; + spin_lock(&htlbpage_lock); + list_for_each(p, &htlbpage_freelist) { + if (map) { + list_del(&map->list); + update_and_free_page(map); + htlbpagemem--; + map = NULL; + if (++count == 0) + break; + } + page = list_entry(p, struct page, list); + if ((page_zone(page))->name[0] != 'H') //Look for non-Highmem zones. + map = page; + } + if (map) { + list_del(&map->list); + update_and_free_page(map); + htlbpagemem--; + count++; + } + spin_unlock(&htlbpage_lock); + return count; +} + +int set_hugetlb_mem_size(int count) +{ + int j, lcount; + struct page *page, *map; + extern long htlbzone_pages; + extern struct list_head htlbpage_freelist; + + if (count < 0) + lcount = count; + else + lcount = count - htlbzone_pages; + + if (lcount == 0) + return (int)htlbzone_pages; + if (lcount > 0) { /* Increase the mem size. */ + while (lcount--) { + page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + if (page == NULL) + break; + map = page; + for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) { + SetPageReserved(map); + map++; + } + spin_lock(&htlbpage_lock); + list_add(&page->list, &htlbpage_freelist); + htlbpagemem++; + htlbzone_pages++; + spin_unlock(&htlbpage_lock); + } + return (int) htlbzone_pages; + } + /* Shrink the memory size. */ + lcount = try_to_free_low(lcount); + while (lcount++ < 0) { + page = alloc_hugetlb_page(); + if (page == NULL) + break; + spin_lock(&htlbpage_lock); + update_and_free_page(page); + spin_unlock(&htlbpage_lock); + } + return (int) htlbzone_pages; +} + +int hugetlb_sysctl_handler(ctl_table *table, int write, struct file *file, void *buffer, size_t *length) +{ + proc_dointvec(table, write, file, buffer, length); + htlbpage_max = set_hugetlb_mem_size(htlbpage_max); + return 0; +} + +static int __init hugetlb_setup(char *s) +{ + if (sscanf(s, "%d", &htlbpage_max) <= 0) + htlbpage_max = 0; + return 1; +} +__setup("hugepages=", hugetlb_setup); + +static int __init hugetlb_init(void) +{ + int i, j; + struct page *page; + + for (i = 0; i < htlbpage_max; ++i) { + page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + if (!page) + break; + for (j = 0; j < HPAGE_SIZE/PAGE_SIZE; ++j) + SetPageReserved(&page[j]); + spin_lock(&htlbpage_lock); + list_add(&page->list, &htlbpage_freelist); + spin_unlock(&htlbpage_lock); + } + htlbpage_max = htlbpagemem = htlbzone_pages = i; + printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem); + return 0; +} +module_init(hugetlb_init); + +int hugetlb_report_meminfo(char *buf) +{ + return sprintf(buf, + "HugePages_Total: %5lu\n" + "HugePages_Free: %5lu\n" + "Hugepagesize: %5lu kB\n", + htlbzone_pages, + htlbpagemem, + HPAGE_SIZE/1024); +} + +int is_hugepage_mem_enough(size_t size) +{ + if (size > (htlbpagemem << HPAGE_SHIFT)) + return 0; + return 1; +} + +static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int unused) +{ + BUG(); + return NULL; +} + +struct vm_operations_struct hugetlb_vm_ops = { + .nopage = hugetlb_nopage, +}; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/init.c linux2.4.21_itanium/arch/ia64/mm/init.c --- linux2.4.21_itanium.org/arch/ia64/mm/init.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/mm/init.c Wed Jul 23 18:28:58 2003 @@ -26,9 +26,6 @@ #include #include #include -#include - -mmu_gather_t mmu_gathers[NR_CPUS]; /* References to section boundaries: */ extern char _stext, _etext, _edata, __init_begin, __init_end; @@ -255,7 +252,7 @@ pte_t *pte; if (!PageReserved(page)) - printk("put_gate_page: gate page at 0x%p not in reserved memory\n", + printk(KERN_ERR "put_gate_page: gate page at 0x%p not in reserved memory\n", page_address(page)); pgd = pgd_offset_k(address); /* note: this is NOT pgd_offset()! */ @@ -560,7 +557,7 @@ efi_memmap_walk(create_mem_map_page_table, 0); free_area_init_node(0, NULL, vmem_map, zones_size, 0, zholes_size); - printk("Virtual mem_map starts at 0x%p\n", mem_map); + printk(KERN_INFO "Virtual mem_map starts at 0x%p\n", mem_map); } #endif } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/mm/tlb.c linux2.4.21_itanium/arch/ia64/mm/tlb.c --- linux2.4.21_itanium.org/arch/ia64/mm/tlb.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/mm/tlb.c Wed Jul 23 18:28:58 2003 @@ -34,10 +34,10 @@ 1 << _PAGE_SIZE_4K ) struct ia64_ctx ia64_ctx = { - lock: SPIN_LOCK_UNLOCKED, - next: 1, - limit: (1 << 15) - 1, /* start out with the safe (architected) limit */ - max_ctx: ~0U + .lock = SPIN_LOCK_UNLOCKED, + .next = 1, + .limit =(1 << 15) - 1, /* start out with the safe (architected) limit */ + .max_ctx = ~0U }; /* @@ -48,6 +48,7 @@ { unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; struct task_struct *tsk; + int i; if (ia64_ctx.next > max_ctx) ia64_ctx.next = 300; /* skip daemons */ @@ -76,7 +77,14 @@ ia64_ctx.limit = tsk_context; } read_unlock(&tasklist_lock); - flush_tlb_all(); + /* + * Can't call flush_tlb_all() here because of race condition with scheduler [EF] + * and because interrupts are disabled during context switch. + */ + for (i = 0; i < NR_CPUS; ++i) + if (i != smp_processor_id()) + cpu_data(i)->need_tlb_flush = 1; + local_flush_tlb_all(); } void diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/scripts/unwcheck.sh linux2.4.21_itanium/arch/ia64/scripts/unwcheck.sh --- linux2.4.21_itanium.org/arch/ia64/scripts/unwcheck.sh Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/scripts/unwcheck.sh Wed Jul 23 18:29:00 2003 @@ -0,0 +1,109 @@ +#!/bin/sh +# Usage: unwcheck.sh +# Pre-requisite: readelf [from Gnu binutils package] +# Purpose: Check the following invariant +# For each code range in the input binary: +# Sum[ lengths of unwind regions] = Number of slots in code range. +# Author : Harish Patil +# First version: January 2002 +# Modified : 2/13/2002 +# Modified : 3/15/2002: duplicate detection +readelf -u $1 | gawk '\ + function todec(hexstr){ + dec = 0; + l = length(hexstr); + for (i = 1; i <= l; i++) + { + c = substr(hexstr, i, 1); + if (c == "A") + dec = dec*16 + 10; + else if (c == "B") + dec = dec*16 + 11; + else if (c == "C") + dec = dec*16 + 12; + else if (c == "D") + dec = dec*16 + 13; + else if (c == "E") + dec = dec*16 + 14; + else if (c == "F") + dec = dec*16 + 15; + else + dec = dec*16 + c; + } + return dec; + } + BEGIN { first = 1; sum_rlen = 0; no_slots = 0; errors=0; no_code_ranges=0; } + { + if (NF==5 && $3=="info") + { + no_code_ranges += 1; + if (first == 0) + { + if (sum_rlen != no_slots) + { + print full_code_range; + print " ", "lo = ", lo, " hi =", hi; + print " ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots; + print " "," ", "*******ERROR ***********"; + print " "," ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots; + errors += 1; + } + sum_rlen = 0; + } + full_code_range = $0; + code_range = $2; + gsub("..$", "", code_range); + gsub("^.", "", code_range); + split(code_range, addr, "-"); + lo = toupper(addr[1]); + + code_range_lo[no_code_ranges] = addr[1]; + occurs[addr[1]] += 1; + full_range[addr[1]] = $0; + + gsub("0X.[0]*", "", lo); + hi = toupper(addr[2]); + gsub("0X.[0]*", "", hi); + no_slots = (todec(hi) - todec(lo))/ 16*3 + first = 0; + } + if (index($0,"rlen") > 0 ) + { + rlen_str = substr($0, index($0,"rlen")); + rlen = rlen_str; + gsub("rlen=", "", rlen); + gsub(")", "", rlen); + sum_rlen = sum_rlen + rlen; + } + } + END { + if (first == 0) + { + if (sum_rlen != no_slots) + { + print "code_range=", code_range; + print " ", "lo = ", lo, " hi =", hi; + print " ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots; + print " "," ", "*******ERROR ***********"; + print " "," ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots; + errors += 1; + } + } + no_duplicates = 0; + for (i=1; i<=no_code_ranges; i++) + { + cr = code_range_lo[i]; + if (reported_cr[cr]==1) continue; + if ( occurs[cr] > 1) + { + reported_cr[cr] = 1; + print "Code range low ", code_range_lo[i], ":", full_range[cr], " occurs: ", occurs[cr], " times."; + print " "; + no_duplicates++; + } + } + print "======================================" + print "Total errors:", errors, "/", no_code_ranges, " duplicates:", no_duplicates; + print "======================================" + } + ' diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/Makefile linux2.4.21_itanium/arch/ia64/sn/fakeprom/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/Makefile Wed Jul 23 18:28:59 2003 @@ -3,7 +3,7 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (c) 2000-2002 Silicon Graphics, Inc. All rights reserved. +# Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved. # TOPDIR=../../../.. @@ -13,14 +13,15 @@ OBJ=fpromasm.o main.o fw-emu.o fpmem.o klgraph_init.o obj-y=fprom +EXTRA_CFLAGS += -DSGI_SN2 +EXTRA_AFLAGS += -DSGI_SN2 +AFLAGS += -DSGI_SN2 fprom: $(OBJ) $(LD) -static -Tfprom.lds -o fprom $(OBJ) $(LIB) .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< -.c.o: - $(CC) $(CFLAGS) $(CFLAGS_KERNEL) -c -o $*.o $< + $(CC) -D__ASSEMBLY__ $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< clean: rm -f *.o fprom diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/README linux2.4.21_itanium/arch/ia64/sn/fakeprom/README --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/README Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/README Wed Jul 23 18:28:59 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fpmem.c linux2.4.21_itanium/arch/ia64/sn/fakeprom/fpmem.c --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fpmem.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/fpmem.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -13,7 +13,7 @@ * FPROM EFI memory descriptor build routines * * - Routines to build the EFI memory descriptor map - * - Should also be usable by the SGI SN1 prom to convert + * - Should also be usable by the SGI prom to convert * klconfig to efi_memmap */ @@ -53,10 +53,7 @@ #define KERNEL_SIZE (4*MB) #define PROMRESERVED_SIZE (1*MB) -#ifdef CONFIG_IA64_SGI_SN1 -#define PHYS_ADDRESS(_n, _x) (((long)_n<<33) | (long)_x) -#define MD_BANK_SHFT 30 -#else +#ifdef SGI_SN2 #define PHYS_ADDRESS(_n, _x) (((long)_n<<38) | (long)_x | 0x3000000000UL) #define MD_BANK_SHFT 34 #endif @@ -77,7 +74,7 @@ return sn_config->cpus; } -/* For SN1, get the index th nasid */ +/* For SN, get the index th nasid */ int GetNasid(int index) @@ -104,40 +101,7 @@ * actually disabled etc. */ -#ifdef CONFIG_IA64_SGI_SN1 -int -IsBankPresent(int index, node_memmap_t nmemmap) -{ - switch (index) { - case 0:return nmemmap.b0; - case 1:return nmemmap.b1; - case 2:return nmemmap.b2; - case 3:return nmemmap.b3; - case 4:return nmemmap.b4; - case 5:return nmemmap.b5; - case 6:return nmemmap.b6; - case 7:return nmemmap.b7; - default:return -1 ; - } -} - -int -GetBankSize(int index, node_memmap_t nmemmap) -{ - switch (index) { - case 0: - case 1:return nmemmap.b01size; - case 2: - case 3:return nmemmap.b23size; - case 4: - case 5:return nmemmap.b45size; - case 6: - case 7:return nmemmap.b67size; - default:return -1 ; - } -} - -#else +#ifdef SGI_SN2 int IsBankPresent(int index, node_memmap_t nmemmap) { @@ -168,13 +132,13 @@ #endif void -build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes) +build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes, long attr) { md->type = type; md->phys_addr = paddr; md->virt_addr = 0; md->num_pages = numbytes >> 12; - md->attribute = EFI_MEMORY_WB; + md->attribute = attr; } int @@ -192,12 +156,12 @@ for (cnode=0;cnode /* - * Structure of the mem config of the node as a SN1 MI reg + * Structure of the mem config of the node as a SN MI reg * Medusa supports this reg config. * * BankSize nibble to bank size mapping @@ -24,32 +24,7 @@ #define MBSHIFT 20 -#ifdef CONFIG_IA64_SGI_SN1 -typedef struct node_memmap_s -{ - unsigned int b0 :1, /* 0 bank 0 present */ - b1 :1, /* 1 bank 1 present */ - r01 :2, /* 2-3 reserved */ - b01size :4, /* 4-7 Size of bank 0 and 1 */ - b2 :1, /* 8 bank 2 present */ - b3 :1, /* 9 bank 3 present */ - r23 :2, /* 10-11 reserved */ - b23size :4, /* 12-15 Size of bank 2 and 3 */ - b4 :1, /* 16 bank 4 present */ - b5 :1, /* 17 bank 5 present */ - r45 :2, /* 18-19 reserved */ - b45size :4, /* 20-23 Size of bank 4 and 5 */ - b6 :1, /* 24 bank 6 present */ - b7 :1, /* 25 bank 7 present */ - r67 :2, /* 26-27 reserved */ - b67size :4; /* 28-31 Size of bank 6 and 7 */ -} node_memmap_t ; - -/* Support the medusa hack for 8M/16M/32M nodes */ -#define SN1_BANK_SIZE_SHIFT (MBSHIFT+6) /* 64 MB */ -#define BankSizeBytes(bsize) ((bsize<6) ? (1<<((bsize-1)+SN1_BANK_SIZE_SHIFT)) :\ - (1<<((bsize-9)+MBSHIFT))) -#else +#ifdef SGI_SN2 typedef struct node_memmap_s { unsigned int b0size :3, /* 0-2 bank 0 size */ @@ -73,6 +48,8 @@ #define SN2_BANK_SIZE_SHIFT (MBSHIFT+6) /* 64 MB */ #define BankPresent(bsize) (bsize<6) #define BankSizeBytes(bsize) (BankPresent(bsize) ? 1UL<<((bsize)+SN2_BANK_SIZE_SHIFT) : 0) +#define MD_BANKS_PER_NODE 4 +#define MD_BANKSIZE (1UL << 34) #endif typedef struct sn_memmap_s diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fprom.lds linux2.4.21_itanium/arch/ia64/sn/fakeprom/fprom.lds --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fprom.lds Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/fprom.lds Wed Jul 23 18:28:59 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fpromasm.S linux2.4.21_itanium/arch/ia64/sn/fakeprom/fpromasm.S --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fpromasm.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/fpromasm.S Wed Jul 23 18:28:59 2003 @@ -8,7 +8,7 @@ * Copyright (C) 1998-2000 Hewlett-Packard Co * Copyright (C) 1998-2000 David Mosberger-Tang * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -57,9 +57,7 @@ * be 0x00000ffffc000000, but on snia we use the (inverse swizzled) * IOSPEC_BASE value */ -#ifdef CONFIG_IA64_SGI_SN1 -#define IOPB_PA 0xc0000FFFFC000000 -#else +#ifdef SGI_SN2 #define IOPB_PA 0xc000000fcc000000 #endif @@ -84,10 +82,7 @@ // Isolate node number we are running on. mov r6 = ip;; -#ifdef CONFIG_IA64_SGI_SN1 - shr r5 = r6,33;; // r5 = node number - shl r6 = r5,33 // r6 = base memory address of node -#else +#ifdef SGI_SN2 shr r5 = r6,38 // r5 = node number dep r6 = 0,r6,0,36 // r6 = base memory address of node @@ -99,7 +94,7 @@ or r1 = r1,r6 // Relocate to boot node // Lets figure out who we are & put it in the LID register. -#ifdef CONFIG_IA64_SGI_SN2 +#ifdef SGI_SN2 // On SN2, we (currently) pass the cpu number in r10 at boot and r25=3,r10;; movl r16=0x8000008110000400 // Allow IPIs @@ -324,10 +319,7 @@ 1: cmp.eq p6,p7=8,r28 /* PAL_VM_SUMMARY */ (p7) br.cond.sptk.few 1f movl r8=0 -#ifdef CONFIG_IA64_SGI_SN1 - movl r9=0x0203083001151059 - movl r10=0x1232 -#else +#ifdef SGI_SN2 movl r9=0x0203083001151065 movl r10=0x183f #endif diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fw-emu.c linux2.4.21_itanium/arch/ia64/sn/fakeprom/fw-emu.c --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/fw-emu.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/fw-emu.c Wed Jul 23 18:28:59 2003 @@ -5,7 +5,7 @@ * Copyright (C) 1998-2000 David Mosberger-Tang * * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -42,7 +42,7 @@ #include #include #include -#ifdef CONFIG_IA64_SGI_SN2 +#ifdef SGI_SN2 #include #include #endif @@ -68,10 +68,7 @@ #define ACPI_SLIT_REVISION 1 #define OEMID "SGI" -#ifdef CONFIG_IA64_SGI_SN1 -#define PRODUCT "SN1" -#define PROXIMITY_DOMAIN(nasid) (nasid) -#else +#ifdef SGI_SN2 #define PRODUCT "SN2" #define PROXIMITY_DOMAIN(nasid) (((nasid)>>1) & 255) #endif @@ -99,12 +96,7 @@ typedef union ia64_nasid_va { struct { -#if defined(CONFIG_IA64_SGI_SN1) - unsigned long off : 33; /* intra-region offset */ - unsigned long nasid : 7; /* NASID */ - unsigned long off2 : 21; /* fill */ - unsigned long reg : 3; /* region number */ -#elif defined(CONFIG_IA64_SGI_SN2) +#if defined(SGI_SN2) unsigned long off : 36; /* intra-region offset */ unsigned long attr : 2; unsigned long nasid : 11; /* NASID */ @@ -124,9 +116,7 @@ #define IS_VIRTUAL_MODE() ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;}) #define ADDR_OF(p) (IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p))) -#if defined(CONFIG_IA64_SGI_SN1) -#define __fwtab_pa(n,x) ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.l;}) -#elif defined(CONFIG_IA64_SGI_SN2) +#if defined(SGI_SN2) #define __fwtab_pa(n,x) ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.f.attr = 3; _v.l;}) #endif @@ -207,7 +197,7 @@ return EFI_UNSUPPORTED; } -#ifdef CONFIG_IA64_SGI_SN2 +#ifdef SGI_SN2 #undef cpu_physical_id #define cpu_physical_id(cpuid) ((ia64_get_lid() >> 16) & 0xffff) @@ -300,7 +290,7 @@ ; } else if (index == SAL_UPDATE_PAL) { ; -#ifdef CONFIG_IA64_SGI_SN2 +#ifdef SGI_SN2 } else if (index == SN_SAL_LOG_CE) { #ifdef ajmtestcpei fprom_send_cpei(); @@ -500,9 +490,7 @@ /* * Pass the parameter base address to the build_efi_xxx routines. */ -#if defined(CONFIG_IA64_SGI_SN1) - build_init(8LL*GB*base_nasid); -#else +#if defined(SGI_SN2) build_init(0x3000000000UL | ((long)base_nasid<<38)); #endif @@ -624,10 +612,7 @@ lsapic20->header.length = sizeof(struct acpi_table_lsapic); lsapic20->acpi_id = cnode*4+cpu; lsapic20->flags.enabled = 1; -#if defined(CONFIG_IA64_SGI_SN1) - lsapic20->eid = cpu; - lsapic20->id = nasid; -#else +#if defined(SGI_SN2) lsapic20->eid = nasid&0xffff; lsapic20->id = (cpu<<4) | (nasid>>16); #endif @@ -648,12 +633,9 @@ srat_memory_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid); srat_memory_affinity->base_addr_lo = 0; srat_memory_affinity->length_lo = 0; -#if defined(CONFIG_IA64_SGI_SN1) - srat_memory_affinity->base_addr_hi = nasid<<1; - srat_memory_affinity->length_hi = SN1_NODE_SIZE>>32; -#else +#if defined(SGI_SN2) srat_memory_affinity->base_addr_hi = (nasid<<6) | (3<<4); - srat_memory_affinity->length_hi = SN2_NODE_SIZE>>32; + srat_memory_affinity->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32; #endif srat_memory_affinity->memory_type = ACPI_ADDRESS_RANGE_MEMORY; srat_memory_affinity->flags.enabled = 1; @@ -670,10 +652,7 @@ srat_cpu_affinity->header.length = sizeof(struct acpi_table_processor_affinity); srat_cpu_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid); srat_cpu_affinity->flags.enabled = 1; -#if defined(CONFIG_IA64_SGI_SN1) - srat_cpu_affinity->apic_id = nasid; - srat_cpu_affinity->lsapic_eid = cpu; -#else +#if defined(SGI_SN2) srat_cpu_affinity->lsapic_eid = nasid&0xffff; srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>16); #endif @@ -707,7 +686,7 @@ sal_systab->sal_b_rev_minor = 0x0; /* 1.00 */ strcpy(sal_systab->oem_id, "SGI"); - strcpy(sal_systab->product_id, "SN1"); + strcpy(sal_systab->product_id, "SN2"); /* fill in an entry point: */ sal_ed->type = SAL_DESC_ENTRY_POINT; @@ -785,9 +764,7 @@ for(cpu=0; cpu 0) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/klgraph_init.c linux2.4.21_itanium/arch/ia64/sn/fakeprom/klgraph_init.c --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/klgraph_init.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/klgraph_init.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ @@ -49,41 +49,13 @@ klgraph_init(void) { -#ifdef CONFIG_IA64_SGI_SN1 u64 *temp; -#endif /* * Initialize some hub/xbow registers that allows access to * Xbridge etc. These are normally done in PROM. */ /* Write IOERR clear to clear the CRAZY bit in the status */ -#ifdef CONFIG_IA64_SGI_SN1 - *(volatile uint64_t *)0xc0000a0001c001f8 = (uint64_t)0xffffffff; - - /* set widget control register...setting bedrock widget id to b */ - *(volatile uint64_t *)0xc0000a0001c00020 = (uint64_t)0x801b; - - /* set io outbound widget access...allow all */ - *(volatile uint64_t *)0xc0000a0001c00110 = (uint64_t)0xff01; - - /* set io inbound widget access...allow all */ - *(volatile uint64_t *)0xc0000a0001c00118 = (uint64_t)0xff01; - - /* set io crb timeout to max */ - *(volatile uint64_t *)0xc0000a0001c003c0 = (uint64_t)0xffffff; - *(volatile uint64_t *)0xc0000a0001c003c0 = (uint64_t)0xffffff; - - /* set local block io permission...allow all */ - *(volatile uint64_t *)0xc0000a0001e04010 = (uint64_t)0xfffffffffffffff; - - /* clear any errors */ - /* clear_ii_error(); medusa should have cleared these */ - - /* set default read response buffers in bridge */ - *(volatile u32 *)0xc0000a000f000280L = 0xba98; - *(volatile u32 *)0xc0000a000f000288L = 0xba98; -#elif CONFIG_IA64_SGI_SN2 *(volatile uint64_t *)0xc000000801c001f8 = (uint64_t)0xffffffff; /* set widget control register...setting bedrock widget id to a */ @@ -108,184 +80,126 @@ /* set default read response buffers in bridge */ // [PI] *(volatile u32 *)0xc00000080f000280L = 0xba98; // [PI] *(volatile u32 *)0xc00000080f000288L = 0xba98; -#endif /* CONFIG_IA64_SGI_SN1 */ - -#ifdef CONFIG_IA64_SGI_SN1 - - /* - * kldir entries initialization - mankato - */ - convert(0x8000000000002000, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002010, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002020, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002030, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002040, 0x434d5f53505f5357, 0x0000000000030000); - convert(0x8000000000002050, 0x0000000000000000, 0x0000000000010000); - convert(0x8000000000002060, 0x0000000000000001, 0x0000000000000000); - convert(0x8000000000002070, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002080, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002090, 0x0000000000000000, 0x0000000000000000); - convert(0x80000000000020a0, 0x0000000000000000, 0x0000000000000000); - convert(0x80000000000020b0, 0x0000000000000000, 0x0000000000000000); - convert(0x80000000000020c0, 0x434d5f53505f5357, 0x0000000000000000); - convert(0x80000000000020d0, 0x0000000000002400, 0x0000000000000400); - convert(0x80000000000020e0, 0x0000000000000001, 0x0000000000000000); - convert(0x80000000000020f0, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002100, 0x434d5f53505f5357, 0x0000000000040000); - convert(0x8000000000002110, 0x0000000000000000, 0xffffffffffffffff); - convert(0x8000000000002120, 0x0000000000000001, 0x0000000000000000); - convert(0x8000000000002130, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002140, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002150, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002160, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002170, 0x0000000000000000, 0x0000000000000000); - convert(0x8000000000002180, 0x434d5f53505f5357, 0x0000000000020000); - convert(0x8000000000002190, 0x0000000000000000, 0x0000000000010000); - convert(0x80000000000021a0, 0x0000000000000001, 0x0000000000000000); - /* - * klconfig entries initialization - mankato - */ - convert(0x0000000000030000, 0x00000000beedbabe, 0x0000004800000000); - convert(0x0000000000030010, 0x0003007000000018, 0x800002000f820178); - convert(0x0000000000030020, 0x80000a000f024000, 0x800002000f800000); - convert(0x0000000000030030, 0x0300fafa00012580, 0x00000000040f0000); - convert(0x0000000000030040, 0x0000000000000000, 0x0003097000030070); - convert(0x0000000000030050, 0x00030970000303b0, 0x0003181000033f70); - convert(0x0000000000030060, 0x0003d51000037570, 0x0000000000038330); - convert(0x0000000000030070, 0x0203110100030140, 0x0001000000000101); - convert(0x0000000000030080, 0x0900000000000000, 0x000000004e465e67); - convert(0x0000000000030090, 0x0003097000000000, 0x00030b1000030a40); - convert(0x00000000000300a0, 0x00030cb000030be0, 0x000315a0000314d0); - convert(0x00000000000300b0, 0x0003174000031670, 0x0000000000000000); - convert(0x0000000000030100, 0x000000000000001a, 0x3350490000000000); - convert(0x0000000000030110, 0x0000000000000037, 0x0000000000000000); - convert(0x0000000000030140, 0x0002420100030210, 0x0001000000000101); - convert(0x0000000000030150, 0x0100000000000000, 0xffffffffffffffff); - convert(0x0000000000030160, 0x00030d8000000000, 0x0000000000030e50); - convert(0x00000000000301c0, 0x0000000000000000, 0x0000000000030070); - convert(0x00000000000301d0, 0x0000000000000025, 0x424f490000000000); - convert(0x00000000000301e0, 0x000000004b434952, 0x0000000000000000); - convert(0x0000000000030210, 0x00027101000302e0, 0x00010000000e4101); - convert(0x0000000000030220, 0x0200000000000000, 0xffffffffffffffff); - convert(0x0000000000030230, 0x00030f2000000000, 0x0000000000030ff0); - convert(0x0000000000030290, 0x0000000000000000, 0x0000000000030140); - convert(0x00000000000302a0, 0x0000000000000026, 0x7262490000000000); - convert(0x00000000000302b0, 0x00000000006b6369, 0x0000000000000000); - convert(0x00000000000302e0, 0x0002710100000000, 0x00010000000f3101); - convert(0x00000000000302f0, 0x0500000000000000, 0xffffffffffffffff); - convert(0x0000000000030300, 0x000310c000000000, 0x0003126000031190); - convert(0x0000000000030310, 0x0003140000031330, 0x0000000000000000); - convert(0x0000000000030360, 0x0000000000000000, 0x0000000000030140); - convert(0x0000000000030370, 0x0000000000000029, 0x7262490000000000); - convert(0x0000000000030380, 0x00000000006b6369, 0x0000000000000000); - convert(0x0000000000030970, 0x0000000002010102, 0x0000000000000000); - convert(0x0000000000030980, 0x000000004e465e67, 0xffffffff00000000); - /* convert(0x00000000000309a0, 0x0000000000037570, 0x0000000100000000); */ - convert(0x00000000000309a0, 0x0000000000037570, 0xffffffff00000000); - convert(0x00000000000309b0, 0x0000000000030070, 0x0000000000000000); - convert(0x00000000000309c0, 0x000000000003f420, 0x0000000000000000); - convert(0x0000000000030a40, 0x0000000002010125, 0x0000000000000000); - convert(0x0000000000030a50, 0xffffffffffffffff, 0xffffffff00000000); - convert(0x0000000000030a70, 0x0000000000037b78, 0x0000000000000000); - convert(0x0000000000030b10, 0x0000000002010125, 0x0000000000000000); - convert(0x0000000000030b20, 0xffffffffffffffff, 0xffffffff00000000); - convert(0x0000000000030b40, 0x0000000000037d30, 0x0000000000000001); - convert(0x0000000000030be0, 0x00000000ff010203, 0x0000000000000000); - convert(0x0000000000030bf0, 0xffffffffffffffff, 0xffffffff000000ff); - convert(0x0000000000030c10, 0x0000000000037ee8, 0x0100010000000200); - convert(0x0000000000030cb0, 0x00000000ff310111, 0x0000000000000000); - convert(0x0000000000030cc0, 0xffffffffffffffff, 0x0000000000000000); - convert(0x0000000000030d80, 0x0000000002010104, 0x0000000000000000); - convert(0x0000000000030d90, 0xffffffffffffffff, 0x00000000000000ff); - convert(0x0000000000030db0, 0x0000000000037f18, 0x0000000000000000); - convert(0x0000000000030dc0, 0x0000000000000000, 0x0003007000060000); - convert(0x0000000000030de0, 0x0000000000000000, 0x0003021000050000); - convert(0x0000000000030df0, 0x000302e000050000, 0x0000000000000000); - convert(0x0000000000030e30, 0x0000000000000000, 0x000000000000000a); - convert(0x0000000000030e50, 0x00000000ff00011a, 0x0000000000000000); - convert(0x0000000000030e60, 0xffffffffffffffff, 0x0000000000000000); - convert(0x0000000000030e80, 0x0000000000037fe0, 0x9e6e9e9e9e9e9e9e); - convert(0x0000000000030e90, 0x000000000000bc6e, 0x0000000000000000); - convert(0x0000000000030f20, 0x0000000002010205, 0x00000000d0020000); - convert(0x0000000000030f30, 0xffffffffffffffff, 0x0000000e0000000e); - convert(0x0000000000030f40, 0x000000000000000e, 0x0000000000000000); - convert(0x0000000000030f50, 0x0000000000038010, 0x00000000000007ff); - convert(0x0000000000030f70, 0x0000000000000000, 0x0000000022001077); - convert(0x0000000000030fa0, 0x0000000000000000, 0x000000000003f4a8); - convert(0x0000000000030ff0, 0x0000000000310120, 0x0000000000000000); - convert(0x0000000000031000, 0xffffffffffffffff, 0xffffffff00000002); - convert(0x0000000000031010, 0x000000000000000e, 0x0000000000000000); - convert(0x0000000000031020, 0x0000000000038088, 0x0000000000000000); - convert(0x00000000000310c0, 0x0000000002010205, 0x00000000d0020000); - convert(0x00000000000310d0, 0xffffffffffffffff, 0x0000000f0000000f); - convert(0x00000000000310e0, 0x000000000000000f, 0x0000000000000000); - convert(0x00000000000310f0, 0x00000000000380b8, 0x00000000000007ff); - convert(0x0000000000031120, 0x0000000022001077, 0x00000000000310a9); - convert(0x0000000000031130, 0x00000000580211c1, 0x000000008009104c); - convert(0x0000000000031140, 0x0000000000000000, 0x000000000003f4c0); - convert(0x0000000000031190, 0x0000000000310120, 0x0000000000000000); - convert(0x00000000000311a0, 0xffffffffffffffff, 0xffffffff00000003); - convert(0x00000000000311b0, 0x000000000000000f, 0x0000000000000000); - convert(0x00000000000311c0, 0x0000000000038130, 0x0000000000000000); - convert(0x0000000000031260, 0x0000000000110106, 0x0000000000000000); - convert(0x0000000000031270, 0xffffffffffffffff, 0xffffffff00000004); - convert(0x0000000000031280, 0x000000000000000f, 0x0000000000000000); - convert(0x00000000000312a0, 0x00000000ff110013, 0x0000000000000000); - convert(0x00000000000312b0, 0xffffffffffffffff, 0xffffffff00000000); - convert(0x00000000000312c0, 0x000000000000000f, 0x0000000000000000); - convert(0x00000000000312e0, 0x0000000000110012, 0x0000000000000000); - convert(0x00000000000312f0, 0xffffffffffffffff, 0xffffffff00000000); - convert(0x0000000000031300, 0x000000000000000f, 0x0000000000000000); - convert(0x0000000000031310, 0x0000000000038160, 0x0000000000000000); - convert(0x0000000000031330, 0x00000000ff310122, 0x0000000000000000); - convert(0x0000000000031340, 0xffffffffffffffff, 0xffffffff00000005); - convert(0x0000000000031350, 0x000000000000000f, 0x0000000000000000); - convert(0x0000000000031360, 0x0000000000038190, 0x0000000000000000); - convert(0x0000000000031400, 0x0000000000310121, 0x0000000000000000); - convert(0x0000000000031400, 0x0000000000310121, 0x0000000000000000); - convert(0x0000000000031410, 0xffffffffffffffff, 0xffffffff00000006); - convert(0x0000000000031420, 0x000000000000000f, 0x0000000000000000); - convert(0x0000000000031430, 0x00000000000381c0, 0x0000000000000000); - convert(0x00000000000314d0, 0x00000000ff010201, 0x0000000000000000); - convert(0x00000000000314e0, 0xffffffffffffffff, 0xffffffff00000000); - convert(0x0000000000031500, 0x00000000000381f0, 0x000030430000ffff); - convert(0x0000000000031510, 0x000000000000ffff, 0x0000000000000000); - convert(0x00000000000315a0, 0x00000020ff000201, 0x0000000000000000); - convert(0x00000000000315b0, 0xffffffffffffffff, 0xffffffff00000001); - convert(0x00000000000315d0, 0x0000000000038240, 0x00003f3f0000ffff); - convert(0x00000000000315e0, 0x000000000000ffff, 0x0000000000000000); - convert(0x0000000000031670, 0x00000000ff010201, 0x0000000000000000); - convert(0x0000000000031680, 0xffffffffffffffff, 0x0000000100000002); - convert(0x00000000000316a0, 0x0000000000038290, 0x000030430000ffff); - convert(0x00000000000316b0, 0x000000000000ffff, 0x0000000000000000); - convert(0x0000000000031740, 0x00000020ff000201, 0x0000000000000000); - convert(0x0000000000031750, 0xffffffffffffffff, 0x0000000500000003); - convert(0x0000000000031770, 0x00000000000382e0, 0x00003f3f0000ffff); - convert(0x0000000000031780, 0x000000000000ffff, 0x0000000000000000); - - /* - * GDA initialization - mankato - */ - convert(0x8000000000002400, 0x0000000258464552, 0x000000000ead0000); - convert(0x8000000000002480, 0xffffffff00010000, 0xffffffffffffffff); - convert(0x8000000000002490, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024a0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024b0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024c0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024d0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024e0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x80000000000024f0, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002500, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002510, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002520, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002530, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002540, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002550, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002560, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002570, 0xffffffffffffffff, 0xffffffffffffffff); - convert(0x8000000000002580, 0x000000000000ffff, 0x0000000000000000); -#endif - + /* + * klconfig entries initialization - mankato + */ + convert(0xe000003000030000, 0x00000000beedbabe, 0x0000004800000000); + convert(0xe000003000030010, 0x0003007000000018, 0x800002000f820178); + convert(0xe000003000030020, 0x80000a000f024000, 0x800002000f800000); + convert(0xe000003000030030, 0x0300fafa00012580, 0x00000000040f0000); + convert(0xe000003000030040, 0x0000000000000000, 0x0003097000030070); + convert(0xe000003000030050, 0x00030970000303b0, 0x0003181000033f70); + convert(0xe000003000030060, 0x0003d51000037570, 0x0000000000038330); + convert(0xe000003000030070, 0x0203110100030140, 0x0001000000000101); + convert(0xe000003000030080, 0x0900000000000000, 0x000000004e465e67); + convert(0xe000003000030090, 0x0003097000000000, 0x00030b1000030a40); + convert(0xe0000030000300a0, 0x00030cb000030be0, 0x000315a0000314d0); + convert(0xe0000030000300b0, 0x0003174000031670, 0x0000000000000000); + convert(0xe000003000030100, 0x000000000000001a, 0x3350490000000000); + convert(0xe000003000030110, 0x0000000000000037, 0x0000000000000000); + convert(0xe000003000030140, 0x0002420100030210, 0x0001000000000101); + convert(0xe000003000030150, 0x0100000000000000, 0xffffffffffffffff); + convert(0xe000003000030160, 0x00030d8000000000, 0x0000000000030e50); + convert(0xe0000030000301c0, 0x0000000000000000, 0x0000000000030070); + convert(0xe0000030000301d0, 0x0000000000000025, 0x424f490000000000); + convert(0xe0000030000301e0, 0x000000004b434952, 0x0000000000000000); + convert(0xe000003000030210, 0x00027101000302e0, 0x00010000000e4101); + convert(0xe000003000030220, 0x0200000000000000, 0xffffffffffffffff); + convert(0xe000003000030230, 0x00030f2000000000, 0x0000000000030ff0); + convert(0xe000003000030290, 0x0000000000000000, 0x0000000000030140); + convert(0xe0000030000302a0, 0x0000000000000026, 0x7262490000000000); + convert(0xe0000030000302b0, 0x00000000006b6369, 0x0000000000000000); + convert(0xe0000030000302e0, 0x0002710100000000, 0x00010000000f3101); + convert(0xe0000030000302f0, 0x0500000000000000, 0xffffffffffffffff); + convert(0xe000003000030300, 0x000310c000000000, 0x0003126000031190); + convert(0xe000003000030310, 0x0003140000031330, 0x0000000000000000); + convert(0xe000003000030360, 0x0000000000000000, 0x0000000000030140); + convert(0xe000003000030370, 0x0000000000000029, 0x7262490000000000); + convert(0xe000003000030380, 0x00000000006b6369, 0x0000000000000000); + convert(0xe000003000030970, 0x0000000002010102, 0x0000000000000000); + convert(0xe000003000030980, 0x000000004e465e67, 0xffffffff00000000); + /* convert(0x00000000000309a0, 0x0000000000037570, 0x0000000100000000); */ + convert(0xe0000030000309a0, 0x0000000000037570, 0xffffffff00000000); + convert(0xe0000030000309b0, 0x0000000000030070, 0x0000000000000000); + convert(0xe0000030000309c0, 0x000000000003f420, 0x0000000000000000); + convert(0xe000003000030a40, 0x0000000002010125, 0x0000000000000000); + convert(0xe000003000030a50, 0xffffffffffffffff, 0xffffffff00000000); + convert(0xe000003000030a70, 0x0000000000037b78, 0x0000000000000000); + convert(0xe000003000030b10, 0x0000000002010125, 0x0000000000000000); + convert(0xe000003000030b20, 0xffffffffffffffff, 0xffffffff00000000); + convert(0xe000003000030b40, 0x0000000000037d30, 0x0000000000000001); + convert(0xe000003000030be0, 0x00000000ff010203, 0x0000000000000000); + convert(0xe000003000030bf0, 0xffffffffffffffff, 0xffffffff000000ff); + convert(0xe000003000030c10, 0x0000000000037ee8, 0x0100010000000200); + convert(0xe000003000030cb0, 0x00000000ff310111, 0x0000000000000000); + convert(0xe000003000030cc0, 0xffffffffffffffff, 0x0000000000000000); + convert(0xe000003000030d80, 0x0000000002010104, 0x0000000000000000); + convert(0xe000003000030d90, 0xffffffffffffffff, 0x00000000000000ff); + convert(0xe000003000030db0, 0x0000000000037f18, 0x0000000000000000); + convert(0xe000003000030dc0, 0x0000000000000000, 0x0003007000060000); + convert(0xe000003000030de0, 0x0000000000000000, 0x0003021000050000); + convert(0xe000003000030df0, 0x000302e000050000, 0x0000000000000000); + convert(0xe000003000030e30, 0x0000000000000000, 0x000000000000000a); + convert(0xe000003000030e50, 0x00000000ff00011a, 0x0000000000000000); + convert(0xe000003000030e60, 0xffffffffffffffff, 0x0000000000000000); + convert(0xe000003000030e80, 0x0000000000037fe0, 0x9e6e9e9e9e9e9e9e); + convert(0xe000003000030e90, 0x000000000000bc6e, 0x0000000000000000); + convert(0xe000003000030f20, 0x0000000002010205, 0x00000000d0020000); + convert(0xe000003000030f30, 0xffffffffffffffff, 0x0000000e0000000e); + convert(0xe000003000030f40, 0x000000000000000e, 0x0000000000000000); + convert(0xe000003000030f50, 0x0000000000038010, 0x00000000000007ff); + convert(0xe000003000030f70, 0x0000000000000000, 0x0000000022001077); + convert(0xe000003000030fa0, 0x0000000000000000, 0x000000000003f4a8); + convert(0xe000003000030ff0, 0x0000000000310120, 0x0000000000000000); + convert(0xe000003000031000, 0xffffffffffffffff, 0xffffffff00000002); + convert(0xe000003000031010, 0x000000000000000e, 0x0000000000000000); + convert(0xe000003000031020, 0x0000000000038088, 0x0000000000000000); + convert(0xe0000030000310c0, 0x0000000002010205, 0x00000000d0020000); + convert(0xe0000030000310d0, 0xffffffffffffffff, 0x0000000f0000000f); + convert(0xe0000030000310e0, 0x000000000000000f, 0x0000000000000000); + convert(0xe0000030000310f0, 0x00000000000380b8, 0x00000000000007ff); + convert(0xe000003000031120, 0x0000000022001077, 0x00000000000310a9); + convert(0xe000003000031130, 0x00000000580211c1, 0x000000008009104c); + convert(0xe000003000031140, 0x0000000000000000, 0x000000000003f4c0); + convert(0xe000003000031190, 0x0000000000310120, 0x0000000000000000); + convert(0xe0000030000311a0, 0xffffffffffffffff, 0xffffffff00000003); + convert(0xe0000030000311b0, 0x000000000000000f, 0x0000000000000000); + convert(0xe0000030000311c0, 0x0000000000038130, 0x0000000000000000); + convert(0xe000003000031260, 0x0000000000110106, 0x0000000000000000); + convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004); + convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004); + convert(0xe000003000031280, 0x000000000000000f, 0x0000000000000000); + convert(0xe0000030000312a0, 0x00000000ff110013, 0x0000000000000000); + convert(0xe0000030000312b0, 0xffffffffffffffff, 0xffffffff00000000); + convert(0xe0000030000312c0, 0x000000000000000f, 0x0000000000000000); + convert(0xe0000030000312e0, 0x0000000000110012, 0x0000000000000000); + convert(0xe0000030000312f0, 0xffffffffffffffff, 0xffffffff00000000); + convert(0xe000003000031300, 0x000000000000000f, 0x0000000000000000); + convert(0xe000003000031310, 0x0000000000038160, 0x0000000000000000); + convert(0xe000003000031330, 0x00000000ff310122, 0x0000000000000000); + convert(0xe000003000031340, 0xffffffffffffffff, 0xffffffff00000005); + convert(0xe000003000031350, 0x000000000000000f, 0x0000000000000000); + convert(0xe000003000031360, 0x0000000000038190, 0x0000000000000000); + convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000); + convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000); + convert(0xe000003000031410, 0xffffffffffffffff, 0xffffffff00000006); + convert(0xe000003000031420, 0x000000000000000f, 0x0000000000000000); + convert(0xe000003000031430, 0x00000000000381c0, 0x0000000000000000); + convert(0xe0000030000314d0, 0x00000000ff010201, 0x0000000000000000); + convert(0xe0000030000314e0, 0xffffffffffffffff, 0xffffffff00000000); + convert(0xe000003000031500, 0x00000000000381f0, 0x000030430000ffff); + convert(0xe000003000031510, 0x000000000000ffff, 0x0000000000000000); + convert(0xe0000030000315a0, 0x00000020ff000201, 0x0000000000000000); + convert(0xe0000030000315b0, 0xffffffffffffffff, 0xffffffff00000001); + convert(0xe0000030000315d0, 0x0000000000038240, 0x00003f3f0000ffff); + convert(0xe0000030000315e0, 0x000000000000ffff, 0x0000000000000000); + convert(0xe000003000031670, 0x00000000ff010201, 0x0000000000000000); + convert(0xe000003000031680, 0xffffffffffffffff, 0x0000000100000002); + convert(0xe0000030000316a0, 0x0000000000038290, 0x000030430000ffff); + convert(0xe0000030000316b0, 0x000000000000ffff, 0x0000000000000000); + convert(0xe000003000031740, 0x00000020ff000201, 0x0000000000000000); + convert(0xe000003000031750, 0xffffffffffffffff, 0x0000000500000003); + convert(0xe000003000031770, 0x00000000000382e0, 0x00003f3f0000ffff); + convert(0xe000003000031780, 0x000000000000ffff, 0x0000000000000000); } - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/main.c linux2.4.21_itanium/arch/ia64/sn/fakeprom/main.c --- linux2.4.21_itanium.org/arch/ia64/sn/fakeprom/main.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/fakeprom/main.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -33,25 +33,9 @@ * First lets figure out who we are. This is done from the * LID passed to us. */ - -#ifdef CONFIG_IA64_SGI_SN1 - nasid = (lid>>24); - syn = (lid>>17)&1; - cpu = (lid>>16)&1; - - /* - * Now pick a synergy master to initialize synergy registers. - */ - if (test_and_set_bit(syn, &nasidmaster[nasid]) == 0) { - synergy_init(nasid, syn); - test_and_set_bit(syn+2, &nasidmaster[nasid]); - } else - while (get_bit(syn+2, &nasidmaster[nasid]) == 0); -#else nasid = (lid>>16)&0xfff; cpu = (lid>>28)&3; syn = 0; -#endif /* * Now pick a nasid master to initialize Bedrock registers. diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/Makefile linux2.4.21_itanium/arch/ia64/sn/io/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/Makefile Wed Jul 23 18:28:59 2003 @@ -3,31 +3,34 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. # # Makefile for the sn kernel routines. EXTRA_CFLAGS := -DLITTLE_ENDIAN -ifdef CONFIG_IA64_SGI_SN2 EXTRA_CFLAGS += -DSHUB_SWAP_WAR -endif O_TARGET := sgiio.o -export-objs := hcl.o pci_dma.o +obj-y := sgi_if.o xswitch.o sgi_io_sim.o \ + cdl.o io.o + +obj-y += sn2/snio.o machvec/snio.o \ + drivers/snio.o platform_init/snio.o -obj-y := stubs.o sgi_if.o xswitch.o klgraph_hack.o \ - hcl.o labelcl.o invent.o sgi_io_sim.o \ - klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \ - alenlist.o pci.o pci_dma.o ate_utils.o \ - ifconfig_net.o io.o ifconfig_bus.o - -obj-$(CONFIG_IA64_SGI_SN1) += sn1/snio.o -obj-$(CONFIG_IA64_SGI_SN2) += sn2/snio.o -obj-$(CONFIG_PCIBA) += pciba.o +ifdef CONFIG_HWGFS_FS +obj-$(CONFIG_HWGFS_FS) += hwgfs/snio.o +else +obj-$(CONFIG_DEVFS_FS) += hwgdfs/snio.o +endif -subdir-$(CONFIG_IA64_SGI_SN1) += sn1 -subdir-$(CONFIG_IA64_SGI_SN2) += sn2 +subdir-y += sn2 machvec drivers platform_init + +ifdef CONFIG_HWGFS_FS +subdir-$(CONFIG_HWGFS_FS) += hwgfs +else +subdir-$(CONFIG_DEVFS_FS) += hwgdfs +endif include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/cdl.c linux2.4.21_itanium/arch/ia64/sn/io/cdl.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/cdl.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/cdl.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -18,9 +18,9 @@ #include /* these get called directly in cdl_add_connpt in fops bypass hack */ -extern int pcibr_attach(devfs_handle_t); -extern int xbow_attach(devfs_handle_t); -extern int pic_attach(devfs_handle_t); +extern int pcibr_attach(vertex_hdl_t); +extern int xbow_attach(vertex_hdl_t); +extern int pic_attach(vertex_hdl_t); /* @@ -32,75 +32,20 @@ * IO Infrastructure Drivers e.g. pcibr. */ -struct cdl { - int part_num; - int mfg_num; - int (*attach) (devfs_handle_t); -} dummy_reg; - -#ifdef CONFIG_IA64_SGI_SN1 -#define MAX_SGI_IO_INFRA_DRVR 4 -#else #define MAX_SGI_IO_INFRA_DRVR 7 -#endif + static struct cdl sgi_infrastructure_drivers[MAX_SGI_IO_INFRA_DRVR] = { { XBRIDGE_WIDGET_PART_NUM, XBRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, { BRIDGE_WIDGET_PART_NUM, BRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, -#ifndef CONFIG_IA64_SGI_SN1 { PIC_WIDGET_PART_NUM_BUS0, PIC_WIDGET_MFGR_NUM, pic_attach /* &pic_fops */}, { PIC_WIDGET_PART_NUM_BUS1, PIC_WIDGET_MFGR_NUM, pic_attach /* &pic_fops */}, -#endif { XXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, { XBOW_WIDGET_PART_NUM, XBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, -#ifndef CONFIG_IA64_SGI_SN1 { PXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, -#endif }; /* - * cdl_new: Called by pciio and xtalk. - */ -cdl_p -cdl_new(char *name, char *k1str, char *k2str) -{ - /* - * Just return a dummy pointer. - */ - return((cdl_p)&dummy_reg); -} - -/* - * cdl_del: Do nothing. - */ -void -cdl_del(cdl_p reg) -{ - return; -} - -/* - * cdl_add_driver: The driver part number and manufacturers number - * are statically initialized above. - * - Do nothing. - */ -int -cdl_add_driver(cdl_p reg, int key1, int key2, char *prefix, int flags, cdl_drv_f *func) -{ - return 0; -} - -/* - * cdl_del_driver: Not supported. - */ -void -cdl_del_driver(cdl_p reg, char *prefix, cdl_drv_f *func) -{ - return; -} - -/* * cdl_add_connpt: We found a device and it's connect point. Call the * attach routine of that driver. * @@ -112,8 +57,8 @@ * vertices. */ int -cdl_add_connpt(cdl_p reg, int part_num, int mfg_num, - devfs_handle_t connpt, int drv_flags) +cdl_add_connpt(int part_num, int mfg_num, + vertex_hdl_t connpt, int drv_flags) { int i; @@ -121,7 +66,6 @@ * Find the driver entry point and call the attach routine. */ for (i = 0; i < MAX_SGI_IO_INFRA_DRVR; i++) { - if ( (part_num == sgi_infrastructure_drivers[i].part_num) && ( mfg_num == sgi_infrastructure_drivers[i].mfg_num) ) { /* @@ -139,73 +83,3 @@ return (0); } - -/* - * cdl_del_connpt: Not implemented. - */ -int -cdl_del_connpt(cdl_p reg, int key1, int key2, devfs_handle_t connpt, int drv_flags) -{ - - return(0); -} - -/* - * cdl_iterate: Not Implemented. - */ -void -cdl_iterate(cdl_p reg, - char *prefix, - cdl_iter_f * func) -{ - return; -} - -async_attach_t -async_attach_new(void) -{ - - return(0); -} - -void -async_attach_free(async_attach_t aa) -{ - return; -} - -async_attach_t -async_attach_get_info(devfs_handle_t vhdl) -{ - - return(0); -} - -void -async_attach_add_info(devfs_handle_t vhdl, async_attach_t aa) -{ - return; - -} - -void -async_attach_del_info(devfs_handle_t vhdl) -{ - return; -} - -void async_attach_signal_start(async_attach_t aa) -{ - return; -} - -void async_attach_signal_done(async_attach_t aa) -{ - return; -} - -void async_attach_waitall(async_attach_t aa) -{ - return; -} - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/Makefile linux2.4.21_itanium/arch/ia64/sn/io/drivers/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/Makefile Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/drivers/Makefile Wed Jul 23 18:29:00 2003 @@ -0,0 +1,18 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +O_TARGET := snio.o + +obj-y += hubdev.o ioconfig_bus.o ifconfig_net.o + +obj-$(CONFIG_PCIBA) += pciba.o + +include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/hubdev.c linux2.4.21_itanium/arch/ia64/sn/io/drivers/hubdev.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/hubdev.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/drivers/hubdev.c Wed Jul 23 18:29:00 2003 @@ -0,0 +1,100 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct hubdev_callout { + int (*attach_method)(vertex_hdl_t); + struct hubdev_callout *fp; +}; + +typedef struct hubdev_callout hubdev_callout_t; + +mutex_t hubdev_callout_mutex; +static hubdev_callout_t *hubdev_callout_list; + +void +hubdev_init(void) +{ + mutex_init(&hubdev_callout_mutex); + hubdev_callout_list = NULL; +} + +void +hubdev_register(int (*attach_method)(vertex_hdl_t)) +{ + hubdev_callout_t *callout; + + ASSERT(attach_method); + + callout = (hubdev_callout_t *)snia_kmem_zalloc(sizeof(hubdev_callout_t), KM_SLEEP); + ASSERT(callout); + + mutex_lock(&hubdev_callout_mutex); + /* + * Insert at the end of the list + */ + callout->fp = hubdev_callout_list; + hubdev_callout_list = callout; + callout->attach_method = attach_method; + mutex_unlock(&hubdev_callout_mutex); +} + +int +hubdev_unregister(int (*attach_method)(vertex_hdl_t)) +{ + hubdev_callout_t **p; + + ASSERT(attach_method); + + mutex_lock(&hubdev_callout_mutex); + /* + * Remove registry element containing attach_method + */ + for (p = &hubdev_callout_list; *p != NULL; p = &(*p)->fp) { + if ((*p)->attach_method == attach_method) { + hubdev_callout_t* victim = *p; + *p = (*p)->fp; + kfree(victim); + mutex_unlock(&hubdev_callout_mutex); + return (0); + } + } + mutex_unlock(&hubdev_callout_mutex); + return (ENOENT); +} + + +int +hubdev_docallouts(vertex_hdl_t hub) +{ + hubdev_callout_t *p; + int errcode; + + mutex_lock(&hubdev_callout_mutex); + + for (p = hubdev_callout_list; p != NULL; p = p->fp) { + ASSERT(p->attach_method); + errcode = (*p->attach_method)(hub); + if (errcode != 0) { + mutex_unlock(&hubdev_callout_mutex); + return (errcode); + } + } + mutex_unlock(&hubdev_callout_mutex); + return (0); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/ifconfig_net.c linux2.4.21_itanium/arch/ia64/sn/io/drivers/ifconfig_net.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/ifconfig_net.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/drivers/ifconfig_net.c Wed Jul 23 18:29:00 2003 @@ -0,0 +1,298 @@ +/* $Id: ifconfig_net.c,v 1.1.1.1 2003/07/23 09:29:00 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ifconfig_net - SGI's Persistent Network Device names. + * + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGI_IFCONFIG_NET "SGI-PERSISTENT NETWORK DEVICE NAME DRIVER" +#define SGI_IFCONFIG_NET_VERSION "1.0" + +/* + * Some Global definitions. + */ +static devfs_handle_t ifconfig_net_handle; +static unsigned long ifconfig_net_debug; + +/* + * ifconfig_net_open - Opens the special device node "/devhw/.ifconfig_net". + */ +static int ifconfig_net_open(struct inode * inode, struct file * filp) +{ + if (ifconfig_net_debug) { + printk("ifconfig_net_open called.\n"); + } + + return(0); + +} + +/* + * ifconfig_net_close - Closes the special device node "/devhw/.ifconfig_net". + */ +static int ifconfig_net_close(struct inode * inode, struct file * filp) +{ + + if (ifconfig_net_debug) { + printk("ifconfig_net_close called.\n"); + } + + return(0); +} + +/* + * assign_ifname - Assign the next available interface name from the persistent list. + */ +void +assign_ifname(struct net_device *dev, + struct ifname_num *ifname_num) + +{ + + /* + * Handle eth devices. + */ + if ( (memcmp(dev->name, "eth", 3) == 0) ) { + if (ifname_num->next_eth != -1) { + /* + * Assign it the next available eth interface number. + */ + memset(dev->name, 0, strlen(dev->name)); + sprintf(dev->name, "eth%d", (int)ifname_num->next_eth); + ifname_num->next_eth++; + } + + return; + } + + /* + * Handle fddi devices. + */ + if ( (memcmp(dev->name, "fddi", 4) == 0) ) { + if (ifname_num->next_fddi != -1) { + /* + * Assign it the next available fddi interface number. + */ + memset(dev->name, 0, strlen(dev->name)); + sprintf(dev->name, "fddi%d", (int)ifname_num->next_fddi); + ifname_num->next_fddi++; + } + + return; + } + + /* + * Handle hip devices. + */ + if ( (memcmp(dev->name, "hip", 3) == 0) ) { + if (ifname_num->next_hip != -1) { + /* + * Assign it the next available hip interface number. + */ + memset(dev->name, 0, strlen(dev->name)); + sprintf(dev->name, "hip%d", (int)ifname_num->next_hip); + ifname_num->next_hip++; + } + + return; + } + + /* + * Handle tr devices. + */ + if ( (memcmp(dev->name, "tr", 2) == 0) ) { + if (ifname_num->next_tr != -1) { + /* + * Assign it the next available tr interface number. + */ + memset(dev->name, 0, strlen(dev->name)); + sprintf(dev->name, "tr%d", (int)ifname_num->next_tr); + ifname_num->next_tr++; + } + + return; + } + + /* + * Handle fc devices. + */ + if ( (memcmp(dev->name, "fc", 2) == 0) ) { + if (ifname_num->next_fc != -1) { + /* + * Assign it the next available fc interface number. + */ + memset(dev->name, 0, strlen(dev->name)); + sprintf(dev->name, "fc%d", (int)ifname_num->next_fc); + ifname_num->next_fc++; + } + + return; + } +} + +/* + * find_persistent_ifname: Returns the entry that was seen in previous boot. + */ +struct ifname_MAC * +find_persistent_ifname(struct net_device *dev, + struct ifname_MAC *ifname_MAC) + +{ + + while (ifname_MAC->addr_len) { + if (memcmp(dev->dev_addr, ifname_MAC->dev_addr, dev->addr_len) == 0) + return(ifname_MAC); + + ifname_MAC++; + } + + return(NULL); +} + +/* + * ifconfig_net_ioctl: ifconfig_net driver ioctl interface. + */ +static int ifconfig_net_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + extern struct net_device *__dev_get_by_name(const char *); +#ifdef CONFIG_NET + struct net_device *dev; + struct ifname_MAC *found; + char temp[64]; +#endif + struct ifname_MAC *ifname_MAC; + struct ifname_MAC *new_devices, *temp_new_devices; + struct ifname_num *ifname_num; + unsigned long size; + + + if (ifconfig_net_debug) { + printk("HCL: hcl_ioctl called.\n"); + } + + /* + * Read in the header and see how big of a buffer we really need to + * allocate. + */ + ifname_num = (struct ifname_num *) kmalloc(sizeof(struct ifname_num), + GFP_KERNEL); + copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num)); + size = ifname_num->size; + kfree(ifname_num); + ifname_num = (struct ifname_num *) kmalloc(size, GFP_KERNEL); + ifname_MAC = (struct ifname_MAC *) ((char *)ifname_num + (sizeof(struct ifname_num)) ); + + copy_from_user( ifname_num, (char *) arg, size); + new_devices = kmalloc(size - sizeof(struct ifname_num), GFP_KERNEL); + temp_new_devices = new_devices; + + memset(new_devices, 0, size - sizeof(struct ifname_num)); + +#ifdef CONFIG_NET + /* + * Go through the net device entries and make them persistent! + */ + for (dev = dev_base; dev != NULL; dev = dev->next) { + /* + * Skip NULL entries or "lo" + */ + if ( (dev->addr_len == 0) || ( !strncmp(dev->name, "lo", strlen(dev->name))) ){ + continue; + } + + /* + * See if we have a persistent interface name for this device. + */ + found = NULL; + found = find_persistent_ifname(dev, ifname_MAC); + if (found) { + strcpy(dev->name, found->name); + } else { + /* Never seen this before .. */ + assign_ifname(dev, ifname_num); + + /* + * Save the information for the next boot. + */ + sprintf(temp,"%s %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + strcpy(temp_new_devices->name, dev->name); + temp_new_devices->addr_len = dev->addr_len; + memcpy(temp_new_devices->dev_addr, dev->dev_addr, dev->addr_len); + temp_new_devices++; + } + + } +#endif + + /* + * Copy back to the User Buffer area any new devices encountered. + */ + copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices, + size - sizeof(struct ifname_num)); + + return(0); + +} + +struct file_operations ifconfig_net_fops = { + ioctl:ifconfig_net_ioctl, /* ioctl */ + open:ifconfig_net_open, /* open */ + release:ifconfig_net_close /* release */ +}; + + +/* + * init_ifconfig_net() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + */ +#ifdef MODULE +int init_module (void) +#else +int __init init_ifconfig_net(void) +#endif +{ + ifconfig_net_handle = NULL; + ifconfig_net_handle = hwgraph_register(hwgraph_root, ".ifconfig_net", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &ifconfig_net_fops, NULL); + + if (ifconfig_net_handle == NULL) { + panic("Unable to create SGI PERSISTENT NETWORK DEVICE Name Driver.\n"); + } + + return(0); + +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/ioconfig_bus.c linux2.4.21_itanium/arch/ia64/sn/io/drivers/ioconfig_bus.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/ioconfig_bus.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/drivers/ioconfig_bus.c Wed Jul 23 18:29:00 2003 @@ -0,0 +1,401 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ioconfig_bus - SGI's Persistent PCI Bus Numbering. + * + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING" +#define SGI_IOCONFIG_BUS_VERSION "1.0" + +/* + * Some Global definitions. + */ +static vertex_hdl_t ioconfig_bus_handle; +static unsigned long ioconfig_bus_debug; + +#ifdef IOCONFIG_BUS_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +static u64 ioconfig_file; +static u64 ioconfig_file_size; +static u64 ioconfig_activated; +static char ioconfig_kernopts[128]; + +/* + * For debugging purpose .. hardcode a table .. + */ +struct ascii_moduleid *ioconfig_bus_table; +u64 ioconfig_bus_table_size; + + +static int free_entry; +static int new_entry; + +int next_basebus_number; + +void +ioconfig_get_busnum(char *io_moduleid, int *bus_num) +{ + struct ascii_moduleid *temp; + int index; + + DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid); + + *bus_num = -1; + temp = ioconfig_bus_table; + for (index = 0; index < free_entry; temp++, index++) { + if ( (io_moduleid[0] == temp->io_moduleid[0]) && + (io_moduleid[1] == temp->io_moduleid[1]) && + (io_moduleid[2] == temp->io_moduleid[2]) && + (io_moduleid[4] == temp->io_moduleid[4]) && + (io_moduleid[5] == temp->io_moduleid[5]) ) { + *bus_num = index * 0x10; + return; + } + } + + /* + * New IO Brick encountered. + */ + if (((int)io_moduleid[0]) == 0) { + DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid); + return; + } + + io_moduleid[3] = '#'; + strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid); + *bus_num = free_entry * 0x10; + free_entry++; +} + +static void +dump_ioconfig_table(void) +{ + + int index = 0; + struct ascii_moduleid *temp; + + temp = ioconfig_bus_table; + while (index < free_entry) { + DBG("ASSCI Module ID %s\n", temp->io_moduleid); + temp++; + index++; + } +} + +/* + * nextline + * This routine returns the nextline in the buffer. + */ +int nextline(char *buffer, char **next, char *line) +{ + + char *temp; + + if (buffer[0] == 0x0) { + return(0); + } + + temp = buffer; + while (*temp != 0) { + *line = *temp; + if (*temp != '\n'){ + *line = *temp; + temp++; line++; + } else + break; + } + + if (*temp == 0) + *next = temp; + else + *next = ++temp; + + return(1); +} + +/* + * build_pcibus_name + * This routine parses the ioconfig contents read into + * memory by ioconfig command in EFI and builds the + * persistent pci bus naming table. + */ +void +build_moduleid_table(char *file_contents, struct ascii_moduleid *table) +{ + /* + * Read the whole file into memory. + */ + int rc; + char *name; + char *temp; + char *next; + char *current; + char *line; + struct ascii_moduleid *moduleid; + + line = kmalloc(256, GFP_KERNEL); + memset(line, 0,256); + name = kmalloc(125, GFP_KERNEL); + memset(name, 0, 125); + moduleid = table; + current = file_contents; + while (nextline(current, &next, line)){ + + DBG("current 0x%lx next 0x%lx\n", current, next); + + temp = line; + /* + * Skip all leading Blank lines .. + */ + while (isspace(*temp)) + if (*temp != '\n') + temp++; + else + break; + + if (*temp == '\n') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Skip comment lines + */ + if (*temp == '#') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Get the next free entry in the table. + */ + rc = sscanf(temp, "%s", name); + strcpy(&moduleid->io_moduleid[0], name); + DBG("Found %s\n", name); + moduleid++; + free_entry++; + current = next; + memset(line, 0, 256); + } + + new_entry = free_entry; + kfree(line); + kfree(name); + + return; +} + +void +ioconfig_bus_init(void) +{ + + struct ia64_sal_retval ret_stuff; + u64 *temp; + int cnode; + + DBG("ioconfig_bus_init called.\n"); + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid_t nasid; + /* + * Make SAL call to get the address of the bus configuration table. + */ + ret_stuff.status = (uint64_t)0; + ret_stuff.v0 = (uint64_t)0; + ret_stuff.v1 = (uint64_t)0; + ret_stuff.v2 = (uint64_t)0; + nasid = COMPACT_TO_NASID_NODEID(cnode); + SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0); + temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0); + ioconfig_file = *temp; + DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid, + ret_stuff.v0); + if (ioconfig_file) { + ioconfig_file_size = ret_stuff.v1; + ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE); + ioconfig_activated = 1; + break; + } + } + + DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n", + ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size); + + ioconfig_bus_table = kmalloc( 512, GFP_KERNEL ); + memset(ioconfig_bus_table, 0, 512); + + /* + * If ioconfig options are given on the bootline .. take it. + */ + if (*ioconfig_kernopts != '\0') { + /* + * ioconfig="..." kernel options given. + */ + DBG("ioconfig_bus_init: Kernel Options given.\n"); + (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table); + (void) dump_ioconfig_table(); + return; + } + + if (ioconfig_activated) { + DBG("ioconfig_bus_init: ioconfig file given.\n"); + (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table); + (void) dump_ioconfig_table(); + } else { + DBG("ioconfig_bus_init: ioconfig command not executed in prom\n"); + } + +} + +void +ioconfig_bus_new_entries(void) +{ + + + int index = 0; + struct ascii_moduleid *temp; + + if ((ioconfig_activated) && (free_entry > new_entry)) { + printk("### Please add the following new IO Bricks Module ID \n"); + printk("### to your Persistent Bus Numbering Config File\n"); + } else + return; + + index = new_entry; + temp = &ioconfig_bus_table[index]; + while (index < free_entry) { + printk("%s\n", (char *)temp); + temp++; + index++; + } + printk("### End\n"); + +} +static int ioconfig_bus_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + struct ioconfig_parm parm; + + /* + * Copy in the parameters. + */ + copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)); + parm.number = free_entry - new_entry; + parm.ioconfig_activated = ioconfig_activated; + copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)); + copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry)); + + return 0; +} + +/* + * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_open(struct inode * inode, struct file * filp) +{ + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_open called.\n"); + } + + return(0); + +} + +/* + * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_close(struct inode * inode, struct file * filp) +{ + + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_close called.\n"); + } + + return(0); +} + +struct file_operations ioconfig_bus_fops = { + ioctl:ioconfig_bus_ioctl, + open:ioconfig_bus_open, /* open */ + release:ioconfig_bus_close /* release */ +}; + + +/* + * init_ifconfig_bus() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + */ +int init_ioconfig_bus(void) +{ + ioconfig_bus_handle = NULL; + ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &ioconfig_bus_fops, NULL); + + if (ioconfig_bus_handle == NULL) { + panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n"); + } + + return(0); + +} + +static int __init ioconfig_bus_setup (char *str) +{ + + char *temp; + + DBG("ioconfig_bus_setup: Kernel Options %s\n", str); + + temp = (char *)ioconfig_kernopts; + memset(temp, 0, 128); + while ( (*str != '\0') && !isspace (*str) ) { + if (*str == ',') { + *temp = '\n'; + temp++; + str++; + continue; + } + *temp = *str; + temp++; + str++; + } + + return(0); + +} +__setup("ioconfig=", ioconfig_bus_setup); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/pciba.c linux2.4.21_itanium/arch/ia64/sn/io/drivers/pciba.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/drivers/pciba.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/drivers/pciba.c Wed Jul 23 18:29:00 2003 @@ -0,0 +1,945 @@ +/* + * arch/ia64/sn/io/pciba.c + * + * IRIX PCIBA-inspired user mode PCI interface + * + * requires: devfs + * + * device nodes show up in /dev/pci/BB/SS.F (where BB is the bus the + * device is on, SS is the slot the device is in, and F is the + * device's function on a multi-function card). + * + * when compiled into the kernel, it will only be initialized by the + * sgi sn1 specific initialization code. in this case, device nodes + * are under /dev/hw/..../ + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of + * this archive for more details. + * + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. + * + * 03262001 - Initial version by Chad Talbott + */ + + +/* jesse's beefs: + + register_pci_device should be documented + + grossness with do_swap should be documented + + big, gross union'ized node_data should be replaced with independent + structures + + replace global list of nodes with global lists of resources. could + use object oriented approach of allocating and cleaning up + resources. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +MODULE_DESCRIPTION("User mode PCI interface"); +MODULE_AUTHOR("Chad Talbott"); + + +#undef DEBUG_PCIBA +/* #define DEBUG_PCIBA */ + +#undef TRACE_PCIBA +/* #define TRACE_PCIBA */ + +#if defined(DEBUG_PCIBA) +# define DPRINTF(x...) printk(KERN_DEBUG x) +#else +# define DPRINTF(x...) +#endif + +#if defined(TRACE_PCIBA) +# if defined(__GNUC__) +# define TRACE() printk(KERN_DEBUG "%s:%d:%s\n", \ + __FILE__, __LINE__, __FUNCTION__) +# else +# define TRACE() printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__) +# endif +#else +# define TRACE() +#endif + + +typedef enum { failure, success } status; +typedef enum { false, true } boolean; + + +/* major data structures: + + struct node_data - + + one for each file registered with devfs. contains everything + that any file's fops would need to know about. + + struct dma_allocation - + + a single DMA allocation. only the 'dma' nodes care about + these. they are there primarily to allow the driver to look + up the kernel virtual address of dma buffers allocated by + pci_alloc_consistent, as the application is only given the + physical address (to program the device's dma, presumably) and + cannot supply the kernel virtual address when freeing the + buffer. + + it's also useful to maintain a list of buffers allocated + through a specific node to allow some sanity checking by this + driver. this prevents (for example) a broken application from + freeing buffers that it didn't allocate, or buffers allocated + on another node. + + global_node_list - + + a list of all nodes allocated. this allows the driver to free + all the memory it has 'kmalloc'd in case of an error, or on + module removal. + + global_dma_list - + + a list of all dma buffers allocated by this driver. this + allows the driver to 'pci_free_consistent' all buffers on + module removal or error. + +*/ + + +struct node_data { + /* flat list of all the device nodes. makes it easy to free + them all when we're unregistered */ + struct list_head global_node_list; + vertex_hdl_t devfs_handle; + + void (* cleanup)(struct node_data *); + + union { + struct { + struct pci_dev * dev; + struct list_head dma_allocs; + boolean mmapped; + } dma; + struct { + struct pci_dev * dev; + u32 saved_rom_base_reg; + boolean mmapped; + } rom; + struct { + struct resource * res; + } base; + struct { + struct pci_dev * dev; + } config; + } u; +}; + +struct dma_allocation { + struct list_head list; + + dma_addr_t handle; + void * va; + size_t size; +}; + + +static LIST_HEAD(global_node_list); +static LIST_HEAD(global_dma_list); + + +/* module entry points */ +int __init pciba_init(void); +void __exit pciba_exit(void); + +static status __init register_with_devfs(void); +static void __exit unregister_with_devfs(void); + +static status __init register_pci_device(vertex_hdl_t device_dir_handle, + struct pci_dev * dev); + +/* file operations */ +static int generic_open(struct inode * inode, struct file * file); +static int rom_mmap(struct file * file, struct vm_area_struct * vma); +static int rom_release(struct inode * inode, struct file * file); +static int base_mmap(struct file * file, struct vm_area_struct * vma); +static int config_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, + unsigned long arg); +static int dma_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, + unsigned long arg); +static int dma_mmap(struct file * file, struct vm_area_struct * vma); + +/* support routines */ +static int mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va); +static int mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va); + +#ifdef DEBUG_PCIBA +static void dump_nodes(struct list_head * nodes); +static void dump_allocations(struct list_head * dalp); +#endif + +/* file operations for each type of node */ +static struct file_operations rom_fops = { + owner: THIS_MODULE, + mmap: rom_mmap, + open: generic_open, + release: rom_release +}; + + +static struct file_operations base_fops = { + owner: THIS_MODULE, + mmap: base_mmap, + open: generic_open +}; + + +static struct file_operations config_fops = { + owner: THIS_MODULE, + ioctl: config_ioctl, + open: generic_open +}; + +static struct file_operations dma_fops = { + owner: THIS_MODULE, + ioctl: dma_ioctl, + mmap: dma_mmap, + open: generic_open +}; + + +module_init(pciba_init); +module_exit(pciba_exit); + + +int __init +pciba_init(void) +{ + if (!ia64_platform_is("sn2")) + return -ENODEV; + + TRACE(); + + if (register_with_devfs() == failure) + return 1; /* failure */ + + printk("PCIBA (a user mode PCI interface) initialized.\n"); + + return 0; /* success */ +} + + +void __exit +pciba_exit(void) +{ + TRACE(); + + /* FIXME: should also free all that memory that we allocated + ;) */ + unregister_with_devfs(); +} + + +# if 0 +static void __exit +free_nodes(void) +{ + struct node_data * nd; + + TRACE(); + + list_for_each(nd, &node_list) { + kfree(list_entry(nd, struct nd, node_list)); + } +} +#endif + + +static vertex_hdl_t pciba_devfs_handle; + + +extern vertex_hdl_t +devfn_to_vertex(unsigned char busnum, unsigned int devfn); + +static status __init +register_with_devfs(void) +{ + struct pci_dev * dev; + vertex_hdl_t device_dir_handle; + + TRACE(); + + /* FIXME: don't forget /dev/.../pci/mem & /dev/.../pci/io */ + + pci_for_each_dev(dev) { + device_dir_handle = devfn_to_vertex(dev->bus->number, + dev->devfn); + if (device_dir_handle == NULL) + return failure; + + if (register_pci_device(device_dir_handle, dev) == failure) { + hwgraph_vertex_destroy(pciba_devfs_handle); + return failure; + } + } + + return success; +} + +static void __exit +unregister_with_devfs(void) +{ + struct list_head * lhp; + struct node_data * nd; + + TRACE(); + + list_for_each(lhp, &global_node_list) { + nd = list_entry(lhp, struct node_data, global_node_list); + hwgraph_vertex_destroy(nd->devfs_handle); + } + +} + + +struct node_data * new_node(void) +{ + struct node_data * node; + + TRACE(); + + node = kmalloc(sizeof(struct node_data), GFP_KERNEL); + if (node == NULL) + return NULL; + list_add(&node->global_node_list, &global_node_list); + return node; +} + + +void dma_cleanup(struct node_data * dma_node) +{ + TRACE(); + + /* FIXME: should free these allocations */ +#ifdef DEBUG_PCIBA + dump_allocations(&dma_node->u.dma.dma_allocs); +#endif + hwgraph_vertex_destroy(dma_node->devfs_handle); +} + + +void init_dma_node(struct node_data * node, + struct pci_dev * dev, vertex_hdl_t dh) +{ + TRACE(); + + node->devfs_handle = dh; + node->u.dma.dev = dev; + node->cleanup = dma_cleanup; + INIT_LIST_HEAD(&node->u.dma.dma_allocs); +} + + +void rom_cleanup(struct node_data * rom_node) +{ + TRACE(); + + if (rom_node->u.rom.mmapped) + pci_write_config_dword(rom_node->u.rom.dev, + PCI_ROM_ADDRESS, + rom_node->u.rom.saved_rom_base_reg); + hwgraph_vertex_destroy(rom_node->devfs_handle); +} + + +void init_rom_node(struct node_data * node, + struct pci_dev * dev, vertex_hdl_t dh) +{ + TRACE(); + + node->devfs_handle = dh; + node->u.rom.dev = dev; + node->cleanup = rom_cleanup; + node->u.rom.mmapped = false; +} + + +static status __init +register_pci_device(vertex_hdl_t device_dir_handle, struct pci_dev * dev) +{ + struct node_data * nd; + char devfs_path[20]; + vertex_hdl_t node_devfs_handle; + int ri; + + TRACE(); + + + /* register nodes for all the device's base address registers */ + for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) { + if (pci_resource_len(dev, ri) != 0) { + sprintf(devfs_path, "base/%d", ri); + if (hwgraph_register(device_dir_handle, devfs_path, + 0, DEVFS_FL_NONE, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, + &base_fops, + &dev->resource[ri]) == NULL) + return failure; + } + } + + /* register a node corresponding to the first MEM resource on + the device */ + for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) { + if (dev->resource[ri].flags & IORESOURCE_MEM && + pci_resource_len(dev, ri) != 0) { + if (hwgraph_register(device_dir_handle, "mem", + 0, DEVFS_FL_NONE, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, + &base_fops, + &dev->resource[ri]) == NULL) + return failure; + break; + } + } + + /* also register a node corresponding to the first IO resource + on the device */ + for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) { + if (dev->resource[ri].flags & IORESOURCE_IO && + pci_resource_len(dev, ri) != 0) { + if (hwgraph_register(device_dir_handle, "io", + 0, DEVFS_FL_NONE, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, + &base_fops, + &dev->resource[ri]) == NULL) + return failure; + break; + } + } + + /* register a node corresponding to the device's ROM resource, + if present */ + if (pci_resource_len(dev, PCI_ROM_RESOURCE) != 0) { + nd = new_node(); + if (nd == NULL) + return failure; + node_devfs_handle = hwgraph_register(device_dir_handle, "rom", + 0, DEVFS_FL_NONE, 0, 0, + S_IFCHR | S_IRUSR, 0, 0, + &rom_fops, nd); + if (node_devfs_handle == NULL) + return failure; + init_rom_node(nd, dev, node_devfs_handle); + } + + /* register a node that allows ioctl's to read and write to + the device's config space */ + if (hwgraph_register(device_dir_handle, "config", 0, DEVFS_FL_NONE, + 0, 0, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, + &config_fops, dev) == NULL) + return failure; + + + /* finally, register a node that allows ioctl's to allocate + and free DMA buffers, as well as memory map those + buffers. */ + nd = new_node(); + if (nd == NULL) + return failure; + node_devfs_handle = + hwgraph_register(device_dir_handle, "dma", 0, DEVFS_FL_NONE, + 0, 0, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, + &dma_fops, nd); + if (node_devfs_handle == NULL) + return failure; + init_dma_node(nd, dev, node_devfs_handle); + +#ifdef DEBUG_PCIBA + dump_nodes(&global_node_list); +#endif + + return success; +} + + +static int +generic_open(struct inode * inode, struct file * file) +{ + TRACE(); + + /* FIXME: should check that they're not trying to open the ROM + writable */ + + return 0; /* success */ +} + + +static int +rom_mmap(struct file * file, struct vm_area_struct * vma) +{ + unsigned long pci_pa; + struct node_data * nd; + + TRACE(); + +#ifdef CONFIG_HWGFS_FS + nd = (struct node_data * )file->f_dentry->d_fsdata; +#else + nd = (struct node_data * )file->private_data; +#endif + + pci_pa = pci_resource_start(nd->u.rom.dev, PCI_ROM_RESOURCE); + + if (!nd->u.rom.mmapped) { + nd->u.rom.mmapped = true; + DPRINTF("Enabling ROM address decoder.\n"); + DPRINTF( +"rom_mmap: FIXME: some cards do not allow both ROM and memory addresses to\n" +"rom_mmap: FIXME: be enabled simultaneously, as they share a decoder.\n"); + pci_read_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS, + &nd->u.rom.saved_rom_base_reg); + DPRINTF("ROM base address contains %x\n", + nd->u.rom.saved_rom_base_reg); + pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS, + nd->u.rom.saved_rom_base_reg | + PCI_ROM_ADDRESS_ENABLE); + } + + return mmap_pci_address(vma, pci_pa); +} + + +static int +rom_release(struct inode * inode, struct file * file) +{ + struct node_data * nd; + + TRACE(); + +#ifdef CONFIG_HWGFS_FS + nd = (struct node_data * )file->f_dentry->d_fsdata; +#else + nd = (struct node_data * )file->private_data; +#endif + + if (nd->u.rom.mmapped) { + nd->u.rom.mmapped = false; + DPRINTF("Disabling ROM address decoder.\n"); + pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS, + nd->u.rom.saved_rom_base_reg); + } + return 0; /* indicate success */ +} + + +static int +base_mmap(struct file * file, struct vm_area_struct * vma) +{ + struct resource * resource; + + TRACE(); + +#ifdef CONFIG_HWGFS_FS + resource = (struct resource *)file->f_dentry->d_fsdata; +#else + resource = (struct resource *)file->private_data; +#endif + + return mmap_pci_address(vma, resource->start); +} + + +static int +config_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, + unsigned long arg) +{ + struct pci_dev * dev; + + union cfg_data { + uint8_t byte; + uint16_t word; + uint32_t dword; + } read_data, write_data; + + int dir, size, offset; + + TRACE(); + + DPRINTF("cmd = %x (DIR = %x, TYPE = %x, NR = %x, SIZE = %x)\n", + cmd, + _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); + DPRINTF("arg = %lx\n", arg); + +#ifdef CONFIG_HWGFS_FS + dev = (struct pci_dev *)file->f_dentry->d_fsdata; +#else + dev = (struct pci_dev *)file->private_data; +#endif + + /* PCIIOCCFG{RD,WR}: read and/or write PCI configuration + space. If both, the read happens first (this becomes a swap + operation, atomic with respect to other updates through + this path). */ + + dir = _IOC_DIR(cmd); + +#define do_swap(suffix, type) \ + do { \ + if (dir & _IOC_READ) { \ + pci_read_config_##suffix(dev, _IOC_NR(cmd), \ + &read_data.suffix); \ + } \ + if (dir & _IOC_WRITE) { \ + get_user(write_data.suffix, (type)arg); \ + pci_write_config_##suffix(dev, _IOC_NR(cmd), \ + write_data.suffix); \ + } \ + if (dir & _IOC_READ) { \ + put_user(read_data.suffix, (type)arg); \ + } \ + } while (0) + + size = _IOC_SIZE(cmd); + offset = _IOC_NR(cmd); + + DPRINTF("sanity check\n"); + if (((size > 0) || (size <= 4)) && + ((offset + size) <= 256) && + (dir & (_IOC_READ | _IOC_WRITE))) { + + switch (size) + { + case 1: + do_swap(byte, uint8_t *); + break; + case 2: + do_swap(word, uint16_t *); + break; + case 4: + do_swap(dword, uint32_t *); + break; + default: + DPRINTF("invalid ioctl\n"); + return -EINVAL; + } + } else + return -EINVAL; + + return 0; +} + + +#ifdef DEBUG_PCIBA +static void +dump_allocations(struct list_head * dalp) +{ + struct dma_allocation * dap; + struct list_head * p; + + printk("{\n"); + list_for_each(p, dalp) { + dap = list_entry(p, struct dma_allocation, + list); + printk(" handle = %lx, va = %p\n", + dap->handle, dap->va); + } + printk("}\n"); +} + +static void +dump_nodes(struct list_head * nodes) +{ + struct node_data * ndp; + struct list_head * p; + + printk("{\n"); + list_for_each(p, nodes) { + ndp = list_entry(p, struct node_data, + global_node_list); + printk(" %p\n", (void *)ndp); + } + printk("}\n"); +} + + +#if 0 +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) + +static void +test_list(void) +{ + u64 i; + LIST_HEAD(the_list); + + for (i = 0; i < 5; i++) { + struct dma_allocation * new_alloc; + NEW(new_alloc); + new_alloc->va = (void *)i; + new_alloc->handle = 5*i; + printk("%d - the_list->next = %lx\n", i, the_list.next); + list_add(&new_alloc->list, &the_list); + } + dump_allocations(&the_list); +} +#endif +#endif + + +static LIST_HEAD(dma_buffer_list); + + +static int +dma_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, + unsigned long arg) +{ + struct node_data * nd; + uint64_t argv; + int result; + struct dma_allocation * dma_alloc; + struct list_head * iterp; + + TRACE(); + + DPRINTF("cmd = %x\n", cmd); + DPRINTF("arg = %lx\n", arg); + +#ifdef CONFIG_HWGFS_FS + nd = (struct node_data *)file->f_dentry->d_fsdata; +#else + nd = (struct node_data *)file->private_data; +#endif + +#ifdef DEBUG_PCIBA + DPRINTF("at dma_ioctl entry\n"); + dump_allocations(&nd->u.dma.dma_allocs); +#endif + + switch (cmd) { + case PCIIOCDMAALLOC: + /* PCIIOCDMAALLOC: allocate a chunk of physical memory + and set it up for DMA. Return the PCI address that + gets to it. */ + DPRINTF("case PCIIOCDMAALLOC (%lx)\n", PCIIOCDMAALLOC); + + if ( (result = get_user(argv, (uint64_t *)arg)) ) + return result; + DPRINTF("argv (size of buffer) = %lx\n", argv); + + dma_alloc = (struct dma_allocation *) + kmalloc(sizeof(struct dma_allocation), GFP_KERNEL); + if (dma_alloc == NULL) + return -ENOMEM; + + dma_alloc->size = (size_t)argv; + dma_alloc->va = pci_alloc_consistent(nd->u.dma.dev, + dma_alloc->size, + &dma_alloc->handle); + DPRINTF("dma_alloc->va = %p, dma_alloc->handle = %lx\n", + dma_alloc->va, dma_alloc->handle); + if (dma_alloc->va == NULL) { + kfree(dma_alloc); + return -ENOMEM; + } + + list_add(&dma_alloc->list, &nd->u.dma.dma_allocs); + if ( (result = put_user((uint64_t)dma_alloc->handle, + (uint64_t *)arg)) ) { + DPRINTF("put_user failed\n"); + pci_free_consistent(nd->u.dma.dev, (size_t)argv, + dma_alloc->va, dma_alloc->handle); + kfree(dma_alloc); + return result; + } + +#ifdef DEBUG_PCIBA + DPRINTF("after insertion\n"); + dump_allocations(&nd->u.dma.dma_allocs); +#endif + break; + + case PCIIOCDMAFREE: + DPRINTF("case PCIIOCDMAFREE (%lx)\n", PCIIOCDMAFREE); + + if ( (result = get_user(argv, (uint64_t *)arg)) ) { + DPRINTF("get_user failed\n"); + return result; + } + + DPRINTF("argv (physical address of DMA buffer) = %lx\n", argv); + list_for_each(iterp, &nd->u.dma.dma_allocs) { + struct dma_allocation * da = + list_entry(iterp, struct dma_allocation, list); + if (da->handle == argv) { + pci_free_consistent(nd->u.dma.dev, da->size, + da->va, da->handle); + list_del(&da->list); + kfree(da); +#ifdef DEBUG_PCIBA + DPRINTF("after deletion\n"); + dump_allocations(&nd->u.dma.dma_allocs); +#endif + return 0; /* success */ + } + } + /* previously allocated dma buffer wasn't found */ + DPRINTF("attempt to free invalid dma handle\n"); + return -EINVAL; + + default: + DPRINTF("undefined ioctl\n"); + return -EINVAL; + } + + DPRINTF("success\n"); + return 0; +} + + +static int +dma_mmap(struct file * file, struct vm_area_struct * vma) +{ + struct node_data * nd; + struct list_head * iterp; + int result; + + TRACE(); + +#ifdef CONFIG_HWGFS_FS + nd = (struct node_data *)file->f_dentry->d_fsdata; +#else + nd = (struct node_data *)file->private_data; +#endif + + DPRINTF("vma->vm_start is %lx\n", vma->vm_start); + DPRINTF("vma->vm_end is %lx\n", vma->vm_end); + DPRINTF("offset = %lx\n", vma->vm_pgoff); + + /* get kernel virtual address for the dma buffer (necessary + * for the mmap). */ + list_for_each(iterp, &nd->u.dma.dma_allocs) { + struct dma_allocation * da = + list_entry(iterp, struct dma_allocation, list); + /* why does mmap shift its offset argument? */ + if (da->handle == vma->vm_pgoff << PAGE_SHIFT) { + DPRINTF("found dma handle\n"); + if ( (result = mmap_kernel_address(vma, + da->va)) ) { + return result; /* failure */ + } else { + /* it seems like at least one of these + should show up in user land.... + I'm missing something */ + *(char *)da->va = 0xaa; + strncpy(da->va, " Toastie!", da->size); + if (put_user(0x18badbeeful, + (u64 *)vma->vm_start)) + DPRINTF("put_user failed?!\n"); + return 0; /* success */ + } + + } + } + DPRINTF("attempt to mmap an invalid dma handle\n"); + return -EINVAL; +} + + +static int +mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va) +{ + unsigned long pci_pa; + + TRACE(); + + DPRINTF("vma->vm_start is %lx\n", vma->vm_start); + DPRINTF("vma->vm_end is %lx\n", vma->vm_end); + + /* the size of the vma doesn't necessarily correspond to the + size specified in the mmap call. So we can't really do any + kind of sanity check here. This is a dangerous driver, and + it's very easy for a user process to kill the machine. */ + + DPRINTF("PCI base at virtual address %lx\n", pci_va); + /* the __pa macro is intended for region 7 on IA64, so it + doesn't work for region 6 */ + /* pci_pa = __pa(pci_va); */ + /* should be replaced by __tpa or equivalent (preferably a + generic equivalent) */ + pci_pa = pci_va & ~0xe000000000000000ul; + DPRINTF("PCI base at physical address %lx\n", pci_pa); + + /* there are various arch-specific versions of this function + defined in linux/drivers/char/mem.c, but it would be nice + if all architectures put it in pgtable.h. it's defined + there for ia64.... */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO; + + return io_remap_page_range(vma->vm_start, pci_pa, + vma->vm_end-vma->vm_start, + vma->vm_page_prot); +} + + +static int +mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va) +{ + unsigned long kernel_pa; + + TRACE(); + + DPRINTF("vma->vm_start is %lx\n", vma->vm_start); + DPRINTF("vma->vm_end is %lx\n", vma->vm_end); + + /* the size of the vma doesn't necessarily correspond to the + size specified in the mmap call. So we can't really do any + kind of sanity check here. This is a dangerous driver, and + it's very easy for a user process to kill the machine. */ + + DPRINTF("mapping virtual address %p\n", kernel_va); + kernel_pa = __pa(kernel_va); + DPRINTF("mapping physical address %lx\n", kernel_pa); + + vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO; + + return remap_page_range(vma->vm_start, kernel_pa, + vma->vm_end-vma->vm_start, + vma->vm_page_prot); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/Makefile linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/Makefile Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/Makefile Wed Jul 23 18:28:59 2003 @@ -0,0 +1,18 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +O_TARGET := snio.o + +export-objs := hcl.o + +obj-y += hcl.o labelcl.o hcl_util.o invent_stub.o + +include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/hcl.c linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/hcl.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/hcl.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/hcl.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,916 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * hcl - SGI's Hardware Graph compatibility layer. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER" +#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE" +#define HCL_TEMP_NAME_LEN 44 +#define HCL_VERSION "1.0" +vertex_hdl_t hwgraph_root; +vertex_hdl_t linux_busnum; + +extern void pci_bus_cvlink_init(void); + +/* + * Debug flag definition. + */ +#define OPTION_NONE 0x00 +#define HCL_DEBUG_NONE 0x00000 +#define HCL_DEBUG_ALL 0x0ffff +#if defined(CONFIG_HCL_DEBUG) +static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE; +#endif +static unsigned int hcl_debug = HCL_DEBUG_NONE; +#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE) +static unsigned int boot_options = OPTION_NONE; +#endif + +/* + * Some Global definitions. + */ +static vertex_hdl_t hcl_handle; + +invplace_t invplace_none = { + GRAPH_VERTEX_NONE, + GRAPH_VERTEX_PLACE_NONE, + NULL +}; + +/* + * HCL device driver. + * The purpose of this device driver is to provide a facility + * for User Level Apps e.g. hinv, ioconfig etc. an ioctl path + * to manipulate label entries without having to implement + * system call interfaces. This methodology will enable us to + * make this feature module loadable. + */ +static int hcl_open(struct inode * inode, struct file * filp) +{ + if (hcl_debug) { + printk("HCL: hcl_open called.\n"); + } + + return(0); + +} + +static int hcl_close(struct inode * inode, struct file * filp) +{ + + if (hcl_debug) { + printk("HCL: hcl_close called.\n"); + } + + return(0); + +} + +static int hcl_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + if (hcl_debug) { + printk("HCL: hcl_ioctl called.\n"); + } + + switch (cmd) { + default: + if (hcl_debug) { + printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd); + } + } + + return(0); + +} + +struct file_operations hcl_fops = { + (struct module *)0, + NULL, /* lseek - default */ + NULL, /* read - general block-dev read */ + NULL, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* poll */ + hcl_ioctl, /* ioctl */ + NULL, /* mmap */ + hcl_open, /* open */ + NULL, /* flush */ + hcl_close, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* lock */ + NULL, /* readv */ + NULL, /* writev */ +}; + + +/* + * init_hcl() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + * For now this routine is being called out of devfs/base.c. Actually + * Not a bad place to be .. + * + */ +int __init init_hcl(void) +{ + extern void string_table_init(struct string_table *); + extern struct string_table label_string_table; + extern int init_ifconfig_net(void); + extern int init_ioconfig_bus(void); + int status = 0; + int rv = 0; + + if (IS_RUNNING_ON_SIMULATOR()) { + extern u64 klgraph_addr[]; + klgraph_addr[0] = 0xe000003000030000; + } + + /* + * Create the hwgraph_root on devfs. + */ + rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root); + if (rv) + printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv); + + status = devfs_set_flags (hwgraph_root, DEVFS_FL_HIDE); + + /* + * Create the hcl driver to support inventory entry manipulations. + * By default, it is expected that devfs is mounted on /dev. + * + */ + hcl_handle = hwgraph_register(hwgraph_root, ".hcl", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &hcl_fops, NULL); + + if (hcl_handle == NULL) { + panic("HCL: Unable to create HCL Driver in init_hcl().\n"); + return(0); + } + + /* + * Initialize the HCL string table. + */ + string_table_init(&label_string_table); + + /* + * Create the directory that links Linux bus numbers to our Xwidget. + */ + rv = hwgraph_path_add(hwgraph_root, EDGE_LBL_LINUX_BUS, &linux_busnum); + if (linux_busnum == NULL) { + panic("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS); + return(0); + } + + pci_bus_cvlink_init(); + + /* + * Initialize the ifconfgi_net driver that does network devices + * Persistent Naming. + */ + init_ifconfig_net(); + init_ioconfig_bus(); + + return(0); + +} + + +/* + * hcl_setup() - Process boot time parameters if given. + * "hcl=" + * This routine gets called only if "hcl=" is given in the + * boot line and before init_hcl(). + * + * We currently do not have any boot options .. when we do, + * functionalities can be added here. + * + */ +static int __init hcl_setup(char *str) +{ + while ( (*str != '\0') && !isspace (*str) ) + { +#ifdef CONFIG_HCL_DEBUG + if (strncmp (str, "all", 3) == 0) { + hcl_debug_init |= HCL_DEBUG_ALL; + str += 3; + } else + return 0; +#endif + if (*str != ',') return 0; + ++str; + } + + return 1; + +} + +__setup("hcl=", hcl_setup); + + +/* + * Set device specific "fast information". + * + */ +void +hwgraph_fastinfo_set(vertex_hdl_t de, arbitrary_info_t fastinfo) +{ + labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL); +} + + +/* + * Get device specific "fast information". + * + */ +arbitrary_info_t +hwgraph_fastinfo_get(vertex_hdl_t de) +{ + arbitrary_info_t fastinfo; + int rv; + + if (!de) { + printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n"); + return(-1); + } + + rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo); + if (rv == 0) + return(fastinfo); + + return(0); +} + + +/* + * hwgraph_connectpt_set - Sets the connect point handle in de to the + * given connect_de handle. By default, the connect point of the + * devfs node is the parent. This effectively changes this assumption. + */ +int +hwgraph_connectpt_set(vertex_hdl_t de, vertex_hdl_t connect_de) +{ + int rv; + + if (!de) + return(-1); + + rv = labelcl_info_connectpt_set(de, connect_de); + + return(rv); +} + + +/* + * hwgraph_connectpt_get: Returns the entry's connect point in the devfs + * tree. + */ +vertex_hdl_t +hwgraph_connectpt_get(vertex_hdl_t de) +{ + int rv; + arbitrary_info_t info; + vertex_hdl_t connect; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv != 0) { + return(NULL); + } + + connect = (vertex_hdl_t)info; + return(connect); + +} + + +/* + * hwgraph_mk_dir - Creates a directory entry with devfs. + * Note that a directory entry in devfs can have children + * but it cannot be a char|block special file. + */ +vertex_hdl_t +hwgraph_mk_dir(vertex_hdl_t de, const char *name, + unsigned int namelen, void *info) +{ + + int rv; + labelcl_info_t *labelcl_info = NULL; + vertex_hdl_t new_devfs_handle = NULL; + vertex_hdl_t parent = NULL; + + /* + * Create the device info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(NULL); + + /* + * Create a devfs entry. + */ + new_devfs_handle = devfs_mk_dir(de, name, (void *)labelcl_info); + if (!new_devfs_handle) { + labelcl_info_destroy(labelcl_info); + return(NULL); + } + + /* + * Get the parent handle. + */ + parent = devfs_get_parent (new_devfs_handle); + + /* + * To provide the same semantics as the hwgraph, set the connect point. + */ + rv = hwgraph_connectpt_set(new_devfs_handle, parent); + if (!rv) { + /* + * We need to clean up! + */ + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); + + return(new_devfs_handle); + +} + +/* + * hwgraph_path_add - Create a directory node with the given path starting + * from the given vertex_hdl_t. + */ +int +hwgraph_path_add(vertex_hdl_t fromv, + char *path, + vertex_hdl_t *new_de) +{ + + unsigned int namelen = strlen(path); + int rv; + + /* + * We need to handle the case when fromv is NULL .. + * in this case we need to create the path from the + * hwgraph root! + */ + if (fromv == NULL) + fromv = hwgraph_root; + + /* + * check the entry doesn't already exist, if it does + * then we simply want new_de to point to it (otherwise + * we'll overwrite the existing labelcl_info struct) + */ + rv = hwgraph_edge_get(fromv, path, new_de); + if (rv) { /* couldn't find entry so we create it */ + *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL); + if (new_de == NULL) + return(-1); + else + return(0); + } + else + return(0); + +} + +/* + * hwgraph_register - Creates a file entry with devfs. + * Note that a file entry cannot have children .. it is like a + * char|block special vertex in hwgraph. + */ +vertex_hdl_t +hwgraph_register(vertex_hdl_t de, const char *name, + unsigned int namelen, unsigned int flags, + unsigned int major, unsigned int minor, + umode_t mode, uid_t uid, gid_t gid, + struct file_operations *fops, + void *info) +{ + + vertex_hdl_t new_devfs_handle = NULL; + + /* + * Create a devfs entry. + */ + new_devfs_handle = devfs_register(de, name, flags, major, + minor, mode, fops, info); + if (!new_devfs_handle) { + return(NULL); + } + + return(new_devfs_handle); + +} + + +/* + * hwgraph_mk_symlink - Create a symbolic link. + */ +int +hwgraph_mk_symlink(vertex_hdl_t de, const char *name, unsigned int namelen, + unsigned int flags, const char *link, unsigned int linklen, + vertex_hdl_t *handle, void *info) +{ + + void *labelcl_info = NULL; + int status = 0; + vertex_hdl_t new_devfs_handle = NULL; + + /* + * Create the labelcl info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(-1); + + /* + * Create a symbolic link devfs entry. + */ + status = devfs_mk_symlink(de, name, flags, link, + &new_devfs_handle, labelcl_info); + if ( (!new_devfs_handle) || (!status) ){ + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + return(-1); + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); + + *handle = new_devfs_handle; + return(0); + +} + +/* + * hwgraph_vertex_destroy - Destroy the devfs entry + */ +int +hwgraph_vertex_destroy(vertex_hdl_t de) +{ + + void *labelcl_info = NULL; + + labelcl_info = devfs_get_info(de); + devfs_unregister(de); + + if (labelcl_info) + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + + return(0); +} + +/* + * hwgraph_edge_add - This routines has changed from the original conext. + * All it does now is to create a symbolic link from "from" to "to". + */ +/* ARGSUSED */ +int +hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name) +{ + + char *path; + char *s1; + char *index; + int name_start; + vertex_hdl_t handle = NULL; + int rv; + int i, count; + + path = kmalloc(1024, GFP_KERNEL); + memset(path, 0x0, 1024); + name_start = devfs_generate_path (from, path, 1024); + s1 = &path[name_start]; + count = 0; + while (1) { + index = strstr (s1, "/"); + if (index) { + count++; + s1 = ++index; + } else { + count++; + break; + } + } + + memset(path, 0x0, 1024); + name_start = devfs_generate_path (to, path, 1024); + + for (i = 0; i < count; i++) { + strcat(path,"../"); + } + + strcat(path, &path[name_start]); + + /* + * Otherwise, just create a symlink to the vertex. + * In this case the vertex was previous created with a REAL pathname. + */ + rv = devfs_mk_symlink (from, (const char *)name, + DEVFS_FL_DEFAULT, path, + &handle, NULL); + + name_start = devfs_generate_path (handle, path, 1024); + return(rv); + + +} +/* ARGSUSED */ +int +hwgraph_edge_get(vertex_hdl_t from, char *name, vertex_hdl_t *toptr) +{ + + int namelen = 0; + vertex_hdl_t target_handle = NULL; + + if (name == NULL) + return(-1); + + if (toptr == NULL) + return(-1); + + /* + * If the name is "." just return the current devfs entry handle. + */ + if (!strcmp(name, HWGRAPH_EDGELBL_DOT)) { + if (toptr) { + *toptr = from; + } + } else if (!strcmp(name, HWGRAPH_EDGELBL_DOTDOT)) { + /* + * Hmmm .. should we return the connect point or parent .. + * see in hwgraph, the concept of parent is the connectpt! + * + * Maybe we should see whether the connectpt is set .. if + * not just return the parent! + */ + target_handle = hwgraph_connectpt_get(from); + if (target_handle) { + /* + * Just return the connect point. + */ + *toptr = target_handle; + return(0); + } + target_handle = devfs_get_parent(from); + *toptr = target_handle; + + } else { + /* + * Call devfs to get the devfs entry. + */ + namelen = (int) strlen(name); + target_handle = devfs_find_handle (from, name, 0, 0, + 0, 1); /* Yes traverse symbolic links */ + if (target_handle == NULL) + return(-1); + else + *toptr = target_handle; + } + + return(0); +} + +/* + * hwgraph_info_add_LBL - Adds a new label for the device. Mark the info_desc + * of the label as INFO_DESC_PRIVATE and store the info in the label. + */ +/* ARGSUSED */ +int +hwgraph_info_add_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t info) +{ + return(labelcl_info_add_LBL(de, name, INFO_DESC_PRIVATE, info)); +} + +/* + * hwgraph_info_remove_LBL - Remove the label entry for the device. + */ +/* ARGSUSED */ +int +hwgraph_info_remove_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t *old_info) +{ + return(labelcl_info_remove_LBL(de, name, NULL, old_info)); +} + +/* + * hwgraph_info_replace_LBL - replaces an existing label with + * a new label info value. + */ +/* ARGSUSED */ +int +hwgraph_info_replace_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t info, + arbitrary_info_t *old_info) +{ + return(labelcl_info_replace_LBL(de, name, + INFO_DESC_PRIVATE, info, + NULL, old_info)); +} +/* + * hwgraph_info_get_LBL - Get and return the info value in the label of the + * device. + */ +/* ARGSUSED */ +int +hwgraph_info_get_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t *infop) +{ + return(labelcl_info_get_LBL(de, name, NULL, infop)); +} + +/* + * hwgraph_info_get_exported_LBL - Retrieve the info_desc and info pointer + * of the given label for the device. The weird thing is that the label + * that matches the name is return irrespective of the info_desc value! + * Do not understand why the word "exported" is used! + */ +/* ARGSUSED */ +int +hwgraph_info_get_exported_LBL( vertex_hdl_t de, + char *name, + int *export_info, + arbitrary_info_t *infop) +{ + int rc; + arb_info_desc_t info_desc; + + rc = labelcl_info_get_LBL(de, name, &info_desc, infop); + if (rc == 0) + *export_info = (int)info_desc; + + return(rc); +} + +/* + * hwgraph_info_get_next_LBL - Returns the next label info given the + * current label entry in place. + * + * Once again this has no locking or reference count for protection. + * + */ +/* ARGSUSED */ +int +hwgraph_info_get_next_LBL( vertex_hdl_t de, + char *buf, + arbitrary_info_t *infop, + labelcl_info_place_t *place) +{ + return(labelcl_info_get_next_LBL(de, buf, NULL, infop, place)); +} + +/* + * hwgraph_info_export_LBL - Retrieve the specified label entry and modify + * the info_desc field with the given value in nbytes. + */ +/* ARGSUSED */ +int +hwgraph_info_export_LBL(vertex_hdl_t de, char *name, int nbytes) +{ + arbitrary_info_t info; + int rc; + + if (nbytes == 0) + nbytes = INFO_DESC_EXPORT; + + if (nbytes < 0) + return(-1); + + rc = labelcl_info_get_LBL(de, name, NULL, &info); + if (rc != 0) + return(rc); + + rc = labelcl_info_replace_LBL(de, name, + nbytes, info, NULL, NULL); + + return(rc); +} + +/* + * hwgraph_info_unexport_LBL - Retrieve the given label entry and change the + * label info_descr filed to INFO_DESC_PRIVATE. + */ +/* ARGSUSED */ +int +hwgraph_info_unexport_LBL(vertex_hdl_t de, char *name) +{ + arbitrary_info_t info; + int rc; + + rc = labelcl_info_get_LBL(de, name, NULL, &info); + if (rc != 0) + return(rc); + + rc = labelcl_info_replace_LBL(de, name, + INFO_DESC_PRIVATE, info, NULL, NULL); + + return(rc); +} + +/* + * hwgraph_path_lookup - return the handle for the given path. + * + */ +int +hwgraph_path_lookup( vertex_hdl_t start_vertex_handle, + char *lookup_path, + vertex_hdl_t *vertex_handle_ptr, + char **remainder) +{ + *vertex_handle_ptr = devfs_find_handle(start_vertex_handle, /* start dir */ + lookup_path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1); /* traverse symlinks */ + if (*vertex_handle_ptr == NULL) + return(-1); + else + return(0); +} + +/* + * hwgraph_traverse - Find and return the devfs handle starting from de. + * + */ +graph_error_t +hwgraph_traverse(vertex_hdl_t de, char *path, vertex_hdl_t *found) +{ + /* + * get the directory entry (path should end in a directory) + */ + + *found = devfs_find_handle(de, /* start dir */ + path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1); /* traverse symlinks */ + if (*found == NULL) + return(GRAPH_NOT_FOUND); + else + return(GRAPH_SUCCESS); +} + +/* + * hwgraph_path_to_vertex - Return the devfs entry handle for the given + * pathname .. assume traverse symlinks too!. + */ +vertex_hdl_t +hwgraph_path_to_vertex(char *path) +{ + return(devfs_find_handle(NULL, /* start dir */ + path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1)); /* traverse symlinks */ +} + +/* + * hwgraph_inventory_remove - Removes an inventory entry. + * + * Remove an inventory item associated with a vertex. It is the caller's + * responsibility to make sure that there are no races between removing + * inventory from a vertex and simultaneously removing that vertex. +*/ +int +hwgraph_inventory_remove( vertex_hdl_t de, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ + return(0); /* Just a Stub for IRIX code. */ +} + +/* + * Find the canonical name for a given vertex by walking back through + * connectpt's until we hit the hwgraph root vertex (or until we run + * out of buffer space or until something goes wrong). + * + * COMPATIBILITY FUNCTIONALITY + * Walks back through 'parents', not necessarily the same as connectpts. + * + * Need to resolve the fact that devfs does not return the path from + * "/" but rather it just stops right before /dev .. + */ +int +hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen) +{ + char *locbuf; + int pos; + + if (buflen < 1) + return(-1); /* XXX should be GRAPH_BAD_PARAM ? */ + + locbuf = kmalloc(buflen, GFP_KERNEL); + + pos = devfs_generate_path(vhdl, locbuf, buflen); + if (pos < 0) { + kfree(locbuf); + return pos; + } + + strcpy(buf, &locbuf[pos]); + kfree(locbuf); + return 0; +} + +/* +** vertex_to_name converts a vertex into a canonical name by walking +** back through connect points until we hit the hwgraph root (or until +** we run out of buffer space). +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, vertex_to_name +** returns "UnknownDevice". +*/ + +#define DEVNAME_UNKNOWN "UnknownDevice" + +char * +vertex_to_name(vertex_hdl_t vhdl, char *buf, uint buflen) +{ + if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS) + return(buf); + else + return(DEVNAME_UNKNOWN); +} + +graph_error_t +hwgraph_edge_remove(vertex_hdl_t from, char *name, vertex_hdl_t *toptr) +{ + printk("WARNING: hwgraph_edge_remove NOT supported.\n"); + return(GRAPH_ILLEGAL_REQUEST); +} + +graph_error_t +hwgraph_vertex_unref(vertex_hdl_t vhdl) +{ + return(GRAPH_ILLEGAL_REQUEST); +} + + +EXPORT_SYMBOL(hwgraph_mk_dir); +EXPORT_SYMBOL(hwgraph_path_add); +EXPORT_SYMBOL(hwgraph_register); +EXPORT_SYMBOL(hwgraph_vertex_destroy); +EXPORT_SYMBOL(hwgraph_fastinfo_get); +EXPORT_SYMBOL(hwgraph_fastinfo_set); +EXPORT_SYMBOL(hwgraph_connectpt_set); +EXPORT_SYMBOL(hwgraph_connectpt_get); +EXPORT_SYMBOL(hwgraph_info_add_LBL); +EXPORT_SYMBOL(hwgraph_info_remove_LBL); +EXPORT_SYMBOL(hwgraph_info_replace_LBL); +EXPORT_SYMBOL(hwgraph_info_get_LBL); +EXPORT_SYMBOL(hwgraph_info_get_exported_LBL); +EXPORT_SYMBOL(hwgraph_info_get_next_LBL); +EXPORT_SYMBOL(hwgraph_info_export_LBL); +EXPORT_SYMBOL(hwgraph_info_unexport_LBL); +EXPORT_SYMBOL(hwgraph_path_lookup); +EXPORT_SYMBOL(hwgraph_traverse); +EXPORT_SYMBOL(hwgraph_vertex_name_get); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/hcl_util.c linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/hcl_util.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/hcl_util.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/hcl_util.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,200 @@ +/* $Id: hcl_util.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE; +extern vertex_hdl_t hwgraph_root; + + +/* +** Return the "master" for a given vertex. A master vertex is a +** controller or adapter or other piece of hardware that the given +** vertex passes through on the way to the rest of the system. +*/ +vertex_hdl_t +device_master_get(vertex_hdl_t vhdl) +{ + graph_error_t rc; + vertex_hdl_t master; + + rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master); + if (rc == GRAPH_SUCCESS) + return(master); + else + return(GRAPH_VERTEX_NONE); +} + +/* +** Set the master for a given vertex. +** Returns 0 on success, non-0 indicates failure +*/ +int +device_master_set(vertex_hdl_t vhdl, vertex_hdl_t master) +{ + graph_error_t rc; + + rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER); + return(rc != GRAPH_SUCCESS); +} + + +/* +** Return the compact node id of the node that ultimately "owns" the specified +** vertex. In order to do this, we walk back through masters and connect points +** until we reach a vertex that represents a node. +*/ +cnodeid_t +master_node_get(vertex_hdl_t vhdl) +{ + cnodeid_t cnodeid; + vertex_hdl_t master; + + for (;;) { + cnodeid = nodevertex_to_cnodeid(vhdl); + if (cnodeid != CNODEID_NONE) + return(cnodeid); + + master = device_master_get(vhdl); + + /* Check for exceptional cases */ + if (master == vhdl) { + /* Since we got a reference to the "master" thru + * device_master_get() we should decrement + * its reference count by 1 + */ + return(CNODEID_NONE); + } + + if (master == GRAPH_VERTEX_NONE) { + master = hwgraph_connectpt_get(vhdl); + if ((master == GRAPH_VERTEX_NONE) || + (master == vhdl)) { + return(CNODEID_NONE); + } + } + + vhdl = master; + } +} + +static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE; +extern int maxcpus; + +void +mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid) +{ + if (cpuid == CPU_NONE) + return; + + (void)labelcl_info_add_LBL(vhdl, INFO_LBL_CPUID, INFO_DESC_EXPORT, + (arbitrary_info_t)cpuid); + { + char cpuid_buffer[10]; + + if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_CPUNUM, + &hwgraph_all_cpuids); + } + + sprintf(cpuid_buffer, "%ld", cpuid); + (void)hwgraph_edge_add( hwgraph_all_cpuids, + vhdl, + cpuid_buffer); + } +} + +/* +** If the specified device represents a node, return its +** compact node ID; otherwise, return CNODEID_NONE. +*/ +cnodeid_t +nodevertex_to_cnodeid(vertex_hdl_t vhdl) +{ + int rv = 0; + arbitrary_info_t cnodeid = CNODEID_NONE; + + rv = labelcl_info_get_LBL(vhdl, INFO_LBL_CNODEID, NULL, &cnodeid); + + return((cnodeid_t)cnodeid); +} + +void +mark_nodevertex_as_node(vertex_hdl_t vhdl, cnodeid_t cnodeid) +{ + if (cnodeid == CNODEID_NONE) + return; + + cnodeid_to_vertex(cnodeid) = vhdl; + labelcl_info_add_LBL(vhdl, INFO_LBL_CNODEID, INFO_DESC_EXPORT, + (arbitrary_info_t)cnodeid); + + { + char cnodeid_buffer[10]; + + if (hwgraph_all_cnodes == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_NODENUM, + &hwgraph_all_cnodes); + } + + sprintf(cnodeid_buffer, "%d", cnodeid); + (void)hwgraph_edge_add( hwgraph_all_cnodes, + vhdl, + cnodeid_buffer); + } +} + +/* +** If the specified device represents a CPU, return its cpuid; +** otherwise, return CPU_NONE. +*/ +cpuid_t +cpuvertex_to_cpuid(vertex_hdl_t vhdl) +{ + arbitrary_info_t cpuid = CPU_NONE; + + (void)labelcl_info_get_LBL(vhdl, INFO_LBL_CPUID, NULL, &cpuid); + + return((cpuid_t)cpuid); +} + + +/* +** dev_to_name converts a vertex_hdl_t into a canonical name. If the vertex_hdl_t +** represents a vertex in the hardware graph, it is converted in the +** normal way for vertices. If the vertex_hdl_t is an old vertex_hdl_t (one which +** does not represent a hwgraph vertex), we synthesize a name based +** on major/minor number. +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, dev_to_name +** returns "UnknownDevice". +*/ +char * +dev_to_name(vertex_hdl_t dev, char *buf, uint buflen) +{ + return(vertex_to_name(dev, buf, buflen)); +} + + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/invent_stub.c linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/invent_stub.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/invent_stub.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/invent_stub.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,146 @@ +/* $Id: invent_stub.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +/* + * Hardware Inventory + * + * See sys/sn/invent.h for an explanation of the hardware inventory contents. + * + */ +#include +#include +#include +#include +#include + +void +inventinit(void) +{ +} + +/* + * For initializing/updating an inventory entry. + */ +void +replace_in_inventory( + inventory_t *pinv, int class, int type, + int controller, int unit, int state) +{ +} + +/* + * Inventory addition + * + * XXX NOTE: Currently must be called after dynamic memory allocator is + * initialized. + * + */ +void +add_to_inventory(int class, int type, int controller, int unit, int state) +{ +} + + +/* + * Inventory retrieval + * + * These two routines are intended to prevent the caller from having to know + * the internal structure of the inventory table. + * + * The caller of get_next_inventory is supposed to call start_scan_invent + * before the irst call to get_next_inventory, and the caller is required + * to call end_scan_invent after the last call to get_next_inventory. + */ +inventory_t * +get_next_inventory(invplace_t *place) +{ + return((inventory_t *) NULL); +} + +/* ARGSUSED */ +int +get_sizeof_inventory(int abi) +{ + return sizeof(inventory_t); +} + +/* Must be called prior to first call to get_next_inventory */ +void +start_scan_inventory(invplace_t *iplace) +{ +} + +/* Must be called after last call to get_next_inventory */ +void +end_scan_inventory(invplace_t *iplace) +{ +} + +/* + * Hardware inventory scanner. + * + * Calls fun() for every entry in inventory list unless fun() returns something + * other than 0. + */ +int +scaninvent(int (*fun)(inventory_t *, void *), void *arg) +{ + return 0; +} + +/* + * Find a particular inventory object + * + * pinv can be a pointer to an inventory entry and the search will begin from + * there, or it can be 0 in which case the search starts at the beginning. + * A -1 for any of the other arguments is a wildcard (i.e. it always matches). + */ +inventory_t * +find_inventory(inventory_t *pinv, int class, int type, int controller, + int unit, int state) +{ + return((inventory_t *) NULL); +} + + +/* +** Retrieve inventory data associated with a device. +*/ +inventory_t * +device_inventory_get_next( vertex_hdl_t device, + invplace_t *invplace) +{ + return((inventory_t *) NULL); +} + + +/* +** Associate canonical inventory information with a device (and +** add it to the general inventory). +*/ +void +device_inventory_add( vertex_hdl_t device, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ +} + +int +device_controller_num_get(vertex_hdl_t device) +{ + return (0); +} + +void +device_controller_num_set(vertex_hdl_t device, int contr_num) +{ +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/labelcl.c linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/labelcl.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgdfs/labelcl.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgdfs/labelcl.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,653 @@ +/* labelcl - SGI's Hwgraph Compatibility Layer. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** Very simple and dumb string table that supports only find/insert. +** In practice, if this table gets too large, we may need a more +** efficient data structure. Also note that currently there is no +** way to delete an item once it's added. Therefore, name collision +** will return an error. +*/ + +struct string_table label_string_table; + + + +/* + * string_table_init - Initialize the given string table. + */ +void +string_table_init(struct string_table *string_table) +{ + string_table->string_table_head = NULL; + string_table->string_table_generation = 0; + + /* + * We nedd to initialize locks here! + */ + + return; +} + + +/* + * string_table_destroy - Destroy the given string table. + */ +void +string_table_destroy(struct string_table *string_table) +{ + struct string_table_item *item, *next_item; + + item = string_table->string_table_head; + while (item) { + next_item = item->next; + + STRTBL_FREE(item); + item = next_item; + } + + /* + * We need to destroy whatever lock we have here + */ + + return; +} + + + +/* + * string_table_insert - Insert an entry in the string table .. duplicate + * names are not allowed. + */ +char * +string_table_insert(struct string_table *string_table, char *name) +{ + struct string_table_item *item, *new_item = NULL, *last_item = NULL; + +again: + /* + * Need to lock the table .. + */ + item = string_table->string_table_head; + last_item = NULL; + + while (item) { + if (!strcmp(item->string, name)) { + /* + * If we allocated space for the string and the found that + * someone else already entered it into the string table, + * free the space we just allocated. + */ + if (new_item) + STRTBL_FREE(new_item); + + + /* + * Search optimization: move the found item to the head + * of the list. + */ + if (last_item != NULL) { + last_item->next = item->next; + item->next = string_table->string_table_head; + string_table->string_table_head = item; + } + goto out; + } + last_item = item; + item=item->next; + } + + /* + * name was not found, so add it to the string table. + */ + if (new_item == NULL) { + long old_generation = string_table->string_table_generation; + + new_item = STRTBL_ALLOC(strlen(name)); + + strcpy(new_item->string, name); + + /* + * While we allocated memory for the new string, someone else + * changed the string table. + */ + if (old_generation != string_table->string_table_generation) { + goto again; + } + } else { + /* At this we only have the string table lock in access mode. + * Promote the access lock to an update lock for the string + * table insertion below. + */ + long old_generation = + string_table->string_table_generation; + + /* + * After we did the unlock and wer waiting for update + * lock someone could have potentially updated + * the string table. Check the generation number + * for this case. If it is the case we have to + * try all over again. + */ + if (old_generation != + string_table->string_table_generation) { + goto again; + } + } + + /* + * At this point, we're committed to adding new_item to the string table. + */ + new_item->next = string_table->string_table_head; + item = string_table->string_table_head = new_item; + string_table->string_table_generation++; + +out: + /* + * Need to unlock here. + */ + return(item->string); +} + +/* + * labelcl_info_create - Creates the data structure that will hold the + * device private information asscoiated with a devfs entry. + * The pointer to this structure is what gets stored in the devfs + * (void * info). + */ +labelcl_info_t * +labelcl_info_create() +{ + + labelcl_info_t *new = NULL; + + /* Initial allocation does not include any area for labels */ + if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL ) + return NULL; + + memset (new, 0, sizeof(labelcl_info_t)); + new->hwcl_magic = LABELCL_MAGIC; + return( new); + +} + +/* + * labelcl_info_destroy - Frees the data structure that holds the + * device private information asscoiated with a devfs entry. This + * data structure was created by device_info_create(). + * + * The caller is responsible for nulling the (void *info) in the + * corresponding devfs entry. + */ +int +labelcl_info_destroy(labelcl_info_t *labelcl_info) +{ + + if (labelcl_info == NULL) + return(0); + + /* Free the label list */ + if (labelcl_info->label_list) + kfree(labelcl_info->label_list); + + /* Now free the label info area */ + labelcl_info->hwcl_magic = 0; + kfree(labelcl_info); + + return(0); +} + +/* + * labelcl_info_add_LBL - Adds a new label entry in the labelcl info + * structure. + * + * Error is returned if we find another label with the same name. + */ +int +labelcl_info_add_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + char *name; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if (info_name == NULL) + return(-1); + + if (strlen(info_name) >= LABEL_LENGTH_MAX) + return(-1); + + name = string_table_insert(&label_string_table, info_name); + + num_labels = labelcl_info->num_labels; + new_label_list_size = sizeof(label_info_t) * (num_labels+1); + + /* + * Create a new label info area. + */ + if (new_label_list_size != 0) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to adding the labelled info, + * if there isn't already information there with the same name. + */ + old_label_list = labelcl_info->label_list; + + /* + * Look for matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + if (old_label_list != NULL) + kfree(old_label_list); + + return(0); +} + +/* + * labelcl_info_remove_LBL - Remove a label entry. + */ +int +labelcl_info_remove_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t *info_desc, + arbitrary_info_t *info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + arb_info_desc_t label_desc_found; + arbitrary_info_t label_info_found; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + /* + * Create a new info area. + */ + new_label_list_size = sizeof(label_info_t) * (num_labels-1); + if (new_label_list_size) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to removing the labelled info, + * if it still exists. + */ + old_label_list = labelcl_info->label_list; + + /* + * Find matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + kfree(old_label_list); + + if (info != NULL) + *info = label_info_found; + + if (info_desc != NULL) + *info_desc = label_desc_found; + + return(0); +} + + +/* + * labelcl_info_replace_LBL - Replace an existing label entry with the + * given new information. + * + * Label entry must exist. + */ +int +labelcl_info_replace_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info, + arb_info_desc_t *old_info_desc, + arbitrary_info_t *old_info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + label_info_t *label_list; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + if (info_name == NULL) + return(-1); + + label_list = labelcl_info->label_list; + + /* + * Verify that information under info_name already exists. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + label_list = labelcl_info->label_list; + + /* + * Find information under info_name. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + which_info = *placeptr; + + if (which_info >= labelcl_info->num_labels) { + return(-1); + } + + label_list = (label_info_t *) labelcl_info->label_list; + + if (buffer != NULL) + strcpy(buffer, label_list[which_info].name); + + if (infop) + *infop = label_list[which_info].info; + + if (info_descp) + *info_descp = label_list[which_info].desc; + + *placeptr = which_info + 1; + + return(0); +} + + +int +labelcl_info_replace_IDX(vertex_hdl_t de, + int index, + arbitrary_info_t info, + arbitrary_info_t *old_info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) { + printk(KERN_ALERT "labelcl: NULL devfs handle given.\n"); + return(-1); + } + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) { + printk(KERN_ALERT "labelcl: Entry does not have info pointer.\n"); + return(-1); + } + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Replace information at the appropriate index in this vertex with + * the new info. + */ + info_list_IDX = labelcl_info->IDX_list; + if (old_info != NULL) + *old_info = info_list_IDX[index]; + info_list_IDX[index] = info; + + return(0); + +} + +/* + * labelcl_info_connectpt_set - Sets the connectpt. + */ +int +labelcl_info_connectpt_set(struct devfs_entry *de, + struct devfs_entry *connect_de) +{ + arbitrary_info_t old_info; + int rv; + + rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT, + (arbitrary_info_t) connect_de, &old_info); + + if (rv) { + return(rv); + } + + return(0); +} + + +/* + * labelcl_info_get_IDX - Returns the information pointed at by index. + * + */ +int +labelcl_info_get_IDX(vertex_hdl_t de, + int index, + arbitrary_info_t *info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Return information at the appropriate index in this vertex. + */ + info_list_IDX = labelcl_info->IDX_list; + if (info != NULL) + *info = info_list_IDX[index]; + + return(0); +} + +/* + * labelcl_info_connectpt_get - Retrieve the connect point for a device entry. + */ +struct devfs_entry * +labelcl_info_connectpt_get(struct devfs_entry *de) +{ + int rv; + arbitrary_info_t info; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv) + return(NULL); + + return((struct devfs_entry *)info); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/Makefile linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/Makefile Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/Makefile Wed Jul 23 18:28:59 2003 @@ -0,0 +1,19 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +O_TARGET := snio.o + +export-objs := hcl.o ramfs.o interface.o + +obj-y += hcl.o labelcl.o hcl_util.o invent_stub.o \ + ramfs.o interface.o + +include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hcl.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hcl.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hcl.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hcl.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,938 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * hcl - SGI's Hardware Graph compatibility layer. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* needed for smp_lock.h :( */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER" +#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE" +#define HCL_TEMP_NAME_LEN 44 +#define HCL_VERSION "1.0" + +#define vertex_hdl_t hwgfs_handle_t +vertex_hdl_t hwgraph_root; +vertex_hdl_t linux_busnum; + +extern void pci_bus_cvlink_init(void); + +/* + * Debug flag definition. + */ +#define OPTION_NONE 0x00 +#define HCL_DEBUG_NONE 0x00000 +#define HCL_DEBUG_ALL 0x0ffff +#if defined(CONFIG_HCL_DEBUG) +static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE; +#endif +static unsigned int hcl_debug = HCL_DEBUG_NONE; +#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE) +static unsigned int boot_options = OPTION_NONE; +#endif + +/* + * Some Global definitions. + */ +vertex_hdl_t hcl_handle; + +invplace_t invplace_none = { + GRAPH_VERTEX_NONE, + GRAPH_VERTEX_PLACE_NONE, + NULL +}; + +/* + * HCL device driver. + * The purpose of this device driver is to provide a facility + * for User Level Apps e.g. hinv, ioconfig etc. an ioctl path + * to manipulate label entries without having to implement + * system call interfaces. This methodology will enable us to + * make this feature module loadable. + */ +static int hcl_open(struct inode * inode, struct file * filp) +{ + if (hcl_debug) { + printk("HCL: hcl_open called.\n"); + } + + return(0); + +} + +static int hcl_close(struct inode * inode, struct file * filp) +{ + + if (hcl_debug) { + printk("HCL: hcl_close called.\n"); + } + + return(0); + +} + +static int hcl_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + if (hcl_debug) { + printk("HCL: hcl_ioctl called.\n"); + } + + switch (cmd) { + default: + if (hcl_debug) { + printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd); + } + } + + return(0); + +} + +struct file_operations hcl_fops = { + (struct module *)0, + NULL, /* lseek - default */ + NULL, /* read - general block-dev read */ + NULL, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* poll */ + hcl_ioctl, /* ioctl */ + NULL, /* mmap */ + hcl_open, /* open */ + NULL, /* flush */ + hcl_close, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* lock */ + NULL, /* readv */ + NULL, /* writev */ +}; + + +/* + * init_hcl() - Boot time initialization. + * + */ +int __init init_hcl(void) +{ + extern void string_table_init(struct string_table *); + extern struct string_table label_string_table; + extern int init_ifconfig_net(void); + extern int init_ioconfig_bus(void); + extern int init_hwgfs_fs(void); + int rv = 0; + + if (IS_RUNNING_ON_SIMULATOR()) { + extern u64 klgraph_addr[]; + klgraph_addr[0] = 0xe000003000030000; + } + + init_hwgfs_fs(); + + /* + * Create the hwgraph_root. + */ + rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root); + if (rv) + printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv); + + /* + * Create the hcl driver to support inventory entry manipulations. + * + */ + hcl_handle = hwgraph_register(hwgraph_root, ".hcl", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &hcl_fops, NULL); + + if (hcl_handle == NULL) { + panic("HCL: Unable to create HCL Driver in init_hcl().\n"); + return(0); + } + + /* + * Initialize the HCL string table. + */ + + string_table_init(&label_string_table); + + /* + * Create the directory that links Linux bus numbers to our Xwidget. + */ + rv = hwgraph_path_add(hwgraph_root, EDGE_LBL_LINUX_BUS, &linux_busnum); + if (linux_busnum == NULL) { + panic("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS); + return(0); + } + + pci_bus_cvlink_init(); + + /* + * Initialize the ifconfgi_net driver that does network devices + * Persistent Naming. + */ + init_ifconfig_net(); + init_ioconfig_bus(); + + return(0); + +} + + +/* + * hcl_setup() - Process boot time parameters if given. + * "hcl=" + * This routine gets called only if "hcl=" is given in the + * boot line and before init_hcl(). + * + * We currently do not have any boot options .. when we do, + * functionalities can be added here. + * + */ +static int __init hcl_setup(char *str) +{ + while ( (*str != '\0') && !isspace (*str) ) + { +#ifdef CONFIG_HCL_DEBUG + if (strncmp (str, "all", 3) == 0) { + hcl_debug_init |= HCL_DEBUG_ALL; + str += 3; + } else + return 0; +#endif + if (*str != ',') return 0; + ++str; + } + + return 1; + +} + +__setup("hcl=", hcl_setup); + + +/* + * Set device specific "fast information". + * + */ +void +hwgraph_fastinfo_set(vertex_hdl_t de, arbitrary_info_t fastinfo) +{ + labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL); +} + + +/* + * Get device specific "fast information". + * + */ +arbitrary_info_t +hwgraph_fastinfo_get(vertex_hdl_t de) +{ + arbitrary_info_t fastinfo; + int rv; + + if (!de) { + printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n"); + return(-1); + } + + rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo); + if (rv == 0) + return(fastinfo); + + return(0); +} + + +/* + * hwgraph_connectpt_set - Sets the connect point handle in de to the + * given connect_de handle. By default, the connect point of the + * node is the parent. This effectively changes this assumption. + */ +int +hwgraph_connectpt_set(vertex_hdl_t de, vertex_hdl_t connect_de) +{ + int rv; + + if (!de) + return(-1); + + rv = labelcl_info_connectpt_set(de, connect_de); + + return(rv); +} + + +/* + * hwgraph_connectpt_get: Returns the entry's connect point. + * + */ +vertex_hdl_t +hwgraph_connectpt_get(vertex_hdl_t de) +{ + int rv; + arbitrary_info_t info; + vertex_hdl_t connect; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv != 0) { + return(NULL); + } + + connect = (vertex_hdl_t)info; + return(connect); + +} + + +/* + * hwgraph_mk_dir - Creates a directory entry. + */ +vertex_hdl_t +hwgraph_mk_dir(vertex_hdl_t de, const char *name, + unsigned int namelen, void *info) +{ + + int rv; + labelcl_info_t *labelcl_info = NULL; + vertex_hdl_t new_handle = NULL; + vertex_hdl_t parent = NULL; + + /* + * Create the device info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(NULL); + + /* + * Create an entry. + */ + new_handle = hwgfs_mk_dir(de, name, (void *)labelcl_info); + if (!new_handle) { + labelcl_info_destroy(labelcl_info); + return(NULL); + } + + /* + * Get the parent handle. + */ + parent = hwgfs_get_parent (new_handle); + + /* + * To provide the same semantics as the hwgraph, set the connect point. + */ + rv = hwgraph_connectpt_set(new_handle, parent); + if (!rv) { + /* + * We need to clean up! + */ + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_handle, (arbitrary_info_t)info); + + return(new_handle); + +} + +/* + * hwgraph_path_add - Create a directory node with the given path starting + * from the given fromv. + */ +int +hwgraph_path_add(vertex_hdl_t fromv, + char *path, + vertex_hdl_t *new_de) +{ + + unsigned int namelen = strlen(path); + int rv; + + /* + * We need to handle the case when fromv is NULL .. + * in this case we need to create the path from the + * hwgraph root! + */ + if (fromv == NULL) + fromv = hwgraph_root; + + /* + * check the entry doesn't already exist, if it does + * then we simply want new_de to point to it (otherwise + * we'll overwrite the existing labelcl_info struct) + */ + rv = hwgraph_edge_get(fromv, path, new_de); + if (rv) { /* couldn't find entry so we create it */ + *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL); + if (new_de == NULL) + return(-1); + else + return(0); + } + else + return(0); + +} + +/* + * hwgraph_register - Creates a special device file. + * + */ +vertex_hdl_t +hwgraph_register(vertex_hdl_t de, const char *name, + unsigned int namelen, unsigned int flags, + unsigned int major, unsigned int minor, + umode_t mode, uid_t uid, gid_t gid, + struct file_operations *fops, + void *info) +{ + + vertex_hdl_t new_handle = NULL; + + /* + * Create an entry. + */ + new_handle = hwgfs_register(de, name, flags, major, + minor, mode, fops, info); + + return(new_handle); + +} + + +/* + * hwgraph_mk_symlink - Create a symbolic link. + */ +int +hwgraph_mk_symlink(vertex_hdl_t de, const char *name, unsigned int namelen, + unsigned int flags, const char *link, unsigned int linklen, + vertex_hdl_t *handle, void *info) +{ + + void *labelcl_info = NULL; + int status = 0; + vertex_hdl_t new_handle = NULL; + + /* + * Create the labelcl info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(-1); + + /* + * Create a symbolic link. + */ + status = hwgfs_mk_symlink(de, name, flags, link, + &new_handle, labelcl_info); + if ( (!new_handle) || (!status) ){ + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + return(-1); + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_handle, (arbitrary_info_t)info); + + *handle = new_handle; + return(0); + +} + +/* + * hwgraph_vertex_destroy - Destroy the entry + */ +int +hwgraph_vertex_destroy(vertex_hdl_t de) +{ + + void *labelcl_info = NULL; + + labelcl_info = hwgfs_get_info(de); + hwgfs_unregister(de); + + if (labelcl_info) + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + + return(0); +} + +#if 0 +/* + * hwgraph_edge_add - This routines has changed from the original conext. + * All it does now is to create a symbolic link from "from" to "to". + */ +/* ARGSUSED */ +int +hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name) +{ + + char *path, *link; + vertex_hdl_t handle = NULL; + int rv, i; + + handle = hwgfs_find_handle(from, name, 0, 0, 0, 1); + if (handle) { + return(0); + } + + path = kmalloc(1024, GFP_KERNEL); + memset(path, 0x0, 1024); + link = kmalloc(1024, GFP_KERNEL); + memset(path, 0x0, 1024); + i = hwgfs_generate_path (to, link, 1024); + rv = hwgfs_mk_symlink (from, (const char *)name, + DEVFS_FL_DEFAULT, link, + &handle, NULL); + return(0); + + +} +#endif + +int +hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name) +{ + + char *path, *link; + char *s1; + char *index; + vertex_hdl_t handle = NULL; + int rv; + int i, count; + + path = kmalloc(1024, GFP_KERNEL); + memset((char *)path, 0x0, 1024); + link = kmalloc(1024, GFP_KERNEL); + memset((char *)link, 0x0, 1024); + + i = hwgfs_generate_path (from, path, 1024); + s1 = (char *)path; + count = 0; + while (1) { + index = strstr (s1, "/"); + if (index) { + count++; + s1 = ++index; + } else { + count++; + break; + } + } + + for (i = 0; i < count; i++) { + strcat((char *)link,"../"); + } + + memset(path, 0x0, 1024); + i = hwgfs_generate_path (to, path, 1024); + strcat((char *)link, (char *)path); + + /* + * Otherwise, just create a symlink to the vertex. + * In this case the vertex was previous created with a REAL pathname. + */ + rv = hwgfs_mk_symlink (from, (const char *)name, + DEVFS_FL_DEFAULT, link, + &handle, NULL); + kfree(path); + kfree(link); + + return(rv); + + +} + +/* ARGSUSED */ +int +hwgraph_edge_get(vertex_hdl_t from, char *name, vertex_hdl_t *toptr) +{ + + vertex_hdl_t target_handle = NULL; + + if (name == NULL) + return(-1); + + if (toptr == NULL) + return(-1); + + /* + * If the name is "." just return the current entry handle. + */ + if (!strcmp(name, HWGRAPH_EDGELBL_DOT)) { + if (toptr) { + *toptr = from; + } + } else if (!strcmp(name, HWGRAPH_EDGELBL_DOTDOT)) { + /* + * Hmmm .. should we return the connect point or parent .. + * see in hwgraph, the concept of parent is the connectpt! + * + * Maybe we should see whether the connectpt is set .. if + * not just return the parent! + */ + target_handle = hwgraph_connectpt_get(from); + if (target_handle) { + /* + * Just return the connect point. + */ + *toptr = target_handle; + return(0); + } + target_handle = hwgfs_get_parent(from); + *toptr = target_handle; + + } else { + target_handle = hwgfs_find_handle (from, name, 0, 0, + 0, 1); /* Yes traverse symbolic links */ + } + + if (target_handle == NULL) + return(-1); + else + *toptr = target_handle; + + return(0); +} + +/* + * hwgraph_info_add_LBL - Adds a new label for the device. Mark the info_desc + * of the label as INFO_DESC_PRIVATE and store the info in the label. + */ +/* ARGSUSED */ +int +hwgraph_info_add_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t info) +{ + return(labelcl_info_add_LBL(de, name, INFO_DESC_PRIVATE, info)); +} + +/* + * hwgraph_info_remove_LBL - Remove the label entry for the device. + */ +/* ARGSUSED */ +int +hwgraph_info_remove_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t *old_info) +{ + return(labelcl_info_remove_LBL(de, name, NULL, old_info)); +} + +/* + * hwgraph_info_replace_LBL - replaces an existing label with + * a new label info value. + */ +/* ARGSUSED */ +int +hwgraph_info_replace_LBL( vertex_hdl_t de, + char *name, + arbitrary_info_t info, + arbitrary_info_t *old_info) +{ + return(labelcl_info_replace_LBL(de, name, + INFO_DESC_PRIVATE, info, + NULL, old_info)); +} +/* + * hwgraph_info_get_LBL - Get and return the info value in the label of the + * device. + */ +/* ARGSUSED */ +int +hwgraph_info_get_LBL(vertex_hdl_t de, + char *name, + arbitrary_info_t *infop) +{ + return(labelcl_info_get_LBL(de, name, NULL, infop)); +} + +/* + * hwgraph_info_get_exported_LBL - Retrieve the info_desc and info pointer + * of the given label for the device. The weird thing is that the label + * that matches the name is return irrespective of the info_desc value! + * Do not understand why the word "exported" is used! + */ +/* ARGSUSED */ +int +hwgraph_info_get_exported_LBL(vertex_hdl_t de, + char *name, + int *export_info, + arbitrary_info_t *infop) +{ + int rc; + arb_info_desc_t info_desc; + + rc = labelcl_info_get_LBL(de, name, &info_desc, infop); + if (rc == 0) + *export_info = (int)info_desc; + + return(rc); +} + +/* + * hwgraph_info_get_next_LBL - Returns the next label info given the + * current label entry in place. + * + * Once again this has no locking or reference count for protection. + * + */ +/* ARGSUSED */ +int +hwgraph_info_get_next_LBL(vertex_hdl_t de, + char *buf, + arbitrary_info_t *infop, + labelcl_info_place_t *place) +{ + return(labelcl_info_get_next_LBL(de, buf, NULL, infop, place)); +} + +/* + * hwgraph_info_export_LBL - Retrieve the specified label entry and modify + * the info_desc field with the given value in nbytes. + */ +/* ARGSUSED */ +int +hwgraph_info_export_LBL(vertex_hdl_t de, char *name, int nbytes) +{ + arbitrary_info_t info; + int rc; + + if (nbytes == 0) + nbytes = INFO_DESC_EXPORT; + + if (nbytes < 0) + return(-1); + + rc = labelcl_info_get_LBL(de, name, NULL, &info); + if (rc != 0) + return(rc); + + rc = labelcl_info_replace_LBL(de, name, + nbytes, info, NULL, NULL); + + return(rc); +} + +/* + * hwgraph_info_unexport_LBL - Retrieve the given label entry and change the + * label info_descr filed to INFO_DESC_PRIVATE. + */ +/* ARGSUSED */ +int +hwgraph_info_unexport_LBL(vertex_hdl_t de, char *name) +{ + arbitrary_info_t info; + int rc; + + rc = labelcl_info_get_LBL(de, name, NULL, &info); + if (rc != 0) + return(rc); + + rc = labelcl_info_replace_LBL(de, name, + INFO_DESC_PRIVATE, info, NULL, NULL); + + return(rc); +} + +/* + * hwgraph_path_lookup - return the handle for the given path. + * + */ +int +hwgraph_path_lookup(vertex_hdl_t start_vertex_handle, + char *lookup_path, + vertex_hdl_t *vertex_handle_ptr, + char **remainder) +{ + *vertex_handle_ptr = hwgfs_find_handle(start_vertex_handle, /* start dir */ + lookup_path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1); /* traverse symlinks */ + if (*vertex_handle_ptr == NULL) + return(-1); + else + return(0); +} + +/* + * hwgraph_traverse - Find and return the handle starting from de. + * + */ +graph_error_t +hwgraph_traverse(vertex_hdl_t de, char *path, vertex_hdl_t *found) +{ + /* + * get the directory entry (path should end in a directory) + */ + + *found = hwgfs_find_handle(de, /* start dir */ + path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1); /* traverse symlinks */ + if (*found == NULL) + return(GRAPH_NOT_FOUND); + else + return(GRAPH_SUCCESS); +} + +/* + * hwgraph_path_to_vertex - Return the entry handle for the given + * pathname .. assume traverse symlinks too!. + */ +vertex_hdl_t +hwgraph_path_to_vertex(char *path) +{ + return(hwgfs_find_handle(NULL, /* start dir */ + path, /* path */ + 0, /* major */ + 0, /* minor */ + 0, /* char | block */ + 1)); /* traverse symlinks */ +} + +/* + * hwgraph_inventory_remove - Removes an inventory entry. + * + * Remove an inventory item associated with a vertex. It is the caller's + * responsibility to make sure that there are no races between removing + * inventory from a vertex and simultaneously removing that vertex. +*/ +int +hwgraph_inventory_remove( vertex_hdl_t de, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ + return(0); /* Just a Stub for IRIX code. */ +} + +/* + * Find the canonical name for a given vertex by walking back through + * connectpt's until we hit the hwgraph root vertex (or until we run + * out of buffer space or until something goes wrong). + * + * COMPATIBILITY FUNCTIONALITY + * Walks back through 'parents', not necessarily the same as connectpts. + * + * Need to resolve the fact that does not return the path from + * "/" but rather it just stops right before /dev .. + */ +int +hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen) +{ + char *locbuf; + int pos; + + if (buflen < 1) + return(-1); /* XXX should be GRAPH_BAD_PARAM ? */ + + locbuf = kmalloc(buflen, GFP_KERNEL); + + pos = hwgfs_generate_path(vhdl, locbuf, buflen); + if (pos < 0) { + kfree(locbuf); + return pos; + } + + strcpy(buf, &locbuf[pos]); + kfree(locbuf); + return 0; +} + +/* +** vertex_to_name converts a vertex into a canonical name by walking +** back through connect points until we hit the hwgraph root (or until +** we run out of buffer space). +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, vertex_to_name +** returns "UnknownDevice". +*/ + +#define DEVNAME_UNKNOWN "UnknownDevice" + +char * +vertex_to_name(vertex_hdl_t vhdl, char *buf, uint buflen) +{ + if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS) + return(buf); + else + return(DEVNAME_UNKNOWN); +} + +graph_error_t +hwgraph_edge_remove(vertex_hdl_t from, char *name, vertex_hdl_t *toptr) +{ + return(GRAPH_ILLEGAL_REQUEST); +} + +graph_error_t +hwgraph_vertex_unref(vertex_hdl_t vhdl) +{ + return(GRAPH_ILLEGAL_REQUEST); +} + + +EXPORT_SYMBOL(hwgraph_mk_dir); +EXPORT_SYMBOL(hwgraph_path_add); +EXPORT_SYMBOL(hwgraph_register); +EXPORT_SYMBOL(hwgraph_vertex_destroy); +EXPORT_SYMBOL(hwgraph_fastinfo_get); +EXPORT_SYMBOL(hwgraph_fastinfo_set); +EXPORT_SYMBOL(hwgraph_connectpt_set); +EXPORT_SYMBOL(hwgraph_connectpt_get); +EXPORT_SYMBOL(hwgraph_info_add_LBL); +EXPORT_SYMBOL(hwgraph_info_remove_LBL); +EXPORT_SYMBOL(hwgraph_info_replace_LBL); +EXPORT_SYMBOL(hwgraph_info_get_LBL); +EXPORT_SYMBOL(hwgraph_info_get_exported_LBL); +EXPORT_SYMBOL(hwgraph_info_get_next_LBL); +EXPORT_SYMBOL(hwgraph_info_export_LBL); +EXPORT_SYMBOL(hwgraph_info_unexport_LBL); +EXPORT_SYMBOL(hwgraph_path_lookup); +EXPORT_SYMBOL(hwgraph_traverse); +EXPORT_SYMBOL(hwgraph_vertex_name_get); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hcl_util.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hcl_util.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hcl_util.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hcl_util.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,200 @@ +/* $Id: hcl_util.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE; +extern vertex_hdl_t hwgraph_root; + + +/* +** Return the "master" for a given vertex. A master vertex is a +** controller or adapter or other piece of hardware that the given +** vertex passes through on the way to the rest of the system. +*/ +vertex_hdl_t +device_master_get(vertex_hdl_t vhdl) +{ + graph_error_t rc; + vertex_hdl_t master; + + rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master); + if (rc == GRAPH_SUCCESS) + return(master); + else + return(GRAPH_VERTEX_NONE); +} + +/* +** Set the master for a given vertex. +** Returns 0 on success, non-0 indicates failure +*/ +int +device_master_set(vertex_hdl_t vhdl, vertex_hdl_t master) +{ + graph_error_t rc; + + rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER); + return(rc != GRAPH_SUCCESS); +} + + +/* +** Return the compact node id of the node that ultimately "owns" the specified +** vertex. In order to do this, we walk back through masters and connect points +** until we reach a vertex that represents a node. +*/ +cnodeid_t +master_node_get(vertex_hdl_t vhdl) +{ + cnodeid_t cnodeid; + vertex_hdl_t master; + + for (;;) { + cnodeid = nodevertex_to_cnodeid(vhdl); + if (cnodeid != CNODEID_NONE) + return(cnodeid); + + master = device_master_get(vhdl); + + /* Check for exceptional cases */ + if (master == vhdl) { + /* Since we got a reference to the "master" thru + * device_master_get() we should decrement + * its reference count by 1 + */ + return(CNODEID_NONE); + } + + if (master == GRAPH_VERTEX_NONE) { + master = hwgraph_connectpt_get(vhdl); + if ((master == GRAPH_VERTEX_NONE) || + (master == vhdl)) { + return(CNODEID_NONE); + } + } + + vhdl = master; + } +} + +static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE; +extern int maxcpus; + +void +mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid) +{ + if (cpuid == CPU_NONE) + return; + + (void)labelcl_info_add_LBL(vhdl, INFO_LBL_CPUID, INFO_DESC_EXPORT, + (arbitrary_info_t)cpuid); + { + char cpuid_buffer[10]; + + if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_CPUNUM, + &hwgraph_all_cpuids); + } + + sprintf(cpuid_buffer, "%ld", cpuid); + (void)hwgraph_edge_add( hwgraph_all_cpuids, + vhdl, + cpuid_buffer); + } +} + +/* +** If the specified device represents a node, return its +** compact node ID; otherwise, return CNODEID_NONE. +*/ +cnodeid_t +nodevertex_to_cnodeid(vertex_hdl_t vhdl) +{ + int rv = 0; + arbitrary_info_t cnodeid = CNODEID_NONE; + + rv = labelcl_info_get_LBL(vhdl, INFO_LBL_CNODEID, NULL, &cnodeid); + + return((cnodeid_t)cnodeid); +} + +void +mark_nodevertex_as_node(vertex_hdl_t vhdl, cnodeid_t cnodeid) +{ + if (cnodeid == CNODEID_NONE) + return; + + cnodeid_to_vertex(cnodeid) = vhdl; + labelcl_info_add_LBL(vhdl, INFO_LBL_CNODEID, INFO_DESC_EXPORT, + (arbitrary_info_t)cnodeid); + + { + char cnodeid_buffer[10]; + + if (hwgraph_all_cnodes == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_NODENUM, + &hwgraph_all_cnodes); + } + + sprintf(cnodeid_buffer, "%d", cnodeid); + (void)hwgraph_edge_add( hwgraph_all_cnodes, + vhdl, + cnodeid_buffer); + } +} + +/* +** If the specified device represents a CPU, return its cpuid; +** otherwise, return CPU_NONE. +*/ +cpuid_t +cpuvertex_to_cpuid(vertex_hdl_t vhdl) +{ + arbitrary_info_t cpuid = CPU_NONE; + + (void)labelcl_info_get_LBL(vhdl, INFO_LBL_CPUID, NULL, &cpuid); + + return((cpuid_t)cpuid); +} + + +/* +** dev_to_name converts a vertex_hdl_t into a canonical name. If the vertex_hdl_t +** represents a vertex in the hardware graph, it is converted in the +** normal way for vertices. If the vertex_hdl_t is an old vertex_hdl_t (one which +** does not represent a hwgraph vertex), we synthesize a name based +** on major/minor number. +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, dev_to_name +** returns "UnknownDevice". +*/ +char * +dev_to_name(vertex_hdl_t dev, char *buf, uint buflen) +{ + return(vertex_to_name(dev, buf, buflen)); +} + + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hwgfs.h linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hwgfs.h --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/hwgfs.h Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/hwgfs.h Wed Jul 23 18:28:59 2003 @@ -0,0 +1,23 @@ + +typedef struct dentry *hwgfs_handle_t; + +extern hwgfs_handle_t hwgfs_register(hwgfs_handle_t dir, const char *name, + unsigned int flags, + unsigned int major, unsigned int minor, + umode_t mode, void *ops, void *info); +extern int hwgfs_mk_symlink(hwgfs_handle_t dir, const char *name, + unsigned int flags, const char *link, + hwgfs_handle_t *handle, void *info); +extern hwgfs_handle_t hwgfs_mk_dir(hwgfs_handle_t dir, const char *name, + void *info); +extern void hwgfs_unregister(hwgfs_handle_t de); + +extern hwgfs_handle_t hwgfs_find_handle(hwgfs_handle_t dir, const char *name, + unsigned int major,unsigned int minor, + char type, int traverse_symlinks); +extern hwgfs_handle_t hwgfs_get_parent(hwgfs_handle_t de); +extern int hwgfs_generate_path(hwgfs_handle_t de, char *path, int buflen); + +extern void *hwgfs_get_info(hwgfs_handle_t de); +extern int hwgfs_set_info(hwgfs_handle_t de, void *info); + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/interface.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/interface.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/interface.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/interface.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,326 @@ +/* $Id: interface.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include /* needed for smp_lock.h :( */ +#include + +#include + +#include + +extern struct vfsmount *hwgfs_vfsmount; + +/* TODO: Move this to some .h file or, more likely, use a slightly + different interface from lookup_create. */ +extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); + +static int +walk_parents_mkdir( + const char **path, + struct nameidata *nd, + int is_dir) +{ + char *slash; + char buf[strlen(*path)+1]; + int error; + + while ((slash = strchr(*path, '/')) != NULL) { + int len = slash - *path; + memcpy(buf, *path, len); + buf[len] = '\0'; + + error = link_path_walk(buf, nd); + if (unlikely(error)) + return error; + + nd->dentry = lookup_create(nd, is_dir); + if (unlikely(IS_ERR(nd->dentry))) + return PTR_ERR(nd->dentry); + + if (!nd->dentry->d_inode) + error = vfs_mkdir(nd->dentry->d_parent->d_inode, + nd->dentry, 0755); + + up(&nd->dentry->d_parent->d_inode->i_sem); + if (unlikely(error)) + return error; + + *path += len + 1; + } + + return 0; +} + +/* On success, returns with parent_inode->i_sem taken. */ +static int +hwgfs_decode( + hwgfs_handle_t dir, + const char *name, + int is_dir, + struct inode **parent_inode, + struct dentry **dentry) +{ + struct nameidata nd; + int error; + + if (!dir) + dir = hwgfs_vfsmount->mnt_sb->s_root; + + memset(&nd, 0, sizeof(nd)); + nd.flags = LOOKUP_PARENT; + nd.mnt = mntget(hwgfs_vfsmount); + nd.dentry = dget(dir); + + error = walk_parents_mkdir(&name, &nd, is_dir); + if (unlikely(error)) + return error; + + error = link_path_walk(name, &nd); + if (unlikely(error)) + return error; + + *dentry = lookup_create(&nd, is_dir); + + if (unlikely(IS_ERR(*dentry))) + return PTR_ERR(*dentry); + *parent_inode = (*dentry)->d_parent->d_inode; + return 0; +} + +static int +path_len( + struct dentry *de, + struct dentry *root) +{ + int len = 0; + + while (de != root) { + len += de->d_name.len + 1; /* count the '/' */ + de = de->d_parent; + } + return len; /* -1 because we omit the leading '/', + +1 because we include trailing '\0' */ +} + +int +hwgfs_generate_path( + hwgfs_handle_t de, + char *path, + int buflen) +{ + struct dentry *hwgfs_root; + int len; + char *path_orig = path; + + if (unlikely(de == NULL)) + return -EINVAL; + + hwgfs_root = hwgfs_vfsmount->mnt_sb->s_root; + if (unlikely(de == hwgfs_root)) + return -EINVAL; + + spin_lock(&dcache_lock); + len = path_len(de, hwgfs_root); + if (len > buflen) { + spin_unlock(&dcache_lock); + return -ENAMETOOLONG; + } + + path += len - 1; + *path = '\0'; + + for (;;) { + path -= de->d_name.len; + memcpy(path, de->d_name.name, de->d_name.len); + de = de->d_parent; + if (de == hwgfs_root) + break; + *(--path) = '/'; + } + + spin_unlock(&dcache_lock); + BUG_ON(path != path_orig); + return 0; +} + +hwgfs_handle_t +hwgfs_register( + hwgfs_handle_t dir, + const char *name, + unsigned int flags, + unsigned int major, + unsigned int minor, + umode_t mode, + void *ops, + void *info) +{ + dev_t devnum = MKDEV(major, minor); + struct inode *parent_inode; + struct dentry *dentry; + int error; + + error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry); + if (likely(!error)) { + error = vfs_mknod(parent_inode, dentry, mode, devnum); + if (likely(!error)) { + /* + * Do this inside parents i_sem to avoid racing + * with lookups. + */ + if (S_ISCHR(mode)) + dentry->d_inode->i_fop = ops; + dentry->d_fsdata = info; + up(&parent_inode->i_sem); + } else { + up(&parent_inode->i_sem); + dput(dentry); + dentry = NULL; + } + } + + return dentry; +} + +int +hwgfs_mk_symlink( + hwgfs_handle_t dir, + const char *name, + unsigned int flags, + const char *link, + hwgfs_handle_t *handle, + void *info) +{ + struct inode *parent_inode; + struct dentry *dentry; + int error; + + error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry); + if (likely(!error)) { + error = vfs_symlink(parent_inode, dentry, link); + dentry->d_fsdata = info; + if (handle) + *handle = dentry; + up(&parent_inode->i_sem); + /* dput(dentry); */ + } + return error; +} + +hwgfs_handle_t +hwgfs_mk_dir( + hwgfs_handle_t dir, + const char *name, + void *info) +{ + struct inode *parent_inode; + struct dentry *dentry; + int error; + + error = hwgfs_decode(dir, name, 1, &parent_inode, &dentry); + if (likely(!error)) { + error = vfs_mkdir(parent_inode, dentry, 0755); + up(&parent_inode->i_sem); + + if (unlikely(error)) { + dput(dentry); + dentry = NULL; + } else { + dentry->d_fsdata = info; + } + } + return dentry; +} + +void +hwgfs_unregister( + hwgfs_handle_t de) +{ + struct inode *parent_inode = de->d_parent->d_inode; + + if (S_ISDIR(de->d_inode->i_mode)) + vfs_rmdir(parent_inode, de); + else + vfs_unlink(parent_inode, de); +} + +/* XXX: this function is utterly bogus. Every use of it is racy and the + prototype is stupid. You have been warned. --hch. */ +hwgfs_handle_t +hwgfs_find_handle( + hwgfs_handle_t base, + const char *name, + unsigned int major, /* IGNORED */ + unsigned int minor, /* IGNORED */ + char type, /* IGNORED */ + int traverse_symlinks) +{ + struct dentry *dentry = NULL; + struct nameidata nd; + int error; + + BUG_ON(*name=='/'); + + memset(&nd, 0, sizeof(nd)); + + nd.mnt = mntget(hwgfs_vfsmount); + nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root); + nd.flags = LOOKUP_POSITIVE | (traverse_symlinks ? LOOKUP_FOLLOW : 0); + + error = link_path_walk(name, &nd); + if (likely(!error)) { + dentry = nd.dentry; + path_release(&nd); /* stale data from here! */ + } + + return dentry; +} + +hwgfs_handle_t +hwgfs_get_parent( + hwgfs_handle_t de) +{ + struct dentry *parent; + + lock_kernel(); /* XXX: for LBS this must be dparent_lock */ + parent = de->d_parent; + unlock_kernel(); + + return parent; +} + +int +hwgfs_set_info( + hwgfs_handle_t de, + void *info) +{ + if (unlikely(de == NULL)) + return -EINVAL; + de->d_fsdata = info; + return 0; +} + +void * +hwgfs_get_info( + hwgfs_handle_t de) +{ + return de->d_fsdata; +} + +EXPORT_SYMBOL(hwgfs_generate_path); +EXPORT_SYMBOL(hwgfs_register); +EXPORT_SYMBOL(hwgfs_unregister); +EXPORT_SYMBOL(hwgfs_mk_symlink); +EXPORT_SYMBOL(hwgfs_mk_dir); +EXPORT_SYMBOL(hwgfs_find_handle); +EXPORT_SYMBOL(hwgfs_get_parent); +EXPORT_SYMBOL(hwgfs_set_info); +EXPORT_SYMBOL(hwgfs_get_info); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/invent_stub.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/invent_stub.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/invent_stub.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/invent_stub.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,148 @@ +/* $Id: invent_stub.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +/* + * Hardware Inventory + * + * See sys/sn/invent.h for an explanation of the hardware inventory contents. + * + */ +#include +#include +#include +#include +#include +#include +#include + +void +inventinit(void) +{ +} + +/* + * For initializing/updating an inventory entry. + */ +void +replace_in_inventory( + inventory_t *pinv, int class, int type, + int controller, int unit, int state) +{ +} + +/* + * Inventory addition + * + * XXX NOTE: Currently must be called after dynamic memory allocator is + * initialized. + * + */ +void +add_to_inventory(int class, int type, int controller, int unit, int state) +{ +} + + +/* + * Inventory retrieval + * + * These two routines are intended to prevent the caller from having to know + * the internal structure of the inventory table. + * + * The caller of get_next_inventory is supposed to call start_scan_invent + * before the irst call to get_next_inventory, and the caller is required + * to call end_scan_invent after the last call to get_next_inventory. + */ +inventory_t * +get_next_inventory(invplace_t *place) +{ + return((inventory_t *) NULL); +} + +/* ARGSUSED */ +int +get_sizeof_inventory(int abi) +{ + return sizeof(inventory_t); +} + +/* Must be called prior to first call to get_next_inventory */ +void +start_scan_inventory(invplace_t *iplace) +{ +} + +/* Must be called after last call to get_next_inventory */ +void +end_scan_inventory(invplace_t *iplace) +{ +} + +/* + * Hardware inventory scanner. + * + * Calls fun() for every entry in inventory list unless fun() returns something + * other than 0. + */ +int +scaninvent(int (*fun)(inventory_t *, void *), void *arg) +{ + return 0; +} + +/* + * Find a particular inventory object + * + * pinv can be a pointer to an inventory entry and the search will begin from + * there, or it can be 0 in which case the search starts at the beginning. + * A -1 for any of the other arguments is a wildcard (i.e. it always matches). + */ +inventory_t * +find_inventory(inventory_t *pinv, int class, int type, int controller, + int unit, int state) +{ + return((inventory_t *) NULL); +} + + +/* +** Retrieve inventory data associated with a device. +*/ +inventory_t * +device_inventory_get_next( vertex_hdl_t device, + invplace_t *invplace) +{ + return((inventory_t *) NULL); +} + + +/* +** Associate canonical inventory information with a device (and +** add it to the general inventory). +*/ +void +device_inventory_add( vertex_hdl_t device, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ +} + +int +device_controller_num_get(vertex_hdl_t device) +{ + return (0); +} + +void +device_controller_num_set(vertex_hdl_t device, int contr_num) +{ +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/labelcl.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/labelcl.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/labelcl.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/labelcl.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,657 @@ +/* labelcl - SGI's Hwgraph Compatibility Layer. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved. +*/ + +#include +#include +#include +#include +#include +#include /* needed for smp_lock.h :( */ +#include +#include +#include +#include +#include +#include + +/* +** Very simple and dumb string table that supports only find/insert. +** In practice, if this table gets too large, we may need a more +** efficient data structure. Also note that currently there is no +** way to delete an item once it's added. Therefore, name collision +** will return an error. +*/ + +struct string_table label_string_table; + + + +/* + * string_table_init - Initialize the given string table. + */ +void +string_table_init(struct string_table *string_table) +{ + string_table->string_table_head = NULL; + string_table->string_table_generation = 0; + + /* + * We nedd to initialize locks here! + */ + + return; +} + + +/* + * string_table_destroy - Destroy the given string table. + */ +void +string_table_destroy(struct string_table *string_table) +{ + struct string_table_item *item, *next_item; + + item = string_table->string_table_head; + while (item) { + next_item = item->next; + + STRTBL_FREE(item); + item = next_item; + } + + /* + * We need to destroy whatever lock we have here + */ + + return; +} + + + +/* + * string_table_insert - Insert an entry in the string table .. duplicate + * names are not allowed. + */ +char * +string_table_insert(struct string_table *string_table, char *name) +{ + struct string_table_item *item, *new_item = NULL, *last_item = NULL; + +again: + /* + * Need to lock the table .. + */ + item = string_table->string_table_head; + last_item = NULL; + + while (item) { + if (!strcmp(item->string, name)) { + /* + * If we allocated space for the string and the found that + * someone else already entered it into the string table, + * free the space we just allocated. + */ + if (new_item) + STRTBL_FREE(new_item); + + + /* + * Search optimization: move the found item to the head + * of the list. + */ + if (last_item != NULL) { + last_item->next = item->next; + item->next = string_table->string_table_head; + string_table->string_table_head = item; + } + goto out; + } + last_item = item; + item=item->next; + } + + /* + * name was not found, so add it to the string table. + */ + if (new_item == NULL) { + long old_generation = string_table->string_table_generation; + + new_item = STRTBL_ALLOC(strlen(name)); + + strcpy(new_item->string, name); + + /* + * While we allocated memory for the new string, someone else + * changed the string table. + */ + if (old_generation != string_table->string_table_generation) { + goto again; + } + } else { + /* At this we only have the string table lock in access mode. + * Promote the access lock to an update lock for the string + * table insertion below. + */ + long old_generation = + string_table->string_table_generation; + + /* + * After we did the unlock and wer waiting for update + * lock someone could have potentially updated + * the string table. Check the generation number + * for this case. If it is the case we have to + * try all over again. + */ + if (old_generation != + string_table->string_table_generation) { + goto again; + } + } + + /* + * At this point, we're committed to adding new_item to the string table. + */ + new_item->next = string_table->string_table_head; + item = string_table->string_table_head = new_item; + string_table->string_table_generation++; + +out: + /* + * Need to unlock here. + */ + return(item->string); +} + +/* + * labelcl_info_create - Creates the data structure that will hold the + * device private information asscoiated with a entry. + * The pointer to this structure is what gets stored in the + * (void * info). + */ +labelcl_info_t * +labelcl_info_create() +{ + + labelcl_info_t *new = NULL; + + /* Initial allocation does not include any area for labels */ + if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL ) + return NULL; + + memset (new, 0, sizeof(labelcl_info_t)); + new->hwcl_magic = LABELCL_MAGIC; + return( new); + +} + +/* + * labelcl_info_destroy - Frees the data structure that holds the + * device private information asscoiated with a entry. This + * data structure was created by device_info_create(). + * + * The caller is responsible for nulling the (void *info) in the + * corresponding entry. + */ +int +labelcl_info_destroy(labelcl_info_t *labelcl_info) +{ + + if (labelcl_info == NULL) + return(0); + + /* Free the label list */ + if (labelcl_info->label_list) + kfree(labelcl_info->label_list); + + /* Now free the label info area */ + labelcl_info->hwcl_magic = 0; + kfree(labelcl_info); + + return(0); +} + +/* + * labelcl_info_add_LBL - Adds a new label entry in the labelcl info + * structure. + * + * Error is returned if we find another label with the same name. + */ +int +labelcl_info_add_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + char *name; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = hwgfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if (info_name == NULL) + return(-1); + + if (strlen(info_name) >= LABEL_LENGTH_MAX) + return(-1); + + name = string_table_insert(&label_string_table, info_name); + + num_labels = labelcl_info->num_labels; + new_label_list_size = sizeof(label_info_t) * (num_labels+1); + + /* + * Create a new label info area. + */ + if (new_label_list_size != 0) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to adding the labelled info, + * if there isn't already information there with the same name. + */ + old_label_list = labelcl_info->label_list; + + /* + * Look for matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + if (old_label_list != NULL) + kfree(old_label_list); + + return(0); +} + +/* + * labelcl_info_remove_LBL - Remove a label entry. + */ +int +labelcl_info_remove_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t *info_desc, + arbitrary_info_t *info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + arb_info_desc_t label_desc_found; + arbitrary_info_t label_info_found; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = hwgfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + /* + * Create a new info area. + */ + new_label_list_size = sizeof(label_info_t) * (num_labels-1); + if (new_label_list_size) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to removing the labelled info, + * if it still exists. + */ + old_label_list = labelcl_info->label_list; + + /* + * Find matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + kfree(old_label_list); + + if (info != NULL) + *info = label_info_found; + + if (info_desc != NULL) + *info_desc = label_desc_found; + + return(0); +} + + +/* + * labelcl_info_replace_LBL - Replace an existing label entry with the + * given new information. + * + * Label entry must exist. + */ +int +labelcl_info_replace_LBL(vertex_hdl_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info, + arb_info_desc_t *old_info_desc, + arbitrary_info_t *old_info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + label_info_t *label_list; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = hwgfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + if (info_name == NULL) + return(-1); + + label_list = labelcl_info->label_list; + + /* + * Verify that information under info_name already exists. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + label_list = labelcl_info->label_list; + + /* + * Find information under info_name. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + which_info = *placeptr; + + if (which_info >= labelcl_info->num_labels) { + return(-1); + } + + label_list = (label_info_t *) labelcl_info->label_list; + + if (buffer != NULL) + strcpy(buffer, label_list[which_info].name); + + if (infop) + *infop = label_list[which_info].info; + + if (info_descp) + *info_descp = label_list[which_info].desc; + + *placeptr = which_info + 1; + + return(0); +} + + +int +labelcl_info_replace_IDX(vertex_hdl_t de, + int index, + arbitrary_info_t info, + arbitrary_info_t *old_info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) { + printk(KERN_ALERT "labelcl: NULL handle given.\n"); + return(-1); + } + + labelcl_info = hwgfs_get_info(de); + if (labelcl_info == NULL) { + printk(KERN_ALERT "labelcl: Entry %p does not have info pointer.\n", (void *)de); + return(-1); + } + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Replace information at the appropriate index in this vertex with + * the new info. + */ + info_list_IDX = labelcl_info->IDX_list; + if (old_info != NULL) + *old_info = info_list_IDX[index]; + info_list_IDX[index] = info; + + return(0); + +} + +/* + * labelcl_info_connectpt_set - Sets the connectpt. + */ +int +labelcl_info_connectpt_set(hwgfs_handle_t de, + hwgfs_handle_t connect_de) +{ + arbitrary_info_t old_info; + int rv; + + rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT, + (arbitrary_info_t) connect_de, &old_info); + + if (rv) { + return(rv); + } + + return(0); +} + + +/* + * labelcl_info_get_IDX - Returns the information pointed at by index. + * + */ +int +labelcl_info_get_IDX(vertex_hdl_t de, + int index, + arbitrary_info_t *info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) + return(-1); + + labelcl_info = hwgfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Return information at the appropriate index in this vertex. + */ + info_list_IDX = labelcl_info->IDX_list; + if (info != NULL) + *info = info_list_IDX[index]; + + return(0); +} + +/* + * labelcl_info_connectpt_get - Retrieve the connect point for a device entry. + */ +hwgfs_handle_t +labelcl_info_connectpt_get(hwgfs_handle_t de) +{ + int rv; + arbitrary_info_t info; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv) + return(NULL); + + return((hwgfs_handle_t) info); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/ramfs.c linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/ramfs.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/hwgfs/ramfs.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/hwgfs/ramfs.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,341 @@ +/* $Id: ramfs.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* some random number */ +#define HWGFS_MAGIC 0x12061983 + +static struct super_operations hwgfs_ops; +static struct address_space_operations hwgfs_aops; +static struct file_operations hwgfs_file_operations; +static struct inode_operations hwgfs_dir_inode_operations; + +static int hwgfs_statfs(struct super_block *sb, struct statfs *buf) +{ + buf->f_type = HWGFS_MAGIC; + buf->f_bsize = PAGE_CACHE_SIZE; + buf->f_namelen = 255; + return 0; +} + +/* + * Lookup the data. This is trivial - if the dentry didn't already + * exist, we know it is negative. + */ +static struct dentry * hwgfs_lookup(struct inode *dir, struct dentry *dentry) +{ + d_add(dentry, NULL); + return NULL; +} + +/* + * Read a page. Again trivial. If it didn't already exist + * in the page cache, it is zero-filled. + */ +static int hwgfs_readpage(struct file *file, struct page * page) +{ + if (!Page_Uptodate(page)) { + memset(kmap(page), 0, PAGE_CACHE_SIZE); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + } + UnlockPage(page); + return 0; +} + +static int hwgfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) +{ + void *addr = kmap(page); + if (!Page_Uptodate(page)) { + memset(addr, 0, PAGE_CACHE_SIZE); + flush_dcache_page(page); + SetPageUptodate(page); + } + SetPageDirty(page); + return 0; +} + +static int hwgfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +{ + struct inode *inode = page->mapping->host; + loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + + kunmap(page); + if (pos > inode->i_size) + inode->i_size = pos; + return 0; +} + +struct inode *hwgfs_get_inode(struct super_block *sb, int mode, int dev) +{ + struct inode * inode = new_inode(sb); + + if (inode) { + inode->i_mode = mode; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_blksize = PAGE_CACHE_SIZE; + inode->i_blocks = 0; + inode->i_rdev = NODEV; + inode->i_mapping->a_ops = &hwgfs_aops; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + switch (mode & S_IFMT) { + default: + init_special_inode(inode, mode, dev); + break; + case S_IFREG: + inode->i_fop = &hwgfs_file_operations; + break; + case S_IFDIR: + inode->i_op = &hwgfs_dir_inode_operations; + inode->i_fop = &dcache_dir_ops; + break; + case S_IFLNK: + inode->i_op = &page_symlink_inode_operations; + break; + } + } + return inode; +} + +/* + * File creation. Allocate an inode, and we're done.. + */ +static int hwgfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) +{ + struct inode * inode = hwgfs_get_inode(dir->i_sb, mode, dev); + int error = -ENOSPC; + + if (inode) { + d_instantiate(dentry, inode); + dget(dentry); /* Extra count - pin the dentry in core */ + error = 0; + } + return error; +} + +static int hwgfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) +{ + return hwgfs_mknod(dir, dentry, mode | S_IFDIR, 0); +} + +static int hwgfs_create(struct inode *dir, struct dentry *dentry, int mode) +{ + return hwgfs_mknod(dir, dentry, mode | S_IFREG, 0); +} + +/* + * Link a file.. + */ +static int hwgfs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry) +{ + struct inode *inode = old_dentry->d_inode; + + if (S_ISDIR(inode->i_mode)) + return -EPERM; + + inode->i_nlink++; + atomic_inc(&inode->i_count); /* New dentry reference */ + dget(dentry); /* Extra pinning count for the created dentry */ + d_instantiate(dentry, inode); + return 0; +} + +static inline int hwgfs_positive(struct dentry *dentry) +{ + return dentry->d_inode && !d_unhashed(dentry); +} + +/* + * Check that a directory is empty (this works + * for regular files too, they'll just always be + * considered empty..). + * + * Note that an empty directory can still have + * children, they just all have to be negative.. + */ +static int hwgfs_empty(struct dentry *dentry) +{ + struct list_head *list; + + spin_lock(&dcache_lock); + list = dentry->d_subdirs.next; + + while (list != &dentry->d_subdirs) { + struct dentry *de = list_entry(list, struct dentry, d_child); + + if (hwgfs_positive(de)) { + spin_unlock(&dcache_lock); + return 0; + } + list = list->next; + } + spin_unlock(&dcache_lock); + return 1; +} + +/* + * This works for both directories and regular files. + * (non-directories will always have empty subdirs) + */ +static int hwgfs_unlink(struct inode * dir, struct dentry *dentry) +{ + int retval = -ENOTEMPTY; + + if (hwgfs_empty(dentry)) { + struct inode *inode = dentry->d_inode; + + inode->i_nlink--; + dput(dentry); /* Undo the count from "create" - this does all the work */ + retval = 0; + } + return retval; +} + +#define hwgfs_rmdir hwgfs_unlink + +/* + * The VFS layer already does all the dentry stuff for rename, + * we just have to decrement the usage count for the target if + * it exists so that the VFS layer correctly free's it when it + * gets overwritten. + */ +static int hwgfs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry) +{ + int error = -ENOTEMPTY; + + if (hwgfs_empty(new_dentry)) { + struct inode *inode = new_dentry->d_inode; + if (inode) { + inode->i_nlink--; + dput(new_dentry); + } + error = 0; + } + return error; +} + +static int hwgfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) +{ + int error; + + error = hwgfs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0); + if (!error) { + int l = strlen(symname)+1; + struct inode *inode = dentry->d_inode; + error = block_symlink(inode, symname, l); + } + return error; +} + +static int hwgfs_sync_file(struct file * file, struct dentry *dentry, int datasync) +{ + return 0; +} + +static struct address_space_operations hwgfs_aops = { + .readpage = hwgfs_readpage, + .writepage = fail_writepage, + .prepare_write = hwgfs_prepare_write, + .commit_write = hwgfs_commit_write +}; + +static struct file_operations hwgfs_file_operations = { + .read = generic_file_read, + .write = generic_file_write, + .mmap = generic_file_mmap, + .fsync = hwgfs_sync_file, +}; + +static struct inode_operations hwgfs_dir_inode_operations = { + .create = hwgfs_create, + .lookup = hwgfs_lookup, + .link = hwgfs_link, + .unlink = hwgfs_unlink, + .symlink = hwgfs_symlink, + .mkdir = hwgfs_mkdir, + .rmdir = hwgfs_rmdir, + .mknod = hwgfs_mknod, + .rename = hwgfs_rename, +}; + +static struct super_operations hwgfs_ops = { + .statfs = hwgfs_statfs, + .put_inode = force_delete, +}; + +static struct super_block *hwgfs_read_super(struct super_block * sb, void * data, int silent) +{ + struct inode * inode; + struct dentry * root; + + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = HWGFS_MAGIC; + sb->s_op = &hwgfs_ops; + inode = hwgfs_get_inode(sb, S_IFDIR | 0755, 0); + if (!inode) + return NULL; + + root = d_alloc_root(inode); + if (!root) { + iput(inode); + return NULL; + } + sb->s_root = root; + return sb; +} + +static struct file_system_type hwgfs_fs_type = { + .owner = THIS_MODULE, + .name = "hwgfs", + .read_super = hwgfs_read_super, + .fs_flags = FS_SINGLE|FS_LITTER, +}; + +struct vfsmount *hwgfs_vfsmount; + +int __init init_hwgfs_fs(void) +{ + int error; + + if (!ia64_platform_is("sn2")) + return -ENODEV; + + error = register_filesystem(&hwgfs_fs_type); + if (error) + return error; + + hwgfs_vfsmount = kern_mount(&hwgfs_fs_type); + if (IS_ERR(hwgfs_vfsmount)) + goto fail; + return 0; + +fail: + unregister_filesystem(&hwgfs_fs_type); + return PTR_ERR(hwgfs_vfsmount); +} + +static void __exit exit_hwgfs_fs(void) +{ + unregister_filesystem(&hwgfs_fs_type); +} + +MODULE_LICENSE("GPL"); + +module_init(init_hwgfs_fs) +module_exit(exit_hwgfs_fs) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/io.c linux2.4.21_itanium/arch/ia64/sn/io/io.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/io.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/io.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -29,17 +29,11 @@ #include extern xtalk_provider_t hub_provider; -extern void hub_intr_init(devfs_handle_t hubv); +extern void hub_intr_init(vertex_hdl_t hubv); +static int force_fire_and_forget = 1; +static int ignore_conveyor_override; -/* - * Perform any initializations needed to support hub-based I/O. - * Called once during startup. - */ -void -hubio_init(void) -{ -} /* * Implementation of hub iobus operations. @@ -58,8 +52,8 @@ /* * Setup pio structures needed for a particular hub. */ -void -hub_pio_init(devfs_handle_t hubv) +static void +hub_pio_init(vertex_hdl_t hubv) { xwidgetnum_t widget; hubinfo_t hubinfo; @@ -114,7 +108,7 @@ */ /* ARGSUSED */ hub_piomap_t -hub_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ +hub_piomap_alloc(vertex_hdl_t dev, /* set up mapping for this device */ device_desc_t dev_desc, /* device descriptor */ iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ size_t byte_count, @@ -123,7 +117,7 @@ { xwidget_info_t widget_info = xwidget_info_get(dev); xwidgetnum_t widget = xwidget_info_id_get(widget_info); - devfs_handle_t hubv = xwidget_info_master_get(widget_info); + vertex_hdl_t hubv = xwidget_info_master_get(widget_info); hubinfo_t hubinfo; hub_piomap_t bw_piomap; int bigwin, free_bw_index; @@ -288,7 +282,7 @@ void hub_piomap_free(hub_piomap_t hub_piomap) { - devfs_handle_t hubv; + vertex_hdl_t hubv; hubinfo_t hubinfo; nasid_t nasid; unsigned long s; @@ -371,7 +365,7 @@ */ /* ARGSUSED */ caddr_t -hub_piotrans_addr( devfs_handle_t dev, /* translate to this device */ +hub_piotrans_addr( vertex_hdl_t dev, /* translate to this device */ device_desc_t dev_desc, /* device descriptor */ iopaddr_t xtalk_addr, /* Crosstalk address */ size_t byte_count, /* map this many bytes */ @@ -379,7 +373,7 @@ { xwidget_info_t widget_info = xwidget_info_get(dev); xwidgetnum_t widget = xwidget_info_id_get(widget_info); - devfs_handle_t hubv = xwidget_info_master_get(widget_info); + vertex_hdl_t hubv = xwidget_info_master_get(widget_info); hub_piomap_t hub_piomap; hubinfo_t hubinfo; caddr_t addr; @@ -416,7 +410,7 @@ */ /* ARGSUSED */ hub_dmamap_t -hub_dmamap_alloc( devfs_handle_t dev, /* set up mappings for this device */ +hub_dmamap_alloc( vertex_hdl_t dev, /* set up mappings for this device */ device_desc_t dev_desc, /* device descriptor */ size_t byte_count_max, /* max size of a mapping */ unsigned flags) /* defined in dma.h */ @@ -424,7 +418,7 @@ hub_dmamap_t dmamap; xwidget_info_t widget_info = xwidget_info_get(dev); xwidgetnum_t widget = xwidget_info_id_get(widget_info); - devfs_handle_t hubv = xwidget_info_master_get(widget_info); + vertex_hdl_t hubv = xwidget_info_master_get(widget_info); dmamap = kmalloc(sizeof(struct hub_dmamap_s), GFP_ATOMIC); dmamap->hdma_xtalk_info.xd_dev = dev; @@ -460,7 +454,7 @@ paddr_t paddr, /* map for this address */ size_t byte_count) /* map this many bytes */ { - devfs_handle_t vhdl; + vertex_hdl_t vhdl; ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID); @@ -479,12 +473,7 @@ } /* There isn't actually any DMA mapping hardware on the hub. */ -#ifdef CONFIG_IA64_SGI_SN2 return( (PHYS_TO_DMA(paddr)) ); -#else - /* no translation needed */ - return(paddr); -#endif } /* @@ -498,7 +487,7 @@ alenlist_t palenlist, /* map this area of memory */ unsigned flags) { - devfs_handle_t vhdl; + vertex_hdl_t vhdl; ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID); @@ -527,7 +516,7 @@ void hub_dmamap_done(hub_dmamap_t hub_dmamap) /* done with these mapping resources */ { - devfs_handle_t vhdl; + vertex_hdl_t vhdl; if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) { hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED; @@ -549,18 +538,13 @@ */ /* ARGSUSED */ iopaddr_t -hub_dmatrans_addr( devfs_handle_t dev, /* translate for this device */ +hub_dmatrans_addr( vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ paddr_t paddr, /* system physical address */ size_t byte_count, /* length */ unsigned flags) /* defined in dma.h */ { -#ifdef CONFIG_IA64_SGI_SN2 return( (PHYS_TO_DMA(paddr)) ); -#else - /* no translation needed */ - return(paddr); -#endif } /* @@ -570,7 +554,7 @@ */ /* ARGSUSED */ alenlist_t -hub_dmatrans_list( devfs_handle_t dev, /* translate for this device */ +hub_dmatrans_list( vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ alenlist_t palenlist, /* system address/length list */ unsigned flags) /* defined in dma.h */ @@ -589,7 +573,7 @@ /*ARGSUSED*/ void -hub_dmaaddr_drain( devfs_handle_t vhdl, +hub_dmaaddr_drain( vertex_hdl_t vhdl, paddr_t addr, size_t bytes) { @@ -598,7 +582,7 @@ /*ARGSUSED*/ void -hub_dmalist_drain( devfs_handle_t vhdl, +hub_dmalist_drain( vertex_hdl_t vhdl, alenlist_t list) { /* XXX- flush caches, if cache coherency WAR is needed */ @@ -612,10 +596,8 @@ * Perform initializations that allow this hub to start crosstalk support. */ void -hub_provider_startup(devfs_handle_t hubv) +hub_provider_startup(vertex_hdl_t hubv) { - extern void hub_pio_init(devfs_handle_t hubv); - hub_pio_init(hubv); hub_intr_init(hubv); } @@ -624,14 +606,14 @@ * Shutdown crosstalk support from a hub. */ void -hub_provider_shutdown(devfs_handle_t hub) +hub_provider_shutdown(vertex_hdl_t hub) { /* TBD */ xtalk_provider_unregister(hub); } /* - * Check that an address is in teh real small window widget 0 space + * Check that an address is in the real small window widget 0 space * or else in the big window we're using to emulate small window 0 * in the kernel. */ @@ -666,49 +648,9 @@ /* - * Determine whether two PCI addresses actually refer to the same device. - * This only works if both addresses are in small windows. It's used to - * determine whether prom addresses refer to particular PCI devices. - */ -/* - * XXX - This won't work as written if we ever have more than two nodes - * on a crossbow. In that case, we'll need an array or partners. - */ -int -hub_check_pci_equiv(void *addra, void *addrb) -{ - nasid_t nasida, nasidb; - - /* - * This is for a permanent workaround that causes us to use a - * big window in place of small window 0. - */ - if (!hub_check_window_equiv(addra, addrb)) - return 0; - - /* If the offsets aren't the same, forget it. */ - if (SWIN_WIDGETADDR((__psunsigned_t)addra) != - (SWIN_WIDGETADDR((__psunsigned_t)addrb))) - return 0; - - /* Now, check the nasids */ - nasida = NASID_GET(addra); - nasidb = NASID_GET(addrb); - - ASSERT(NASID_TO_COMPACT_NODEID(nasida) != INVALID_NASID); - ASSERT(NASID_TO_COMPACT_NODEID(nasidb) != INVALID_NASID); - - /* - * Either the NASIDs must be the same or they must be crossbow - * partners (on the same crossbow). - */ - return (check_nasid_equiv(nasida, nasidb)); -} - -/* * hub_setup_prb(nasid, prbnum, credits, conveyor) * - * Put a PRB into fire-and-forget mode if conveyor isn't set. Otehrwise, + * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, * put it into conveyor belt mode with the specified number of credits. */ void @@ -716,8 +658,6 @@ { iprb_t prb; int prb_offset; - extern int force_fire_and_forget; - extern volatile int ignore_conveyor_override; if (force_fire_and_forget && !ignore_conveyor_override) if (conveyor == HUB_PIO_CONVEYOR) @@ -776,13 +716,8 @@ int direct_connect; hubii_wcr_t ii_wcr; int prbnum; - int cons_lock = 0; ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID); - if (nasid == get_console_nasid()) { - PUTBUF_LOCK(s); - cons_lock = 1; - } ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS); REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0); @@ -812,9 +747,6 @@ } REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa); - - if (cons_lock) - PUTBUF_UNLOCK(s); } /* Interface to allow special drivers to set hub specific * device flags. @@ -842,90 +774,6 @@ return 1; } -/* Interface to allow special drivers to set hub specific - * device flags. - * Return 0 on failure , 1 on success - */ -int -hub_device_flags_set(devfs_handle_t widget_vhdl, - hub_widget_flags_t flags) -{ - xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); - xwidgetnum_t widget_num = xwidget_info_id_get(widget_info); - devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); - hubinfo_t hub_info = 0; - nasid_t nasid; - unsigned long s; - int rv; - - /* Use the nasid from the hub info hanging off the hub vertex - * and widget number from the widget vertex - */ - hubinfo_get(hub_vhdl, &hub_info); - /* Being over cautious by grabbing a lock */ - s = mutex_spinlock(&hub_info->h_bwlock); - nasid = hub_info->h_nasid; - rv = hub_widget_flags_set(nasid,widget_num,flags); - mutex_spinunlock(&hub_info->h_bwlock, s); - - return rv; -} - -/* - * hub_device_inquiry - * Find out the xtalk widget related information stored in this - * hub's II. - */ -void -hub_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget) -{ - devfs_handle_t xconn, hub_vhdl; - char widget_name[8]; - hubreg_t ii_iidem,ii_iiwa, ii_iowa; - hubinfo_t hubinfo; - nasid_t nasid; - int d; - - sprintf(widget_name, "%d", widget); - if (hwgraph_traverse(xbus_vhdl, widget_name, &xconn) - != GRAPH_SUCCESS) - return; - - hub_vhdl = device_master_get(xconn); - if (hub_vhdl == GRAPH_VERTEX_NONE) - return; - - hubinfo_get(hub_vhdl, &hubinfo); - if (!hubinfo) - return; - - nasid = hubinfo->h_nasid; - - ii_iidem = REMOTE_HUB_L(nasid, IIO_IIDEM); - ii_iiwa = REMOTE_HUB_L(nasid, IIO_IIWA); - ii_iowa = REMOTE_HUB_L(nasid, IIO_IOWA); - -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk("Inquiry Info for %v\n", xconn); -#else - printk("Inquiry Info for %p\n", (void *)xconn); -#endif - - printk("\tDevices shutdown [ "); - - for (d = 0 ; d <= 7 ; d++) - if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d)))) - printk(" %d", d); - - printk("]\n"); - - printk("\tInbound access ? %s\n", - ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no"); - - printk("\tOutbound access ? %s\n", - ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no"); - -} /* * A pointer to this structure hangs off of every hub hwgraph vertex. @@ -955,8 +803,6 @@ (xtalk_intr_free_f *) hub_intr_free, (xtalk_intr_connect_f *) hub_intr_connect, (xtalk_intr_disconnect_f *) hub_intr_disconnect, - (xtalk_intr_cpu_get_f *) hub_intr_cpu_get, - (xtalk_provider_startup_f *) hub_provider_startup, (xtalk_provider_shutdown_f *) hub_provider_shutdown, }; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/Makefile linux2.4.21_itanium/arch/ia64/sn/io/machvec/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/Makefile Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/machvec/Makefile Wed Jul 23 18:28:59 2003 @@ -0,0 +1,18 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +O_TARGET := snio.o + +export-objs := pci_dma.o iomv.o + +obj-y += pci.o pci_dma.o pci_bus_cvlink.o iomv.o + +include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/iomv.c linux2.4.21_itanium/arch/ia64/sn/io/machvec/iomv.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/iomv.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/machvec/iomv.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,75 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * sn_io_addr - convert an in/out port to an i/o address + * @port: port to convert + * + * Legacy in/out instructions are converted to ld/st instructions + * on IA64. This routine will convert a port number into a valid + * SN i/o address. Used by sn_in*() and sn_out*(). + */ +void * +sn_io_addr(unsigned long port) +{ + if (!IS_RUNNING_ON_SIMULATOR()) { + /* On sn2, legacy I/O ports don't point at anything */ + if (port < 64*1024) + return 0; + return( (void *) (port | __IA64_UNCACHED_OFFSET)); + } else { + /* but the simulator uses them... */ + unsigned long io_base; + unsigned long addr; + + /* + * word align port, but need more than 10 bits + * for accessing registers in bedrock local block + * (so we don't do port&0xfff) + */ + if ((port >= 0x1f0 && port <= 0x1f7) || + port == 0x3f6 || port == 0x3f7) { + io_base = (0xc000000fcc000000 | ((unsigned long)get_nasid() << 38)); + addr = io_base | ((port >> 2) << 12) | (port & 0xfff); + } else { + addr = __ia64_get_io_port_base() | ((port >> 2) << 2); + } + return(void *) addr; + } +} + +EXPORT_SYMBOL(sn_io_addr); + +/** + * sn_mmiob - I/O space memory barrier + * + * Acts as a memory mapped I/O barrier for platforms that queue writes to + * I/O space. This ensures that subsequent writes to I/O space arrive after + * all previous writes. For most ia64 platforms, this is a simple + * 'mf.a' instruction. For other platforms, mmiob() may have to read + * a chipset register to ensure ordering. + * + * On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear. + * See PV 871084 for details about the WAR about zero value. + * + */ +void +sn_mmiob (void) +{ + while ((((volatile unsigned long) (*pda.pio_write_status_addr)) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != + SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) + udelay(1); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci.c linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,291 @@ +/* + * + * SNI64 specific PCI support for SNI IO. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1997, 1998, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_CONFIG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + + +#ifdef CONFIG_PCI + +extern vertex_hdl_t pci_bus_to_vertex(unsigned char); +extern vertex_hdl_t devfn_to_vertex(unsigned char bus, unsigned char devfn); + +/* + * snia64_read_config_byte - Read a byte from the config area of the device. + */ +static int snia64_read_config_byte (struct pci_dev *dev, + int where, unsigned char *val) +{ + unsigned long res = 0; + unsigned size = 1; + vertex_hdl_t device_vertex; + + if ( (dev == (struct pci_dev *)0) || (val == (unsigned char *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned char) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_read_config_word - Read 2 bytes from the config area of the device. + */ +static int snia64_read_config_word (struct pci_dev *dev, + int where, unsigned short *val) +{ + unsigned long res = 0; + unsigned size = 2; /* 2 bytes */ + vertex_hdl_t device_vertex; + + if ( (dev == (struct pci_dev *)0) || (val == (unsigned short *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned short) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_read_config_dword - Read 4 bytes from the config area of the device. + */ +static int snia64_read_config_dword (struct pci_dev *dev, + int where, unsigned int *val) +{ + unsigned long res = 0; + unsigned size = 4; /* 4 bytes */ + vertex_hdl_t device_vertex; + + if (where & 3) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( (dev == (struct pci_dev *)0) || (val == (unsigned int *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned int) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_byte - Writes 1 byte to the config area of the device. + */ +static int snia64_write_config_byte (struct pci_dev *dev, + int where, unsigned char val) +{ + vertex_hdl_t device_vertex; + + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3 ) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 1, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_word - Writes 2 bytes to the config area of the device. + */ +static int snia64_write_config_word (struct pci_dev *dev, + int where, unsigned short val) +{ + vertex_hdl_t device_vertex = NULL; + + if (where & 1) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 2, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_dword - Writes 4 bytes to the config area of the device. + */ +static int snia64_write_config_dword (struct pci_dev *dev, + int where, unsigned int val) +{ + vertex_hdl_t device_vertex; + + if (where & 3) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 4, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops snia64_pci_ops = { + snia64_read_config_byte, + snia64_read_config_word, + snia64_read_config_dword, + snia64_write_config_byte, + snia64_write_config_word, + snia64_write_config_dword +}; + +/* + * snia64_pci_find_bios - SNIA64 pci_find_bios() platform specific code. + */ +void __init +sn_pci_find_bios(void) +{ + extern struct pci_ops *pci_root_ops; + /* + * Go initialize our IO Infrastructure .. + */ + extern void sgi_master_io_infr_init(void); + + sgi_master_io_infr_init(); + + /* sn_io_infrastructure_init(); */ + pci_root_ops = &snia64_pci_ops; +} + +void +pci_fixup_ioc3(struct pci_dev *d) +{ + int i; + unsigned int size; + + /* IOC3 only decodes 0x20 bytes of the config space, reading + * beyond that is relatively benign but writing beyond that + * (especially the base address registers) will shut down the + * pci bus...so avoid doing so. + * NOTE: this means we can't program the intr_pin into the device, + * currently we hack this with special code in + * sgi_pci_intr_support() + */ + DBG("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name); + + /* I happen to know from the spec that the ioc3 needs only 0xfffff + * The standard pci trick of writing ~0 to the baddr and seeing + * what comes back doesn't work with the ioc3 + */ + size = 0xfffff; + d->resource[0].end = (unsigned long) d->resource[0].start + (unsigned long) size; + + /* + * Zero out the resource structure .. because we did not go through + * the normal PCI Infrastructure Init, garbbage are left in these + * fileds. + */ + for (i = 1; i <= PCI_ROM_RESOURCE; i++) { + d->resource[i].start = 0UL; + d->resource[i].end = 0UL; + d->resource[i].flags = 0UL; + } + + d->subsystem_vendor = 0; + d->subsystem_device = 0; + +} + +#else +void sn_pci_find_bios(void) {} +void pci_fixup_ioc3(struct pci_dev *d) {} +struct list_head pci_root_buses; +struct list_head pci_root_buses; +struct list_head pci_devices; + +#endif /* CONFIG_PCI */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci_bus_cvlink.c linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,930 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int bridge_rev_b_data_check_disable; + +vertex_hdl_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET]; +nasid_t busnum_to_nid[MAX_PCI_XWIDGET]; +void * busnum_to_atedmamaps[MAX_PCI_XWIDGET]; +unsigned char num_bridges; +static int done_probing; +extern irqpda_t *irqpdaindr; + +static int pci_bus_map_create(vertex_hdl_t xtalk, char * io_moduleid); +vertex_hdl_t devfn_to_vertex(unsigned char busnum, unsigned int devfn); + +extern void register_pcibr_intr(int irq, pcibr_intr_t intr); + +void sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot); + + +/* + * For the given device, initialize whether it is a PIC device. + */ +static void +set_isPIC(struct sn_device_sysdata *device_sysdata) +{ + pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);; +} + +/* + * pci_bus_cvlink_init() - To be called once during initialization before + * SGI IO Infrastructure init is called. + */ +void +pci_bus_cvlink_init(void) +{ + + extern void ioconfig_bus_init(void); + + memset(busnum_to_pcibr_vhdl, 0x0, sizeof(vertex_hdl_t) * MAX_PCI_XWIDGET); + memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); + + memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET); + + num_bridges = 0; + + ioconfig_bus_init(); +} + +/* + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci bus vertex from the SGI IO Infrastructure. + */ +vertex_hdl_t +pci_bus_to_vertex(unsigned char busnum) +{ + + vertex_hdl_t pci_bus = NULL; + + + /* + * First get the xwidget vertex. + */ + pci_bus = busnum_to_pcibr_vhdl[busnum]; + return(pci_bus); +} + +/* + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * and function numbers. + */ +vertex_hdl_t +devfn_to_vertex(unsigned char busnum, unsigned int devfn) +{ + + int slot = 0; + int func = 0; + char name[16]; + vertex_hdl_t pci_bus = NULL; + vertex_hdl_t device_vertex = (vertex_hdl_t)NULL; + + /* + * Go get the pci bus vertex. + */ + pci_bus = pci_bus_to_vertex(busnum); + if (!pci_bus) { + /* + * During probing, the Linux pci code invents non-existent + * bus numbers and pci_dev structures and tries to access + * them to determine existence. Don't crib during probing. + */ + if (done_probing) + printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum); + return(NULL); + } + + + /* + * Go get the slot&function vertex. + * Should call pciio_slot_func_to_name() when ready. + */ + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* + * For a NON Multi-function card the name of the device looks like: + * ../pci/1, ../pci/2 .. + */ + if (func == 0) { + sprintf(name, "%d", slot); + if (hwgraph_traverse(pci_bus, name, &device_vertex) == + GRAPH_SUCCESS) { + if (device_vertex) { + return(device_vertex); + } + } + } + + /* + * This maybe a multifunction card. It's names look like: + * ../pci/1a, ../pci/1b, etc. + */ + sprintf(name, "%d%c", slot, 'a'+func); + if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) { + if (!device_vertex) { + return(NULL); + } + } + + return(device_vertex); +} + +/* + * For the given device, initialize the addresses for both the Device(x) Flush + * Write Buffer register and the Xbow Flush Register for the port the PCI bus + * is connected. + */ +static void +set_flush_addresses(struct pci_dev *device_dev, + struct sn_device_sysdata *device_sysdata) +{ + pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + nasid_t nasid; + + /* + * Get the nasid from the bridge. + */ + nasid = NASID_GET(device_sysdata->dma_buf_sync); + if (IS_PIC_DEVICE(device_dev)) { + device_sysdata->dma_buf_sync = (volatile unsigned int *) + &bridge->b_wr_req_buf[pciio_slot].reg; + device_sysdata->xbow_buf_sync = (volatile unsigned int *) + XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0), + pcibr_soft->bs_xid); + } else { + /* + * Accessing Xbridge and Xbow register when SHUB swapoper is on!. + */ + device_sysdata->dma_buf_sync = (volatile unsigned int *) + ((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4); + device_sysdata->xbow_buf_sync = (volatile unsigned int *) + ((uint64_t)(XBOW_PRIO_LINKREGS_PTR( + NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4); + } + +#ifdef DEBUG + printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", + device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync); + +printk("set_flush_addresses: dma_buf_sync\n"); + while((volatile unsigned int )*device_sysdata->dma_buf_sync); +printk("set_flush_addresses: xbow_buf_sync\n"); + while((volatile unsigned int )*device_sysdata->xbow_buf_sync); +#endif + +} + +struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS]; + +// Initialize the data structures for flushing write buffers after a PIO read. +// The theory is: +// Take an unused int. pin and associate it with a pin that is in use. +// After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush +// on the in use pin. This will prevent the race condition between PIO read responses and +// DMA writes. +void +sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot) { + nasid_t nasid; + unsigned long dnasid; + int wid_num; + int bus; + struct sn_flush_device_list *p; + bridge_t *b; + bridgereg_t dev_sel; + extern int isIO9(int); + int bwin; + int i; + + nasid = NASID_GET(start); + wid_num = SWIN_WIDGETNUM(start); + bus = (start >> 23) & 0x1; + bwin = BWIN_WINDOWNUM(start); + + if (flush_nasid_list[nasid].widget_p == NULL) { + flush_nasid_list[nasid].widget_p = (struct sn_flush_device_list **)kmalloc((HUB_WIDGET_ID_MAX+1) * + sizeof(struct sn_flush_device_list *), GFP_KERNEL); + memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *)); + } + if (bwin > 0) { + bwin--; + switch (bwin) { + case 0: + flush_nasid_list[nasid].iio_itte1 = HUB_L(IIO_ITTE_GET(nasid, 0)); + wid_num = ((flush_nasid_list[nasid].iio_itte1) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte1 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 1: + flush_nasid_list[nasid].iio_itte2 = HUB_L(IIO_ITTE_GET(nasid, 1)); + wid_num = ((flush_nasid_list[nasid].iio_itte2) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte2 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 2: + flush_nasid_list[nasid].iio_itte3 = HUB_L(IIO_ITTE_GET(nasid, 2)); + wid_num = ((flush_nasid_list[nasid].iio_itte3) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte3 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 3: + flush_nasid_list[nasid].iio_itte4 = HUB_L(IIO_ITTE_GET(nasid, 3)); + wid_num = ((flush_nasid_list[nasid].iio_itte4) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte4 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 4: + flush_nasid_list[nasid].iio_itte5 = HUB_L(IIO_ITTE_GET(nasid, 4)); + wid_num = ((flush_nasid_list[nasid].iio_itte5) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte5 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 5: + flush_nasid_list[nasid].iio_itte6 = HUB_L(IIO_ITTE_GET(nasid, 5)); + wid_num = ((flush_nasid_list[nasid].iio_itte6) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte6 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + case 6: + flush_nasid_list[nasid].iio_itte7 = HUB_L(IIO_ITTE_GET(nasid, 6)); + wid_num = ((flush_nasid_list[nasid].iio_itte7) >> 8) & 0xf; + bus = flush_nasid_list[nasid].iio_itte7 & 0xf; + if (bus == 0x4 || bus == 0x8) + bus = 0; + else + bus = 1; + break; + } + } + + // if it's IO9, bus 1, we don't care about slots 1, 3, and 4. This is + // because these are the IOC4 slots and we don't flush them. + if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) { + return; + } + if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) { + flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc( + DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL); + memset(flush_nasid_list[nasid].widget_p[wid_num], 0, + DEV_PER_WIDGET * sizeof (struct sn_flush_device_list)); + p = &flush_nasid_list[nasid].widget_p[wid_num][0]; + for (i=0; ibus = -1; + p->pin = -1; + p++; + } + } + + p = &flush_nasid_list[nasid].widget_p[wid_num][0]; + for (i=0;ipin == pin && p->bus == bus) break; + if (p->pin < 0) { + p->pin = pin; + p->bus = bus; + break; + } + p++; + } + + for (i=0; ibar_list[i].start == 0) { + p->bar_list[i].start = start; + p->bar_list[i].end = end; + break; + } + } + b = (bridge_t *)(NODE_SWIN_BASE(nasid, wid_num) | (bus << 23) ); + + // If it's IO9, then slot 2 maps to slot 7 and slot 6 maps to slot 8. + // To see this is non-trivial. By drawing pictures and reading manuals and talking + // to HW guys, we can see that on IO9 bus 1, slots 7 and 8 are always unused. + // Further, since we short-circuit slots 1, 3, and 4 above, we only have to worry + // about the case when there is a card in slot 2. A multifunction card will appear + // to be in slot 6 (from an interrupt point of view) also. That's the most we'll + // have to worry about. A four function card will overload the interrupt lines in + // slot 2 and 6. + // We also need to special case the 12160 device in slot 3. Fortunately, we have + // a spare intr. line for pin 4, so we'll use that for the 12160. + // All other buses have slot 3 and 4 and slots 7 and 8 unused. Since we can only + // see slots 1 and 2 and slots 5 and 6 coming through here for those buses (this + // is true only on Pxbricks with 2 physical slots per bus), we just need to add + // 2 to the slot number to find an unused slot. + // We have convinced ourselves that we will never see a case where two different cards + // in two different slots will ever share an interrupt line, so there is no need to + // special case this. + + if (isIO9(nasid) && wid_num == 0xc && bus == 0) { + if (slot == 2) { + p->force_int_addr = (unsigned long)&b->b_force_always[6].intr; + dev_sel = b->b_int_device; + dev_sel |= (1<<18); + b->b_int_device = dev_sel; + dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); + b->p_int_addr_64[6] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | + (dnasid << 36) | (0xfUL << 48); + } else if (slot == 3) { /* 12160 SCSI device in IO9 */ + p->force_int_addr = (unsigned long)&b->b_force_always[4].intr; + dev_sel = b->b_int_device; + dev_sel |= (2<<12); + b->b_int_device = dev_sel; + dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); + b->p_int_addr_64[4] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | + (dnasid << 36) | (0xfUL << 48); + } else { /* slot == 6 */ + p->force_int_addr = (unsigned long)&b->b_force_always[7].intr; + dev_sel = b->b_int_device; + dev_sel |= (5<<21); + b->b_int_device = dev_sel; + dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); + b->p_int_addr_64[7] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | + (dnasid << 36) | (0xfUL << 48); + } + } else { + p->force_int_addr = (unsigned long)&b->b_force_always[pin + 2].intr; + dev_sel = b->b_int_device; + dev_sel |= ((slot - 1) << ( pin * 3) ); + b->b_int_device = dev_sel; + dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); + b->p_int_addr_64[pin + 2] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | + (dnasid << 36) | (0xfUL << 48); + } +} + +/* + * Most drivers currently do not properly tell the arch specific pci dma + * interfaces whether they can handle A64. Here is where we privately + * keep track of this. + */ +static void __init +set_sn_pci64(struct pci_dev *dev) +{ + unsigned short vendor = dev->vendor; + unsigned short device = dev->device; + + if (vendor == PCI_VENDOR_ID_QLOGIC) { + if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) || + (device == PCI_DEVICE_ID_QLOGIC_ISP2200)) { + SET_PCIA64(dev); + return; + } + } + + if (vendor == PCI_VENDOR_ID_SGI) { + if (device == PCI_DEVICE_ID_SGI_IOC3) { + SET_PCIA64(dev); + return; + } + } + +} + +/* + * sn_pci_fixup() - This routine is called when platform_pci_fixup() is + * invoked at the end of pcibios_init() to link the Linux pci + * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c + * + * Other platform specific fixup can also be done here. + */ +void +sn_pci_fixup(int arg) +{ + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *device_dev = NULL; + struct sn_widget_sysdata *widget_sysdata; + struct sn_device_sysdata *device_sysdata; + pciio_intr_t intr_handle; + int cpuid, bit; + vertex_hdl_t device_vertex; + pciio_intr_line_t lines; + extern void sn_pci_find_bios(void); + extern int numnodes; + int cnode; + + if (arg == 0) { +#ifdef CONFIG_PROC_FS + extern void register_sn_procfs(void); +#endif + + sn_pci_find_bios(); + for (cnode = 0; cnode < numnodes; cnode++) { + extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int); + intr_init_vecblk(NODEPDA(cnode), cnode, 0); + } +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif + return; + } + + + done_probing = 1; + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), + GFP_KERNEL); + widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number); + pci_bus->sysdata = (void *)widget_sysdata; + } + + /* + * set the root start and end so that drivers calling check_region() + * won't see a conflict + */ + ioport_resource.start = 0xc000000000000000; + ioport_resource.end = 0xcfffffffffffffff; + + /* + * Set the root start and end for Mem Resource. + */ + iomem_resource.start = 0; + iomem_resource.end = 0xffffffffffffffff; + + /* + * Initialize the device vertex in the pci_dev struct. + */ + pci_for_each_dev(device_dev) { + unsigned int irq; + int idx; + u16 cmd; + vertex_hdl_t vhdl; + unsigned long size; + extern int bit_pos_to_irq(int); + + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3) { + extern void pci_fixup_ioc3(struct pci_dev *d); + pci_fixup_ioc3(device_dev); + } + + /* Set the device vertex */ + + device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), + GFP_KERNEL); + device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); + device_sysdata->isa64 = 0; + /* + * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush + * register addresses. + */ + (void) set_flush_addresses(device_dev, device_sysdata); + + device_dev->sysdata = (void *) device_sysdata; + set_sn_pci64(device_dev); + set_isPIC(device_sysdata); + + pci_read_config_word(device_dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure .. + */ + vhdl = device_sysdata->vhdl; + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + size = 0; + size = device_dev->resource[idx].end - + device_dev->resource[idx].start; + if (size) { + device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); + device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET; + } + else + continue; + + device_dev->resource[idx].end = + device_dev->resource[idx].start + size; + + if (device_dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + + if (device_dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } +#if 0 + /* + * Software WAR for a Software BUG. + * This is only temporary. + * See PV 872791 + */ + + /* + * Now handle the ROM resource .. + */ + size = device_dev->resource[PCI_ROM_RESOURCE].end - + device_dev->resource[PCI_ROM_RESOURCE].start; + + if (size) { + device_dev->resource[PCI_ROM_RESOURCE].start = + (unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, + size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); + device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET; + device_dev->resource[PCI_ROM_RESOURCE].end = + device_dev->resource[PCI_ROM_RESOURCE].start + size; + } +#endif + + /* + * Update the Command Word on the Card. + */ + cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ + /* bit gets dropped .. no harm */ + pci_write_config_word(device_dev, PCI_COMMAND, cmd); + + pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) { + lines = 1; + } + + device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; + device_vertex = device_sysdata->vhdl; + + irqpdaindr->current = device_dev; + intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex); + + irq = intr_handle->pi_irq; + irqpdaindr->device_dev[irq] = device_dev; + cpuid = intr_handle->pi_cpu; + pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0); + device_dev->irq = irq; + register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); + + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + int ibits = ((pcibr_intr_t)intr_handle)->bi_ibits; + int i; + + size = device_dev->resource[idx].end - + device_dev->resource[idx].start; + if (size == 0) continue; + + for (i=0; i<8; i++) { + if (ibits & (1 << i) ) { + sn_dma_flush_init(device_dev->resource[idx].start, + device_dev->resource[idx].end, + idx, + i, + PCI_SLOT(device_dev->devfn)); + } + } + } + + } +#ifdef ajmtestintr + { + int slot = PCI_SLOT(device_dev->devfn); + static int timer_set = 0; + pcibr_intr_t pcibr_intr = (pcibr_intr_t)intr_handle; + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + extern void intr_test_handle_intr(int, void*, struct pt_regs *); + + if (!timer_set) { + intr_test_set_timer(); + timer_set = 1; + } + intr_test_register_irq(irq, pcibr_soft, slot); + request_irq(irq, intr_test_handle_intr,0,NULL, NULL); + } +#endif +} + +/* + * linux_bus_cvlink() Creates a link between the Linux PCI Bus number + * to the actual hardware component that it represents: + * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * + * The bus vertex, when called to devfs_generate_path() returns: + * hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/0 + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/1 + */ +void +linux_bus_cvlink(void) +{ + char name[8]; + int index; + + for (index=0; index < MAX_PCI_XWIDGET; index++) { + if (!busnum_to_pcibr_vhdl[index]) + continue; + + sprintf(name, "%x", index); + (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], + name); + } +} + +/* + * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job. + * + * Linux PCI Bus numbers are assigned from lowest module_id numbers + * (rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to + * HUB_WIDGET_ID_MIN: + * widgetnum 15 gets lower Bus Number than widgetnum 14 etc. + * + * Given 2 modules 001c01 and 001c02 we get the following mappings: + * 001c01, widgetnum 15 = Bus number 0 + * 001c01, widgetnum 14 = Bus number 1 + * 001c02, widgetnum 15 = Bus number 3 + * 001c02, widgetnum 14 = Bus number 4 + * etc. + * + * The rational for starting Bus Number 0 with Widget number 15 is because + * the system boot disks are always connected via Widget 15 Slot 0 of the + * I-brick. Linux creates /dev/sd* devices(naming) strating from Bus Number 0 + * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest + * module id(Master Cnode) of the system. + * + */ +static int +pci_bus_map_create(vertex_hdl_t xtalk, char * io_moduleid) +{ + + vertex_hdl_t master_node_vertex = NULL; + vertex_hdl_t xwidget = NULL; + vertex_hdl_t pci_bus = NULL; + hubinfo_t hubinfo = NULL; + xwidgetnum_t widgetnum; + char pathname[128]; + graph_error_t rv; + int bus; + int basebus_num; + extern void ioconfig_get_busnum(char *, int *); + + int bus_number; + + /* + * Loop throught this vertex and get the Xwidgets .. + */ + + + /* PCI devices */ + + for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; +} + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + num_bridges++; + busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus; + + /* + * Get the master node and from there get the NASID. + */ + master_node_vertex = device_master_get(xwidget); + if (!master_node_vertex) { + printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget); + } + + hubinfo_get(master_node_vertex, &hubinfo); + if (!hubinfo) { + printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex); + return(1); + } else { + busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; + } + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[num_bridges - 1]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + + } + + /* + * PCIX devices + * We number busses differently for PCI-X devices. + * We start from Lowest Widget on up .. + */ + + (void) ioconfig_get_busnum((char *)io_moduleid, &basebus_num); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + + /* Do both buses */ + for ( bus = 0; bus < 2; bus++ ) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + if ( bus == 0 ) + sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); + else + sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; + } + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum); +#ifdef DEBUG + printk("bus_number %d basebus_num %d bus %d io %d\n", + bus_number, basebus_num, bus, + io_brick_map_widget(MODULE_PXBRICK, widgetnum)); +#endif + busnum_to_pcibr_vhdl[bus_number] = pci_bus; + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[bus_number] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[bus_number]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[bus_number], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + } + } + + return(0); +} + +/* + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * initialization has completed to set up the mappings between Xbridge + * and logical pci bus numbers. We also set up the NASID for each of these + * xbridges. + * + * Must be called before pci_init() is invoked. + */ +int +pci_bus_to_hcl_cvlink(void) +{ + + vertex_hdl_t devfs_hdl = NULL; + vertex_hdl_t xtalk = NULL; + int rv = 0; + char name[256]; + char tmp_name[256]; + int i, ii, j; + char *brick_name; + extern void ioconfig_bus_new_entries(void); + + /* + * Figure out which IO Brick is connected to the Compute Bricks. + */ + for (i = 0; i < nummodules; i++) { + extern int iomoduleid_get(nasid_t); + moduleid_t iobrick_id; + nasid_t nasid = -1; + int nodecnt; + int n = 0; + + nodecnt = modules[i]->nodecnt; + for ( n = 0; n < nodecnt; n++ ) { + nasid = cnodeid_to_nasid(modules[i]->nodes[n]); + iobrick_id = iomoduleid_get(nasid); + if ((int)iobrick_id > 0) { /* Valid module id */ + char name[12]; + memset(name, 0, 12); + format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF); + } + } + } + + devfs_hdl = hwgraph_path_to_vertex("hw/module"); + for (i = 0; i < nummodules ; i++) { + for ( j = 0; j < 3; j++ ) { + if ( j == 0 ) + brick_name = EDGE_LBL_PBRICK; + else if ( j == 1 ) + brick_name = EDGE_LBL_PXBRICK; + else + brick_name = EDGE_LBL_IXBRICK; + + for ( ii = 0; ii < 2 ; ii++ ) { + memset(name, 0, 256); + memset(tmp_name, 0, 256); + format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF); + sprintf(tmp_name, "/slab/%d/%s/xtalk", geo_slab(modules[i]->geoid[ii]), brick_name); + strcat(name, tmp_name); + xtalk = NULL; + rv = hwgraph_edge_get(devfs_hdl, name, &xtalk); + if ( rv == 0 ) + pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid)); + } + } + } + + /* + * Create the Linux PCI bus number vertex link. + */ + (void)linux_bus_cvlink(); + (void)ioconfig_bus_new_entries(); + + return(0); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci_dma.c linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci_dma.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/machvec/pci_dma.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/machvec/pci_dma.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,584 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000,2002-2003 Silicon Graphics, Inc. All rights reserved. + * + * Routines for PCI DMA mapping. See Documentation/DMA-mapping.txt for + * a description of how these routines should be used. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * For ATE allocations + */ +pciio_dmamap_t get_free_pciio_dmamap(vertex_hdl_t); +void free_pciio_dmamap(pcibr_dmamap_t); +static struct sn_dma_maps_s *find_sn_dma_map(dma_addr_t, unsigned char); +void sn_pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction); + +/* + * Toplogy stuff + */ +extern vertex_hdl_t busnum_to_pcibr_vhdl[]; +extern nasid_t busnum_to_nid[]; +extern void * busnum_to_atedmamaps[]; + +/** + * get_free_pciio_dmamap - find and allocate an ATE + * @pci_bus: PCI bus to get an entry for + * + * Finds and allocates an ATE on the PCI bus specified + * by @pci_bus. + */ +pciio_dmamap_t +get_free_pciio_dmamap(vertex_hdl_t pci_bus) +{ + int i; + struct sn_dma_maps_s *sn_dma_map = NULL; + + /* + * Darn, we need to get the maps allocated for this bus. + */ + for (i = 0; i < MAX_PCI_XWIDGET; i++) { + if (busnum_to_pcibr_vhdl[i] == pci_bus) { + sn_dma_map = busnum_to_atedmamaps[i]; + } + } + + /* + * Now get a free dmamap entry from this list. + */ + for (i = 0; i < MAX_ATE_MAPS; i++, sn_dma_map++) { + if (!sn_dma_map->dma_addr) { + sn_dma_map->dma_addr = -1; + return( (pciio_dmamap_t) sn_dma_map ); + } + } + + return NULL; +} + +/** + * free_pciio_dmamap - free an ATE + * @dma_map: ATE to free + * + * Frees the ATE specified by @dma_map. + */ +void +free_pciio_dmamap(pcibr_dmamap_t dma_map) +{ + struct sn_dma_maps_s *sn_dma_map; + + sn_dma_map = (struct sn_dma_maps_s *) dma_map; + sn_dma_map->dma_addr = 0; +} + +/** + * find_sn_dma_map - find an ATE associated with @dma_addr and @busnum + * @dma_addr: DMA address to look for + * @busnum: PCI bus to look on + * + * Finds the ATE associated with @dma_addr and @busnum. + */ +static struct sn_dma_maps_s * +find_sn_dma_map(dma_addr_t dma_addr, unsigned char busnum) +{ + + struct sn_dma_maps_s *sn_dma_map = NULL; + int i; + + sn_dma_map = busnum_to_atedmamaps[busnum]; + + for (i = 0; i < MAX_ATE_MAPS; i++, sn_dma_map++) { + if (sn_dma_map->dma_addr == dma_addr) { + return sn_dma_map; + } + } + + return NULL; +} + +/** + * sn_pci_alloc_consistent - allocate memory for coherent DMA + * @hwdev: device to allocate for + * @size: size of the region + * @dma_handle: DMA (bus) address + * + * pci_alloc_consistent() returns a pointer to a memory region suitable for + * coherent DMA traffic to/from a PCI device. On SN platforms, this means + * that @dma_handle will have the %PCIIO_DMA_CMD flag set. + * + * This interface is usually used for "command" streams (e.g. the command + * queue for a SCSI controller). See Documentation/DMA-mapping.txt for + * more information. Note that this routine will always put a 32 bit + * DMA address into @dma_handle. This is because most devices + * that are capable of 64 bit PCI DMA transactions can't do 64 bit _coherent_ + * DMAs, and unfortunately this interface has to cater to the LCD. Oh well. + * + * Also known as platform_pci_alloc_consistent() by the IA64 machvec code. + */ +void * +sn_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +{ + void *cpuaddr; + vertex_hdl_t vhdl; + struct sn_device_sysdata *device_sysdata; + unsigned long phys_addr; + pciio_dmamap_t dma_map = 0; + struct sn_dma_maps_s *sn_dma_map; + + *dma_handle = 0; + + if (hwdev->dma_mask < 0xffffffffUL) + return NULL; + + /* + * Get hwgraph vertex for the device + */ + device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + vhdl = device_sysdata->vhdl; + + /* + * Allocate the memory. FIXME: if we're allocating for + * two devices on the same bus, we should at least try to + * allocate memory in the same 2 GB window to avoid using + * ATEs for the translation. See the comment above about the + * 32 bit requirement for this function. + */ + if(!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) + return NULL; + + /* physical addr. of the memory we just got */ + phys_addr = __pa(cpuaddr); + + /* + * This will try to use a Direct Map register to do the + * 32 bit DMA mapping, but it may not succeed if another + * device on the same bus is already mapped with different + * attributes or to a different memory region. + */ + *dma_handle = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_CMD); + + /* + * If this device is in PCI-X mode, the system would have + * automatically allocated a 64Bits DMA Address. Error out if the + * device cannot support DAC. + */ + if (*dma_handle > hwdev->consistent_dma_mask) { + free_pages((unsigned long) cpuaddr, get_order(size)); + return NULL; + } + + /* + * It is a 32 bit card and we cannot do direct mapping, + * so we try to use an ATE. + */ + if (!(*dma_handle)) { + dma_map = pciio_dmamap_alloc(vhdl, NULL, size, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_CMD); + if (!dma_map) { + printk(KERN_ERR "sn_pci_alloc_consistent: Unable to " + "allocate anymore 32 bit page map entries.\n"); + return 0; + } + *dma_handle = (dma_addr_t) pciio_dmamap_addr(dma_map,phys_addr, + size); + sn_dma_map = (struct sn_dma_maps_s *)dma_map; + sn_dma_map->dma_addr = *dma_handle; + } + + return cpuaddr; +} + +/** + * sn_pci_free_consistent - free memory associated with coherent DMAable region + * @hwdev: device to free for + * @size: size to free + * @vaddr: kernel virtual address to free + * @dma_handle: DMA address associated with this region + * + * Frees the memory allocated by pci_alloc_consistent(). Also known + * as platform_pci_free_consistent() by the IA64 machvec code. + */ +void +sn_pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +{ + struct sn_dma_maps_s *sn_dma_map = NULL; + + /* + * Get the sn_dma_map entry. + */ + if (IS_PCI32_MAPPED(dma_handle)) + sn_dma_map = find_sn_dma_map(dma_handle, hwdev->bus->number); + + /* + * and free it if necessary... + */ + if (sn_dma_map) { + pciio_dmamap_done((pciio_dmamap_t)sn_dma_map); + pciio_dmamap_free((pciio_dmamap_t)sn_dma_map); + sn_dma_map->dma_addr = (dma_addr_t)NULL; + } + free_pages((unsigned long) vaddr, get_order(size)); +} + +/** + * sn_pci_map_sg - map a scatter-gather list for DMA + * @hwdev: device to map for + * @sg: scatterlist to map + * @nents: number of entries + * @direction: direction of the DMA transaction + * + * Maps each entry of @sg for DMA. Also known as platform_pci_map_sg by the + * IA64 machvec code. + */ +int +sn_pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) +{ + + int i; + vertex_hdl_t vhdl; + unsigned long phys_addr; + struct sn_device_sysdata *device_sysdata; + pciio_dmamap_t dma_map; + struct sn_dma_maps_s *sn_dma_map; + struct scatterlist *saved_sg = sg; + + /* can't go anywhere w/o a direction in life */ + if (direction == PCI_DMA_NONE) + BUG(); + + /* + * Get the hwgraph vertex for the device + */ + device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + vhdl = device_sysdata->vhdl; + + /* + * Setup a DMA address for each entry in the + * scatterlist. + */ + for (i = 0; i < nents; i++, sg++) { + phys_addr = __pa(sg->address ? sg->address : + page_address(sg->page) + sg->offset); + + /* + * Handle the most common case: 64 bit cards. This + * call should always succeed. + */ + if (IS_PCIA64(hwdev)) { + sg->dma_address = pciio_dmatrans_addr(vhdl, NULL, phys_addr, + sg->length, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA | + PCIIO_DMA_A64); + sg->dma_length = sg->length; + continue; + } + + /* + * Handle 32-63 bit cards via direct mapping + */ + if (IS_PCI32G(hwdev)) { + sg->dma_address = pciio_dmatrans_addr(vhdl, NULL, phys_addr, + sg->length, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA); + sg->dma_length = sg->length; + /* + * See if we got a direct map entry + */ + if (sg->dma_address) { + continue; + } + + } + + /* + * It is a 32 bit card and we cannot do direct mapping, + * so we use an ATE. + */ + dma_map = pciio_dmamap_alloc(vhdl, NULL, sg->length, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA); + if (!dma_map) { + printk(KERN_ERR "sn_pci_map_sg: Unable to allocate " + "anymore 32 bit page map entries.\n"); + /* + * We will need to free all previously allocated entries. + */ + if (i > 0) { + sn_pci_unmap_sg(hwdev, saved_sg, i, direction); + } + return (0); + } + + sg->dma_address = pciio_dmamap_addr(dma_map, phys_addr, sg->length); + sg->dma_length = sg->length; + sn_dma_map = (struct sn_dma_maps_s *)dma_map; + sn_dma_map->dma_addr = sg->dma_address; + } + + return nents; + +} + +/** + * sn_pci_unmap_sg - unmap a scatter-gather list + * @hwdev: device to unmap + * @sg: scatterlist to unmap + * @nents: number of scatterlist entries + * @direction: DMA direction + * + * Unmap a set of streaming mode DMA translations. Again, cpu read rules + * concerning calls here are the same as for pci_unmap_single() below. Also + * known as sn_pci_unmap_sg() by the IA64 machvec code. + */ +void +sn_pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) +{ + int i; + struct sn_dma_maps_s *sn_dma_map; + + /* can't go anywhere w/o a direction in life */ + if (direction == PCI_DMA_NONE) + BUG(); + + for (i = 0; i < nents; i++, sg++){ + + if (IS_PCI32_MAPPED(sg->dma_address)) { + sn_dma_map = NULL; + sn_dma_map = find_sn_dma_map(sg->dma_address, hwdev->bus->number); + if (sn_dma_map) { + pciio_dmamap_done((pciio_dmamap_t)sn_dma_map); + pciio_dmamap_free((pciio_dmamap_t)sn_dma_map); + sn_dma_map->dma_addr = (dma_addr_t)NULL; + } + } + + sg->dma_address = (dma_addr_t)NULL; + sg->dma_length = 0; + } +} + +/** + * sn_pci_map_single - map a single region for DMA + * @hwdev: device to map for + * @ptr: kernel virtual address of the region to map + * @size: size of the region + * @direction: DMA direction + * + * Map the region pointed to by @ptr for DMA and return the + * DMA address. Also known as platform_pci_map_single() by + * the IA64 machvec code. + * + * We map this to the one step pciio_dmamap_trans interface rather than + * the two step pciio_dmamap_alloc/pciio_dmamap_addr because we have + * no way of saving the dmamap handle from the alloc to later free + * (which is pretty much unacceptable). + * + * TODO: simplify our interface; + * get rid of dev_desc and vhdl (seems redundant given a pci_dev); + * figure out how to save dmamap handle so can use two step. + */ +dma_addr_t +sn_pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction) +{ + vertex_hdl_t vhdl; + dma_addr_t dma_addr; + unsigned long phys_addr; + struct sn_device_sysdata *device_sysdata; + pciio_dmamap_t dma_map = NULL; + struct sn_dma_maps_s *sn_dma_map; + + if (direction == PCI_DMA_NONE) + BUG(); + + /* SN cannot support DMA addresses smaller than 32 bits. */ + if (IS_PCI32L(hwdev)) + return 0; + + /* + * find vertex for the device + */ + device_sysdata = (struct sn_device_sysdata *)hwdev->sysdata; + vhdl = device_sysdata->vhdl; + + /* + * Call our dmamap interface + */ + dma_addr = 0; + phys_addr = __pa(ptr); + + if (IS_PCIA64(hwdev)) { + /* This device supports 64 bit DMA addresses. */ + dma_addr = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA | + PCIIO_DMA_A64); + return dma_addr; + } + + /* + * Devices that support 32 bit to 63 bit DMA addresses get + * 32 bit DMA addresses. + * + * First try to get a 32 bit direct map register. + */ + if (IS_PCI32G(hwdev)) { + dma_addr = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA); + if (dma_addr) + return dma_addr; + } + + /* + * It's a 32 bit card and we cannot do direct mapping so + * let's use the PMU instead. + */ + dma_map = NULL; + dma_map = pciio_dmamap_alloc(vhdl, NULL, size, + ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | + PCIIO_DMA_DATA); + + if (!dma_map) { + printk(KERN_ERR "pci_map_single: Unable to allocate anymore " + "32 bit page map entries.\n"); + return 0; + } + + dma_addr = (dma_addr_t) pciio_dmamap_addr(dma_map, phys_addr, size); + sn_dma_map = (struct sn_dma_maps_s *)dma_map; + sn_dma_map->dma_addr = dma_addr; + + return ((dma_addr_t)dma_addr); +} + +/** + * sn_pci_unmap_single - unmap a region used for DMA + * @hwdev: device to unmap + * @dma_addr: DMA address to unmap + * @size: size of region + * @direction: DMA direction + * + * Unmaps the region pointed to by @dma_addr. Also known as + * platform_pci_unmap_single() by the IA64 machvec code. + */ +void +sn_pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction) +{ + struct sn_dma_maps_s *sn_dma_map = NULL; + + if (direction == PCI_DMA_NONE) + BUG(); + + /* + * Get the sn_dma_map entry. + */ + if (IS_PCI32_MAPPED(dma_addr)) + sn_dma_map = find_sn_dma_map(dma_addr, hwdev->bus->number); + + /* + * and free it if necessary... + */ + if (sn_dma_map) { + pciio_dmamap_done((pciio_dmamap_t)sn_dma_map); + pciio_dmamap_free((pciio_dmamap_t)sn_dma_map); + sn_dma_map->dma_addr = (dma_addr_t)NULL; + } +} + +/** + * sn_pci_dma_sync_single - make sure all DMAs have completed + * @hwdev: device to sync + * @dma_handle: DMA address to sync + * @size: size of region + * @direction: DMA direction + * + * This routine is supposed to sync the DMA region specified + * by @dma_handle into the 'coherence domain'. We do not need to do + * anything on our platform. + */ +void +sn_pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction) +{ + return; + +} + +/** + * sn_pci_dma_sync_sg - make sure all DMAs have completed + * @hwdev: device to sync + * @sg: scatterlist to sync + * @nents: number of entries in the scatterlist + * @direction: DMA direction + * + * This routine is supposed to sync the DMA regions specified + * by @sg into the 'coherence domain'. We do not need to do anything + * on our platform. + */ +void +sn_pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) +{ + return; + +} + +/** + * sn_dma_supported - test a DMA mask + * @hwdev: device to test + * @mask: DMA mask to test + * + * Return whether the given PCI device DMA address mask can be supported + * properly. For example, if your device can only drive the low 24-bits + * during PCI bus mastering, then you would pass 0x00ffffff as the mask to + * this function. Of course, SN only supports devices that have 32 or more + * address bits when using the PMU. We could theoretically support <32 bit + * cards using direct mapping, but we'll worry about that later--on the off + * chance that someone actually wants to use such a card. + */ +int +sn_pci_dma_supported(struct pci_dev *hwdev, u64 mask) +{ + if (mask < 0xffffffff) + return 0; + return 1; +} + +EXPORT_SYMBOL(sn_pci_unmap_single); +EXPORT_SYMBOL(sn_pci_map_single); +EXPORT_SYMBOL(sn_pci_dma_sync_single); +EXPORT_SYMBOL(sn_pci_map_sg); +EXPORT_SYMBOL(sn_pci_unmap_sg); +EXPORT_SYMBOL(sn_pci_alloc_consistent); +EXPORT_SYMBOL(sn_pci_free_consistent); +EXPORT_SYMBOL(sn_pci_dma_supported); + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/Makefile linux2.4.21_itanium/arch/ia64/sn/io/platform_init/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/Makefile Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/platform_init/Makefile Wed Jul 23 18:28:59 2003 @@ -0,0 +1,16 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +O_TARGET := snio.o + +obj-y += sgi_io_init.o irix_io_init.o + +include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/irix_io_init.c linux2.4.21_itanium/arch/ia64/sn/io/platform_init/irix_io_init.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/irix_io_init.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/platform_init/irix_io_init.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,89 @@ +/* $Id: irix_io_init.c,v 1.1.1.1 2003/07/23 09:28:59 kameyama Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void init_all_devices(void); +extern void klhwg_add_all_modules(vertex_hdl_t); +extern void klhwg_add_all_nodes(vertex_hdl_t); + +extern vertex_hdl_t hwgraph_root; +extern void io_module_init(void); +extern int pci_bus_to_hcl_cvlink(void); +extern void mlreset(void); + +/* #define DEBUG_IO_INIT 1 */ +#ifdef DEBUG_IO_INIT +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_IO_INIT */ + +/* + * This routine is responsible for the setup of all the IRIX hwgraph style + * stuff that's been pulled into linux. It's called by sn_pci_find_bios which + * is called just before the generic Linux PCI layer does its probing (by + * platform_pci_fixup aka sn_pci_fixup). + * + * It is very IMPORTANT that this call is only made by the Master CPU! + * + */ + +void +irix_io_init(void) +{ + cnodeid_t cnode; + + /* + * This is the Master CPU. Emulate mlsetup and main.c in Irix. + */ + mlreset(); + + /* + * Initialize platform-dependent vertices in the hwgraph: + * module + * node + * cpu + * memory + * slot + * hub + * router + * xbow + */ + + io_module_init(); /* Use to be called module_init() .. */ + klhwg_add_all_modules(hwgraph_root); + klhwg_add_all_nodes(hwgraph_root); + + for (cnode = 0; cnode < numnodes; cnode++) { + extern void per_hub_init(cnodeid_t); + per_hub_init(cnode); + } + + /* We can do headless hub cnodes here .. */ + + /* + * + * Our IO Infrastructure drivers are in place .. + * Initialize the whole IO Infrastructure .. xwidget/device probes. + * + */ + init_all_devices(); + pci_bus_to_hcl_cvlink(); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/sgi_io_init.c linux2.4.21_itanium/arch/ia64/sn/io/platform_init/sgi_io_init.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/platform_init/sgi_io_init.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/platform_init/sgi_io_init.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,109 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int init_hcl(void); + +/* + * per_hub_init + * + * This code is executed once for each Hub chip. + */ +void +per_hub_init(cnodeid_t cnode) +{ + nasid_t nasid; + nodepda_t *npdap; + ii_icmr_u_t ii_icmr; + ii_ibcr_u_t ii_ibcr; + ii_ilcsr_u_t ii_ilcsr; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + ASSERT(nasid != INVALID_NASID); + ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode); + + npdap = NODEPDA(cnode); + + /* Disable the request and reply errors. */ + REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000); + + /* + * Set the total number of CRBs that can be used. + */ + ii_icmr.ii_icmr_regval= 0x0; + ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf; + if (enable_shub_wars_1_1() ) { + // Set bit one of ICMR to prevent II from sending interrupt for II bug. + ii_icmr.ii_icmr_regval |= 0x1; + } + REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); + + /* + * Set the number of CRBs that both of the BTEs combined + * can use minus 1. + */ + ii_ibcr.ii_ibcr_regval= 0x0; + ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR); + if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) { + ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; + } else { + /* + * if the LLP is down, there is no attached I/O, so + * give BTE all the CRBs. + */ + ii_ibcr.ii_ibcr_fld_s.i_count = 0x14; + } + REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); + + /* + * Set CRB timeout to be 10ms. + */ + REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff ); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); + + /* Initialize error interrupts for this hub. */ + hub_error_init(cnode); +} + +/* + * This routine is responsible for the setup of all the IRIX hwgraph style + * stuff that's been pulled into linux. It's called by sn_pci_find_bios which + * is called just before the generic Linux PCI layer does its probing (by + * platform_pci_fixup aka sn_pci_fixup). + * + * It is very IMPORTANT that this call is only made by the Master CPU! + * + */ + +void +sgi_master_io_infr_init(void) +{ + extern void irix_io_init(void); + + init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */ + irix_io_init(); /* Do IRIX Compatibility IO Init */ + +#ifdef CONFIG_KDB + { + extern void kdba_io_init(void); + kdba_io_init(); + } +#endif + +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sgi_if.c linux2.4.21_itanium/arch/ia64/sn/io/sgi_if.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sgi_if.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sgi_if.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -20,8 +20,6 @@ #include #include -unsigned char Is_pic_on_this_nasid[512]; /* non-0 when this is a pic shub */ - void * snia_kmem_zalloc(size_t size, int flag) { @@ -37,13 +35,6 @@ kfree(ptr); } -int -nic_vertex_info_match(devfs_handle_t v, char *s) -{ - /* we don't support this */ - return(0); -} - /* * the alloc/free_node routines do a simple kmalloc for now .. */ @@ -64,74 +55,6 @@ } -#define xtod(c) ((c) <= '9' ? '0' - (c) : 'a' - (c) - 10) -long -atoi(register char *p) -{ - register long n; - register int c, neg = 0; - - if (p == NULL) - return 0; - - if (!isdigit(c = *p)) { - while (isspace(c)) - c = *++p; - switch (c) { - case '-': - neg++; - case '+': /* fall-through */ - c = *++p; - } - if (!isdigit(c)) - return (0); - } - if (c == '0' && *(p + 1) == 'x') { - p += 2; - c = *p; - n = xtod(c); - while ((c = *++p) && isxdigit(c)) { - n *= 16; /* two steps to avoid unnecessary overflow */ - n += xtod(c); /* accum neg to avoid surprises at MAX */ - } - } else { - n = '0' - c; - while ((c = *++p) && isdigit(c)) { - n *= 10; /* two steps to avoid unnecessary overflow */ - n += '0' - c; /* accum neg to avoid surprises at MAX */ - } - } - return (neg ? n : -n); -} - -char * -strtok_r(char *string, const char *sepset, char **lasts) -{ - register char *q, *r; - - /*first or subsequent call*/ - if (string == NULL) - string = *lasts; - - if(string == 0) /* return if no tokens remaining */ - return(NULL); - - q = string + strspn(string, sepset); /* skip leading separators */ - - if(*q == '\0') { /* return if no tokens remaining */ - *lasts = 0; /* indicate this is last token */ - return(NULL); - } - - if((r = strpbrk(q, sepset)) == NULL) /* move past token */ - *lasts = 0; /* indicate this is last token */ - else { - *r = '\0'; - *lasts = r+1; - } - return(q); -} - /* * print_register() allows formatted printing of bit fields. individual * bit fields are described by a struct reg_desc, multiple bit fields within diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sgi_io_sim.c linux2.4.21_itanium/arch/ia64/sn/io/sgi_io_sim.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sgi_io_sim.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sgi_io_sim.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -15,18 +15,11 @@ #include #include #include -#include #include -cpuid_t master_procid = 0; +cpuid_t master_procid; char arg_maxnodes[4]; -extern void init_all_devices(void); - -#if defined(CONFIG_IA64_SGI_SN1) -synergy_da_t *Synergy_da_indr[MAX_COMPACT_NODES * 2]; -#endif - /* * Return non-zero if the given variable was specified */ @@ -36,44 +29,12 @@ return (strlen(s) != 0); } -void xbmon_init(void) -{ - FIXME("xbmon_init : no-op\n"); - -} - -void pciiox_init(void) -{ - FIXME("pciiox_init : no-op\n"); - -} - -void usrpci_init(void) -{ - FIXME("usrpci_init : no-op\n"); - -} - -void ioc3_init(void) -{ - FIXME("ioc3_init : no-op\n"); - -} - -void initialize_io(void) -{ - - init_all_devices(); -} - /* * Routines provided by ml/SN/promif.c. */ -static __psunsigned_t master_bridge_base = (__psunsigned_t)NULL; +static __psunsigned_t master_bridge_base; nasid_t console_nasid = (nasid_t)-1; -#if !defined(CONFIG_IA64_SGI_SN1) char master_baseio_wid; -#endif static char console_wid; static char console_pcislot; @@ -95,27 +56,6 @@ return 0; } -#if defined(CONFIG_IA64_SGI_SN1) -int -is_master_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid) -{ - - /* - * If the widget numbers are different, we're not the master. - */ - if (test_wid != (xwidgetnum_t)console_wid) - return 0; - - /* - * If the NASIDs are the same or equivalent, we're the master. - */ - if (check_nasid_equiv(test_nasid, console_nasid)) { - return 1; - } else { - return 0; - } -} -#else int is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid) { @@ -137,14 +77,3 @@ return 0; } } -#endif /* CONFIG_IA64_SGI_SN1 */ - -/* - * Routines provided by ml/SN/nvram.c - */ -void -nvram_baseinit(void) -{ - FIXME("nvram_baseinit : no-op\n"); - -} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/Makefile linux2.4.21_itanium/arch/ia64/sn/io/sn2/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/Makefile Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/Makefile Wed Jul 23 18:29:00 2003 @@ -3,7 +3,7 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. # # Makefile for the sn2 io routines. @@ -15,13 +15,11 @@ obj-y += ml_SN_intr.o shub_intr.o shuberror.o shub.o \ bte_error.o pcibr/pcibr.o pic.o geo_op.o \ - l1.o l1_command.o klconflib.o klgraph.o \ + l1_command.o klconflib.o klgraph.o \ ml_SN_init.o ml_iograph.o module.o pciio.o \ - xbow.o xtalk.o \ - pci_bus_cvlink.o sgi_io_init.o shubio.o + xbow.o xtalk.o shubio.o +obj-$(CONFIG_KDB) += kdba_io.o subdir-y += pcibr -obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o - include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/bte_error.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/bte_error.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/bte_error.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/bte_error.c Wed Jul 23 18:29:00 2003 @@ -1,10 +1,35 @@ -/* $Id: bte_error.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $ +/* * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. * - * Copyright (C) 1992 - 1997, 2000,2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ @@ -29,121 +54,208 @@ #include #include -/************************************************************************ - * * - * BTE ERROR RECOVERY * - * * - * Given a BTE error, the node causing the error must do the following: * - * a) Clear all crbs relating to that BTE * - * 1) Read CRBA value for crb in question * - * 2) Mark CRB as VALID, store local physical * - * address known to be good in the address field * - * (bte_notification_targ is a known good local * - * address). * - * 3) Write CRBA * - * 4) Using ICCR, FLUSH the CRB, and wait for it to * - * complete. * - * ... BTE BUSY bit should now be clear (or at least * - * should be after ALL CRBs associated with the * - * transfer are complete. * - * * - * b) Re-enable BTE * - * 1) Write IMEM with BTE Enable + XXX bits - * 2) Write IECLR with BTE clear bits - * 3) Clear IIDSR INT_SENT bits. - * * - ************************************************************************/ - -/* - * >>> bte_crb_error_handler needs to be broken into two parts. The - * first should cleanup the CRB. The second should wait until all bte - * related CRB's are complete and then do the error reset. + +/* + * Bte error handling is done in two parts. The first captures + * any crb related errors. Since there can be multiple crbs per + * interface and multiple interfaces active, we need to wait until + * all active crbs are completed. This is the first job of the + * second part error handler. When all bte related CRBs are cleanly + * completed, it resets the interfaces and gets them ready for new + * transfers to be queued. */ -void -bte_crb_error_handler(devfs_handle_t hub_v, int btenum, - int crbnum, ioerror_t *ioe, int bteop) + + +void bte_error_handler(unsigned long); + + /* - * Function: bte_crb_error_handler - * Purpose: Process a CRB for a specific HUB/BTE - * Parameters: hub_v - vertex of hub in HW graph - * btenum - bte number on hub (0 == a, 1 == b) - * crbnum - crb number being processed - * Notes: - * This routine assumes serialization at a higher level. A CRB - * should not be processed more than once. The error recovery - * follows the following sequence - if you change this, be real - * sure about what you are doing. - * + * First part error handler. This is called whenever any error CRB interrupt + * is generated by the II. */ +void +bte_crb_error_handler(vertex_hdl_t hub_v, int btenum, + int crbnum, ioerror_t * ioe, int bteop) { - hubinfo_t hinfo; - icrba_t crba; - icrbb_t crbb; - nasid_t n; - hubreg_t iidsr, imem, ieclr; + hubinfo_t hinfo; + struct bteinfo_s *bte; + hubinfo_get(hub_v, &hinfo); + bte = &hinfo->h_nodepda->bte_if[btenum]; + + /* + * The caller has already figured out the error type, we save that + * in the bte handle structure for the thread excercising the + * interface to consume. + */ + switch (ioe->ie_errortype) { + case IIO_ICRB_ECODE_PERR: + bte->bh_error = BTEFAIL_POISON; + break; + case IIO_ICRB_ECODE_WERR: + bte->bh_error = BTEFAIL_PROT; + break; + case IIO_ICRB_ECODE_AERR: + bte->bh_error = BTEFAIL_ACCESS; + break; + case IIO_ICRB_ECODE_TOUT: + bte->bh_error = BTEFAIL_TOUT; + break; + case IIO_ICRB_ECODE_XTERR: + bte->bh_error = BTEFAIL_XTERR; + break; + case IIO_ICRB_ECODE_DERR: + bte->bh_error = BTEFAIL_DIR; + break; + case IIO_ICRB_ECODE_PWERR: + case IIO_ICRB_ECODE_PRERR: + /* NO BREAK */ + default: + bte->bh_error = BTEFAIL_ERROR; + } + + bte->bte_error_count++; + BTE_PRINTK(("Got an error on cnode %d bte %d\n", + bte->bte_cnode, bte->bte_num)); + bte_error_handler((unsigned long) hinfo->h_nodepda); +} - n = hinfo->h_nasid; - +/* + * Second part error handler. Wait until all BTE related CRBs are completed + * and then reset the interfaces. + */ +void +bte_error_handler(unsigned long _nodepda) +{ + struct nodepda_s *err_nodepda = (struct nodepda_s *) _nodepda; + spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; + struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; + nasid_t nasid; + int i; + int valid_crbs; + unsigned long irq_flags; + volatile u64 *notify; + bte_result_t bh_error; + ii_imem_u_t imem; /* II IMEM Register */ + ii_icrb0_d_u_t icrbd; /* II CRB Register D */ + ii_ibcr_u_t ibcr; + ii_icmr_u_t icmr; + + + BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda, + smp_processor_id())); + + spin_lock_irqsave(recovery_lock, irq_flags); + + if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) && + (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { + BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, + smp_processor_id())); + spin_unlock_irqrestore(recovery_lock, irq_flags); + return; + } /* - * The following 10 lines (or so) are adapted from IRIXs - * bte_crb_error function. No clear documentation tells - * why the crb needs to complete normally in order for - * the BTE to resume normal operations. This first step - * appears vital! + * Lock all interfaces on this node to prevent new transfers + * from being queued. */ + for (i = 0; i < BTES_PER_NODE; i++) { + if (err_nodepda->bte_if[i].cleanup_active) { + continue; + } + spin_lock(&err_nodepda->bte_if[i].spinlock); + BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda, + smp_processor_id(), i)); + err_nodepda->bte_if[i].cleanup_active = 1; + } + + /* Determine information about our hub */ + nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); + /* - * Zero error and error code to prevent error_dump complaining - * about these CRBs. Copy the CRB to the notification line. - * The crb address is in shub format (physical address shifted - * right by cacheline size). + * A BTE transfer can use multiple CRBs. We need to make sure + * that all the BTE CRBs are complete (or timed out) before + * attempting to clean up the error. Resetting the BTE while + * there are still BTE CRBs active will hang the BTE. + * We should look at all the CRBs to see if they are allocated + * to the BTE and see if they are still active. When none + * are active, we can continue with the cleanup. + * + * We also want to make sure that the local NI port is up. + * When a router resets the NI port can go down, while it + * goes through the LLP handshake, but then comes back up. */ - crbb.ii_icrb0_b_regval = REMOTE_HUB_L(n, IIO_ICRB_B(crbnum)); - crbb.b_error=0; - crbb.b_ecode=0; - REMOTE_HUB_S(n, IIO_ICRB_B(crbnum), crbb.ii_icrb0_b_regval); - - crba.ii_icrb0_a_regval = REMOTE_HUB_L(n, IIO_ICRB_A(crbnum)); - crba.a_addr = TO_PHYS((u64)&nodepda->bte_if[btenum].notify) >> 3; - crba.a_valid = 1; - REMOTE_HUB_S(n, IIO_ICRB_A(crbnum), crba.ii_icrb0_a_regval); - - REMOTE_HUB_S(n, IIO_ICCR, - IIO_ICCR_PENDING | IIO_ICCR_CMD_FLUSH | crbnum); - - while (REMOTE_HUB_L(n, IIO_ICCR) & IIO_ICCR_PENDING) - ; - - - /* Terminate the BTE. */ - /* >>> The other bte transfer will need to be restarted. */ - HUB_L((shubreg_t *)((nodepda->bte_if[btenum].bte_base_addr + - IIO_IBCT0 - IIO_IBLS0))); - - imem = REMOTE_HUB_L(n, IIO_IMEM); - ieclr = REMOTE_HUB_L(n, IIO_IECLR); - if (btenum == 0) { - imem |= IIO_IMEM_W0ESD | IIO_IMEM_B0ESD; - ieclr|= IECLR_BTE0; - } else { - imem |= IIO_IMEM_W0ESD | IIO_IMEM_B1ESD; - ieclr|= IECLR_BTE1; - } - REMOTE_HUB_S(n, IIO_IMEM, imem); - REMOTE_HUB_S(n, IIO_IECLR, ieclr); - - iidsr = REMOTE_HUB_L(n, IIO_IIDSR); - iidsr &= ~IIO_IIDSR_SENT_MASK; - iidsr |= IIO_IIDSR_ENB_MASK; - REMOTE_HUB_S(n, IIO_IIDSR, iidsr); + icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR); + if (icmr.ii_icmr_fld_s.i_crb_mark != 0) { + /* + * There are errors which still need to be cleaned up by + * hubiio_crb_error_handler + */ + mod_timer(recovery_timer, HZ * 5); + BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, + smp_processor_id())); + spin_unlock_irqrestore(recovery_lock, irq_flags); + return; + } + if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { + valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld; - bte_reset_nasid(n); + for (i = 0; i < IIO_NUM_CRBS; i++) { + if (!((1 << i) & valid_crbs)) { + /* This crb was not marked as valid, ignore */ + continue; + } + icrbd.ii_icrb0_d_regval = + REMOTE_HUB_L(nasid, IIO_ICRB_D(i)); + if (icrbd.d_bteop) { + mod_timer(recovery_timer, HZ * 5); + BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", + err_nodepda, smp_processor_id(), i)); + spin_unlock_irqrestore(recovery_lock, + irq_flags); + return; + } + } + } - *nodepda->bte_if[btenum].most_rcnt_na = IBLS_ERROR; -} + BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, + smp_processor_id())); + /* Reenable both bte interfaces */ + imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM); + imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1; + REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval); + + /* Reinitialize both BTE state machines. */ + ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR); + ibcr.ii_ibcr_fld_s.i_soft_reset = 1; + REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); + + + for (i = 0; i < BTES_PER_NODE; i++) { + bh_error = err_nodepda->bte_if[i].bh_error; + if (bh_error != BTE_SUCCESS) { + /* There is an error which needs to be notified */ + notify = err_nodepda->bte_if[i].most_rcnt_na; + BTE_PRINTK(("cnode %d bte %d error=0x%lx\n", + err_nodepda->bte_if[i].bte_cnode, + err_nodepda->bte_if[i].bte_num, + IBLS_ERROR | (u64) bh_error)); + *notify = IBLS_ERROR | bh_error; + err_nodepda->bte_if[i].bh_error = BTE_SUCCESS; + } + + err_nodepda->bte_if[i].cleanup_active = 0; + BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda, + smp_processor_id(), i)); + spin_unlock(&pda.cpu_bte_if[i]->spinlock); + } + + del_timer(recovery_timer); + + spin_unlock_irqrestore(recovery_lock, irq_flags); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/geo_op.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/geo_op.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/geo_op.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/geo_op.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ /* diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/kdba_io.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/kdba_io.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/kdba_io.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/kdba_io.c Wed Jul 23 18:29:00 2003 @@ -0,0 +1,76 @@ +/* + * Kernel Debugger Architecture Dependent POD functions. + * + * Copyright (C) 1999-2003 Silicon Graphics, Inc. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#include +#include +//#include + +/** + * kdba_io - enter POD mode from kdb + * @argc: arg count + * @argv: arg values + * @envp: kdb env. vars + * @regs: current register state + * + * Enter POD mode from kdb using SGI SN specific SAL function call. + */ +static int +kdba_io(int argc, const char **argv, const char **envp, struct pt_regs *regs) +{ + kdb_printf("kdba_io entered with addr 0x%p\n", (void *) regs); + + return(0); +} + +/** + * kdba_io_init - register 'io' command with kdb + * + * Register the 'io' command with kdb at load time. + */ +void +kdba_io_init(void) +{ + kdb_register("io", kdba_io, "", "Display IO Contents", 0); +} + +/** + * kdba_io_exit - unregister the 'io' command + * + * Tell kdb that the 'io' command is no longer available. + */ +static void __exit +kdba_exit(void) +{ + kdb_unregister("io"); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/klconflib.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/klconflib.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/klconflib.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/klconflib.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -24,8 +24,6 @@ #include #include -#define printf printk -int hasmetarouter; #define LDEBUG 0 #define NIC_UNKNOWN ((nic_t) -1) @@ -37,10 +35,11 @@ #define DBG(x...) #endif /* DEBUG_KLGRAPH */ -static void sort_nic_names(lboard_t *) ; - u64 klgraph_addr[MAX_COMPACT_NODES]; -int module_number = 0; +static int hasmetarouter; + + +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=012345"; lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) @@ -135,23 +134,6 @@ return (lboard_t *)NULL; } -lboard_t * -find_lboard_module_class(lboard_t *start, geoid_t geoid, - unsigned char brd_type) -{ - while (start) { - DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type); - - if (geo_cmp(start->brd_geoid, geoid) && - (KLCLASS(start->brd_type) == KLCLASS(brd_type))) - return start; - start = KLCF_NEXT(start); - } - - /* Didn't find it. */ - return (lboard_t *)NULL; -} - /* * Convert a NIC name to a name for use in the hardware graph. */ @@ -205,63 +187,6 @@ } /* - * Find the lboard structure and get the board name. - * If we can't find the structure or it's too low a revision, - * use default name. - */ -lboard_t * -get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name) -{ - lboard_t *brd; - - brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), - geoid); - -#ifndef _STANDALONE - { - cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); - - if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) - brd = find_lboard_modslot((lboard_t *) - KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), - geoid); - } -#endif - - if (!brd || (brd->brd_sversion < 2)) { - strcpy(name, EDGE_LBL_XWIDGET); - } else { - nic_name_convert(brd->brd_name, name); - } - - /* - * PV # 540860 - * If the name is not 'baseio' - * get the lowest of all the names in the nic string. - * This is needed for boards like divo, which can have - * a bunch of daughter cards, but would like to be called - * divo. We could do this for baseio - * but it has some special case names that we would not - * like to disturb at this point. - */ - - /* gfx boards don't need any of this name scrambling */ - if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) { - return(brd); - } - - if (!(!strcmp(name, "baseio") )) { - if (brd) { - sort_nic_names(brd) ; - /* Convert to small case, '-' to '_' etc */ - nic_name_convert(brd->brd_name, name) ; - } - } - - return(brd); -} - -/* * get_actual_nasid * * Completely disabled brds have their klconfig on @@ -341,12 +266,20 @@ board_name = EDGE_LBL_IO; break; case KLCLASS_IOBRICK: - if (brd->brd_type == KLTYPE_PBRICK) + if (brd->brd_type == KLTYPE_PXBRICK) + board_name = EDGE_LBL_PXBRICK; + else if (brd->brd_type == KLTYPE_IXBRICK) + board_name = EDGE_LBL_IXBRICK; + else if (brd->brd_type == KLTYPE_PBRICK) board_name = EDGE_LBL_PBRICK; else if (brd->brd_type == KLTYPE_IBRICK) board_name = EDGE_LBL_IBRICK; else if (brd->brd_type == KLTYPE_XBRICK) board_name = EDGE_LBL_XBRICK; + else if (brd->brd_type == KLTYPE_PEBRICK) + board_name = EDGE_LBL_PEBRICK; + else if (brd->brd_type == KLTYPE_CGBRICK) + board_name = EDGE_LBL_CGBRICK; else board_name = EDGE_LBL_IOBRICK; break; @@ -623,185 +556,6 @@ #include "asm/sn/sn_private.h" -xwidgetnum_t -nodevertex_widgetnum_get(devfs_handle_t node_vtx) -{ - hubinfo_t hubinfo_p; - - hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, - (arbitrary_info_t *) &hubinfo_p); - return(hubinfo_p->h_widgetid); -} - -devfs_handle_t -nodevertex_xbow_peer_get(devfs_handle_t node_vtx) -{ - hubinfo_t hubinfo_p; - nasid_t xbow_peer_nasid; - cnodeid_t xbow_peer; - - hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, - (arbitrary_info_t *) &hubinfo_p); - xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer; - if(xbow_peer_nasid == INVALID_NASID) - return ( (devfs_handle_t)-1); - xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid); - return(NODEPDA(xbow_peer)->node_vertex); -} - -/* NIC Sorting Support */ - -#define MAX_NICS_PER_STRING 32 -#define MAX_NIC_NAME_LEN 32 - -static char * -get_nic_string(lboard_t *lb) -{ - int i; - klinfo_t *k = NULL ; - klconf_off_t mfg_off = 0 ; - char *mfg_nic = NULL ; - - for (i = 0; i < KLCF_NUM_COMPS(lb); i++) { - k = KLCF_COMP(lb, i) ; - switch(k->struct_type) { - case KLSTRUCT_BRI: - mfg_off = ((klbri_t *)k)->bri_mfg_nic ; - break ; - - case KLSTRUCT_HUB: - mfg_off = ((klhub_t *)k)->hub_mfg_nic ; - break ; - - case KLSTRUCT_ROU: - mfg_off = ((klrou_t *)k)->rou_mfg_nic ; - break ; - - case KLSTRUCT_GFX: - mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ; - break ; - - case KLSTRUCT_TPU: - mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ; - break ; - - case KLSTRUCT_GSN_A: - case KLSTRUCT_GSN_B: - mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ; - break ; - - case KLSTRUCT_XTHD: - mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ; - break; - - default: - mfg_off = 0 ; - break ; - } - if (mfg_off) - break ; - } - - if ((mfg_off) && (k)) - mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ; - - return mfg_nic ; -} - -char * -get_first_string(char **ptrs, int n) -{ - int i ; - char *tmpptr ; - - if ((ptrs == NULL) || (n == 0)) - return NULL ; - - tmpptr = ptrs[0] ; - - if (n == 1) - return tmpptr ; - - for (i = 0 ; i < n ; i++) { - if (strcmp(tmpptr, ptrs[i]) > 0) - tmpptr = ptrs[i] ; - } - - return tmpptr ; -} - -int -get_ptrs(char *idata, char **ptrs, int n, char *label) -{ - int i = 0 ; - char *tmp = idata ; - - if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0)) - return 0 ; - - while ( (tmp = strstr(tmp, label)) ){ - tmp += strlen(label) ; - /* check for empty name field, and last NULL ptr */ - if ((i < (n-1)) && (*tmp != ';')) { - ptrs[i++] = tmp ; - } - } - - ptrs[i] = NULL ; - - return i ; -} - -/* - * sort_nic_names - * - * Does not really do sorting. Find the alphabetically lowest - * name among all the nic names found in a nic string. - * - * Return: - * Nothing - * - * Side Effects: - * - * lb->brd_name gets the new name found - */ - -static void -sort_nic_names(lboard_t *lb) -{ - char *nic_str ; - char *ptrs[MAX_NICS_PER_STRING] ; - char name[MAX_NIC_NAME_LEN] ; - char *tmp, *tmp1 ; - - *name = 0 ; - - /* Get the nic pointer from the lb */ - - if ((nic_str = get_nic_string(lb)) == NULL) - return ; - - tmp = get_first_string(ptrs, - get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ; - - if (tmp == NULL) - return ; - - if ( (tmp1 = strchr(tmp, ';')) ){ - strncpy(name, tmp, tmp1-tmp) ; - name[tmp1-tmp] = 0 ; - } else { - strncpy(name, tmp, (sizeof(name) -1)) ; - name[sizeof(name)-1] = 0 ; - } - - strcpy(lb->brd_name, name) ; -} - - - -char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345"; - /* * Format a module id for printing. */ @@ -814,6 +568,7 @@ rack = MODULE_GET_RACK(m); ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); brickchar = MODULE_GET_BTCHAR(m); + position = MODULE_GET_BPOS(m); if (fmt == MODULE_FORMAT_BRIEF) { diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/klgraph.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/klgraph.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/klgraph.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/klgraph.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ /* @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -42,7 +41,7 @@ extern char arg_maxnodes[]; extern u64 klgraph_addr[]; -void mark_cpuvertex_as_cpu(devfs_handle_t vhdl, cpuid_t cpuid); +void mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid); /* @@ -69,7 +68,7 @@ * Add detailed disabled cpu inventory info to the hardware graph. */ void -klhwg_disabled_cpu_invent_info(devfs_handle_t cpuv, +klhwg_disabled_cpu_invent_info(vertex_hdl_t cpuv, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) { @@ -118,7 +117,7 @@ * Add detailed cpu inventory info to the hardware graph. */ void -klhwg_cpu_invent_info(devfs_handle_t cpuv, +klhwg_cpu_invent_info(vertex_hdl_t cpuv, cnodeid_t cnode, klcpu_t *cpu) { @@ -153,7 +152,7 @@ * as a part of detailed inventory info in the hwgraph. */ void -klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode) +klhwg_baseio_inventory_add(vertex_hdl_t baseio_vhdl,cnodeid_t cnode) { invent_miscinfo_t *baseio_inventory; unsigned char version = 0,revision = 0; @@ -177,20 +176,11 @@ sizeof(invent_miscinfo_t)); } -char *hub_rev[] = { - "0.0", - "1.0", - "2.0", - "2.1", - "2.2", - "2.3" -}; - /* * Add detailed cpu inventory info to the hardware graph. */ void -klhwg_hub_invent_info(devfs_handle_t hubv, +klhwg_hub_invent_info(vertex_hdl_t hubv, cnodeid_t cnode, klhub_t *hub) { @@ -215,10 +205,10 @@ /* ARGSUSED */ void -klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode) +klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode) { - devfs_handle_t myhubv; - devfs_handle_t hub_mon; + vertex_hdl_t myhubv; + vertex_hdl_t hub_mon; int rc; extern struct file_operations shub_mon_fops; @@ -234,9 +224,9 @@ /* ARGSUSED */ void -klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) +klhwg_add_disabled_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) { - devfs_handle_t my_cpu; + vertex_hdl_t my_cpu; char name[120]; cpuid_t cpu_id; nasid_t nasid; @@ -257,9 +247,9 @@ /* ARGSUSED */ void -klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu) +klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu) { - devfs_handle_t my_cpu, cpu_dir; + vertex_hdl_t my_cpu, cpu_dir; char name[120]; cpuid_t cpu_id; nasid_t nasid; @@ -295,7 +285,7 @@ nasid_t hub_nasid; cnodeid_t hub_cnode; int widgetnum; - devfs_handle_t xbow_v, hubv; + vertex_hdl_t xbow_v, hubv; /*REFERENCED*/ graph_error_t err; @@ -363,12 +353,12 @@ /* ARGSUSED */ void -klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap) +klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode) { nasid_t nasid; lboard_t *brd; klhub_t *hub; - devfs_handle_t node_vertex = NULL; + vertex_hdl_t node_vertex = NULL; char path_buffer[100]; int rv; char *s; @@ -382,7 +372,7 @@ ASSERT(brd); do { - devfs_handle_t cpu_dir; + vertex_hdl_t cpu_dir; /* Generate a hardware graph path for this board. */ board_to_path(brd, path_buffer); @@ -443,7 +433,7 @@ while (cpu) { cpuid_t cpu_id; cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid); - if (cpu_enabled(cpu_id)) + if (cpu_online(cpu_id)) klhwg_add_cpu(node_vertex, cnode, cpu); else klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot); @@ -466,12 +456,12 @@ /* ARGSUSED */ void -klhwg_add_all_routers(devfs_handle_t hwgraph_root) +klhwg_add_all_routers(vertex_hdl_t hwgraph_root) { nasid_t nasid; cnodeid_t cnode; lboard_t *brd; - devfs_handle_t node_vertex; + vertex_hdl_t node_vertex; char path_buffer[100]; int rv; @@ -525,14 +515,14 @@ /* ARGSUSED */ void -klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd, +klhwg_connect_one_router(vertex_hdl_t hwgraph_root, lboard_t *brd, cnodeid_t cnode, nasid_t nasid) { klrou_t *router; char path_buffer[50]; char dest_path[50]; - devfs_handle_t router_hndl; - devfs_handle_t dest_hndl; + vertex_hdl_t router_hndl; + vertex_hdl_t dest_hndl; int rc; int port; lboard_t *dest_brd; @@ -619,7 +609,7 @@ void -klhwg_connect_routers(devfs_handle_t hwgraph_root) +klhwg_connect_routers(vertex_hdl_t hwgraph_root) { nasid_t nasid; cnodeid_t cnode; @@ -652,15 +642,15 @@ void -klhwg_connect_hubs(devfs_handle_t hwgraph_root) +klhwg_connect_hubs(vertex_hdl_t hwgraph_root) { nasid_t nasid; cnodeid_t cnode; lboard_t *brd; klhub_t *hub; lboard_t *dest_brd; - devfs_handle_t hub_hndl; - devfs_handle_t dest_hndl; + vertex_hdl_t hub_hndl; + vertex_hdl_t dest_hndl; char path_buffer[50]; char dest_path[50]; graph_error_t rc; @@ -796,12 +786,12 @@ } void -klhwg_add_all_modules(devfs_handle_t hwgraph_root) +klhwg_add_all_modules(vertex_hdl_t hwgraph_root) { cmoduleid_t cm; char name[128]; - devfs_handle_t vhdl; - devfs_handle_t module_vhdl; + vertex_hdl_t vhdl; + vertex_hdl_t module_vhdl; int rc; char buffer[16]; @@ -837,12 +827,12 @@ } void -klhwg_add_all_nodes(devfs_handle_t hwgraph_root) +klhwg_add_all_nodes(vertex_hdl_t hwgraph_root) { cnodeid_t cnode; for (cnode = 0; cnode < numnodes; cnode++) { - klhwg_add_node(hwgraph_root, cnode, NULL); + klhwg_add_node(hwgraph_root, cnode); } for (cnode = 0; cnode < numnodes; cnode++) { diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/l1_command.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/l1_command.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/l1_command.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/l1_command.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -26,37 +25,6 @@ #include #include -#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */ -#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */ - -#define hub_cpu_get() 0 - -#define LBYTE(caddr) (*(char *) caddr) - -extern char *bcopy(const char * src, char * dest, int count); - -#define LDEBUG 0 - -/* - * ELSC data is in NVRAM page 7 at the following offsets. - */ - -#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */ -#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */ -#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */ -#define NVRAM_DBG2 0x706 /* physical XOR debug switches */ -#define NVRAM_CFG 0x707 /* ELSC Configuration info */ -#define NVRAM_MODULE 0x708 /* system module number */ -#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */ -#define NVRAM_PARTITION 0x70a /* module's partition id */ -#define NVRAM_DOMAIN 0x70b /* module's domain id */ -#define NVRAM_CLUSTER 0x70c /* module's cluster id */ -#define NVRAM_CELL 0x70d /* module's cellid */ - -#define NVRAM_MAGIC_NO 0x37 /* value of magic number */ -#define NVRAM_SIZE 16 /* 16 bytes in nvram */ - - /* elsc_display_line writes up to 12 characters to either the top or bottom * line of the L1 display. line points to a buffer containing the message * to be displayed. The zero-based line number is specified by lnum (so @@ -69,6 +37,7 @@ return 0; } + /* * iobrick routines */ @@ -88,15 +57,25 @@ if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) return( ELSC_ERROR_CMD_SEND ); - *rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT; - *bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT; - *brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT; + *rack = (result & MODULE_RACK_MASK) >> MODULE_RACK_SHFT; + *bay = (result & MODULE_BPOS_MASK) >> MODULE_BPOS_SHFT; + *brick_type = (result & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT; *brick_type = toupper(*brick_type); return 0; } +int iomoduleid_get(nasid_t nasid) +{ + int result = 0; + + if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) + return( ELSC_ERROR_CMD_SEND ); + + return result; +} + int iobrick_module_get(nasid_t nasid) { uint rnum, rack, bay, brick_type, t; @@ -130,11 +109,15 @@ RACK_ADD_NUM(rack, t); switch( brick_type ) { - case 'I': + case L1_BRICKTYPE_IX: + brick_type = MODULE_IXBRICK; break; + case L1_BRICKTYPE_PX: + brick_type = MODULE_PXBRICK; break; + case L1_BRICKTYPE_I: brick_type = MODULE_IBRICK; break; - case 'P': + case L1_BRICKTYPE_P: brick_type = MODULE_PBRICK; break; - case 'X': + case L1_BRICKTYPE_X: brick_type = MODULE_XBRICK; break; } @@ -167,8 +150,9 @@ /* convert to a module.h brick type */ for( t = 0; t < MAX_BRICK_TYPES; t++ ) { - if( brick_types[t] == type ) + if( brick_types[t] == type ) { return t; + } } return -1; /* unknown brick */ @@ -178,18 +162,42 @@ { int io_moduleid; -#ifdef PIC_LATER - uint rack, bay; + io_moduleid = iobrick_module_get(nasid); + return io_moduleid; +} + +/* + * given a L1 bricktype, return a bricktype string. This string is the + * string that will be used in the hwpath for I/O bricks + */ +char * +iobrick_L1bricktype_to_name(int type) +{ + switch (type) + { + default: + return("Unknown"); - if (PEBRICK_NODE(nasid)) { - if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) { - printf("Could not read rack and bay location " - "of PEBrick at nasid %d\n", nasid); - } + case L1_BRICKTYPE_X: + return("Xbrick"); - io_moduleid = peer_iobrick_module_get(sc, rack, bay); + case L1_BRICKTYPE_I: + return("Ibrick"); + + case L1_BRICKTYPE_P: + return("Pbrick"); + + case L1_BRICKTYPE_PX: + return("PXbrick"); + + case L1_BRICKTYPE_IX: + return("IXbrick"); + + case L1_BRICKTYPE_C: + return("Cbrick"); + + case L1_BRICKTYPE_R: + return("Rbrick"); } -#endif /* PIC_LATER */ - io_moduleid = iobrick_module_get(nasid); - return io_moduleid; } + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_SN_init.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_SN_init.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_SN_init.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_SN_init.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -19,25 +19,12 @@ #include #include #include -#include -extern int numcpus; -extern char arg_maxnodes[]; extern cpuid_t master_procid; - -extern int hasmetarouter; - int maxcpus; -cpumask_t boot_cpumask; -hubreg_t region_mask = 0; - extern xwidgetnum_t hub_widget_id(nasid_t); -extern int valid_icache_reasons; /* Reasons to flush the icache */ -extern int valid_dcache_reasons; /* Reasons to flush the dcache */ -extern u_char miniroot; -extern volatile int need_utlbmiss_patch; extern void iograph_early_init(void); nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */ @@ -123,16 +110,6 @@ mutex_init_locked(&npda->xbow_sema); /* init it locked? */ } -/* XXX - Move the interrupt stuff to intr.c ? */ -/* - * Set up the platform-dependent fields in the processor pda. - * Must be done _after_ init_platform_nodepda(). - * If we need a lock here, something else is wrong! - */ -void init_platform_pda(cpuid_t cpu) -{ -} - void update_node_information(cnodeid_t cnodeid) { diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_SN_intr.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_SN_intr.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_SN_intr.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_SN_intr.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -40,30 +40,13 @@ #include #include -extern irqpda_t *irqpdaindr[]; -extern cnodeid_t master_node_get(devfs_handle_t vhdl); +extern irqpda_t *irqpdaindr; +extern cnodeid_t master_node_get(vertex_hdl_t vhdl); extern nasid_t master_nasid; // Initialize some shub registers for interrupts, both IO and error. // -#ifdef BRINGUP2 -static long vec1_opt, ii0_opt; -static int __init set_vec1_opt(char *str) -{ - vec1_opt = 1; - return 1; -} - -static int __init set_ii0_opt(char *str) -{ - ii0_opt = 1; - return 1; -} - -__setup("vec1", set_vec1_opt); -__setup("ii0", set_ii0_opt); -#endif void @@ -78,6 +61,8 @@ nodepda_t *lnodepda; sh_ii_int0_enable_u_t ii_int_enable; sh_int_node_id_config_u_t node_id_config; + sh_local_int5_config_u_t local5_config; + sh_local_int5_enable_u_t local5_enable; extern void sn_init_cpei_timer(void); static int timer_added = 0; @@ -113,6 +98,19 @@ HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_ERROR_MASK), 0); HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_PI_CRBP_ERROR_MASK), 0); + // Config and enable UART interrupt, all nodes. + + local5_config.sh_local_int5_config_regval = 0; + local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR; + local5_config.sh_local_int5_config_s.pid = cpu0; + HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG), + local5_config.sh_local_int5_config_regval); + + local5_enable.sh_local_int5_enable_regval = 0; + local5_enable.sh_local_int5_enable_s.uart_int = 1; + HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_ENABLE), + local5_enable.sh_local_int5_enable_regval); + // The II_INT_CONFIG register for cpu 0. ii_int_config.sh_ii_int0_config_regval = 0; @@ -139,13 +137,6 @@ // Enable interrupts for II_INT0 and 1. ii_int_enable.sh_ii_int0_enable_regval = 0; ii_int_enable.sh_ii_int0_enable_s.ii_enable = 1; -#if defined(BUS_INT_WAR) && defined(CONFIG_SHUB_1_0_SPECIFIC) - /* Dont enable any ints from II. We will poll for interrupts. */ - ii_int_enable.sh_ii_int0_enable_s.ii_enable = 0; - - /* Enable IPIs. We use them ONLY for send INITs to hung cpus */ - *(volatile long*)GLOBAL_MMR_ADDR(nasid, SH_IPI_INT_ENABLE) = 1; -#endif HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_II_INT0_ENABLE), ii_int_enable.sh_ii_int0_enable_regval); @@ -167,24 +158,44 @@ int reserve) { int i; - irqpda_t *irqs = irqpdaindr[cpu]; - static int nextvec=IA64_SN2_FIRST_DEVICE_VECTOR; + irqpda_t *irqs = irqpdaindr; + int min_shared; if (reserve) { if (bit < 0) { - for (i = nextvec; i <= IA64_SN2_LAST_DEVICE_VECTOR; i++) { + for (i = IA64_SN2_FIRST_DEVICE_VECTOR; i <= IA64_SN2_LAST_DEVICE_VECTOR; i++) { if (irqs->irq_flags[i] == 0) { bit = i; -#ifdef BRINGUP2 - if (vec1_opt) - nextvec = i+1; -#endif break; } } } - if (bit < 0) { - return -1; + if (bit < 0) { /* ran out of irqs. Have to share. This will be rare. */ + min_shared = 256; + for (i=IA64_SN2_FIRST_DEVICE_VECTOR; i < IA64_SN2_LAST_DEVICE_VECTOR; i++) { + /* Share with the same device class */ + if (irqpdaindr->current->vendor == irqpdaindr->device_dev[i]->vendor && + irqpdaindr->current->device == irqpdaindr->device_dev[i]->device && + irqpdaindr->share_count[i] < min_shared) { + min_shared = irqpdaindr->share_count[i]; + bit = i; + } + } + min_shared = 256; + if (bit < 0) { /* didn't find a matching device, just pick one. This will be */ + /* exceptionally rare. */ + for (i=IA64_SN2_FIRST_DEVICE_VECTOR; i < IA64_SN2_LAST_DEVICE_VECTOR; i++) { + if (irqpdaindr->share_count[i] < min_shared) { + min_shared = irqpdaindr->share_count[i]; + bit = i; + } + } + } + irqpdaindr->share_count[bit]++; + } + if (irqs->irq_flags[bit] & SN2_IRQ_SHARED) { + irqs->irq_flags[bit] |= SN2_IRQ_RESERVED; + return bit; } if (irqs->irq_flags[bit] & SN2_IRQ_RESERVED) { return -1; @@ -208,7 +219,7 @@ intr_reserve_level(cpuid_t cpu, int bit, int resflags, - devfs_handle_t owner_dev, + vertex_hdl_t owner_dev, char *name) { return(do_intr_reserve_level(cpu, bit, 1)); @@ -228,9 +239,13 @@ int bit, int connect) { - irqpda_t *irqs = irqpdaindr[cpu]; + irqpda_t *irqs = irqpdaindr; if (connect) { + if (irqs->irq_flags[bit] & SN2_IRQ_SHARED) { + irqs->irq_flags[bit] |= SN2_IRQ_CONNECTED; + return bit; + } if (irqs->irq_flags[bit] & SN2_IRQ_CONNECTED) { return -1; } else { @@ -273,28 +288,29 @@ int slice, min_count = 1000; irqpda_t *irqs; - for (slice = 0; slice < CPUS_PER_NODE; slice++) { + for (slice = CPUS_PER_NODE - 1; slice >= 0; slice--) { int intrs; cpu = cnode_slice_to_cpuid(cnode, slice); - if (cpu == CPU_NONE) { + if (cpu == smp_num_cpus) { continue; } - if (!cpu_enabled(cpu)) { + if (!cpu_online(cpu)) { continue; } - irqs = irqpdaindr[cpu]; + irqs = irqpdaindr; intrs = irqs->num_irq_used; if (min_count > intrs) { min_count = intrs; best_cpu = cpu; -#ifdef BRINGUP2 - if (ii0_opt) + if ( enable_shub_wars_1_1() ) { + /* Rather than finding the best cpu, always return the first cpu*/ + /* This forces all interrupts to the same cpu */ break; -#endif + } } } return best_cpu; @@ -314,7 +330,7 @@ cnodeid_t cnode, int req_bit, int resflags, - devfs_handle_t owner_dev, + vertex_hdl_t owner_dev, char *name, int *resp_bit) { @@ -336,18 +352,18 @@ // Find the node to assign for this interrupt. cpuid_t -intr_heuristic(devfs_handle_t dev, +intr_heuristic(vertex_hdl_t dev, device_desc_t dev_desc, int req_bit, int resflags, - devfs_handle_t owner_dev, + vertex_hdl_t owner_dev, char *name, int *resp_bit) { cpuid_t cpuid; cpuid_t candidate = CPU_NONE; cnodeid_t candidate_node; - devfs_handle_t pconn_vhdl; + vertex_hdl_t pconn_vhdl; pcibr_soft_t pcibr_soft; int bit; @@ -398,8 +414,8 @@ if (candidate != CPU_NONE) { printk("Cannot target interrupt to target node (%ld).\n",candidate); return CPU_NONE; } else { - printk("Cannot target interrupt to closest node (%d) 0x%p\n", - master_node_get(dev), (void *)owner_dev); + /* printk("Cannot target interrupt to closest node (%d) 0x%p\n", + master_node_get(dev), (void *)owner_dev); */ } // We couldn't put it on the closest node. Try to find another one. diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_iograph.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_iograph.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/ml_iograph.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/ml_iograph.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -43,8 +42,6 @@ /* At most 2 hubs can be connected to an xswitch */ #define NUM_XSWITCH_VOLUNTEER 2 -extern unsigned char Is_pic_on_this_nasid[512]; - /* * Track which hubs have volunteered to manage devices hanging off of * a Crosstalk Switch (e.g. xbow). This structure is allocated, @@ -54,11 +51,11 @@ typedef struct xswitch_vol_s { mutex_t xswitch_volunteer_mutex; int xswitch_volunteer_count; - devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; + vertex_hdl_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; } *xswitch_vol_t; void -xswitch_vertex_init(devfs_handle_t xswitch) +xswitch_vertex_init(vertex_hdl_t xswitch) { xswitch_vol_t xvolinfo; int rc; @@ -78,7 +75,7 @@ * xswitch volunteer structure hanging around. Destroy it. */ static void -xswitch_volunteer_delete(devfs_handle_t xswitch) +xswitch_volunteer_delete(vertex_hdl_t xswitch) { xswitch_vol_t xvolinfo; int rc; @@ -94,10 +91,10 @@ */ /* ARGSUSED */ static void -volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) +volunteer_for_widgets(vertex_hdl_t xswitch, vertex_hdl_t master) { xswitch_vol_t xvolinfo = NULL; - devfs_handle_t hubv; + vertex_hdl_t hubv; hubinfo_t hubinfo; (void)hwgraph_info_get_LBL(xswitch, @@ -140,7 +137,7 @@ */ /* ARGSUSED */ static void -assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) +assign_widgets_to_volunteers(vertex_hdl_t xswitch, vertex_hdl_t hubv) { xswitch_info_t xswitch_info; xswitch_vol_t xvolinfo = NULL; @@ -223,18 +220,6 @@ bt = iobrick_type_get_nasid(nasid); if (bt >= 0) { - /* - * PXBRICK has two busses per widget so this - * algorithm wouldn't work (all busses would - * be assigned to one volunteer). Change the - * bricktype to PBRICK whose mapping is setup - * suchthat 2 of the PICs will be assigned to - * one volunteer and the other one will be - * assigned to the other volunteer. - */ - if (bt == MODULE_PXBRICK) - bt = MODULE_PBRICK; - i = io_brick_map_widget(bt, widgetnum) & 1; } } @@ -281,8 +266,6 @@ DBG("iograph_early_init: Found board 0x%p\n", board); } } - - hubio_init(); } /* @@ -307,7 +290,7 @@ * hwid for our use. */ static void -early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid) +early_probe_for_widget(vertex_hdl_t hubv, xwidget_hwid_t hwid) { hubreg_t llp_csr_reg; nasid_t nasid; @@ -351,7 +334,7 @@ * added as inventory information. */ static void -xwidget_inventory_add(devfs_handle_t widgetv, +xwidget_inventory_add(vertex_hdl_t widgetv, lboard_t *board, struct xwidget_hwid_s hwid) { @@ -374,14 +357,13 @@ */ void -io_xswitch_widget_init(devfs_handle_t xswitchv, - devfs_handle_t hubv, - xwidgetnum_t widgetnum, - async_attach_t aa) +io_xswitch_widget_init(vertex_hdl_t xswitchv, + vertex_hdl_t hubv, + xwidgetnum_t widgetnum) { xswitch_info_t xswitch_info; xwidgetnum_t hub_widgetid; - devfs_handle_t widgetv; + vertex_hdl_t widgetv; cnodeid_t cnode; widgetreg_t widget_id; nasid_t nasid, peer_nasid; @@ -427,6 +409,7 @@ char name[4]; lboard_t dummy; + /* * If the current hub is not supposed to be the master * for this widgetnum, then skip this widget. @@ -470,12 +453,15 @@ memset(buffer, 0, 16); format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); - sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%cbrick" "/%s/%d", + + sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%s" "/%s/%d", buffer, geo_slab(board->brd_geoid), - (board->brd_type == KLTYPE_IBRICK) ? 'I' : - (board->brd_type == KLTYPE_PBRICK) ? 'P' : - (board->brd_type == KLTYPE_XBRICK) ? 'X' : '?', + (board->brd_type == KLTYPE_IBRICK) ? EDGE_LBL_IBRICK : + (board->brd_type == KLTYPE_PBRICK) ? EDGE_LBL_PBRICK : + (board->brd_type == KLTYPE_PXBRICK) ? EDGE_LBL_PXBRICK : + (board->brd_type == KLTYPE_IXBRICK) ? EDGE_LBL_IXBRICK : + (board->brd_type == KLTYPE_XBRICK) ? EDGE_LBL_XBRICK : "?brick", EDGE_LBL_XTALK, widgetnum); DBG("io_xswitch_widget_init: path= %s\n", pathname); @@ -514,36 +500,46 @@ xwidget_inventory_add(widgetv,board,hwid); (void)xwidget_register(&hwid, widgetv, widgetnum, - hubv, hub_widgetid, - aa); + hubv, hub_widgetid); ia64_sn_sysctl_iobrick_module_get(nasid, &io_module); if (io_module >= 0) { char buffer[16]; - devfs_handle_t to, from; + vertex_hdl_t to, from; + char *brick_name; + extern char *iobrick_L1bricktype_to_name(int type); + memset(buffer, 0, 16); format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); - bt = toupper(MODULE_GET_BTCHAR(io_module)); + if ( islower(MODULE_GET_BTCHAR(io_module)) ) { + bt = toupper(MODULE_GET_BTCHAR(io_module)); + } + else { + bt = MODULE_GET_BTCHAR(io_module); + } + + brick_name = iobrick_L1bricktype_to_name(bt); + /* Add a helper vertex so xbow monitoring * can identify the brick type. It's simply * an edge from the widget 0 vertex to the * brick vertex. */ - sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + sprintf(pathname, EDGE_LBL_HW "/" EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/" EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/" "0", buffer, geo_slab(board->brd_geoid)); from = hwgraph_path_to_vertex(pathname); ASSERT_ALWAYS(from); - sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + sprintf(pathname, EDGE_LBL_HW "/" EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/" - "%cbrick", - buffer, geo_slab(board->brd_geoid), bt); + "%s", + buffer, geo_slab(board->brd_geoid), brick_name); to = hwgraph_path_to_vertex(pathname); ASSERT_ALWAYS(to); @@ -566,12 +562,9 @@ static void -io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode) +io_init_xswitch_widgets(vertex_hdl_t xswitchv, cnodeid_t cnode) { xwidgetnum_t widgetnum; - async_attach_t aa; - - aa = async_attach_new(); DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode); @@ -579,13 +572,8 @@ widgetnum++) { io_xswitch_widget_init(xswitchv, cnodeid_to_vertex(cnode), - widgetnum, aa); + widgetnum); } - /* - * Wait for parallel attach threads, if any, to complete. - */ - async_attach_waitall(aa); - async_attach_free(aa); } /* @@ -595,11 +583,11 @@ * graph and risking hangs. */ static void -io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid) +io_link_xswitch_widgets(vertex_hdl_t xswitchv, cnodeid_t cnodeid) { xwidgetnum_t widgetnum; char pathname[128]; - devfs_handle_t vhdl; + vertex_hdl_t vhdl; nasid_t nasid, peer_nasid; lboard_t *board; @@ -638,21 +626,12 @@ return; } - if ( Is_pic_on_this_nasid[nasid] ) { - /* Check both buses */ - sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); - if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) - board->brd_graph_link = vhdl; - else { - sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); - if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) - board->brd_graph_link = vhdl; - else - board->brd_graph_link = GRAPH_VERTEX_NONE; - } - } + /* Check both buses */ + sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) + board->brd_graph_link = vhdl; else { - sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) board->brd_graph_link = vhdl; else @@ -668,16 +647,15 @@ io_init_node(cnodeid_t cnodeid) { /*REFERENCED*/ - devfs_handle_t hubv, switchv, widgetv; + vertex_hdl_t hubv, switchv, widgetv; struct xwidget_hwid_s hwid; hubinfo_t hubinfo; int is_xswitch; nodepda_t *npdap; struct semaphore *peer_sema = 0; uint32_t widget_partnum; - nodepda_router_info_t *npda_rip; cpu_cookie_t c = 0; - extern int hubdev_docallouts(devfs_handle_t); + extern int hubdev_docallouts(vertex_hdl_t); npdap = NODEPDA(cnodeid); @@ -696,21 +674,6 @@ hubdev_docallouts(hubv); /* - * Set up the dependent routers if we have any. - */ - npda_rip = npdap->npda_rip_first; - - while(npda_rip) { - /* If the router info has not been initialized - * then we need to do the router initialization - */ - if (!npda_rip->router_infop) { - router_init(cnodeid,0,npda_rip); - } - npda_rip = npda_rip->router_next; - } - - /* * Read mfg info on this hub */ @@ -833,7 +796,7 @@ */ hubinfo_get(hubv, &hubinfo); - (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL); + (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid); if (!is_xswitch) { /* io_init_done takes cpu cookie as 2nd argument @@ -915,231 +878,9 @@ * XXX Irix legacy..controller numbering should be part of devfsd's job */ int num_base_io_scsi_ctlr = 2; /* used by syssgi */ -devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR]; -static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl; - -/* - * Put the logical controller number information in the - * scsi controller vertices for each scsi controller that - * is in a "fixed position". - */ -static void -scsi_ctlr_nums_add(devfs_handle_t pci_vhdl) -{ - { - int i; - - num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR; - - /* Initialize base_io_scsi_ctlr_vhdl array */ - for (i=0; i -devfs_handle_t sys_critical_graph_root = GRAPH_VERTEX_NONE; - -/* Define the system critical vertices and connect them through - * a canonical parent-child relationships for easy traversal - * during io error handling. - */ -static void -sys_critical_graph_init(void) -{ - devfs_handle_t bridge_vhdl,master_node_vhdl; - devfs_handle_t xbow_vhdl = GRAPH_VERTEX_NONE; - extern devfs_handle_t hwgraph_root; - devfs_handle_t pci_slot_conn; - int slot; - devfs_handle_t baseio_console_conn; - - DBG("sys_critical_graph_init: FIXME.\n"); - baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl); - - if (baseio_console_conn == NULL) { - return; - } - - /* Get the vertex handle for the baseio bridge */ - bridge_vhdl = device_master_get(baseio_console_conn); - - /* Get the master node of the baseio card */ - master_node_vhdl = cnodeid_to_vertex( - master_node_get(baseio_console_vhdl)); - - /* Add the "root->node" part of the system critical graph */ - - sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl); - - /* Check if we have a crossbow */ - if (hwgraph_traverse(master_node_vhdl, - EDGE_LBL_XTALK"/0", - &xbow_vhdl) == GRAPH_SUCCESS) { - /* We have a crossbow.Add "node->xbow" part of the system - * critical graph. - */ - sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl); - - /* Add "xbow->baseio bridge" of the system critical graph */ - sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl); - - hwgraph_vertex_unref(xbow_vhdl); - } else - /* We donot have a crossbow. Add "node->baseio_bridge" - * part of the system critical graph. - */ - sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl); - - /* Add all the populated PCI slot vertices to the system critical - * graph with the bridge vertex as the parent. - */ - for (slot = 0 ; slot < 8; slot++) { - char slot_edge[10]; - - sprintf(slot_edge,"%d",slot); - if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn) - != GRAPH_SUCCESS) - continue; - sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn); - hwgraph_vertex_unref(pci_slot_conn); - } - - hwgraph_vertex_unref(bridge_vhdl); - - /* Add the "ioc3 pci connection point -> console ioc3" part - * of the system critical graph - */ - - if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) == - GRAPH_SUCCESS) { - sys_critical_graph_vertex_add(pci_slot_conn, - baseio_console_vhdl); - hwgraph_vertex_unref(pci_slot_conn); - } - - /* Add the "ethernet pci connection point -> base ethernet" part of - * the system critical graph - */ - if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) == - GRAPH_SUCCESS) { - sys_critical_graph_vertex_add(pci_slot_conn, - baseio_enet_vhdl); - hwgraph_vertex_unref(pci_slot_conn); - } - - /* Add the "scsi controller pci connection point -> base scsi - * controller" part of the system critical graph - */ - if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0], - "../..",&pci_slot_conn) == GRAPH_SUCCESS) { - sys_critical_graph_vertex_add(pci_slot_conn, - base_io_scsi_ctlr_vhdl[0]); - hwgraph_vertex_unref(pci_slot_conn); - } - if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1], - "../..",&pci_slot_conn) == GRAPH_SUCCESS) { - sys_critical_graph_vertex_add(pci_slot_conn, - base_io_scsi_ctlr_vhdl[1]); - hwgraph_vertex_unref(pci_slot_conn); - } - hwgraph_vertex_unref(baseio_console_conn); - -} - -static void -baseio_ctlr_num_set(void) -{ - char name[MAXDEVNAME]; - devfs_handle_t console_vhdl, pci_vhdl, enet_vhdl; - devfs_handle_t ioc3_console_vhdl_get(void); - - - DBG("baseio_ctlr_num_set; FIXME\n"); - console_vhdl = ioc3_console_vhdl_get(); - if (console_vhdl == GRAPH_VERTEX_NONE) - return; - /* Useful for setting up the system critical graph */ - baseio_console_vhdl = console_vhdl; - - vertex_to_name(console_vhdl,name,MAXDEVNAME); - - strcat(name,__DEVSTR1); - pci_vhdl = hwgraph_path_to_vertex(name); - scsi_ctlr_nums_add(pci_vhdl); - /* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex - */ - hwgraph_vertex_unref(pci_vhdl); - - vertex_to_name(console_vhdl, name, MAXDEVNAME); - strcat(name, __DEVSTR4); - enet_vhdl = hwgraph_path_to_vertex(name); - - /* Useful for setting up the system critical graph */ - baseio_enet_vhdl = enet_vhdl; - - device_controller_num_set(enet_vhdl, 0); - /* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex - */ - hwgraph_vertex_unref(enet_vhdl); -} /* #endif */ /* @@ -1168,13 +909,6 @@ */ update_node_information(cnodeid); - baseio_ctlr_num_set(); - /* Setup the system critical graph (which is a subgraph of the - * main hwgraph). This information is useful during io error - * handling. - */ - sys_critical_graph_init(); - #if HWG_PRINT hwgraph_print(); #endif @@ -1279,10 +1013,10 @@ 2, /* 0x8 */ 1, /* 0x9 */ 0, 0, /* 0xa - 0xb */ - 5, /* 0xc */ + 4, /* 0xc */ 6, /* 0xd */ - 4, /* 0xe */ - 3 /* 0xf */ + 3, /* 0xe */ + 5 /* 0xf */ } }, @@ -1300,6 +1034,20 @@ } }, +/* IXbrick widget number to PCI bus number map */ + { MODULE_IXBRICK, /* IXbrick type */ + /* PCI Bus # Widget # */ + { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ + 0, /* 0x8 */ + 0, /* 0x9 */ + 0, 0, /* 0xa - 0xb */ + 1, /* 0xc */ + 5, /* 0xd */ + 0, /* 0xe */ + 3 /* 0xf */ + } + }, + /* Xbrick widget to XIO slot map */ { MODULE_XBRICK, /* Xbrick type */ /* XIO Slot # Widget # */ @@ -1335,61 +1083,3 @@ return 0; } - -/* - * Use the device's vertex to map the device's widget to a meaningful int - */ -int -io_path_map_widget(devfs_handle_t vertex) -{ - char hw_path_name[MAXDEVNAME]; - char *wp, *bp, *sp = NULL; - int widget_num; - long atoi(char *); - int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen); - - - /* Get the full path name of the vertex */ - if (GRAPH_SUCCESS != hwgraph_vertex_name_get(vertex, hw_path_name, - MAXDEVNAME)) - return 0; - - /* Find the widget number in the path name */ - wp = strstr(hw_path_name, "/"EDGE_LBL_XTALK"/"); - if (wp == NULL) - return 0; - widget_num = atoi(wp+7); - if (widget_num < XBOW_PORT_8 || widget_num > XBOW_PORT_F) - return 0; - - /* Find "brick" in the path name */ - bp = strstr(hw_path_name, "brick"); - if (bp == NULL) - return 0; - - /* Find preceding slash */ - sp = bp; - while (sp > hw_path_name) { - sp--; - if (*sp == '/') - break; - } - - /* Invalid if no preceding slash */ - if (!sp) - return 0; - - /* Bump slash pointer to "brick" prefix */ - sp++; - /* - * Verify "brick" prefix length; valid exaples: - * 'I' from "/Ibrick" - * 'P' from "/Pbrick" - * 'X' from "/Xbrick" - */ - if ((bp - sp) != 1) - return 0; - - return (io_brick_map_widget((int)*sp, widget_num)); - -} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/module.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/module.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/module.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/module.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -261,20 +260,5 @@ nserial); if (nserial == 0) - printk(KERN_WARNING "io_module_init: No serial number found.\n"); -} - -int -get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info) -{ - if (cmod < 0 || cmod >= nummodules) - return -EINVAL; - - mod_info->mod_num = modules[cmod]->id; - - ia64_sn_sys_serial_get(mod_info->serial_str); - - mod_info->serial_num = ia64_sn_partition_serial_get(); - - return 0; + DPRINTF(KERN_WARNING "io_module_init: No serial number found.\n"); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/Makefile linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/Makefile Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/Makefile Wed Jul 23 18:29:00 2003 @@ -3,21 +3,20 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. # # Makefile for the sn2 io pcibr routines. EXTRA_CFLAGS := -DLITTLE_ENDIAN -ifdef CONFIG_IA64_SGI_SN2 EXTRA_CFLAGS += -DSHUB_SWAP_WAR -endif O_TARGET := pcibr.o +export-objs := pcibr_intr.o -obj-$(CONFIG_IA64_SGI_SN2) += pcibr_dvr.o pcibr_ate.o pcibr_config.o \ - pcibr_dvr.o pcibr_hints.o \ - pcibr_intr.o pcibr_rrb.o pcibr_slot.o \ - pcibr_error.o +obj-y += pcibr_ate.o pcibr_config.o \ + pcibr_dvr.o pcibr_hints.o \ + pcibr_intr.o pcibr_rrb.o pcibr_slot.o \ + pcibr_error.o include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,23 +27,9 @@ #include #include #include -#include #include #include -#ifdef __ia64 -uint64_t atealloc(struct map *mp, size_t size); -void atefree(struct map *mp, size_t size, uint64_t a); -void atemapfree(struct map *mp); -struct map *atemapalloc(uint64_t mapsiz); - -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc -#endif - - #ifndef LOCAL #define LOCAL static #endif @@ -101,73 +87,26 @@ int i, j; bridgereg_t old_enable, new_enable; int s; - int this_is_pic = is_pic(bridge); /* Probe SSRAM to determine its size. */ - if ( this_is_pic ) { - old_enable = bridge->b_int_enable; - new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; - bridge->b_int_enable = new_enable; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - old_enable = BRIDGE_REG_GET32((&bridge->b_int_enable)); - new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; - BRIDGE_REG_SET32((&bridge->b_int_enable)) = new_enable; - } - else { - old_enable = bridge->b_int_enable; - new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; - bridge->b_int_enable = new_enable; - } - } + old_enable = bridge->b_int_enable; + new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; + bridge->b_int_enable = new_enable; for (i = 1; i < ATE_NUM_SIZES; i++) { /* Try writing a value */ - if ( this_is_pic ) { - bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) - bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = __swab64(ATE_PROBE_VALUE); - else - bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE; - } + bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE; /* Guard against wrap */ for (j = 1; j < i; j++) bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0; /* See if value was written */ - if ( this_is_pic ) { - if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE) + if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE) largest_working_size = i; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == __swab64(ATE_PROBE_VALUE)) - largest_working_size = i; - else { - if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE) - largest_working_size = i; - } - } - } - } - if ( this_is_pic ) { - bridge->b_int_enable = old_enable; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_int_enable)) = old_enable; - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */ - } - else { - bridge->b_int_enable = old_enable; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } } + bridge->b_int_enable = old_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ /* * ensure that we write and read without any interruption. @@ -175,26 +114,10 @@ */ s = splhi(); - if ( this_is_pic ) { - bridge->b_wid_control = (bridge->b_wid_control + bridge->b_wid_control = (bridge->b_wid_control & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size); - bridge->b_wid_control; /* inval addr bug war */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&(bridge->b_wid_control))) = - __swab32((BRIDGE_REG_GET32((&bridge->b_wid_control)) - & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) - | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size)); - BRIDGE_REG_GET32((&bridge->b_wid_control));/* inval addr bug war */ - } - else { - bridge->b_wid_control = (bridge->b_wid_control & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) - | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size); - bridge->b_wid_control; /* inval addr bug war */ - } - } + bridge->b_wid_control; /* inval addr bug war */ splx(s); num_entries = ATE_NUM_ENTRIES(largest_working_size); @@ -229,32 +152,55 @@ int pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count) { - int index = 0; - - index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count); + int status = 0; + struct resource *new_res; + struct resource **allocated_res; + + new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_ATOMIC); + memset(new_res, 0, sizeof(*new_res)); + status = allocate_resource( &pcibr_soft->bs_int_ate_resource, new_res, + count, pcibr_soft->bs_int_ate_resource.start, + pcibr_soft->bs_int_ate_resource.end, 1, + NULL, NULL); + + if ( status && (pcibr_soft->bs_ext_ate_resource.end != 0) ) { + status = allocate_resource( &pcibr_soft->bs_ext_ate_resource, new_res, + count, pcibr_soft->bs_ext_ate_resource.start, + pcibr_soft->bs_ext_ate_resource.end, 1, + NULL, NULL); + if (status) { + new_res->start = -1; + } + } - if (!index && pcibr_soft->bs_ext_ate_map) - index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count); + if (status) { + /* Failed to allocate */ + kfree(new_res); + return -1; + } + + /* Save the resource for freeing */ + allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + new_res->start * sizeof( unsigned long)); + *allocated_res = new_res; - /* rmalloc manages resources in the 1..n - * range, with 0 being failure. - * pcibr_ate_alloc manages resources - * in the 0..n-1 range, with -1 being failure. - */ - return index - 1; + return new_res->start; } void pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count) /* Who says there's no such thing as a free meal? :-) */ { - /* note the "+1" since rmalloc handles 1..n but - * we start counting ATEs at zero. - */ - rmfree((index < pcibr_soft->bs_int_ate_size) - ? pcibr_soft->bs_int_ate_map - : pcibr_soft->bs_ext_ate_map, - count, index + 1); + + struct resource **allocated_res; + int status = 0; + + allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + index * sizeof(unsigned long)); + + status = release_resource(*allocated_res); + if (status) + BUG(); /* Ouch .. */ + kfree(*allocated_res); + } /* @@ -362,7 +308,7 @@ /* Bridge Hardware Bug WAR #484930: * Bridge can't handle updating External ATEs - * while DMA is occuring that uses External ATEs, + * while DMA is occurring that uses External ATEs, * even if the particular ATEs involved are disjoint. */ @@ -423,16 +369,7 @@ /* Flush the write buffer associated with this * PCI device which might be using dma map RAM. */ - if ( is_pic(bridge) ) { - bridge->b_wr_req_buf[slot].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge)) ) { - BRIDGE_REG_GET32((&bridge->b_wr_req_buf[slot].reg)); - } - else - bridge->b_wr_req_buf[slot].reg; - } + bridge->b_wr_req_buf[slot].reg; } } } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -28,21 +28,18 @@ #include #include #include -#include #include #include -extern pcibr_info_t pcibr_info_get(devfs_handle_t); +extern pcibr_info_t pcibr_info_get(vertex_hdl_t); -uint64_t pcibr_config_get(devfs_handle_t, unsigned, unsigned); -uint64_t do_pcibr_config_get(int, cfg_p, unsigned, unsigned); -void pcibr_config_set(devfs_handle_t, unsigned, unsigned, uint64_t); -void do_pcibr_config_set(int, cfg_p, unsigned, unsigned, uint64_t); -static void swap_do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); +uint64_t pcibr_config_get(vertex_hdl_t, unsigned, unsigned); +uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned); +void pcibr_config_set(vertex_hdl_t, unsigned, unsigned, uint64_t); +void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); -#ifdef LITTLE_ENDIAN /* - * on sn-ia we need to twiddle the addresses going out + * on sn-ia we need to twiddle the the addresses going out * the pci bus because we use the unswizzled synergy space * (the alternative is to use the swizzled synergy space * and byte swap the data) @@ -51,18 +48,13 @@ #define CS(b,r) (((volatile uint16_t *) b)[((r^4)/2)]) #define CW(b,r) (((volatile uint32_t *) b)[((r^4)/4)]) -#define CBP(b,r) (((volatile uint8_t *) b)[(r)^3]) -#define CSP(b,r) (((volatile uint16_t *) b)[((r)/2)^1]) +#define CBP(b,r) (((volatile uint8_t *) b)[(r)]) +#define CSP(b,r) (((volatile uint16_t *) b)[((r)/2)]) #define CWP(b,r) (((volatile uint32_t *) b)[(r)/4]) #define SCB(b,r) (((volatile uint8_t *) b)[((r)^3)]) #define SCS(b,r) (((volatile uint16_t *) b)[((r^2)/2)]) #define SCW(b,r) (((volatile uint32_t *) b)[((r)/4)]) -#else -#define CB(b,r) (((volatile uint8_t *) cfgbase)[(r)^3]) -#define CS(b,r) (((volatile uint16_t *) cfgbase)[((r)/2)^1]) -#define CW(b,r) (((volatile uint32_t *) cfgbase)[(r)/4]) -#endif /* * Return a config space address for given slot / func / offset. Note the @@ -84,8 +76,7 @@ /* * Type 0 config space */ - if (is_pic(bridge)) - slot++; + slot++; return &bridge->b_type0_cfg_dev[slot].f[func].l[offset]; } @@ -109,7 +100,7 @@ cfg_p cfg_base; cfg_base = pcibr_slot_config_addr(bridge, slot, 0); - return (do_pcibr_config_get(is_pic(bridge), cfg_base, offset, sizeof(unsigned))); + return (do_pcibr_config_get(cfg_base, offset, sizeof(unsigned))); } /* @@ -122,7 +113,7 @@ cfg_p cfg_base; cfg_base = pcibr_func_config_addr(bridge, 0, slot, func, 0); - return (do_pcibr_config_get(is_pic(bridge), cfg_base, offset, sizeof(unsigned))); + return (do_pcibr_config_get(cfg_base, offset, sizeof(unsigned))); } /* @@ -135,7 +126,7 @@ cfg_p cfg_base; cfg_base = pcibr_slot_config_addr(bridge, slot, 0); - do_pcibr_config_set(is_pic(bridge), cfg_base, offset, sizeof(unsigned), val); + do_pcibr_config_set(cfg_base, offset, sizeof(unsigned), val); } /* @@ -148,13 +139,13 @@ cfg_p cfg_base; cfg_base = pcibr_func_config_addr(bridge, 0, slot, func, 0); - do_pcibr_config_set(is_pic(bridge), cfg_base, offset, sizeof(unsigned), val); + do_pcibr_config_set(cfg_base, offset, sizeof(unsigned), val); } int pcibr_config_debug = 0; cfg_p -pcibr_config_addr(devfs_handle_t conn, +pcibr_config_addr(vertex_hdl_t conn, unsigned reg) { pcibr_info_t pcibr_info; @@ -183,19 +174,6 @@ pciio_func = PCI_TYPE1_FUNC(reg); ASSERT(pciio_bus != 0); -#if 0 - } else if (conn != pciio_info_hostdev_get(pciio_info)) { - /* - * Conn is on a subordinate bus, so get bus/slot/func directly from - * its pciio_info_t structure. - */ - pciio_bus = pciio_info->c_bus; - pciio_slot = pciio_info->c_slot; - pciio_func = pciio_info->c_func; - if (pciio_func == PCIIO_FUNC_NONE) { - pciio_func = 0; - } -#endif } else { /* * Conn is directly connected to the host bus. PCI bus number is @@ -224,44 +202,23 @@ return cfgbase; } -extern unsigned char Is_pic_on_this_nasid[]; uint64_t -pcibr_config_get(devfs_handle_t conn, +pcibr_config_get(vertex_hdl_t conn, unsigned reg, unsigned size) { - if ( !Is_pic_on_this_nasid[ NASID_GET((pcibr_config_addr(conn, reg)))] ) - return do_pcibr_config_get(0, pcibr_config_addr(conn, reg), - PCI_TYPE1_REG(reg), size); - else - return do_pcibr_config_get(1, pcibr_config_addr(conn, reg), + return do_pcibr_config_get(pcibr_config_addr(conn, reg), PCI_TYPE1_REG(reg), size); } uint64_t -do_pcibr_config_get( - int pic, - cfg_p cfgbase, +do_pcibr_config_get(cfg_p cfgbase, unsigned reg, unsigned size) { unsigned value; - if ( pic ) { - value = CWP(cfgbase, reg); - } - else { - if ( io_get_sh_swapper(NASID_GET(cfgbase)) ) { - /* - * Shub Swapper on - 0 returns PCI Offset 0 but byte swapped! - * Do not swizzle address and byte swap the result. - */ - value = SCW(cfgbase, reg); - value = __swab32(value); - } else { - value = CW(cfgbase, reg); - } - } + value = CWP(cfgbase, reg); if (reg & 3) value >>= 8 * (reg & 3); if (size < 4) @@ -270,108 +227,43 @@ } void -pcibr_config_set(devfs_handle_t conn, +pcibr_config_set(vertex_hdl_t conn, unsigned reg, unsigned size, uint64_t value) { - if ( Is_pic_on_this_nasid[ NASID_GET((pcibr_config_addr(conn, reg)))] ) - do_pcibr_config_set(1, pcibr_config_addr(conn, reg), - PCI_TYPE1_REG(reg), size, value); - else - swap_do_pcibr_config_set(pcibr_config_addr(conn, reg), + do_pcibr_config_set(pcibr_config_addr(conn, reg), PCI_TYPE1_REG(reg), size, value); } void -do_pcibr_config_set(int pic, - cfg_p cfgbase, +do_pcibr_config_set(cfg_p cfgbase, unsigned reg, unsigned size, uint64_t value) { - if ( pic ) { - switch (size) { - case 1: + switch (size) { + case 1: + CBP(cfgbase, reg) = value; + break; + case 2: + if (reg & 1) { CBP(cfgbase, reg) = value; - break; - case 2: - if (reg & 1) { - CBP(cfgbase, reg) = value; - CBP(cfgbase, reg + 1) = value >> 8; - } else - CSP(cfgbase, reg) = value; - break; - case 3: - if (reg & 1) { - CBP(cfgbase, reg) = value; - CSP(cfgbase, (reg + 1)) = value >> 8; - } else { - CSP(cfgbase, reg) = value; - CBP(cfgbase, reg + 2) = value >> 16; - } - break; - case 4: - CWP(cfgbase, reg) = value; - break; - } - } - else { - switch (size) { - case 1: - CB(cfgbase, reg) = value; - break; - case 2: - if (reg & 1) { - CB(cfgbase, reg) = value; - CB(cfgbase, reg + 1) = value >> 8; - } else - CS(cfgbase, reg) = value; - break; - case 3: - if (reg & 1) { - CB(cfgbase, reg) = value; - CS(cfgbase, (reg + 1)) = value >> 8; - } else { - CS(cfgbase, reg) = value; - CB(cfgbase, reg + 2) = value >> 16; - } - break; - case 4: - CW(cfgbase, reg) = value; - break; - } - } -} - -void -swap_do_pcibr_config_set(cfg_p cfgbase, - unsigned reg, - unsigned size, - uint64_t value) -{ - - uint64_t temp_value = 0; - - switch (size) { - case 1: - SCB(cfgbase, reg) = value; - break; - case 2: - temp_value = __swab16(value); - if (reg & 1) { - SCB(cfgbase, reg) = temp_value; - SCB(cfgbase, reg + 1) = temp_value >> 8; - } else - SCS(cfgbase, reg) = temp_value; - break; - case 3: - BUG(); - break; - - case 4: - temp_value = __swab32(value); - SCW(cfgbase, reg) = temp_value; - break; - } + CBP(cfgbase, reg + 1) = value >> 8; + } else + CSP(cfgbase, reg) = value; + break; + case 3: + if (reg & 1) { + CBP(cfgbase, reg) = value; + CSP(cfgbase, (reg + 1)) = value >> 8; + } else { + CSP(cfgbase, reg) = value; + CBP(cfgbase, reg + 2) = value >> 16; + } + break; + case 4: + CWP(cfgbase, reg) = value; + break; + } } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Wed Jul 23 18:29:00 2003 @@ -4,13 +4,17 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include #include #include +#include +#include +#include #include +#include #include #include #include @@ -18,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -27,17 +32,9 @@ #include #include #include -#include #include #include -#ifdef __ia64 -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc -#endif - /* * global variables to toggle the different levels of pcibr debugging. * -pcibr_debug_mask is the mask of the different types of debugging @@ -74,32 +71,6 @@ #define USS302_BRIDGE_TIMEOUT_HLD 4 #endif -int pcibr_devflag = D_MP; - -/* - * This is the file operation table for the pcibr driver. - * As each of the functions are implemented, put the - * appropriate function name below. - */ -struct file_operations pcibr_fops = { - owner: THIS_MODULE, - llseek: NULL, - read: NULL, - write: NULL, - readdir: NULL, - poll: NULL, - ioctl: NULL, - mmap: NULL, - open: NULL, - flush: NULL, - release: NULL, - fsync: NULL, - fasync: NULL, - lock: NULL, - readv: NULL, - writev: NULL -}; - /* kbrick widgetnum-to-bus layout */ int p_busnum[MAX_PORT_NUM] = { /* widget# */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ @@ -116,17 +87,16 @@ pcibr_list_p pcibr_list = 0; #endif -extern int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen); -extern int hub_device_flags_set(devfs_handle_t widget_dev, hub_widget_flags_t flags); +extern int hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen); extern long atoi(register char *p); -extern cnodeid_t nodevertex_to_cnodeid(devfs_handle_t vhdl); -extern char *dev_to_name(devfs_handle_t dev, char *buf, uint buflen); +extern cnodeid_t nodevertex_to_cnodeid(vertex_hdl_t vhdl); +extern char *dev_to_name(vertex_hdl_t dev, char *buf, uint buflen); extern struct map *atemapalloc(uint64_t); extern void atefree(struct map *, size_t, uint64_t); extern void atemapfree(struct map *); -extern pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t); +extern pciio_dmamap_t get_free_pciio_dmamap(vertex_hdl_t); extern void free_pciio_dmamap(pcibr_dmamap_t); -extern void xwidget_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t); +extern void xwidget_error_register(vertex_hdl_t, error_handler_f *, error_handler_arg_t); #define ATE_WRITE() ate_write(pcibr_soft, ate_ptr, ate_count, ate) #if PCIBR_FREEZE_TIME @@ -153,9 +123,9 @@ extern int do_pcibr_rrb_free_all(pcibr_soft_t, bridge_t *, pciio_slot_t); extern void do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int, int); -extern int pcibr_wrb_flush(devfs_handle_t); -extern int pcibr_rrb_alloc(devfs_handle_t, int *, int *); -extern void pcibr_rrb_flush(devfs_handle_t); +extern int pcibr_wrb_flush(vertex_hdl_t); +extern int pcibr_rrb_alloc(vertex_hdl_t, int *, int *); +extern void pcibr_rrb_flush(vertex_hdl_t); static int pcibr_try_set_device(pcibr_soft_t, pciio_slot_t, unsigned, bridgereg_t); void pcibr_release_device(pcibr_soft_t, pciio_slot_t, bridgereg_t); @@ -166,21 +136,15 @@ extern iopaddr_t pcibr_bus_addr_alloc(pcibr_soft_t, pciio_win_info_t, pciio_space_t, int, int, int); -void pcibr_init(void); -int pcibr_attach(devfs_handle_t); -int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, +int pcibr_attach(vertex_hdl_t); +int pcibr_attach2(vertex_hdl_t, bridge_t *, vertex_hdl_t, int, pcibr_soft_t *); -int pcibr_detach(devfs_handle_t); -int pcibr_open(devfs_handle_t *, int, int, cred_t *); -int pcibr_close(devfs_handle_t, int, int, cred_t *); -int pcibr_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); -int pcibr_unmap(devfs_handle_t, vhandl_t *); -int pcibr_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); +int pcibr_detach(vertex_hdl_t); int pcibr_pcix_rbars_calc(pcibr_soft_t); extern int pcibr_init_ext_ate_ram(bridge_t *); extern int pcibr_ate_alloc(pcibr_soft_t, int); extern void pcibr_ate_free(pcibr_soft_t, int, int); -extern int pcibr_widget_to_bus(devfs_handle_t pcibr_vhdl); +extern int pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl); extern unsigned ate_freeze(pcibr_dmamap_t pcibr_dmamap, #if PCIBR_FREEZE_TIME @@ -197,45 +161,43 @@ unsigned *cmd_regs, unsigned s); -pcibr_info_t pcibr_info_get(devfs_handle_t); +pcibr_info_t pcibr_info_get(vertex_hdl_t); -static iopaddr_t pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned); +static iopaddr_t pcibr_addr_pci_to_xio(vertex_hdl_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned); -pcibr_piomap_t pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); +pcibr_piomap_t pcibr_piomap_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); void pcibr_piomap_free(pcibr_piomap_t); caddr_t pcibr_piomap_addr(pcibr_piomap_t, iopaddr_t, size_t); void pcibr_piomap_done(pcibr_piomap_t); -caddr_t pcibr_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); -iopaddr_t pcibr_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); -void pcibr_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); +caddr_t pcibr_piotrans_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +iopaddr_t pcibr_piospace_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, size_t, size_t); +void pcibr_piospace_free(vertex_hdl_t, pciio_space_t, iopaddr_t, size_t); static iopaddr_t pcibr_flags_to_d64(unsigned, pcibr_soft_t); extern bridge_ate_t pcibr_flags_to_ate(unsigned); -pcibr_dmamap_t pcibr_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +pcibr_dmamap_t pcibr_dmamap_alloc(vertex_hdl_t, device_desc_t, size_t, unsigned); void pcibr_dmamap_free(pcibr_dmamap_t); extern bridge_ate_p pcibr_ate_addr(pcibr_soft_t, int); static iopaddr_t pcibr_addr_xio_to_pci(pcibr_soft_t, iopaddr_t, size_t); iopaddr_t pcibr_dmamap_addr(pcibr_dmamap_t, paddr_t, size_t); -alenlist_t pcibr_dmamap_list(pcibr_dmamap_t, alenlist_t, unsigned); void pcibr_dmamap_done(pcibr_dmamap_t); -cnodeid_t pcibr_get_dmatrans_node(devfs_handle_t); -iopaddr_t pcibr_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); -alenlist_t pcibr_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +cnodeid_t pcibr_get_dmatrans_node(vertex_hdl_t); +iopaddr_t pcibr_dmatrans_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, unsigned); void pcibr_dmamap_drain(pcibr_dmamap_t); -void pcibr_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); -void pcibr_dmalist_drain(devfs_handle_t, alenlist_t); +void pcibr_dmaaddr_drain(vertex_hdl_t, paddr_t, size_t); +void pcibr_dmalist_drain(vertex_hdl_t, alenlist_t); iopaddr_t pcibr_dmamap_pciaddr_get(pcibr_dmamap_t); extern unsigned pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines, int nslots); -extern pcibr_intr_t pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +extern pcibr_intr_t pcibr_intr_alloc(vertex_hdl_t, device_desc_t, pciio_intr_line_t, vertex_hdl_t); extern void pcibr_intr_free(pcibr_intr_t); extern void pcibr_setpciint(xtalk_intr_t); extern int pcibr_intr_connect(pcibr_intr_t, intr_func_t, intr_arg_t); extern void pcibr_intr_disconnect(pcibr_intr_t); -extern devfs_handle_t pcibr_intr_cpu_get(pcibr_intr_t); +extern vertex_hdl_t pcibr_intr_cpu_get(pcibr_intr_t); extern void pcibr_intr_func(intr_arg_t); extern void print_bridge_errcmd(uint32_t, char *); @@ -253,51 +215,48 @@ extern int pcibr_dmawr_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *); extern int pcibr_error_handler(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *); extern int pcibr_error_handler_wrapper(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *); -void pcibr_provider_startup(devfs_handle_t); -void pcibr_provider_shutdown(devfs_handle_t); +void pcibr_provider_startup(vertex_hdl_t); +void pcibr_provider_shutdown(vertex_hdl_t); -int pcibr_reset(devfs_handle_t); -pciio_endian_t pcibr_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); +int pcibr_reset(vertex_hdl_t); +pciio_endian_t pcibr_endian_set(vertex_hdl_t, pciio_endian_t, pciio_endian_t); int pcibr_priority_bits_set(pcibr_soft_t, pciio_slot_t, pciio_priority_t); -pciio_priority_t pcibr_priority_set(devfs_handle_t, pciio_priority_t); -int pcibr_device_flags_set(devfs_handle_t, pcibr_device_flags_t); +pciio_priority_t pcibr_priority_set(vertex_hdl_t, pciio_priority_t); +int pcibr_device_flags_set(vertex_hdl_t, pcibr_device_flags_t); + +extern cfg_p pcibr_config_addr(vertex_hdl_t, unsigned); +extern uint64_t pcibr_config_get(vertex_hdl_t, unsigned, unsigned); +extern void pcibr_config_set(vertex_hdl_t, unsigned, unsigned, uint64_t); + +extern pcibr_hints_t pcibr_hints_get(vertex_hdl_t, int); +extern void pcibr_hints_fix_rrbs(vertex_hdl_t); +extern void pcibr_hints_dualslot(vertex_hdl_t, pciio_slot_t, pciio_slot_t); +extern void pcibr_hints_intr_bits(vertex_hdl_t, pcibr_intr_bits_f *); +extern void pcibr_set_rrb_callback(vertex_hdl_t, rrb_alloc_funct_t); +extern void pcibr_hints_handsoff(vertex_hdl_t); +extern void pcibr_hints_subdevs(vertex_hdl_t, pciio_slot_t, uint64_t); -extern cfg_p pcibr_config_addr(devfs_handle_t, unsigned); -extern uint64_t pcibr_config_get(devfs_handle_t, unsigned, unsigned); -extern void pcibr_config_set(devfs_handle_t, unsigned, unsigned, uint64_t); - -extern pcibr_hints_t pcibr_hints_get(devfs_handle_t, int); -extern void pcibr_hints_fix_rrbs(devfs_handle_t); -extern void pcibr_hints_dualslot(devfs_handle_t, pciio_slot_t, pciio_slot_t); -extern void pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *); -extern void pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t); -extern void pcibr_hints_handsoff(devfs_handle_t); -extern void pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t); - -extern int pcibr_slot_reset(devfs_handle_t,pciio_slot_t); -extern int pcibr_slot_info_init(devfs_handle_t,pciio_slot_t); -extern int pcibr_slot_info_free(devfs_handle_t,pciio_slot_t); +extern int pcibr_slot_info_init(vertex_hdl_t,pciio_slot_t); +extern int pcibr_slot_info_free(vertex_hdl_t,pciio_slot_t); extern int pcibr_slot_info_return(pcibr_soft_t, pciio_slot_t, pcibr_slot_info_resp_t); extern void pcibr_slot_func_info_return(pcibr_info_h, int, pcibr_slot_func_info_resp_t); -extern int pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t); +extern int pcibr_slot_addr_space_init(vertex_hdl_t,pciio_slot_t); extern int pcibr_slot_pcix_rbar_init(pcibr_soft_t, pciio_slot_t); -extern int pcibr_slot_device_init(devfs_handle_t, pciio_slot_t); -extern int pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t); -extern int pcibr_slot_call_device_attach(devfs_handle_t, +extern int pcibr_slot_device_init(vertex_hdl_t, pciio_slot_t); +extern int pcibr_slot_guest_info_init(vertex_hdl_t,pciio_slot_t); +extern int pcibr_slot_call_device_attach(vertex_hdl_t, pciio_slot_t, int); -extern int pcibr_slot_call_device_detach(devfs_handle_t, +extern int pcibr_slot_call_device_detach(vertex_hdl_t, pciio_slot_t, int); -extern int pcibr_slot_attach(devfs_handle_t, pciio_slot_t, int, +extern int pcibr_slot_attach(vertex_hdl_t, pciio_slot_t, int, char *, int *); -extern int pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int, +extern int pcibr_slot_detach(vertex_hdl_t, pciio_slot_t, int, char *, int *); -extern int pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t); - -extern int pcibr_slot_initial_rrb_alloc(devfs_handle_t, pciio_slot_t); -extern int pcibr_initial_rrb(devfs_handle_t, pciio_slot_t, pciio_slot_t); +extern int pcibr_slot_initial_rrb_alloc(vertex_hdl_t, pciio_slot_t); +extern int pcibr_initial_rrb(vertex_hdl_t, pciio_slot_t, pciio_slot_t); /* ===================================================================== * Device(x) register management @@ -623,172 +582,52 @@ */ -/* - * pcibr_init: called once during system startup or - * when a loadable driver is loaded. - * - * The driver_register function should normally - * be in _reg, not _init. But the pcibr driver is - * required by devinit before the _reg routines - * are called, so this is an exception. - */ -void -pcibr_init(void) +static int +pcibr_mmap(struct file * file, struct vm_area_struct * vma) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pcibr_init()\n")); + vertex_hdl_t pcibr_vhdl; + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + unsigned long phys_addr; + int error = 0; - xwidget_driver_register(XBRIDGE_WIDGET_PART_NUM, - XBRIDGE_WIDGET_MFGR_NUM, - "pcibr_", - 0); - xwidget_driver_register(BRIDGE_WIDGET_PART_NUM, - BRIDGE_WIDGET_MFGR_NUM, - "pcibr_", - 0); +#ifdef CONFIG_HWGFS_FS + pcibr_vhdl = (vertex_hdl_t) file->f_dentry->d_fsdata; +#else + pcibr_vhdl = (vertex_hdl_t) file->private_data; +#endif + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge = pcibr_soft->bs_base; + phys_addr = (unsigned long)bridge & ~0xc000000000000000; /* Mask out the Uncache bits */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO; + error = io_remap_page_range(vma->vm_start, phys_addr, + vma->vm_end-vma->vm_start, + vma->vm_page_prot); + return(error); } /* - * open/close mmap/munmap interface would be used by processes - * that plan to map the PCI bridge, and muck around with the - * registers. This is dangerous to do, and will be allowed - * to a select brand of programs. Typically these are - * diagnostics programs, or some user level commands we may - * write to do some weird things. - * To start with expect them to have root priveleges. - * We will ask for more later. + * This is the file operation table for the pcibr driver. + * As each of the functions are implemented, put the + * appropriate function name below. */ -/* ARGSUSED */ -int -pcibr_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) -{ - return 0; -} - -/*ARGSUSED */ -int -pcibr_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) -{ - return 0; -} - -/*ARGSUSED */ -int -pcibr_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) -{ - int error; - devfs_handle_t vhdl = dev_to_vhdl(dev); - devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get(vhdl); - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - bridge_t *bridge = pcibr_soft->bs_base; - - hwgraph_vertex_unref(pcibr_vhdl); - - ASSERT(pcibr_soft); - len = ctob(btoc(len)); /* Make len page aligned */ - error = v_mapphys(vt, (void *) ((__psunsigned_t) bridge + off), len); - - /* - * If the offset being mapped corresponds to the flash prom - * base, and if the mapping succeeds, and if the user - * has requested the protections to be WRITE, enable the - * flash prom to be written. - * - * XXX- deprecate this in favor of using the - * real flash driver ... - */ - if (IS_BRIDGE_SOFT(pcibr_soft) && !error && - ((off == BRIDGE_EXTERNAL_FLASH) || - (len > BRIDGE_EXTERNAL_FLASH))) { - int s; - - /* - * ensure that we write and read without any interruption. - * The read following the write is required for the Bridge war - */ - s = splhi(); - - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_wid_control)) |= __swab32(BRIDGE_CTRL_FLASH_WR_EN); - BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */ - } else { - bridge->b_wid_control |= BRIDGE_CTRL_FLASH_WR_EN; - bridge->b_wid_control; /* inval addr bug war */ - } - splx(s); - } - return error; -} - -/*ARGSUSED */ -int -pcibr_unmap(devfs_handle_t dev, vhandl_t *vt) -{ - devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t) dev); - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - bridge_t *bridge = pcibr_soft->bs_base; - - hwgraph_vertex_unref(pcibr_vhdl); - - if ( IS_PIC_SOFT(pcibr_soft) ) { - /* - * If flashprom write was enabled, disable it, as - * this is the last unmap. - */ - if (IS_BRIDGE_SOFT(pcibr_soft) && - (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN)) { - int s; - - /* - * ensure that we write and read without any interruption. - * The read following the write is required for the Bridge war - */ - s = splhi(); - bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN; - bridge->b_wid_control; /* inval addr bug war */ - splx(s); - } - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - if (BRIDGE_REG_GET32((&bridge->b_wid_control)) & BRIDGE_CTRL_FLASH_WR_EN) { - int s; - - /* - * ensure that we write and read without any interruption. - * The read following the write is required for the Bridge war - */ - s = splhi(); - BRIDGE_REG_SET32((&bridge->b_wid_control)) &= __swab32((unsigned int)~BRIDGE_CTRL_FLASH_WR_EN); - BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */ - splx(s); - } else { - if (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN) { - int s; +static int pcibr_mmap(struct file * file, struct vm_area_struct * vma); +struct file_operations pcibr_fops = { + .owner = THIS_MODULE, + .mmap = pcibr_mmap, +}; - /* - * ensure that we write and read without any interruption. - * The read following the write is required for the Bridge war - */ - s = splhi(); - bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN; - bridge->b_wid_control; /* inval addr bug war */ - splx(s); - } - } - } - } - return 0; -} /* This is special case code used by grio. There are plans to make * this a bit more general in the future, but till then this should * be sufficient. */ pciio_slot_t -pcibr_device_slot_get(devfs_handle_t dev_vhdl) +pcibr_device_slot_get(vertex_hdl_t dev_vhdl) { char devname[MAXDEVNAME]; - devfs_handle_t tdev; + vertex_hdl_t tdev; pciio_info_t pciio_info; pciio_slot_t slot = PCIIO_SLOT_NONE; @@ -812,20 +651,8 @@ return slot; } -/*ARGSUSED */ -int -pcibr_ioctl(devfs_handle_t dev, - int cmd, - void *arg, - int flag, - struct cred *cr, - int *rvalp) -{ - return 0; -} - pcibr_info_t -pcibr_info_get(devfs_handle_t vhdl) +pcibr_info_get(vertex_hdl_t vhdl) { return (pcibr_info_t) pciio_info_get(vhdl); } @@ -849,7 +676,7 @@ * will set the c_slot (which is suppose to represent the external * slot (i.e the slot number silk screened on the back of the I/O * brick)). So for PIC we need to adjust this "internal slot" num - * passed into us, into it's external representation. See comment + * passed into us, into its external representation. See comment * for the PCIBR_DEVICE_TO_SLOT macro for more information. */ NEW(pcibr_info); @@ -902,10 +729,10 @@ * This is usually used at the time of shutting down of the PCI card. */ int -pcibr_device_unregister(devfs_handle_t pconn_vhdl) +pcibr_device_unregister(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info; - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; bridge_t *bridge; @@ -982,12 +809,12 @@ * slot's device status to be set. */ void -pcibr_driver_reg_callback(devfs_handle_t pconn_vhdl, +pcibr_driver_reg_callback(vertex_hdl_t pconn_vhdl, int key1, int key2, int error) { pciio_info_t pciio_info; pcibr_info_t pcibr_info; - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; @@ -1033,12 +860,12 @@ * slot's device status to be set. */ void -pcibr_driver_unreg_callback(devfs_handle_t pconn_vhdl, +pcibr_driver_unreg_callback(vertex_hdl_t pconn_vhdl, int key1, int key2, int error) { pciio_info_t pciio_info; pcibr_info_t pcibr_info; - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; @@ -1084,14 +911,14 @@ * depends on hwgraph separator == '/' */ int -pcibr_bus_cnvlink(devfs_handle_t f_c) +pcibr_bus_cnvlink(vertex_hdl_t f_c) { char dst[MAXDEVNAME]; char *dp = dst; char *cp, *xp; int widgetnum; char pcibus[8]; - devfs_handle_t nvtx, svtx; + vertex_hdl_t nvtx, svtx; int rv; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n")); @@ -1105,7 +932,7 @@ xp = strstr(dst, "/"EDGE_LBL_XTALK"/"); if (xp == NULL) return 0; - widgetnum = atoi(xp+7); + widgetnum = simple_strtoul(xp+7, NULL, 0); if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) return 0; @@ -1145,11 +972,11 @@ */ /*ARGSUSED */ int -pcibr_attach(devfs_handle_t xconn_vhdl) +pcibr_attach(vertex_hdl_t xconn_vhdl) { /* REFERENCED */ graph_error_t rc; - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; bridge_t *bridge; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, xconn_vhdl, "pcibr_attach\n")); @@ -1180,11 +1007,11 @@ /*ARGSUSED */ int -pcibr_attach2(devfs_handle_t xconn_vhdl, bridge_t *bridge, - devfs_handle_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp) +pcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge, + vertex_hdl_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp) { /* REFERENCED */ - devfs_handle_t ctlr_vhdl; + vertex_hdl_t ctlr_vhdl; bridgereg_t id; int rev; pcibr_soft_t pcibr_soft; @@ -1193,7 +1020,7 @@ xtalk_intr_t xtalk_intr; int slot; int ibit; - devfs_handle_t noslot_conn; + vertex_hdl_t noslot_conn; char devnm[MAXDEVNAME], *s; pcibr_hints_t pcibr_hints; uint64_t int_enable; @@ -1209,23 +1036,15 @@ nasid_t nasid; int iobrick_type_get_nasid(nasid_t nasid); int iobrick_module_get_nasid(nasid_t nasid); - extern unsigned char Is_pic_on_this_nasid[512]; - - - async_attach_t aa = NULL; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum)); - aa = async_attach_get_info(xconn_vhdl); - ctlr_vhdl = NULL; - ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER, - 0, DEVFS_FL_AUTO_DEVNUM, - 0, 0, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, - &pcibr_fops, NULL); - + ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER, 0, + DEVFS_FL_AUTO_DEVNUM, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + (struct file_operations *)&pcibr_fops, (void *)pcibr_vhdl); ASSERT(ctlr_vhdl != NULL); /* @@ -1261,13 +1080,7 @@ pcibr_soft->bs_min_slot = 0; /* lowest possible slot# */ pcibr_soft->bs_max_slot = 7; /* highest possible slot# */ pcibr_soft->bs_busnum = busnum; - if (is_xbridge(bridge)) { - pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_XBRIDGE; - } else if (is_pic(bridge)) { - pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC; - } else { - pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_BRIDGE; - } + pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC; switch(pcibr_soft->bs_bridge_type) { case PCIBR_BRIDGETYPE_BRIDGE: pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES; @@ -1367,10 +1180,6 @@ nasid = NASID_GET(bridge); - /* set whether it is a PIC or not */ - Is_pic_on_this_nasid[nasid] = (IS_PIC_SOFT(pcibr_soft)) ? 1 : 0; - - if ((pcibr_soft->bs_bricktype = iobrick_type_get_nasid(nasid)) < 0) printk(KERN_WARNING "0x%p: Unknown bricktype : 0x%x\n", (void *)xconn_vhdl, (unsigned int)pcibr_soft->bs_bricktype); @@ -1380,11 +1189,27 @@ if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { case MODULE_PXBRICK: + case MODULE_IXBRICK: pcibr_soft->bs_first_slot = 0; pcibr_soft->bs_last_slot = 1; pcibr_soft->bs_last_reset = 1; + + /* If Bus 1 has IO9 then there are 4 devices in that bus. Note + * we figure this out from klconfig since the kernel has yet to + * probe + */ + if (pcibr_widget_to_bus(pcibr_vhdl) == 1) { + lboard_t *brd = (lboard_t *)KL_CONFIG_INFO(nasid); + + while (brd) { + if (brd->brd_flags & LOCAL_MASTER_IO6) { + pcibr_soft->bs_last_slot = 3; + pcibr_soft->bs_last_reset = 3; + } + brd = KLCF_NEXT(brd); + } + } break; - case MODULE_PEBRICK: case MODULE_PBRICK: pcibr_soft->bs_first_slot = 1; pcibr_soft->bs_last_slot = 2; @@ -1559,11 +1384,6 @@ int entry; cnodeid_t cnodeid; nasid_t nasid; -#ifdef PIC_LATER - char *node_val; - devfs_handle_t node_vhdl; - char vname[MAXDEVNAME]; -#endif /* Set the Bridge's 32-bit PCI to XTalk * Direct Map register to the most useful @@ -1582,30 +1402,6 @@ */ cnodeid = 0; /* default node id */ - /* - * Determine the base address node id to be used for all 32-bit - * Direct Mapping I/O. The default is node 0, but this can be changed - * via a DEVICE_ADMIN directive and the PCIBUS_DMATRANS_NODE - * attribute in the irix.sm config file. A device driver can obtain - * this node value via a call to pcibr_get_dmatrans_node(). - */ -#ifdef PIC_LATER -// This probably needs to be addressed - pfg - node_val = device_admin_info_get(pcibr_vhdl, ADMIN_LBL_DMATRANS_NODE); - if (node_val != NULL) { - node_vhdl = hwgraph_path_to_vertex(node_val); - if (node_vhdl != GRAPH_VERTEX_NONE) { - cnodeid = nodevertex_to_cnodeid(node_vhdl); - } - if ((node_vhdl == GRAPH_VERTEX_NONE) || (cnodeid == CNODEID_NONE)) { - cnodeid = 0; - vertex_to_name(pcibr_vhdl, vname, sizeof(vname)); - printk(KERN_WARNING "Invalid hwgraph node path specified:\n" - " DEVICE_ADMIN: %s %s=%s\n", - vname, ADMIN_LBL_DMATRANS_NODE, node_val); - } - } -#endif /* PIC_LATER */ nasid = COMPACT_TO_NASID_NODEID(cnodeid); paddr = NODE_OFFSET(nasid) + 0; @@ -1697,18 +1493,21 @@ /* we always have 128 ATEs (512 for Xbridge) inside the chip * even if disabled for debugging. */ - pcibr_soft->bs_int_ate_map = rmallocmap(pcibr_soft->bs_int_ate_size); - pcibr_ate_free(pcibr_soft, 0, pcibr_soft->bs_int_ate_size); + pcibr_soft->bs_int_ate_resource.start = 0; + pcibr_soft->bs_int_ate_resource.end = pcibr_soft->bs_int_ate_size - 1; if (num_entries > pcibr_soft->bs_int_ate_size) { #if PCIBR_ATE_NOTBOTH /* for debug -- forces us to use external ates */ printk("pcibr_attach: disabling internal ATEs.\n"); pcibr_ate_alloc(pcibr_soft, pcibr_soft->bs_int_ate_size); #endif - pcibr_soft->bs_ext_ate_map = rmallocmap(num_entries); - pcibr_ate_free(pcibr_soft, pcibr_soft->bs_int_ate_size, - num_entries - pcibr_soft->bs_int_ate_size); + pcibr_soft->bs_ext_ate_resource.start = pcibr_soft->bs_int_ate_size; + pcibr_soft->bs_ext_ate_resource.end = num_entries; } + + pcibr_soft->bs_allocated_ate_res = (void *) kmalloc(pcibr_soft->bs_int_ate_size * sizeof(unsigned long), GFP_KERNEL); + memset(pcibr_soft->bs_allocated_ate_res, 0x0, pcibr_soft->bs_int_ate_size * sizeof(unsigned long)); + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_vhdl, "pcibr_attach2: %d ATEs, %d internal & %d external\n", num_entries ? num_entries : pcibr_soft->bs_int_ate_size, @@ -1763,6 +1562,13 @@ */ xtalk_intr = xtalk_intr_alloc(xconn_vhdl, (device_desc_t)0, pcibr_vhdl); + { + int irq = ((hub_intr_t)xtalk_intr)->i_bit; + int cpu = ((hub_intr_t)xtalk_intr)->i_cpuid; + + intr_unreserve_level(cpu, irq); + ((hub_intr_t)xtalk_intr)->i_bit = SGI_PCIBR_ERROR; + } ASSERT(xtalk_intr != NULL); pcibr_soft->bsi_err_intr = xtalk_intr; @@ -1778,12 +1584,8 @@ xtalk_intr_connect(xtalk_intr, (intr_func_t) pcibr_error_intr_handler, (intr_arg_t) pcibr_soft, (xtalk_intr_setfunc_t)pcibr_setwidint, (void *)bridge); -#ifdef BUS_INT_WAR_NOT_YET - request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid, - ((hub_intr_t)xtalk_intr)->i_bit), - (intr_func_t)pcibr_error_intr_handler, 0, "PCIBR error", + request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, "PCIBR error", (intr_arg_t) pcibr_soft); -#endif PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_vhdl, "pcibr_setwidint: b_wid_int_upper=0x%x, b_wid_int_lower=0x%x\n", @@ -1801,18 +1603,16 @@ if (IS_PIC_SOFT(pcibr_soft)) { int_enable_64 = bridge->p_int_enable_64 | BRIDGE_ISR_ERRORS; int_enable = (uint64_t)int_enable_64; +#ifdef PFG_TEST + int_enable = (uint64_t)0x7ffffeff7ffffeff; +#endif } else { int_enable_32 = bridge->b_int_enable | (BRIDGE_ISR_ERRORS & 0xffffffff); int_enable = ((uint64_t)int_enable_32 & 0xffffffff); - } -#ifdef BUS_INT_WAR_NOT_YET - { - extern void sn_add_polled_interrupt(int irq, int interval); - - sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid, - ((hub_intr_t)xtalk_intr)->i_bit), 20000); - } +#ifdef PFG_TEST + int_enable = (uint64_t)0x7ffffeff; #endif + } #if BRIDGE_ERROR_INTR_WAR @@ -1849,24 +1649,6 @@ } #endif -#ifdef BRIDGE_B_DATACORR_WAR - - /* WAR panic for Rev B silent data corruption. - * PIOERR turned off here because there is a problem - * with not re-arming it in pcibr_error_intr_handler. - * We don't get LLP error interrupts if we don't - * re-arm PIOERR interrupts! Just disable them here - */ - - if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_B) { - int_enable |= BRIDGE_IMR_LLP_REC_CBERR; - int_enable &= ~BRIDGE_ISR_PCIBUS_PIOERR; - - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, - "Turning on LLP_REC_CBERR for Rev B Bridge.\n")); - } -#endif - /* PIC BRINGUP WAR (PV# 856864 & 856865): allow the tnums that are * locked out to be freed up sooner (by timing out) so that the * read tnums are never completely used up. @@ -1918,16 +1700,12 @@ if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_B) pcibr_soft->bs_dma_flags |= PCIBR_NOPREFETCH; else if (pcibr_soft->bs_rev_num < - (BRIDGE_WIDGET_PART_NUM << 4 | pcibr_prefetch_enable_rev)) + (BRIDGE_WIDGET_PART_NUM << 4)) pcibr_soft->bs_dma_flags |= PCIIO_NOPREFETCH; - /* WRITE_GATHER: - * Disabled up to but not including the - * rev number in pcibr_wg_enable_rev. There - * is no "WAR range" as with prefetch. - */ + /* WRITE_GATHER: Disabled */ if (pcibr_soft->bs_rev_num < - (BRIDGE_WIDGET_PART_NUM << 4 | pcibr_wg_enable_rev)) + (BRIDGE_WIDGET_PART_NUM << 4)) pcibr_soft->bs_dma_flags |= PCIBR_NOWRITE_GATHER; /* PIC only supports 64-bit direct mapping in PCI-X mode. Since @@ -1940,10 +1718,10 @@ { - pciio_win_map_t win_map_p; iopaddr_t prom_base_addr = pcibr_soft->bs_xid << 24; int prom_base_size = 0x1000000; - iopaddr_t prom_base_limit = prom_base_addr + prom_base_size; + int status; + struct resource *res; /* Allocate resource maps based on bus page size; for I/O and memory * space, free all pages except those in the base area and in the @@ -1953,35 +1731,38 @@ * the widget number and s is the device register offset for the slot. */ - win_map_p = &pcibr_soft->bs_io_win_map; - pciio_device_win_map_new(win_map_p, - PCIBR_BUS_IO_MAX + 1, - PCIBR_BUS_IO_PAGE); - pciio_device_win_populate(win_map_p, - PCIBR_BUS_IO_BASE, - prom_base_addr - PCIBR_BUS_IO_BASE); - pciio_device_win_populate(win_map_p, - prom_base_limit, - (PCIBR_BUS_IO_MAX + 1) - prom_base_limit); - - win_map_p = &pcibr_soft->bs_swin_map; - pciio_device_win_map_new(win_map_p, - PCIBR_BUS_SWIN_MAX + 1, - PCIBR_BUS_SWIN_PAGE); - pciio_device_win_populate(win_map_p, - PCIBR_BUS_SWIN_BASE, - (PCIBR_BUS_SWIN_MAX + 1) - PCIBR_BUS_SWIN_PAGE); - - win_map_p = &pcibr_soft->bs_mem_win_map; - pciio_device_win_map_new(win_map_p, - PCIBR_BUS_MEM_MAX + 1, - PCIBR_BUS_MEM_PAGE); - pciio_device_win_populate(win_map_p, - PCIBR_BUS_MEM_BASE, - prom_base_addr - PCIBR_BUS_MEM_BASE); - pciio_device_win_populate(win_map_p, - prom_base_limit, - (PCIBR_BUS_MEM_MAX + 1) - prom_base_limit); + /* Setup the Bus's PCI IO Root Resource. */ + pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE; + pcibr_soft->bs_io_win_root_resource.end = 0xffffffff; + res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); + if (!res) + panic("PCIBR:Unable to allocate resource structure\n"); + + /* Block off the range used by PROM. */ + res->start = prom_base_addr; + res->end = prom_base_addr + (prom_base_size - 1); + status = request_resource(&pcibr_soft->bs_io_win_root_resource, res); + if (status) + panic("PCIBR:Unable to request_resource()\n"); + + /* Setup the Small Window Root Resource */ + pcibr_soft->bs_swin_root_resource.start = _PAGESZ; + pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF; + + /* Setup the Bus's PCI Memory Root Resource */ + pcibr_soft->bs_mem_win_root_resource.start = 0x200000; + pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff; + res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); + if (!res) + panic("PCIBR:Unable to allocate resource structure\n"); + + /* Block off the range used by PROM. */ + res->start = prom_base_addr; + res->end = prom_base_addr + (prom_base_size - 1);; + status = request_resource(&pcibr_soft->bs_mem_win_root_resource, res); + if (status) + panic("PCIBR:Unable to request_resource()\n"); + } /* build "no-slot" connection point @@ -2064,7 +1845,23 @@ */ if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { + case MODULE_PBRICK: + do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8); + do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8); + break; + case MODULE_IBRICK: + /* port 0xe on the Ibrick only has slots 1 and 2 */ + if (pcibr_soft->bs_xid == 0xe) { + do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8); + do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8); + } + else { + /* allocate one RRB for the serial port */ + do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 1); + } + break; case MODULE_PXBRICK: + case MODULE_IXBRICK: /* * If the IO9 is in the PXBrick (bus1, slot1) allocate * RRBs to all the devices @@ -2080,23 +1877,6 @@ do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 8); do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8); } - - break; - case MODULE_PEBRICK: - case MODULE_PBRICK: - do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8); - do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8); - break; - case MODULE_IBRICK: - /* port 0xe on the Ibrick only has slots 1 and 2 */ - if (pcibr_soft->bs_xid == 0xe) { - do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8); - do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8); - } - else { - /* allocate one RRB for the serial port */ - do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 1); - } break; } /* switch */ } @@ -2113,78 +1893,8 @@ /* Call the device attach */ (void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0); -#ifdef PIC_LATER -#if (defined(USS302_TIMEOUT_WAR)) - /* - * If this bridge holds a Lucent USS-302 or USS-312 pci/usb controller, - * increase the Bridge PCI retry backoff interval. This part seems - * to go away for long periods of time if a DAC appears on the bus during - * a read command that is being retried. - */ - -{ - ii_ixtt_u_t ixtt; - - for (slot = pcibr_soft->bs_min_slot; - slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { - if (pcibr_soft->bs_slot[slot].bss_vendor_id == - LUCENT_USBHC_VENDOR_ID_NUM && - (pcibr_soft->bs_slot[slot].bss_device_id == - LUCENT_USBHC302_DEVICE_ID_NUM || - pcibr_soft->bs_slot[slot].bss_device_id == - LUCENT_USBHC312_DEVICE_ID_NUM)) { - printk(KERN_NOTICE - "pcibr_attach: %x Bus holds a usb part - setting" - "bridge PCI_RETRY_HLD to %d\n", - pcibr_vhdl, USS302_BRIDGE_TIMEOUT_HLD); - - bridge->b_bus_timeout &= ~BRIDGE_BUS_PCI_RETRY_HLD_MASK; - bridge->b_bus_timeout |= - BRIDGE_BUS_PCI_RETRY_HLD(USS302_BRIDGE_TIMEOUT_HLD); - - /* - * Have to consider the read response timer in the hub II as well - */ - - hubii_ixtt_get(xconn_vhdl, &ixtt); - - /* - * bump rrsp_ps to allow at least 1ms for read - * responses from this widget - */ - - ixtt.ii_ixtt_fld_s.i_rrsp_ps = 20000; - hubii_ixtt_set(xconn_vhdl, &ixtt); - - /* - * print the current setting - */ - - hubii_ixtt_get(xconn_vhdl, &ixtt); - printk( "Setting hub ixtt.rrsp_ps field to 0x%x\n", - ixtt.ii_ixtt_fld_s.i_rrsp_ps); - - break; /* only need to do it once */ - } - } -} -#endif /* (defined(USS302_TIMEOUT_WAR)) */ -#else - FIXME("pcibr_attach: Call do_pcibr_rrb_autoalloc nicinfo\n"); -#endif /* PIC_LATER */ - - if (aa) - async_attach_add_info(noslot_conn, aa); - pciio_device_attach(noslot_conn, (int)0); - /* - * Tear down pointer to async attach info -- async threads for - * bridge's descendants may be running but the bridge's work is done. - */ - if (aa) - async_attach_del_info(xconn_vhdl); - return 0; } @@ -2195,10 +1905,10 @@ */ int -pcibr_detach(devfs_handle_t xconn) +pcibr_detach(vertex_hdl_t xconn) { pciio_slot_t slot; - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; pcibr_soft_t pcibr_soft; bridge_t *bridge; unsigned s; @@ -2235,15 +1945,6 @@ spin_lock_destroy(&pcibr_soft->bs_lock); kfree(pcibr_soft->bs_name); - /* Error handler gets unregistered when the widget info is - * cleaned - */ - /* Free the soft ATE maps */ - if (pcibr_soft->bs_int_ate_map) - rmfreemap(pcibr_soft->bs_int_ate_map); - if (pcibr_soft->bs_ext_ate_map) - rmfreemap(pcibr_soft->bs_ext_ate_map); - /* Disconnect the error interrupt and free the xtalk resources * associated with it. */ @@ -2265,9 +1966,9 @@ } int -pcibr_asic_rev(devfs_handle_t pconn_vhdl) +pcibr_asic_rev(vertex_hdl_t pconn_vhdl) { - devfs_handle_t pcibr_vhdl; + vertex_hdl_t pcibr_vhdl; int tmp_vhdl; arbitrary_info_t ainfo; @@ -2294,7 +1995,7 @@ } int -pcibr_write_gather_flush(devfs_handle_t pconn_vhdl) +pcibr_write_gather_flush(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); @@ -2309,7 +2010,7 @@ */ static iopaddr_t -pcibr_addr_pci_to_xio(devfs_handle_t pconn_vhdl, +pcibr_addr_pci_to_xio(vertex_hdl_t pconn_vhdl, pciio_slot_t slot, pciio_space_t space, iopaddr_t pci_addr, @@ -2323,6 +2024,8 @@ unsigned bar; /* which BASE reg on device is decoding */ iopaddr_t xio_addr = XIO_NOWHERE; + iopaddr_t base; /* base of devio(x) mapped area on PCI */ + iopaddr_t limit; /* base of devio(x) mapped area on PCI */ pciio_space_t wspace; /* which space device is decoding */ iopaddr_t wbase; /* base of device decode on PCI */ @@ -2533,8 +2236,6 @@ PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pconn_vhdl, "pcibr_addr_pci_to_xio: Device(%d): %x\n", win, devreg, device_bits)); -#else - printk("pcibr_addr_pci_to_xio: Device(%d): %x\n", win, devreg); #endif } pcibr_soft->bs_slot[win].bss_devio.bssd_space = space; @@ -2620,18 +2321,46 @@ */ case PCIIO_SPACE_MEM: /* "mem space" */ case PCIIO_SPACE_MEM32: /* "mem, use 32-bit-wide bus" */ - if ((pci_addr + BRIDGE_PCI_MEM32_BASE + req_size - 1) <= - BRIDGE_PCI_MEM32_LIMIT) - xio_addr = pci_addr + BRIDGE_PCI_MEM32_BASE; + if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 0)) { /* PIC bus 0 */ + base = PICBRIDGE0_PCI_MEM32_BASE; + limit = PICBRIDGE0_PCI_MEM32_LIMIT; + } else if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 1)) { /* PIC bus 1 */ + base = PICBRIDGE1_PCI_MEM32_BASE; + limit = PICBRIDGE1_PCI_MEM32_LIMIT; + } else { /* Bridge/Xbridge */ + base = BRIDGE_PCI_MEM32_BASE; + limit = BRIDGE_PCI_MEM32_LIMIT; + } + + if ((pci_addr + base + req_size - 1) <= limit) + xio_addr = pci_addr + base; break; case PCIIO_SPACE_MEM64: /* "mem, use 64-bit-wide bus" */ - if ((pci_addr + BRIDGE_PCI_MEM64_BASE + req_size - 1) <= - BRIDGE_PCI_MEM64_LIMIT) - xio_addr = pci_addr + BRIDGE_PCI_MEM64_BASE; + if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 0)) { /* PIC bus 0 */ + base = PICBRIDGE0_PCI_MEM64_BASE; + limit = PICBRIDGE0_PCI_MEM64_LIMIT; + } else if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 1)) { /* PIC bus 1 */ + base = PICBRIDGE1_PCI_MEM64_BASE; + limit = PICBRIDGE1_PCI_MEM64_LIMIT; + } else { /* Bridge/Xbridge */ + base = BRIDGE_PCI_MEM64_BASE; + limit = BRIDGE_PCI_MEM64_LIMIT; + } + + if ((pci_addr + base + req_size - 1) <= limit) + xio_addr = pci_addr + base; break; case PCIIO_SPACE_IO: /* "i/o space" */ + /* + * PIC bridges do not support big-window aliases into PCI I/O space + */ + if (IS_PIC_SOFT(pcibr_soft)) { + xio_addr = XIO_NOWHERE; + break; + } + /* Bridge Hardware Bug WAR #482741: * The 4G area that maps directly from * XIO space to PCI I/O space is busted @@ -2725,7 +2454,7 @@ /*ARGSUSED6 */ pcibr_piomap_t -pcibr_piomap_alloc(devfs_handle_t pconn_vhdl, +pcibr_piomap_alloc(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, pciio_space_t space, iopaddr_t pci_addr, @@ -2737,7 +2466,7 @@ pciio_info_t pciio_info = &pcibr_info->f_c; pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; pcibr_piomap_t *mapptr; pcibr_piomap_t maplist; @@ -2867,7 +2596,7 @@ /*ARGSUSED */ caddr_t -pcibr_piotrans_addr(devfs_handle_t pconn_vhdl, +pcibr_piotrans_addr(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, pciio_space_t space, iopaddr_t pci_addr, @@ -2877,7 +2606,7 @@ pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; iopaddr_t xio_addr; caddr_t addr; @@ -2908,7 +2637,7 @@ /*ARGSUSED */ iopaddr_t -pcibr_piospace_alloc(devfs_handle_t pconn_vhdl, +pcibr_piospace_alloc(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, pciio_space_t space, size_t req_size, @@ -3010,7 +2739,7 @@ /*ARGSUSED */ void -pcibr_piospace_free(devfs_handle_t pconn_vhdl, +pcibr_piospace_free(vertex_hdl_t pconn_vhdl, pciio_space_t space, iopaddr_t pciaddr, size_t req_size) @@ -3161,14 +2890,14 @@ /*ARGSUSED */ pcibr_dmamap_t -pcibr_dmamap_alloc(devfs_handle_t pconn_vhdl, +pcibr_dmamap_alloc(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, size_t req_size_max, unsigned flags) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; pciio_slot_t slot; xwidgetnum_t xio_port; @@ -3216,7 +2945,7 @@ /* Device is capable of A64 operations, * and the attributes of the DMA are - * consistant with any previous DMA + * consistent with any previous DMA * mappings using shared resources. */ @@ -3266,7 +2995,7 @@ if (!pcibr_try_set_device(pcibr_soft, slot, flags, BRIDGE_DEV_D32_BITS)) { /* User desires DIRECT A32 operations, * and the attributes of the DMA are - * consistant with any previous DMA + * consistent with any previous DMA * mappings using shared resources. * Mapping calls may fail if target * is outside the direct32 range. @@ -3454,6 +3183,29 @@ iopaddr_t pci_addr; pciio_slot_t slot; + if (IS_PIC_BUSNUM_SOFT(soft, 0)) { + if ((xio_addr >= PICBRIDGE0_PCI_MEM32_BASE) && + (xio_lim <= PICBRIDGE0_PCI_MEM32_LIMIT)) { + pci_addr = xio_addr - PICBRIDGE0_PCI_MEM32_BASE; + return pci_addr; + } + if ((xio_addr >= PICBRIDGE0_PCI_MEM64_BASE) && + (xio_lim <= PICBRIDGE0_PCI_MEM64_LIMIT)) { + pci_addr = xio_addr - PICBRIDGE0_PCI_MEM64_BASE; + return pci_addr; + } + } else if (IS_PIC_BUSNUM_SOFT(soft, 1)) { + if ((xio_addr >= PICBRIDGE1_PCI_MEM32_BASE) && + (xio_lim <= PICBRIDGE1_PCI_MEM32_LIMIT)) { + pci_addr = xio_addr - PICBRIDGE1_PCI_MEM32_BASE; + return pci_addr; + } + if ((xio_addr >= PICBRIDGE1_PCI_MEM64_BASE) && + (xio_lim <= PICBRIDGE1_PCI_MEM64_LIMIT)) { + pci_addr = xio_addr - PICBRIDGE1_PCI_MEM64_BASE; + return pci_addr; + } + } else { if ((xio_addr >= BRIDGE_PCI_MEM32_BASE) && (xio_lim <= BRIDGE_PCI_MEM32_LIMIT)) { pci_addr = xio_addr - BRIDGE_PCI_MEM32_BASE; @@ -3464,6 +3216,7 @@ pci_addr = xio_addr - BRIDGE_PCI_MEM64_BASE; return pci_addr; } + } for (slot = soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(soft); ++slot) if ((xio_addr >= PCIBR_BRIDGE_DEVIO(soft, slot)) && (xio_lim < PCIBR_BRIDGE_DEVIO(soft, slot + 1))) { @@ -3505,7 +3258,7 @@ } else xio_port = pcibr_dmamap->bd_xio_port; - /* If this DMA is to an addres that + /* If this DMA is to an address that * refers back to this Bridge chip, * reduce it back to the correct * PCI MEM address. @@ -3644,243 +3397,6 @@ } /*ARGSUSED */ -alenlist_t -pcibr_dmamap_list(pcibr_dmamap_t pcibr_dmamap, - alenlist_t palenlist, - unsigned flags) -{ - pcibr_soft_t pcibr_soft; - bridge_t *bridge=NULL; - - unsigned al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0; - int inplace = flags & PCIIO_INPLACE; - - alenlist_t pciio_alenlist = 0; - alenlist_t xtalk_alenlist; - size_t length; - iopaddr_t offset; - unsigned direct64; - int ate_index = 0; - int ate_count = 0; - int ate_total = 0; - bridge_ate_p ate_ptr = (bridge_ate_p)0; - bridge_ate_t ate_proto = (bridge_ate_t)0; - bridge_ate_t ate_prev; - bridge_ate_t ate; - alenaddr_t xio_addr; - xwidgetnum_t xio_port; - iopaddr_t pci_addr; - alenaddr_t new_addr; - unsigned cmd_regs[8]; - unsigned s = 0; - -#if PCIBR_FREEZE_TIME - unsigned freeze_time; -#endif - int ate_freeze_done = 0; /* To pair ATE_THAW - * with an ATE_FREEZE - */ - - pcibr_soft = pcibr_dmamap->bd_soft; - - xtalk_alenlist = xtalk_dmamap_list(pcibr_dmamap->bd_xtalk, palenlist, - flags & DMAMAP_FLAGS); - if (!xtalk_alenlist) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: xtalk_dmamap_list() failed, " - "pcibr_dmamap=0x%x\n", pcibr_dmamap)); - goto fail; - } - alenlist_cursor_init(xtalk_alenlist, 0, NULL); - - if (inplace) { - pciio_alenlist = xtalk_alenlist; - } else { - pciio_alenlist = alenlist_create(al_flags); - if (!pciio_alenlist) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: alenlist_create() failed, " - "pcibr_dmamap=0x%lx\n", (unsigned long)pcibr_dmamap)); - goto fail; - } - } - - direct64 = pcibr_dmamap->bd_flags & PCIIO_DMA_A64; - if (!direct64) { - bridge = pcibr_soft->bs_base; - ate_ptr = pcibr_dmamap->bd_ate_ptr; - ate_index = pcibr_dmamap->bd_ate_index; - ate_proto = pcibr_dmamap->bd_ate_proto; - ATE_FREEZE(); - ate_freeze_done = 1; /* Remember that we need to do an ATE_THAW */ - } - pci_addr = pcibr_dmamap->bd_pci_addr; - - ate_prev = 0; /* matches no valid ATEs */ - while (ALENLIST_SUCCESS == - alenlist_get(xtalk_alenlist, NULL, 0, - &xio_addr, &length, al_flags)) { - if (XIO_PACKED(xio_addr)) { - xio_port = XIO_PORT(xio_addr); - xio_addr = XIO_ADDR(xio_addr); - } else - xio_port = pcibr_dmamap->bd_xio_port; - - if (xio_port == pcibr_soft->bs_xid) { - new_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, length); - if (new_addr == PCI_NOWHERE) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: pcibr_addr_xio_to_pci failed, " - "pcibr_dmamap=0x%x\n", pcibr_dmamap)); - goto fail; - } - } else if (direct64) { - new_addr = pci_addr | xio_addr - | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); - - /* Bridge Hardware WAR #482836: - * If the transfer is not cache aligned - * and the Bridge Rev is <= B, force - * prefetch to be off. - */ - if (flags & PCIBR_NOPREFETCH) - new_addr &= ~PCI64_ATTR_PREF; - - } else { - /* calculate the ate value for - * the first address. If it - * matches the previous - * ATE written (ie. we had - * multiple blocks in the - * same IOPG), then back up - * and reuse that ATE. - * - * We are NOT going to - * aggressively try to - * reuse any other ATEs. - */ - offset = IOPGOFF(xio_addr); - ate = ate_proto - | (xio_port << ATE_TIDSHIFT) - | (xio_addr - offset); - if (ate == ate_prev) { - PCIBR_DEBUG((PCIBR_DEBUG_ATE, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: ATE share\n")); - ate_ptr--; - ate_index--; - pci_addr -= IOPGSIZE; - } - new_addr = pci_addr + offset; - - /* Fill in the hardware ATEs - * that contain this block. - */ - ate_count = IOPG(offset + length - 1) + 1; - ate_total += ate_count; - - /* Ensure that this map contains enough ATE's */ - if (ate_total > pcibr_dmamap->bd_ate_count) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list :\n" - "\twanted xio_addr [0x%x..0x%x]\n" - "\tate_total 0x%x bd_ate_count 0x%x\n" - "\tATE's required > number allocated\n", - xio_addr, xio_addr + length - 1, - ate_total, pcibr_dmamap->bd_ate_count)); - goto fail; - } - - ATE_WRITE(); - - ate_index += ate_count; - ate_ptr += ate_count; - - ate_count <<= IOPFNSHIFT; - ate += ate_count; - pci_addr += ate_count; - } - - /* write the PCI DMA address - * out to the scatter-gather list. - */ - if (inplace) { - if (ALENLIST_SUCCESS != - alenlist_replace(pciio_alenlist, NULL, - &new_addr, &length, al_flags)) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: alenlist_replace() failed, " - "pcibr_dmamap=0x%x\n", pcibr_dmamap)); - - goto fail; - } - } else { - if (ALENLIST_SUCCESS != - alenlist_append(pciio_alenlist, - new_addr, length, al_flags)) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: alenlist_append() failed, " - "pcibr_dmamap=0x%x\n", pcibr_dmamap)); - goto fail; - } - } - } - if (!inplace) - alenlist_done(xtalk_alenlist); - - /* Reset the internal cursor of the alenlist to be returned back - * to the caller. - */ - alenlist_cursor_init(pciio_alenlist, 0, NULL); - - - /* In case an ATE_FREEZE was done do the ATE_THAW to unroll all the - * changes that ATE_FREEZE has done to implement the external SSRAM - * bug workaround. - */ - if (ate_freeze_done) { - ATE_THAW(); - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); - } else { - bridge->b_wid_tflush; - } - } - } - PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_list: pcibr_dmamap=0x%x, pciio_alenlist=0x%x\n", - pcibr_dmamap, pciio_alenlist)); - - return pciio_alenlist; - - fail: - /* There are various points of failure after doing an ATE_FREEZE - * We need to do an ATE_THAW. Otherwise the ATEs are locked forever. - * The decision to do an ATE_THAW needs to be based on whether a - * an ATE_FREEZE was done before. - */ - if (ate_freeze_done) { - ATE_THAW(); - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_wid_tflush; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); - } else { - bridge->b_wid_tflush; - } - } - } - if (pciio_alenlist && !inplace) - alenlist_destroy(pciio_alenlist); - return 0; -} - -/*ARGSUSED */ void pcibr_dmamap_done(pcibr_dmamap_t pcibr_dmamap) { @@ -3917,7 +3433,7 @@ /*ARGSUSED */ cnodeid_t -pcibr_get_dmatrans_node(devfs_handle_t pconn_vhdl) +pcibr_get_dmatrans_node(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); @@ -3928,7 +3444,7 @@ /*ARGSUSED */ iopaddr_t -pcibr_dmatrans_addr(devfs_handle_t pconn_vhdl, +pcibr_dmatrans_addr(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, paddr_t paddr, size_t req_size, @@ -3936,7 +3452,7 @@ { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot]; @@ -4149,213 +3665,6 @@ return 0; } -/*ARGSUSED */ -alenlist_t -pcibr_dmatrans_list(devfs_handle_t pconn_vhdl, - device_desc_t dev_desc, - alenlist_t palenlist, - unsigned flags) -{ - pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); - pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; - pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); - pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot]; - xwidgetnum_t xio_port; - - alenlist_t pciio_alenlist = 0; - alenlist_t xtalk_alenlist = 0; - - int inplace; - unsigned direct64; - unsigned al_flags; - - iopaddr_t xio_base; - alenaddr_t xio_addr; - size_t xio_size; - - size_t map_size; - iopaddr_t pci_base; - alenaddr_t pci_addr; - - unsigned relbits = 0; - - /* merge in forced flags */ - flags |= pcibr_soft->bs_dma_flags; - - inplace = flags & PCIIO_INPLACE; - direct64 = flags & PCIIO_DMA_A64; - al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0; - - if (direct64) { - map_size = 1ull << 48; - xio_base = 0; - pci_base = slotp->bss_d64_base; - if ((pci_base != PCIBR_D64_BASE_UNSET) && - (flags == slotp->bss_d64_flags)) { - /* reuse previous base info */ - } else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D64_BITS) < 0) { - /* DMA configuration conflict */ - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: DMA configuration conflict " - "for direct64, flags=0x%x\n", flags)); - goto fail; - } else { - relbits = BRIDGE_DEV_D64_BITS; - pci_base = - pcibr_flags_to_d64(flags, pcibr_soft); - } - } else { - xio_base = pcibr_soft->bs_dir_xbase; - map_size = 1ull << 31; - pci_base = slotp->bss_d32_base; - if ((pci_base != PCIBR_D32_BASE_UNSET) && - (flags == slotp->bss_d32_flags)) { - /* reuse previous base info */ - } else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D32_BITS) < 0) { - /* DMA configuration conflict */ - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: DMA configuration conflict " - "for direct32, flags=0x%x\n", flags)); - goto fail; - } else { - relbits = BRIDGE_DEV_D32_BITS; - pci_base = PCI32_DIRECT_BASE; - } - } - - xtalk_alenlist = xtalk_dmatrans_list(xconn_vhdl, 0, palenlist, - flags & DMAMAP_FLAGS); - if (!xtalk_alenlist) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: xtalk_dmatrans_list failed " - "xtalk_alenlist=0x%x\n", xtalk_alenlist)); - goto fail; - } - - alenlist_cursor_init(xtalk_alenlist, 0, NULL); - - if (inplace) { - pciio_alenlist = xtalk_alenlist; - } else { - pciio_alenlist = alenlist_create(al_flags); - if (!pciio_alenlist) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: alenlist_create failed with " - " 0x%x\n", pciio_alenlist)); - goto fail; - } - } - - while (ALENLIST_SUCCESS == - alenlist_get(xtalk_alenlist, NULL, 0, - &xio_addr, &xio_size, al_flags)) { - - /* - * find which XIO port this goes to. - */ - if (XIO_PACKED(xio_addr)) { - if (xio_addr == XIO_NOWHERE) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: xio_addr == XIO_NOWHERE\n")); - return 0; - } - xio_port = XIO_PORT(xio_addr); - xio_addr = XIO_ADDR(xio_addr); - } else - xio_port = pcibr_soft->bs_mxid; - - /* - * If this DMA comes back to us, - * return the PCI MEM address on - * which it would land, or NULL - * if the target is something - * on bridge other than PCI MEM. - */ - if (xio_port == pcibr_soft->bs_xid) { - pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, xio_size); - if (pci_addr == (alenaddr_t)NULL) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: pcibr_addr_xio_to_pci failed " - "xio_addr=0x%x, xio_size=0x%x\n", xio_addr, xio_size)); - goto fail; - } - } else if (direct64) { - ASSERT(xio_port != 0); - pci_addr = pci_base | xio_addr - | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); - } else { - iopaddr_t offset = xio_addr - xio_base; - iopaddr_t endoff = xio_size + offset; - - if ((xio_size > map_size) || - (xio_addr < xio_base) || - (xio_port != pcibr_soft->bs_dir_xport) || - (endoff > map_size)) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: xio_size > map_size fail\n" - "xio_addr=0x%x, xio_size=0x%x. map_size=0x%x, " - "xio_port=0x%x, endoff=0x%x\n", - xio_addr, xio_size, map_size, xio_port, endoff)); - goto fail; - } - - pci_addr = pci_base + (xio_addr - xio_base); - } - - /* write the PCI DMA address - * out to the scatter-gather list. - */ - if (inplace) { - if (ALENLIST_SUCCESS != - alenlist_replace(pciio_alenlist, NULL, - &pci_addr, &xio_size, al_flags)) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: alenlist_replace failed\n")); - goto fail; - } - } else { - if (ALENLIST_SUCCESS != - alenlist_append(pciio_alenlist, - pci_addr, xio_size, al_flags)) { - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: alenlist_append failed\n")); - goto fail; - } - } - } - - if (relbits) { - if (direct64) { - slotp->bss_d64_flags = flags; - slotp->bss_d64_base = pci_base; - } else { - slotp->bss_d32_flags = flags; - slotp->bss_d32_base = pci_base; - } - } - if (!inplace) - alenlist_done(xtalk_alenlist); - - /* Reset the internal cursor of the alenlist to be returned back - * to the caller. - */ - alenlist_cursor_init(pciio_alenlist, 0, NULL); - - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_list: pciio_alenlist=0x%x\n", - pciio_alenlist)); - - return pciio_alenlist; - - fail: - if (relbits) - pcibr_release_device(pcibr_soft, pciio_slot, relbits); - if (pciio_alenlist && !inplace) - alenlist_destroy(pciio_alenlist); - return 0; -} - void pcibr_dmamap_drain(pcibr_dmamap_t map) { @@ -4363,24 +3672,24 @@ } void -pcibr_dmaaddr_drain(devfs_handle_t pconn_vhdl, +pcibr_dmaaddr_drain(vertex_hdl_t pconn_vhdl, paddr_t paddr, size_t bytes) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; xtalk_dmaaddr_drain(xconn_vhdl, paddr, bytes); } void -pcibr_dmalist_drain(devfs_handle_t pconn_vhdl, +pcibr_dmalist_drain(vertex_hdl_t pconn_vhdl, alenlist_t list) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; xtalk_dmalist_drain(xconn_vhdl, list); } @@ -4402,18 +3711,18 @@ */ /*ARGSUSED */ void -pcibr_provider_startup(devfs_handle_t pcibr) +pcibr_provider_startup(vertex_hdl_t pcibr) { } /*ARGSUSED */ void -pcibr_provider_shutdown(devfs_handle_t pcibr) +pcibr_provider_shutdown(vertex_hdl_t pcibr) { } int -pcibr_reset(devfs_handle_t conn) +pcibr_reset(vertex_hdl_t conn) { #ifdef PIC_LATER pciio_info_t pciio_info = pciio_info_get(conn); @@ -4484,7 +3793,7 @@ } pciio_endian_t -pcibr_endian_set(devfs_handle_t pconn_vhdl, +pcibr_endian_set(vertex_hdl_t pconn_vhdl, pciio_endian_t device_end, pciio_endian_t desired_end) { @@ -4629,7 +3938,7 @@ } pciio_priority_t -pcibr_priority_set(devfs_handle_t pconn_vhdl, +pcibr_priority_set(vertex_hdl_t pconn_vhdl, pciio_priority_t device_prio) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); @@ -4653,7 +3962,7 @@ * Returns 0 on failure, 1 on success */ int -pcibr_device_flags_set(devfs_handle_t pconn_vhdl, +pcibr_device_flags_set(vertex_hdl_t pconn_vhdl, pcibr_device_flags_t flags) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); @@ -4792,10 +4101,8 @@ (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, (pciio_dmamap_free_f *) pcibr_dmamap_free, (pciio_dmamap_addr_f *) pcibr_dmamap_addr, - (pciio_dmamap_list_f *) pcibr_dmamap_list, (pciio_dmamap_done_f *) pcibr_dmamap_done, (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, - (pciio_dmatrans_list_f *) pcibr_dmatrans_list, (pciio_dmamap_drain_f *) pcibr_dmamap_drain, (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, (pciio_dmalist_drain_f *) pcibr_dmalist_drain, @@ -4814,23 +4121,16 @@ (pciio_priority_set_f *) pcibr_priority_set, (pciio_config_get_f *) pcibr_config_get, (pciio_config_set_f *) pcibr_config_set, -#ifdef PIC_LATER - (pciio_error_devenable_f *) pcibr_error_devenable, - (pciio_error_extract_f *) pcibr_error_extract, - (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback, - (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback, -#else (pciio_error_devenable_f *) 0, (pciio_error_extract_f *) 0, (pciio_driver_reg_callback_f *) 0, (pciio_driver_unreg_callback_f *) 0, -#endif /* PIC_LATER */ (pciio_device_unregister_f *) pcibr_device_unregister, (pciio_dma_enabled_f *) pcibr_dma_enabled, }; int -pcibr_dma_enabled(devfs_handle_t pconn_vhdl) +pcibr_dma_enabled(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); @@ -4857,7 +4157,7 @@ * parameter 'format' is sent to the console. */ void -pcibr_debug(uint32_t type, devfs_handle_t vhdl, char *format, ...) +pcibr_debug(uint32_t type, vertex_hdl_t vhdl, char *format, ...) { char hwpath[MAXDEVNAME] = "\0"; char copy_of_hwpath[MAXDEVNAME]; @@ -4865,7 +4165,6 @@ short widget = -1; short slot = -1; va_list ap; - char *strtok_r(char *string, const char *sepset, char **lasts); if (pcibr_debug_mask & type) { if (vhdl) { @@ -4873,27 +4172,26 @@ char *cp; if (strcmp(module, pcibr_debug_module)) { - /* strtok_r() wipes out string, use a copy */ + /* use a copy */ (void)strcpy(copy_of_hwpath, hwpath); cp = strstr(copy_of_hwpath, "/module/"); if (cp) { - char *last = NULL; cp += strlen("/module"); - module = strtok_r(cp, "/", &last); + module = strsep(&cp, "/"); } } if (pcibr_debug_widget != -1) { cp = strstr(hwpath, "/xtalk/"); if (cp) { cp += strlen("/xtalk/"); - widget = atoi(cp); + widget = simple_strtoul(cp, NULL, 0); } } if (pcibr_debug_slot != -1) { cp = strstr(hwpath, "/pci/"); if (cp) { cp += strlen("/pci/"); - slot = atoi(cp); + slot = simple_strtoul(cp, NULL, 0); } } } @@ -4912,9 +4210,38 @@ * Since we have a variable length argument list, we * need to call printk this way rather than directly */ - va_start(ap, format); - printk(format, ap); - va_end(ap); + { + char buffer[500]; + + va_start(ap, format); + vsnprintf(buffer, 500, format, ap); + va_end(ap); + buffer[499] = (char)0; /* just to be safe */ + printk("%s", buffer); + } } } } + +int +isIO9(nasid_t nasid) { + lboard_t *brd = (lboard_t *)KL_CONFIG_INFO(nasid); + + while (brd) { + if (brd->brd_flags & LOCAL_MASTER_IO6) { + return 1; + } + brd = KLCF_NEXT(brd); + } + /* if it's dual ported, check the peer also */ + nasid = NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer; + if (nasid < 0) return 0; + brd = (lboard_t *)KL_CONFIG_INFO(nasid); + while (brd) { + if (brd->brd_flags & LOCAL_MASTER_IO6) { + return 1; + } + brd = KLCF_NEXT(brd); + } + return 0; +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,26 +27,11 @@ #include #include #include -#include #include #include -#ifdef __ia64 -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc -#endif - extern int hubii_check_widget_disabled(nasid_t, int); -#ifdef BRIDGE_B_DATACORR_WAR -extern int ql_bridge_rev_b_war(devfs_handle_t); -extern int bridge_rev_b_data_check_disable; -char *rev_b_datacorr_warning = -"***************************** WARNING! ******************************\n"; -char *rev_b_datacorr_mesg = -"UNRECOVERABLE IO LINK ERROR. CONTACT SERVICE PROVIDER\n"; -#endif + /* ===================================================================== * ERROR HANDLING @@ -76,13 +61,9 @@ BRIDGE_ISR_PCIBUS_PIOERR; #endif -#if defined (PCIBR_LLP_CONTROL_WAR) -int pcibr_llp_control_war_cnt; -#endif /* PCIBR_LLP_CONTROL_WAR */ +int pcibr_llp_control_war_cnt; /* PCIBR_LLP_CONTROL_WAR */ -/* FIXME: can these arrays be local ? */ - -struct reg_values xio_cmd_pactyp[] = +static struct reg_values xio_cmd_pactyp[] = { {0x0, "RdReq"}, {0x1, "RdResp"}, @@ -103,7 +84,7 @@ {0} }; -struct reg_desc xio_cmd_bits[] = +static struct reg_desc xio_cmd_bits[] = { {WIDGET_DIDN, -28, "DIDN", "%x"}, {WIDGET_SIDN, -24, "SIDN", "%x"}, @@ -120,58 +101,7 @@ #define F(s,n) { 1l<<(s),-(s), n } -struct reg_desc bridge_int_status_desc[] = -{ - F(45, "PCI_X_SPLIT_MES_PE"),/* PIC ONLY */ - F(44, "PCI_X_SPLIT_EMES"), /* PIC ONLY */ - F(43, "PCI_X_SPLIT_TO"), /* PIC ONLY */ - F(42, "PCI_X_UNEX_COMP"), /* PIC ONLY */ - F(41, "INT_RAM_PERR"), /* PIC ONLY */ - F(40, "PCI_X_ARB_ERR"), /* PIC ONLY */ - F(39, "PCI_X_REQ_TOUT"), /* PIC ONLY */ - F(38, "PCI_X_TABORT"), /* PIC ONLY */ - F(37, "PCI_X_PERR"), /* PIC ONLY */ - F(36, "PCI_X_SERR"), /* PIC ONLY */ - F(35, "PCI_X_MRETRY"), /* PIC ONLY */ - F(34, "PCI_X_MTOUT"), /* PIC ONLY */ - F(33, "PCI_X_DA_PARITY"), /* PIC ONLY */ - F(32, "PCI_X_AD_PARITY"), /* PIC ONLY */ - F(31, "MULTI_ERR"), /* BRIDGE ONLY */ - F(30, "PMU_ESIZE_EFAULT"), - F(29, "UNEXPECTED_RESP"), - F(28, "BAD_XRESP_PACKET"), - F(27, "BAD_XREQ_PACKET"), - F(26, "RESP_XTALK_ERROR"), - F(25, "REQ_XTALK_ERROR"), - F(24, "INVALID_ADDRESS"), - F(23, "UNSUPPORTED_XOP"), - F(22, "XREQ_FIFO_OFLOW"), - F(21, "LLP_REC_SNERROR"), - F(20, "LLP_REC_CBERROR"), - F(19, "LLP_RCTY"), - F(18, "LLP_TX_RETRY"), - F(17, "LLP_TCTY"), - F(16, "SSRAM_PERR"), /* BRIDGE ONLY */ - F(15, "PCI_ABORT"), - F(14, "PCI_PARITY"), - F(13, "PCI_SERR"), - F(12, "PCI_PERR"), - F(11, "PCI_MASTER_TOUT"), - F(10, "PCI_RETRY_CNT"), - F(9, "XREAD_REQ_TOUT"), - F(8, "GIO_BENABLE_ERR"), /* BRIDGE ONLY */ - F(7, "INT7"), - F(6, "INT6"), - F(5, "INT5"), - F(4, "INT4"), - F(3, "INT3"), - F(2, "INT2"), - F(1, "INT1"), - F(0, "INT0"), - {0} -}; - -struct reg_values space_v[] = +static struct reg_values space_v[] = { {PCIIO_SPACE_NONE, "none"}, {PCIIO_SPACE_ROM, "ROM"}, @@ -189,13 +119,13 @@ {PCIIO_SPACE_BAD, "BAD"}, {0} }; -struct reg_desc space_desc[] = +static struct reg_desc space_desc[] = { {0xFF, 0, "space", 0, space_v}, {0} }; #define device_desc device_bits -struct reg_desc device_bits[] = +static struct reg_desc device_bits[] = { {BRIDGE_DEV_ERR_LOCK_EN, 0, "ERR_LOCK_EN"}, {BRIDGE_DEV_PAGE_CHK_DIS, 0, "PAGE_CHK_DIS"}, @@ -218,14 +148,14 @@ {0} }; -void +static void print_bridge_errcmd(uint32_t cmdword, char *errtype) { printk("\t Bridge %s Error Command Word Register ", errtype); print_register(cmdword, xio_cmd_bits); } -char *pcibr_isr_errs[] = +static char *pcibr_isr_errs[] = { "", "", "", "", "", "", "", "", "08: GIO non-contiguous byte enable in crosstalk packet", /* BRIDGE ONLY */ @@ -279,7 +209,7 @@ /* * display memory directory state */ -void +static void pcibr_show_dir_state(paddr_t paddr, char *prefix) { #ifdef LATER @@ -428,7 +358,6 @@ break; case BRIDGE_ISR_PAGE_FAULT: /* bit30 PMU_PAGE_FAULT */ -/* case BRIDGE_ISR_PMU_ESIZE_FAULT: bit30 PMU_ESIZE_FAULT */ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) reg_desc = "Map Fault Address"; else @@ -592,31 +521,9 @@ printk( "\t%s\n", pcibr_isr_errs[i]); } } - -#if BRIDGE_ERROR_INTR_WAR - if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) { /* known bridge bug */ - /* - * Should never receive interrupts for these reasons on Rev 1 bridge - * as they are not enabled. Assert for it. - */ - ASSERT((int_status & (BRIDGE_IMR_PCI_MST_TIMEOUT | - BRIDGE_ISR_RESP_XTLK_ERR | - BRIDGE_ISR_LLP_TX_RETRY)) == 0); - } - if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_C) { /* known bridge bug */ - /* - * This interrupt is turned off at init time. So, should never - * see this interrupt. - */ - ASSERT((int_status & BRIDGE_ISR_BAD_XRESP_PKT) == 0); - } -#endif } -#define PCIBR_ERRINTR_GROUP(error) \ - (( error & (BRIDGE_IRR_PCI_GRP|BRIDGE_IRR_GIO_GRP) - -uint32_t +static uint32_t pcibr_errintr_group(uint32_t error) { uint32_t group = BRIDGE_IRR_MULTI_CLR; @@ -741,15 +648,7 @@ picreg_t int_status_64; int number_bits; int i; - - /* REFERENCED */ uint64_t disable_errintr_mask = 0; -#ifdef EHE_ENABLE - int rv; - int error_code = IOECODE_DMA | IOECODE_READ; - ioerror_mode_t mode = MODE_DEVERROR; - ioerror_t ioe; -#endif /* EHE_ENABLE */ nasid_t nasid; @@ -806,10 +705,6 @@ pcibr_soft->bs_errinfo.bserr_toutcnt++; /* Let's go recursive */ return(pcibr_error_intr_handler(irq, arg, ep)); -#ifdef LATER - timeout(pcibr_error_intr_handler, pcibr_soft, BRIDGE_PIOERR_TIMEOUT); -#endif - return; } /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a @@ -847,24 +742,6 @@ pcibr_pioerr_check(pcibr_soft); } -#ifdef BRIDGE_B_DATACORR_WAR - if ((pcibr_soft->bs_rev_num == BRIDGE_PART_REV_B) && - (err_status & BRIDGE_IMR_LLP_REC_CBERR)) { - if (bridge_rev_b_data_check_disable) - printk(KERN_WARNING "\n%s%s: %s%s\n", rev_b_datacorr_warning, - pcibr_soft->bs_name, rev_b_datacorr_mesg, - rev_b_datacorr_warning); - else { - ql_bridge_rev_b_war(pcibr_soft->bs_vhdl); - PRINT_PANIC( "\n%s%s: %s%s\n", rev_b_datacorr_warning, - pcibr_soft->bs_name, rev_b_datacorr_mesg, - rev_b_datacorr_warning); - } - - err_status &= ~BRIDGE_IMR_LLP_REC_CBERR; - } -#endif /* BRIDGE_B_DATACORR_WAR */ - if (err_status) { struct bs_errintr_stat_s *bs_estat = pcibr_soft->bs_errintr_stat; @@ -1024,9 +901,8 @@ (0x00402000 == (0x00F07F00 & bridge->b_wid_err_cmdword))) { err_status &= ~BRIDGE_ISR_INVLD_ADDR; } -#if defined (PCIBR_LLP_CONTROL_WAR) /* - * The bridge bug, where the llp_config or control registers + * The bridge bug (PCIBR_LLP_CONTROL_WAR), where the llp_config or control registers * need to be read back after being written, affects an MP * system since there could be small windows between writing * the register and reading it back on one cpu while another @@ -1039,40 +915,9 @@ if ((err_status & BRIDGE_ISR_INVLD_ADDR) && ((((uint64_t) bridge->b_wid_err_upper << 32) | (bridge->b_wid_err_lower)) == (BRIDGE_INT_RST_STAT & 0xff0))) { -#if 0 - if (kdebug) - printk(KERN_NOTICE "%s bridge: ignoring llp/control address interrupt", - pcibr_soft->bs_name); -#endif pcibr_llp_control_war_cnt++; err_status &= ~BRIDGE_ISR_INVLD_ADDR; } -#endif /* PCIBR_LLP_CONTROL_WAR */ - -#ifdef EHE_ENABLE - /* Check if this is the RESP_XTALK_ERROR interrupt. - * This can happen due to a failed DMA READ operation. - */ - if (err_status & BRIDGE_ISR_RESP_XTLK_ERR) { - /* Phase 1 : Look at the error state in the bridge and further - * down in the device layers. - */ - (void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_LOOKUP); - IOERROR_SETVALUE(&ioe, widgetnum, pcibr_soft->bs_xid); - (void)pcibr_error_handler((error_handler_arg_t)pcibr_soft, - error_code, - mode, - &ioe); - /* Phase 2 : Perform the action agreed upon in phase 1. - */ - (void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_ACTION); - rv = pcibr_error_handler((error_handler_arg_t)pcibr_soft, - error_code, - mode, - &ioe); - } - if (rv != IOERROR_HANDLED) { -#endif /* EHE_ENABLE */ bridge_errors_to_dump |= BRIDGE_ISR_PCIBUS_PIOERR; @@ -1089,25 +934,16 @@ */ if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV867308, pcibr_soft) && (err_status & (BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR))) { - printk("BRIDGE ERR_STATUS 0x%x\n", err_status); + printk("BRIDGE ERR_STATUS 0x%lx\n", err_status); pcibr_error_dump(pcibr_soft); -#ifdef LATER - machine_error_dump(""); -#endif PRINT_PANIC("PCI Bridge Error interrupt killed the system"); } if (err_status & BRIDGE_ISR_ERROR_FATAL) { -#ifdef LATER - machine_error_dump(""); -#endif PRINT_PANIC("PCI Bridge Error interrupt killed the system"); /*NOTREACHED */ } -#ifdef EHE_ENABLE - } -#endif /* * We can't return without re-enabling the interrupt, since @@ -1137,136 +973,6 @@ pcibr_soft->bs_errinfo.bserr_intstat = 0; } -/* - * pcibr_addr_toslot - * Given the 'pciaddr' find out which slot this address is - * allocated to, and return the slot number. - * While we have the info handy, construct the - * function number, space code and offset as well. - * - * NOTE: if this routine is called, we don't know whether - * the address is in CFG, MEM, or I/O space. We have to guess. - * This will be the case on PIO stores, where the only way - * we have of getting the address is to check the Bridge, which - * stores the PCI address but not the space and not the xtalk - * address (from which we could get it). - */ -int -pcibr_addr_toslot(pcibr_soft_t pcibr_soft, - iopaddr_t pciaddr, - pciio_space_t *spacep, - iopaddr_t *offsetp, - pciio_function_t *funcp) -{ - int s, f = 0, w; - iopaddr_t base; - size_t size; - pciio_piospace_t piosp; - - /* - * Check if the address is in config space - */ - - if ((pciaddr >= BRIDGE_CONFIG_BASE) && (pciaddr < BRIDGE_CONFIG_END)) { - - if (pciaddr >= BRIDGE_CONFIG1_BASE) - pciaddr -= BRIDGE_CONFIG1_BASE; - else - pciaddr -= BRIDGE_CONFIG_BASE; - - s = pciaddr / BRIDGE_CONFIG_SLOT_SIZE; - pciaddr %= BRIDGE_CONFIG_SLOT_SIZE; - - if (funcp) { - f = pciaddr / 0x100; - pciaddr %= 0x100; - } - if (spacep) - *spacep = PCIIO_SPACE_CFG; - if (offsetp) - *offsetp = pciaddr; - if (funcp) - *funcp = f; - - return s; - } - for (s = pcibr_soft->bs_min_slot; s < PCIBR_NUM_SLOTS(pcibr_soft); ++s) { - int nf = pcibr_soft->bs_slot[s].bss_ninfo; - pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos; - - for (f = 0; f < nf; f++) { - pcibr_info_t pcibr_info = pcibr_infoh[f]; - - if (!pcibr_info) - continue; - for (w = 0; w < 6; w++) { - if (pcibr_info->f_window[w].w_space == PCIIO_SPACE_NONE) { - continue; - } - base = pcibr_info->f_window[w].w_base; - size = pcibr_info->f_window[w].w_size; - - if ((pciaddr >= base) && (pciaddr < (base + size))) { - if (spacep) - *spacep = PCIIO_SPACE_WIN(w); - if (offsetp) - *offsetp = pciaddr - base; - if (funcp) - *funcp = f; - return s; - } /* endif match */ - } /* next window */ - } /* next func */ - } /* next slot */ - - /* - * Check if the address was allocated as part of the - * pcibr_piospace_alloc calls. - */ - for (s = pcibr_soft->bs_min_slot; s < PCIBR_NUM_SLOTS(pcibr_soft); ++s) { - int nf = pcibr_soft->bs_slot[s].bss_ninfo; - pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos; - - for (f = 0; f < nf; f++) { - pcibr_info_t pcibr_info = pcibr_infoh[f]; - - if (!pcibr_info) - continue; - piosp = pcibr_info->f_piospace; - while (piosp) { - if ((piosp->start <= pciaddr) && - ((piosp->count + piosp->start) > pciaddr)) { - if (spacep) - *spacep = piosp->space; - if (offsetp) - *offsetp = pciaddr - piosp->start; - return s; - } /* endif match */ - piosp = piosp->next; - } /* next piosp */ - } /* next func */ - } /* next slot */ - - /* - * Some other random address on the PCI bus ... - * we have no way of knowing whether this was - * a MEM or I/O access; so, for now, we just - * assume that the low 1G is MEM, the next - * 3G is I/O, and anything above the 4G limit - * is obviously MEM. - */ - - if (spacep) - *spacep = ((pciaddr < (1ul << 30)) ? PCIIO_SPACE_MEM : - (pciaddr < (4ul << 30)) ? PCIIO_SPACE_IO : - PCIIO_SPACE_MEM); - if (offsetp) - *offsetp = pciaddr; - - return PCIIO_SLOT_NONE; - -} - void pcibr_error_cleanup(pcibr_soft_t pcibr_soft, int error_code) { @@ -1286,59 +992,6 @@ (void) bridge->b_wid_tflush; /* flushbus */ } -/* - * pcibr_error_extract - * Given the 'pcibr vertex handle' find out which slot - * the bridge status error address (from pcibr_soft info - * hanging off the vertex) - * allocated to, and return the slot number. - * While we have the info handy, construct the - * space code and offset as well. - * - * NOTE: if this routine is called, we don't know whether - * the address is in CFG, MEM, or I/O space. We have to guess. - * This will be the case on PIO stores, where the only way - * we have of getting the address is to check the Bridge, which - * stores the PCI address but not the space and not the xtalk - * address (from which we could get it). - * - * XXX- this interface has no way to return the function - * number on a multifunction card, even though that data - * is available. - */ - -pciio_slot_t -pcibr_error_extract(devfs_handle_t pcibr_vhdl, - pciio_space_t *spacep, - iopaddr_t *offsetp) -{ - pcibr_soft_t pcibr_soft = 0; - iopaddr_t bserr_addr; - bridge_t *bridge; - pciio_slot_t slot = PCIIO_SLOT_NONE; - arbitrary_info_t rev; - - /* Do a sanity check as to whether we really got a - * bridge vertex handle. - */ - if (hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &rev) != - GRAPH_SUCCESS) - return(slot); - - pcibr_soft = pcibr_soft_get(pcibr_vhdl); - if (pcibr_soft) { - bridge = pcibr_soft->bs_base; - bserr_addr = - bridge->b_pci_err_lower | - ((uint64_t) (bridge->b_pci_err_upper & - BRIDGE_ERRUPPR_ADDRMASK) << 32); - - slot = pcibr_addr_toslot(pcibr_soft, bserr_addr, - spacep, offsetp, NULL); - } - return slot; -} - /*ARGSUSED */ void pcibr_device_disable(pcibr_soft_t pcibr_soft, int devnum) @@ -1426,7 +1079,7 @@ { int retval = IOERROR_HANDLED; - devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + vertex_hdl_t pcibr_vhdl = pcibr_soft->bs_vhdl; bridge_t *bridge = pcibr_soft->bs_base; iopaddr_t bad_xaddr; @@ -1806,7 +1459,7 @@ * * CAUTION: Resetting bit BRIDGE_IRR_PCI_GRP_CLR, acknowledges * a group of interrupts. If while handling this error, - * some other error has occured, that would be + * some other error has occurred, that would be * implicitly cleared by this write. * Need a way to ensure we don't inadvertently clear some * other errors. @@ -1837,7 +1490,7 @@ ioerror_mode_t mode, ioerror_t *ioe) { - devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + vertex_hdl_t pcibr_vhdl = pcibr_soft->bs_vhdl; bridge_t *bridge = pcibr_soft->bs_base; bridgereg_t bus_lowaddr, bus_uppraddr; int retval = 0; @@ -1874,7 +1527,7 @@ BRIDGE_ERRUPPR_ADDRMASK) << 32))); /* - * need to ensure that the xtalk adress in ioe + * need to ensure that the xtalk address in ioe * maps to PCI error address read from bridge. * How to convert PCI address back to Xtalk address ? * (better idea: convert XTalk address to PCI address @@ -1946,7 +1599,7 @@ ioerror_mode_t mode, ioerror_t *ioe) { - devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + vertex_hdl_t pcibr_vhdl = pcibr_soft->bs_vhdl; int retval; retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe); @@ -1982,34 +1635,12 @@ pcibr_soft_t pcibr_soft; int retval = IOERROR_BADERRORCODE; -#ifdef EHE_ENABLE - devfs_handle_t xconn_vhdl,pcibr_vhdl; - error_state_t e_state; -#endif /* EHE_ENABLE */ - pcibr_soft = (pcibr_soft_t) einfo; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn, "pcibr_error_handler: pcibr_soft=0x%x, error_code=0x%x\n", pcibr_soft, error_code)); -#ifdef EHE_ENABLE - xconn_vhdl = pcibr_soft->bs_conn; - pcibr_vhdl = pcibr_soft->bs_vhdl; - - e_state = error_state_get(xconn_vhdl); - - if (error_state_set(pcibr_vhdl, e_state) == - ERROR_RETURN_CODE_CANNOT_SET_STATE) - return(IOERROR_UNHANDLED); - - /* If we are in the action handling phase clean out the error state - * on the xswitch. - */ - if (e_state == ERROR_STATE_ACTION) - (void)error_state_set(xconn_vhdl, ERROR_STATE_NONE); -#endif /* EHE_ENABLE */ - #if DEBUG && ERROR_DEBUG printk( "%s: pcibr_error_handler\n", pcibr_soft->bs_name); #endif @@ -2086,11 +1717,6 @@ * the error from the PIO address. */ -#if 0 - if (mode == MODE_DEVPROBE) - pio_retval = IOERROR_HANDLED; - else { -#endif if (error_code & IOECODE_PIO) { iopaddr_t bad_xaddr; /* @@ -2123,9 +1749,6 @@ pio_retval = IOERROR_UNHANDLED; } } -#if 0 - } /* MODE_DEVPROBE */ -#endif /* * If the error was a result of a DMA Write, we tell what bus on the PIC @@ -2201,37 +1824,3 @@ return IOERROR_HANDLED; } } - - -/* - * Reenable a device after handling the error. - * This is called by the lower layers when they wish to be reenabled - * after an error. - * Note that each layer would be calling the previous layer to reenable - * first, before going ahead with their own re-enabling. - */ - -int -pcibr_error_devenable(devfs_handle_t pconn_vhdl, int error_code) -{ - pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); - pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); - pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - - ASSERT(error_code & IOECODE_PIO); - - /* If the error is not known to be a write, - * we have to call devenable. - * write errors are isolated to the bridge. - */ - if (!(error_code & IOECODE_WRITE)) { - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; - int rc; - - rc = xtalk_error_devenable(xconn_vhdl, pciio_slot, error_code); - if (rc != IOERROR_HANDLED) - return rc; - } - pcibr_error_cleanup(pcibr_soft, error_code); - return IOERROR_HANDLED; -} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,20 +27,19 @@ #include #include #include -#include #include #include -pcibr_hints_t pcibr_hints_get(devfs_handle_t, int); -void pcibr_hints_fix_rrbs(devfs_handle_t); -void pcibr_hints_dualslot(devfs_handle_t, pciio_slot_t, pciio_slot_t); -void pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *); -void pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t); -void pcibr_hints_handsoff(devfs_handle_t); -void pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t); +pcibr_hints_t pcibr_hints_get(vertex_hdl_t, int); +void pcibr_hints_fix_rrbs(vertex_hdl_t); +void pcibr_hints_dualslot(vertex_hdl_t, pciio_slot_t, pciio_slot_t); +void pcibr_hints_intr_bits(vertex_hdl_t, pcibr_intr_bits_f *); +void pcibr_set_rrb_callback(vertex_hdl_t, rrb_alloc_funct_t); +void pcibr_hints_handsoff(vertex_hdl_t); +void pcibr_hints_subdevs(vertex_hdl_t, pciio_slot_t, uint64_t); pcibr_hints_t -pcibr_hints_get(devfs_handle_t xconn_vhdl, int alloc) +pcibr_hints_get(vertex_hdl_t xconn_vhdl, int alloc) { arbitrary_info_t ainfo = 0; graph_error_t rv; @@ -79,7 +78,7 @@ } void -pcibr_hints_fix_some_rrbs(devfs_handle_t xconn_vhdl, unsigned mask) +pcibr_hints_fix_some_rrbs(vertex_hdl_t xconn_vhdl, unsigned mask) { pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); @@ -91,13 +90,13 @@ } void -pcibr_hints_fix_rrbs(devfs_handle_t xconn_vhdl) +pcibr_hints_fix_rrbs(vertex_hdl_t xconn_vhdl) { pcibr_hints_fix_some_rrbs(xconn_vhdl, 0xFF); } void -pcibr_hints_dualslot(devfs_handle_t xconn_vhdl, +pcibr_hints_dualslot(vertex_hdl_t xconn_vhdl, pciio_slot_t host, pciio_slot_t guest) { @@ -111,7 +110,7 @@ } void -pcibr_hints_intr_bits(devfs_handle_t xconn_vhdl, +pcibr_hints_intr_bits(vertex_hdl_t xconn_vhdl, pcibr_intr_bits_f *xxx_intr_bits) { pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); @@ -124,7 +123,7 @@ } void -pcibr_set_rrb_callback(devfs_handle_t xconn_vhdl, rrb_alloc_funct_t rrb_alloc_funct) +pcibr_set_rrb_callback(vertex_hdl_t xconn_vhdl, rrb_alloc_funct_t rrb_alloc_funct) { pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); @@ -133,7 +132,7 @@ } void -pcibr_hints_handsoff(devfs_handle_t xconn_vhdl) +pcibr_hints_handsoff(vertex_hdl_t xconn_vhdl) { pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); @@ -145,13 +144,13 @@ } void -pcibr_hints_subdevs(devfs_handle_t xconn_vhdl, +pcibr_hints_subdevs(vertex_hdl_t xconn_vhdl, pciio_slot_t slot, uint64_t subdevs) { arbitrary_info_t ainfo = 0; char sdname[16]; - devfs_handle_t pconn_vhdl = GRAPH_VERTEX_NONE; + vertex_hdl_t pconn_vhdl = GRAPH_VERTEX_NONE; sprintf(sdname, "%s/%d", EDGE_LBL_PCI, slot); (void) hwgraph_path_add(xconn_vhdl, sdname, &pconn_vhdl); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,29 +27,35 @@ #include #include #include -#include #include #include #ifdef __ia64 -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc +inline int +compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr) +{ + FIXME("compare_and_swap_ptr : NOT ATOMIC"); + if (*location == old_ptr) { + *location = new_ptr; + return(1); + } + else + return(0); +} #endif unsigned pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines, int nslots); -pcibr_intr_t pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +pcibr_intr_t pcibr_intr_alloc(vertex_hdl_t, device_desc_t, pciio_intr_line_t, vertex_hdl_t); void pcibr_intr_free(pcibr_intr_t); void pcibr_setpciint(xtalk_intr_t); int pcibr_intr_connect(pcibr_intr_t, intr_func_t, intr_arg_t); void pcibr_intr_disconnect(pcibr_intr_t); -devfs_handle_t pcibr_intr_cpu_get(pcibr_intr_t); +vertex_hdl_t pcibr_intr_cpu_get(pcibr_intr_t); void pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); void pcibr_intr_func(intr_arg_t); -extern pcibr_info_t pcibr_info_get(devfs_handle_t); +extern pcibr_info_t pcibr_info_get(vertex_hdl_t); /* ===================================================================== * INTERRUPT MANAGEMENT @@ -132,6 +138,102 @@ } /* + * On SN systems there is a race condition between a PIO read response + * and DMA's. In rare cases, the read response may beat the DMA, causing + * the driver to think that data in memory is complete and meaningful. + * This code eliminates that race. + * This routine is called by the PIO read routines after doing the read. + * This routine then forces a fake interrupt on another line, which + * is logically associated with the slot that the PIO is addressed to. + * (see sn_dma_flush_init() ) + * It then spins while watching the memory location that the interrupt + * is targetted to. When the interrupt response arrives, we are sure + * that the DMA has landed in memory and it is safe for the driver + * to proceed. + */ + +extern struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS]; + +void +sn_dma_flush(unsigned long addr) { + nasid_t nasid; + int wid_num; + volatile struct sn_flush_device_list *p; + int i,j; + int bwin; + unsigned long flags; + + nasid = NASID_GET(addr); + wid_num = SWIN_WIDGETNUM(addr); + bwin = BWIN_WINDOWNUM(addr); + + if (flush_nasid_list[nasid].widget_p == NULL) return; + if (bwin > 0) { + bwin--; + switch (bwin) { + case 0: + wid_num = ((flush_nasid_list[nasid].iio_itte1) >> 8) & 0xf; + break; + case 1: + wid_num = ((flush_nasid_list[nasid].iio_itte2) >> 8) & 0xf; + break; + case 2: + wid_num = ((flush_nasid_list[nasid].iio_itte3) >> 8) & 0xf; + break; + case 3: + wid_num = ((flush_nasid_list[nasid].iio_itte4) >> 8) & 0xf; + break; + case 4: + wid_num = ((flush_nasid_list[nasid].iio_itte5) >> 8) & 0xf; + break; + case 5: + wid_num = ((flush_nasid_list[nasid].iio_itte6) >> 8) & 0xf; + break; + case 6: + wid_num = ((flush_nasid_list[nasid].iio_itte7) >> 8) & 0xf; + break; + } + } + if (flush_nasid_list[nasid].widget_p == NULL) return; + if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) return; + p = &flush_nasid_list[nasid].widget_p[wid_num][0]; + + // find a matching BAR + + for (i=0; ibar_list[j].start == 0) break; + if (addr >= p->bar_list[j].start && addr <= p->bar_list[j].end) break; + } + if (j < PCI_ROM_RESOURCE && p->bar_list[j].start != 0) break; + p++; + } + + // if no matching BAR, return without doing anything. + + if (i == DEV_PER_WIDGET) return; + + spin_lock_irqsave(&p->flush_lock, flags); + + p->flush_addr = 0; + + // force an interrupt. + + *(bridgereg_t *)(p->force_int_addr) = 1; + + // wait for the interrupt to come back. + + while (p->flush_addr != 0x10f); + + // okay, everything is synched up. + spin_unlock_irqrestore(&p->flush_lock, flags); + + return; +} + +EXPORT_SYMBOL(sn_dma_flush); + +/* * There are end cases where a deadlock can occur if interrupt * processing completes and the Bridge b_int_status bit is still set. * @@ -164,51 +266,42 @@ * to check if a specific Bridge b_int_status bit is set, and if so, * cause the setting of the corresponding interrupt bit. * - * On a XBridge (SN1), we do this by writing the appropriate Bridge Force - * Interrupt register. On SN0, or SN1 with an older Bridge, the Bridge - * Force Interrupt register does not exist, so we write the Hub - * INT_PEND_MOD register directly. Likewise for Octane, where we write the - * Heart Set Interrupt Status register directly. + * On a XBridge (SN1) and PIC (SN2), we do this by writing the appropriate Bridge Force + * Interrupt register. */ void -pcibr_force_interrupt(pcibr_intr_wrap_t wrap) +pcibr_force_interrupt(pcibr_intr_t intr) { -#ifdef PIC_LATER unsigned bit; - pcibr_soft_t pcibr_soft = wrap->iw_soft; + unsigned bits; + pcibr_soft_t pcibr_soft = intr->bi_soft; bridge_t *bridge = pcibr_soft->bs_base; - bit = wrap->iw_ibit; + bits = intr->bi_ibits; + for (bit = 0; bit < 8; bit++) { + if (bits & (1 << bit)) { - PCIBR_DEBUG((PCIBR_DEBUG_INTR, pcibr_soft->bs_vhdl, - "pcibr_force_interrupt: bit=0x%x\n", bit)); + PCIBR_DEBUG((PCIBR_DEBUG_INTR, pcibr_soft->bs_vhdl, + "pcibr_force_interrupt: bit=0x%x\n", bit)); - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - bridge->b_force_pin[bit].intr = 1; - } else if ((1 << bit) & *wrap->iw_stat) { - cpuid_t cpu; - unsigned intr_bit; - xtalk_intr_t xtalk_intr = - pcibr_soft->bs_intr[bit].bsi_xtalk_intr; - - intr_bit = (short) xtalk_intr_vector_get(xtalk_intr); - cpu = xtalk_intr_cpuid_get(xtalk_intr); - REMOTE_CPU_SEND_INTR(cpu, intr_bit); + if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { + bridge->b_force_pin[bit].intr = 1; + } + } } -#endif /* PIC_LATER */ } /*ARGSUSED */ pcibr_intr_t -pcibr_intr_alloc(devfs_handle_t pconn_vhdl, +pcibr_intr_alloc(vertex_hdl_t pconn_vhdl, device_desc_t dev_desc, pciio_intr_line_t lines, - devfs_handle_t owner_dev) + vertex_hdl_t owner_dev) { pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pcibr_info); pcibr_soft_t pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast; - devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + vertex_hdl_t xconn_vhdl = pcibr_soft->bs_conn; bridge_t *bridge = pcibr_soft->bs_base; int is_threaded = 0; @@ -498,25 +591,18 @@ { iopaddr_t addr; xtalk_intr_vector_t vect; - devfs_handle_t vhdl; + vertex_hdl_t vhdl; bridge_t *bridge; + picreg_t *int_addr; addr = xtalk_intr_addr_get(xtalk_intr); vect = xtalk_intr_vector_get(xtalk_intr); vhdl = xtalk_intr_dev_get(xtalk_intr); bridge = (bridge_t *)xtalk_piotrans_addr(vhdl, 0, 0, sizeof(bridge_t), 0); - if (is_pic(bridge)) { - picreg_t *int_addr; - int_addr = (picreg_t *)xtalk_intr_sfarg_get(xtalk_intr); - *int_addr = ((PIC_INT_ADDR_FLD & ((uint64_t)vect << 48)) | + int_addr = (picreg_t *)xtalk_intr_sfarg_get(xtalk_intr); + *int_addr = ((PIC_INT_ADDR_FLD & ((uint64_t)vect << 48)) | (PIC_INT_ADDR_HOST & addr)); - } else { - bridgereg_t *int_addr; - int_addr = (bridgereg_t *)xtalk_intr_sfarg_get(xtalk_intr); - *int_addr = ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) | - (BRIDGE_INT_ADDR_FLD & vect)); - } } /*ARGSUSED */ @@ -582,8 +668,7 @@ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev, "pcibr_setpciint: int_addr=0x%x, *int_addr=0x%x, " "pcibr_int_bit=0x%x\n", int_addr, - (is_pic(bridge) ? - *(picreg_t *)int_addr : *(bridgereg_t *)int_addr), + *(picreg_t *)int_addr, pcibr_int_bit)); } @@ -699,7 +784,7 @@ xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr, pcibr_intr_func, (intr_arg_t) intr_wrap, (xtalk_intr_setfunc_t)pcibr_setpciint, - (void *)pcibr_int_bit); + (void *)(long)pcibr_int_bit); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev, "pcibr_intr_disconnect: now-sharing int_bits=0x%x\n", pcibr_int_bit)); @@ -707,7 +792,7 @@ } /*ARGSUSED */ -devfs_handle_t +vertex_hdl_t pcibr_intr_cpu_get(pcibr_intr_t pcibr_intr) { pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; @@ -780,9 +865,6 @@ bridge->b_wid_int_lower = NEW_b_wid_int_lower; bridge->b_int_host_err = vect; -printk("pcibr_setwidint: b_wid_int_upper 0x%x b_wid_int_lower 0x%x b_int_host_err 0x%x\n", - NEW_b_wid_int_upper, NEW_b_wid_int_lower, vect); - } /* @@ -842,7 +924,7 @@ * * This is the pcibr interrupt "wrapper" function that is called, * in interrupt context, to initiate the interrupt handler(s) registered - * (via pcibr_intr_alloc/connect) for the occuring interrupt. Non-threaded + * (via pcibr_intr_alloc/connect) for the occurring interrupt. Non-threaded * handlers will be called directly, and threaded handlers will have their * thread woken up. */ @@ -957,7 +1039,7 @@ * interrupt to avoid a potential deadlock situation. */ if (wrap->iw_hdlrcnt == 0) { - pcibr_force_interrupt(wrap); + pcibr_force_interrupt((pcibr_intr_t) wrap); } } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -41,11 +40,11 @@ void do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int, int); -int pcibr_wrb_flush(devfs_handle_t); -int pcibr_rrb_alloc(devfs_handle_t, int *, int *); -int pcibr_rrb_check(devfs_handle_t, int *, int *, int *, int *); -void pcibr_rrb_flush(devfs_handle_t); -int pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t); +int pcibr_wrb_flush(vertex_hdl_t); +int pcibr_rrb_alloc(vertex_hdl_t, int *, int *); +int pcibr_rrb_check(vertex_hdl_t, int *, int *, int *, int *); +void pcibr_rrb_flush(vertex_hdl_t); +int pcibr_slot_initial_rrb_alloc(vertex_hdl_t,pciio_slot_t); void pcibr_rrb_debug(char *, pcibr_soft_t); @@ -70,17 +69,15 @@ #define RRB_SIZE (4) /* sizeof rrb within reg (bits) */ #define RRB_ENABLE_BIT(bridge) (0x8) /* [BRIDGE | PIC]_RRB_EN */ -#define NUM_PDEV_BITS(bridge) (is_pic((bridge)) ? 1 : 2) -#define NUM_VDEV_BITS(bridge) (is_pic((bridge)) ? 2 : 1) -#define NUMBER_VCHANNELS(bridge) (is_pic((bridge)) ? 4 : 2) +#define NUM_PDEV_BITS(bridge) (1) +#define NUM_VDEV_BITS(bridge) (2) +#define NUMBER_VCHANNELS(bridge) (4) #define SLOT_2_PDEV(bridge, slot) ((slot) >> 1) #define SLOT_2_RRB_REG(bridge, slot) ((slot) & 0x1) /* validate that the slot and virtual channel are valid for a given bridge */ #define VALIDATE_SLOT_n_VCHAN(bridge, s, v) \ - (is_pic((bridge)) ? \ - (((((s) != PCIIO_SLOT_NONE) && ((s) <= (pciio_slot_t)3)) && (((v) >= 0) && ((v) <= 3))) ? 1 : 0) : \ - (((((s) != PCIIO_SLOT_NONE) && ((s) <= (pciio_slot_t)7)) && (((v) >= 0) && ((v) <= 1))) ? 1 : 0)) + (((((s) != PCIIO_SLOT_NONE) && ((s) <= (pciio_slot_t)3)) && (((v) >= 0) && ((v) <= 3))) ? 1 : 0) /* * Count how many RRBs are marked valid for the specified PCI slot @@ -105,16 +102,7 @@ pdev_bits = SLOT_2_PDEV(bridge, slot); rrb_bits = enable_bit | vchan_bits | pdev_bits; - if ( is_pic(bridge) ) { - tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - tmp = BRIDGE_REG_GET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)); - } else { - tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - } + tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; for (rrb_index = 0; rrb_index < 8; rrb_index++) { if ((tmp & RRB_MASK) == rrb_bits) @@ -144,16 +132,7 @@ enable_bit = RRB_ENABLE_BIT(bridge); - if ( is_pic(bridge) ) { - tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - tmp = BRIDGE_REG_GET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)); - } else { - tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - } + tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; for (rrb_index = 0; rrb_index < 8; rrb_index++) { if ((tmp & enable_bit) != enable_bit) @@ -192,17 +171,8 @@ pdev_bits = SLOT_2_PDEV(bridge, slot); rrb_bits = enable_bit | vchan_bits | pdev_bits; - if ( is_pic(bridge) ) { - reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - reg = tmp = BRIDGE_REG_GET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)); - } else { - reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - } - + reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; + for (rrb_index = 0; ((rrb_index < 8) && (more > 0)); rrb_index++) { if ((tmp & enable_bit) != enable_bit) { /* clear the rrb and OR in the new rrb into 'reg' */ @@ -213,16 +183,7 @@ tmp = (tmp >> RRB_SIZE); } - if ( is_pic(bridge) ) { - bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)) = reg; - } else { - bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; - } - } + bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; return (more ? -1 : 0); } @@ -255,24 +216,15 @@ pdev_bits = SLOT_2_PDEV(bridge, slot); rrb_bits = enable_bit | vchan_bits | pdev_bits; - if ( is_pic(bridge) ) { - reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - reg = BRIDGE_REG_GET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)); - } else { - reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; - } - } - + reg = tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg; + for (rrb_index = 0; ((rrb_index < 8) && (less > 0)); rrb_index++) { if ((tmp & RRB_MASK) == rrb_bits) { /* * the old do_pcibr_rrb_free() code only clears the enable bit * but I say we should clear the whole rrb (ie): * reg = reg & ~(RRB_MASK << (RRB_SIZE * rrb_index)); - * But to be compatable with old code we'll only clear enable. + * But to be compatible with old code we'll only clear enable. */ reg = reg & ~(RRB_ENABLE_BIT(bridge) << (RRB_SIZE * rrb_index)); clr = clr | (enable_bit << (RRB_SIZE * rrb_index)); @@ -281,16 +233,7 @@ tmp = (tmp >> RRB_SIZE); } - if ( is_pic(bridge) ) { - bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg)) = reg; - } else { - bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; - } - } + bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg = reg; /* call do_pcibr_rrb_clear() for all the rrbs we've freed */ for (rrb_index = 0; rrb_index < 8; rrb_index++) { @@ -337,50 +280,18 @@ * this RRB must be disabled. */ - if ( is_pic(bridge) ) { - /* wait until RRB has no outstanduing XIO packets. */ - while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - - /* if the RRB has data, drain it. */ - if (status & BRIDGE_RRB_VALID(rrb)) { - bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb); - - /* wait until RRB is no longer valid. */ - while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - } + /* wait until RRB has no outstanduing XIO packets. */ + while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) { + ; /* XXX- beats on bridge. bad idea? */ } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - while ((status = BRIDGE_REG_GET32((&bridge->b_resp_status))) & BRIDGE_RRB_INUSE(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - - /* if the RRB has data, drain it. */ - if (status & BRIDGE_RRB_VALID(rrb)) { - BRIDGE_REG_SET32((&bridge->b_resp_clear)) = __swab32(BRIDGE_RRB_CLEAR(rrb)); - - /* wait until RRB is no longer valid. */ - while ((status = BRIDGE_REG_GET32((&bridge->b_resp_status))) & BRIDGE_RRB_VALID(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - } - } else { /* io_get_sh_swapper(NASID_GET(bridge)) */ - while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - - /* if the RRB has data, drain it. */ - if (status & BRIDGE_RRB_VALID(rrb)) { - bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb); - /* wait until RRB is no longer valid. */ - while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) { - ; /* XXX- beats on bridge. bad idea? */ - } - } + + /* if the RRB has data, drain it. */ + if (status & BRIDGE_RRB_VALID(rrb)) { + bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb); + + /* wait until RRB is no longer valid. */ + while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) { + ; /* XXX- beats on bridge. bad idea? */ } } } @@ -399,43 +310,16 @@ int shft = (RRB_SIZE * (rrbn >> 1)); unsigned long ebit = RRB_ENABLE_BIT(bridge) << shft; - if ( is_pic(bridge) ) { - rrbv = *rrbp; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - rrbv = BRIDGE_REG_GET32((&rrbp)); - } else { - rrbv = *rrbp; - } - } + rrbv = *rrbp; if (rrbv & ebit) { - if ( is_pic(bridge) ) { - *rrbp = rrbv & ~ebit; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&rrbp)) = __swab32((rrbv & ~ebit)); - } else { - *rrbp = rrbv & ~ebit; - } - } + *rrbp = rrbv & ~ebit; } do_pcibr_rrb_clear(bridge, rrbn); if (rrbv & ebit) { - if ( is_pic(bridge) ) { - *rrbp = rrbv; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&rrbp)) = __swab32(rrbv); - } else { - *rrbp = rrbv; - } - } + *rrbp = rrbv; } } @@ -475,7 +359,7 @@ * Flush all the rrb's assigned to the specified connection point. */ void -pcibr_rrb_flush(devfs_handle_t pconn_vhdl) +pcibr_rrb_flush(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pcibr_soft_t pcibr_soft = (pcibr_soft_t)pciio_info_mfast_get(pciio_info); @@ -510,7 +394,7 @@ * device hanging off the bridge. */ int -pcibr_wrb_flush(devfs_handle_t pconn_vhdl) +pcibr_wrb_flush(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); @@ -546,7 +430,7 @@ * as best we can and return 0. */ int -pcibr_rrb_alloc(devfs_handle_t pconn_vhdl, +pcibr_rrb_alloc(vertex_hdl_t pconn_vhdl, int *count_vchan0, int *count_vchan1) { @@ -753,7 +637,7 @@ */ int -pcibr_rrb_check(devfs_handle_t pconn_vhdl, +pcibr_rrb_check(vertex_hdl_t pconn_vhdl, int *count_vchan0, int *count_vchan1, int *count_reserved, @@ -802,7 +686,7 @@ */ int -pcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl, +pcibr_slot_initial_rrb_alloc(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; @@ -816,10 +700,10 @@ pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) - return(EINVAL); + return(-EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) - return(EINVAL); + return(-EINVAL); bridge = pcibr_soft->bs_base; @@ -857,7 +741,13 @@ pcibr_soft->bs_rrb_valid[slot][3] = chan[3]; - return(ENODEV); + return(-ENODEV); + } + + /* Give back any assigned to empty slots */ + if ((pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) && !pcibr_soft->bs_slot[slot].has_host) { + do_pcibr_rrb_free_all(pcibr_soft, bridge, slot); + return(-ENODEV); } for (vchan = 0; vchan < vchan_total; vchan++) @@ -889,7 +779,7 @@ */ int -pcibr_initial_rrb(devfs_handle_t pcibr_vhdl, +pcibr_initial_rrb(vertex_hdl_t pcibr_vhdl, pciio_slot_t first, pciio_slot_t last) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Wed Jul 23 18:29:00 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -28,55 +28,44 @@ #include #include #include -#include #include #include -#include -#ifdef __ia64 -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc -#endif - - -extern pcibr_info_t pcibr_info_get(devfs_handle_t); -extern int pcibr_widget_to_bus(devfs_handle_t pcibr_vhdl); +extern pcibr_info_t pcibr_info_get(vertex_hdl_t); +extern int pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl); extern pcibr_info_t pcibr_device_info_new(pcibr_soft_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); -extern int pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t); +extern int pcibr_slot_initial_rrb_alloc(vertex_hdl_t,pciio_slot_t); extern int pcibr_pcix_rbars_calc(pcibr_soft_t); -int pcibr_slot_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); -int pcibr_slot_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); -int pcibr_slot_addr_space_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); +int pcibr_slot_info_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); +int pcibr_slot_info_free(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); +int pcibr_slot_addr_space_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); int pcibr_slot_pcix_rbar_init(pcibr_soft_t pcibr_soft, pciio_slot_t slot); -int pcibr_slot_device_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); -int pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); -int pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl, +int pcibr_slot_device_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); +int pcibr_slot_guest_info_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); +int pcibr_slot_call_device_attach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags); -int pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl, +int pcibr_slot_call_device_detach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags); -int pcibr_slot_detach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, +int pcibr_slot_detach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp); -int pcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl, pciio_slot_t slot); static int pcibr_probe_slot(bridge_t *, cfg_p, unsigned int *); -void pcibr_device_info_free(devfs_handle_t, pciio_slot_t); +void pcibr_device_info_free(vertex_hdl_t, pciio_slot_t); iopaddr_t pcibr_bus_addr_alloc(pcibr_soft_t, pciio_win_info_t, pciio_space_t, int, int, int); void pciibr_bus_addr_free(pcibr_soft_t, pciio_win_info_t); cfg_p pcibr_find_capability(cfg_p, unsigned); -extern uint64_t do_pcibr_config_get(int, cfg_p, unsigned, unsigned); -void do_pcibr_config_set(int, cfg_p, unsigned, unsigned, uint64_t); +extern uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned); +void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); -int pcibr_slot_attach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, +int pcibr_slot_attach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp); int pcibr_slot_info_return(pcibr_soft_t pcibr_soft, pciio_slot_t slot, pcibr_slot_info_resp_t respp); -extern devfs_handle_t baseio_pci_vhdl; -int scsi_ctlr_nums_add(devfs_handle_t, devfs_handle_t); +extern vertex_hdl_t baseio_pci_vhdl; +int scsi_ctlr_nums_add(vertex_hdl_t, vertex_hdl_t); /* For now .... */ @@ -111,7 +100,7 @@ #ifdef PIC_LATER int -pcibr_slot_startup(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp) +pcibr_slot_startup(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pciio_slot_t slot; @@ -127,11 +116,6 @@ /* req_slot is the 'external' slot number, convert for internal use */ slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); - /* Do not allow start-up of a slot in a shoehorn */ - if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) { - return(PCI_SLOT_IN_SHOEHORN); - } - /* Check for the valid slot */ if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(PCI_NOT_A_SLOT); @@ -170,7 +154,7 @@ * Software shut-down the PCI slot */ int -pcibr_slot_shutdown(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp) +pcibr_slot_shutdown(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge_t *bridge; @@ -194,11 +178,6 @@ if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(PCI_NOT_A_SLOT); - /* Do not allow shut-down of a slot in a shoehorn */ - if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) { - return(PCI_SLOT_IN_SHOEHORN); - } - #ifdef PIC_LATER /* Acquire update access to the bus */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO); @@ -284,7 +263,6 @@ { pcibr_info_t pcibr_info = pcibr_infoh[func]; int win; - boolean_t is_sys_critical_vertex(devfs_handle_t); funcp->resp_f_status = 0; @@ -296,9 +274,6 @@ #if defined(SUPPORT_PRINTING_V_FORMAT) sprintf(funcp->resp_f_slot_name, "%v", pcibr_info->f_vertex); #endif - if(is_sys_critical_vertex(pcibr_info->f_vertex)) { - funcp->resp_f_status |= FUNC_IS_SYS_CRITICAL; - } funcp->resp_f_bus = pcibr_info->f_bus; funcp->resp_f_slot = PCIBR_INFO_SLOT_GET_EXT(pcibr_info); @@ -345,7 +320,6 @@ reg_p b_respp; pcibr_slot_info_resp_t slotp; pcibr_slot_func_info_resp_t funcp; - boolean_t is_sys_critical_vertex(devfs_handle_t); extern void snia_kmem_free(void *, int); slotp = snia_kmem_zalloc(sizeof(*slotp), 0); @@ -368,11 +342,6 @@ slotp->resp_slot_status = pss->slot_status; slotp->resp_l1_bus_num = pcibr_widget_to_bus(pcibr_soft->bs_vhdl); - - if (is_sys_critical_vertex(pss->slot_conn)) { - slotp->resp_slot_status |= SLOT_IS_SYS_CRITICAL; - } - slotp->resp_bss_ninfo = pss->bss_ninfo; for (func = 0; func < pss->bss_ninfo; func++) { @@ -455,7 +424,7 @@ * External SSRAM workaround info */ int -pcibr_slot_query(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp) +pcibr_slot_query(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pciio_slot_t slot; @@ -481,11 +450,6 @@ return(PCI_NOT_A_SLOT); } - /* Do not allow a query of a slot in a shoehorn */ - if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) { - return(PCI_SLOT_IN_SHOEHORN); - } - /* Return information for the requested PCI slot */ if (slot != PCIIO_SLOT_NONE) { if (size < sizeof(*respp)) { @@ -534,88 +498,6 @@ return(error); } -#if 0 -/* - * pcibr_slot_reset - * Reset the PCI device in the particular slot. - * - * The Xbridge does not comply with the PCI Specification - * when resetting an indiviaudl slot. An individual slot is - * is reset by toggling the slot's bit in the Xbridge Control - * Register. The Xbridge will assert the target slot's - * (non-bussed) RST signal, but does not assert the (bussed) - * REQ64 signal as required by the specification. As - * designed, the Xbridge cannot assert the REQ64 signal - * becuase it may interfere with a bus transaction in progress. - * The practical effects of this Xbridge implementation is - * device dependent; it probably will not adversely effect - * 32-bit cards, but may disable 64-bit data transfers by those - * cards that normally support 64-bit data transfers. - * - * The Xbridge will assert REQ64 when all four slots are reset - * by simultaneously toggling all four slot reset bits in the - * Xbridge Control Register. This is basically a PCI bus reset - * and asserting the (bussed) REQ64 signal will not interfere - * with any bus transactions in progress. - * - * The Xbridge (and the SN0 Bridge) support resetting only - * four PCI bus slots via the (X)bridge Control Register. - * - * To reset an individual slot for the PCI Hot-Plug feature - * use the L1 console commands to power-down and then - * power-up the slot, or use the kernel infrastructure - * functions to power-down/up the slot when they are - * implemented for SN1. - */ -int -pcibr_slot_reset(devfs_handle_t pcibr_vhdl, pciio_slot_t slot) -{ - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - bridge_t *bridge; - bridgereg_t ctrlreg,tmp; - volatile bridgereg_t *wrb_flush; - - if (!pcibr_soft) - return(EINVAL); - - if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) - return(EINVAL); - - /* Enable the DMA operations from this device of the xtalk widget - * (PCI host bridge in this case). - */ - xtalk_widgetdev_enable(pcibr_soft->bs_conn, slot); - - /* Set the reset slot bit in the bridge's wid control register - * to reset the PCI slot - */ - bridge = pcibr_soft->bs_base; - - /* Read the bridge widget control and clear out the reset pin - * bit for the corresponding slot. - */ - tmp = ctrlreg = bridge->b_wid_control; - - tmp &= ~BRIDGE_CTRL_RST_PIN(slot); - - bridge->b_wid_control = tmp; - tmp = bridge->b_wid_control; - - /* Restore the old control register back. - * NOTE : PCI card gets reset when the reset pin bit - * changes from 0 (set above) to 1 (going to be set now). - */ - - bridge->b_wid_control = ctrlreg; - - /* Flush the write buffers if any !! */ - wrb_flush = &(bridge->b_wr_req_buf[slot].reg); - while (*wrb_flush); - - return(0); -} -#endif - #define PROBE_LOCK 0 /* FIXME: we're attempting to lock around accesses * to b_int_enable. This hangs pcibr_probe_slot() */ @@ -627,7 +509,7 @@ * information associated with this particular PCI device. */ int -pcibr_slot_info_init(devfs_handle_t pcibr_vhdl, +pcibr_slot_info_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; @@ -650,7 +532,7 @@ int nfunc; pciio_function_t rfunc; int func; - devfs_handle_t conn_vhdl; + vertex_hdl_t conn_vhdl; pcibr_soft_slot_t slotp; /* Get the basic software information required to proceed */ @@ -669,10 +551,6 @@ return(0); } - /* Check for a slot with any system critical functions */ - if (pcibr_is_slot_sys_critical(pcibr_vhdl, slot)) - return(EPERM); - /* Try to read the device-id/vendor-id from the config space */ cfgw = pcibr_slot_config_addr(bridge, slot, 0); @@ -701,7 +579,7 @@ if (vendor == 0xFFFF) return(ENODEV); - htype = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_HEADER_TYPE, 1); + htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1); nfunc = 1; rfunc = PCIIO_FUNC_NONE; pfail = 0; @@ -750,7 +628,7 @@ cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); device = 0xFFFF & (idword >> 16); - htype = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_HEADER_TYPE, 1); + htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1); rfunc = func; } htype &= 0x7f; @@ -803,23 +681,17 @@ * 'min_gnt' and attempt to calculate a latency time. * * NOTE: For now if the device is on the 'real time' arbitration - * ring we dont set the latency timer. + * ring we don't set the latency timer. * * WAR: SGI's IOC3 and RAD devices target abort if you write a * single byte into their config space. So don't set the Latency * Timer for these devices */ - lt_time = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_LATENCY_TIMER, 1); + lt_time = do_pcibr_config_get(cfgw, PCI_CFG_LATENCY_TIMER, 1); if ((lt_time == 0) && !(bridge->b_device[slot].reg & BRIDGE_DEV_RT) && - !((vendor == IOC3_VENDOR_ID_NUM) && - ( -#ifdef PIC_LATER - (device == IOC3_DEVICE_ID_NUM) || - (device == LINC_DEVICE_ID_NUM) || -#endif - (device == 0x5 /* RAD_DEV */)))) { + (device == 0x5 /* RAD_DEV */)) { unsigned min_gnt; unsigned min_gnt_mult; @@ -827,7 +699,7 @@ * needs in increments of 250ns. But latency timer is in * PCI clock cycles, so a conversion is needed. */ - min_gnt = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_MIN_GNT, 1); + min_gnt = do_pcibr_config_get(cfgw, PCI_MIN_GNT, 1); if (IS_133MHZ(pcibr_soft)) min_gnt_mult = 32; /* 250ns @ 133MHz in clocks */ @@ -843,7 +715,7 @@ else lt_time = 4 * min_gnt_mult; /* 1 micro second */ - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_LATENCY_TIMER, 1, lt_time); + do_pcibr_config_set(cfgw, PCI_CFG_LATENCY_TIMER, 1, lt_time); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_CONFIG, pcibr_vhdl, "pcibr_slot_info_init: set Latency Timer for slot=%d, " @@ -851,12 +723,27 @@ PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, lt_time)); } - /* Get the PCI-X capability if running in PCI-X mode. If the func - * doesnt have a pcix capability, allocate a PCIIO_VENDOR_ID_NONE - * pcibr_info struct so the device driver for that function is not - * called. + + /* In our architecture the setting of the cacheline size isn't + * beneficial for cards in PCI mode, but in PCI-X mode devices + * can optionally use the cacheline size value for internal + * device optimizations (See 7.1.5 of the PCI-X v1.0 spec). + * NOTE: cachline size is in doubleword increments */ if (IS_PCIX(pcibr_soft)) { + if (!do_pcibr_config_get(cfgw, PCI_CFG_CACHE_LINE, 1)) { + do_pcibr_config_set(cfgw, PCI_CFG_CACHE_LINE, 1, 0x20); + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_CONFIG, pcibr_vhdl, + "pcibr_slot_info_init: set CacheLine for slot=%d, " + "func=%d, to 0x20\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func)); + } + + /* Get the PCI-X capability if running in PCI-X mode. If the func + * doesnt have a pcix capability, allocate a PCIIO_VENDOR_ID_NONE + * pcibr_info struct so the device driver for that function is not + * called. + */ if (!(pcix_cap = pcibr_find_capability(cfgw, PCI_CAP_PCIX))) { printk(KERN_WARNING #if defined(SUPPORT_PRINTING_V_FORMAT) @@ -898,7 +785,7 @@ if (func == 0) slotp->slot_conn = conn_vhdl; - cmd_reg = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4); + cmd_reg = do_pcibr_config_get(cfgw, PCI_CFG_COMMAND, 4); wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; @@ -949,7 +836,7 @@ * this could be pushed up into pciio, when we * start supporting more PCI providers. */ - base = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4); + base = do_pcibr_config_get(wptr, (win * 4), 4); if (base & PCI_BA_IO_SPACE) { /* BASE is in I/O space. */ @@ -975,7 +862,7 @@ } else if (base & 0xC0000000) { base = 0; /* outside permissable range */ } else if ((code == PCI_BA_MEM_64BIT) && - (do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, ((win + 1)*4), 4) != 0)) { + (do_pcibr_config_get(wptr, ((win + 1)*4), 4) != 0)) { base = 0; /* outside permissable range */ } } @@ -983,8 +870,8 @@ if (base != 0) { /* estimate size */ size = base & -base; } else { /* calculate size */ - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4, ~0); /* write 1's */ - size = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4); /* read back */ + do_pcibr_config_set(wptr, (win * 4), 4, ~0); /* write 1's */ + size = do_pcibr_config_get(wptr, (win * 4), 4); /* read back */ size &= mask; /* keep addr */ size &= -size; /* keep lsbit */ if (size == 0) @@ -995,45 +882,9 @@ pcibr_info->f_window[win].w_base = base; pcibr_info->f_window[win].w_size = size; -#if defined(IOC3_VENDOR_ID_NUM) && defined(IOC3_DEVICE_ID_NUM) - /* - * IOC3 BASE_ADDR* BUG WORKAROUND - * - - * If we write to BASE1 on the IOC3, the - * data in BASE0 is replaced. The - * original workaround was to remember - * the value of BASE0 and restore it - * when we ran off the end of the BASE - * registers; however, a later - * workaround was added (I think it was - * rev 1.44) to avoid setting up - * anything but BASE0, with the comment - * that writing all ones to BASE1 set - * the enable-parity-error test feature - * in IOC3's SCR bit 14. - * - * So, unless we defer doing any PCI - * space allocation until drivers - * attach, and set up a way for drivers - * (the IOC3 in paricular) to tell us - * generically to keep our hands off - * BASE registers, we gotta "know" about - * the IOC3 here. - * - * Too bad the PCI folks didn't reserve the - * all-zero value for 'no BASE here' (it is a - * valid code for an uninitialized BASE in - * 32-bit PCI memory space). - */ - - if ((vendor == IOC3_VENDOR_ID_NUM) && - (device == IOC3_DEVICE_ID_NUM)) - break; -#endif if (code == PCI_BA_MEM_64BIT) { win++; /* skip upper half */ - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4, 0); /* must be zero */ + do_pcibr_config_set(wptr, (win * 4), 4, 0); /* must be zero */ } } /* next win */ } /* next func */ @@ -1056,7 +907,7 @@ int defend_against_circular_linkedlist = 0; /* Check to see if there is a capabilities pointer in the cfg header */ - if (!(do_pcibr_config_get(1, cfgw, PCI_CFG_STATUS, 2) & PCI_STAT_CAP_LIST)) { + if (!(do_pcibr_config_get(cfgw, PCI_CFG_STATUS, 2) & PCI_STAT_CAP_LIST)) { return (NULL); } @@ -1067,14 +918,14 @@ * significant bits of the next pointer must be ignored, so we mask * with 0xfc). */ - cap_nxt = (do_pcibr_config_get(1, cfgw, PCI_CAPABILITIES_PTR, 1) & 0xfc); + cap_nxt = (do_pcibr_config_get(cfgw, PCI_CAPABILITIES_PTR, 1) & 0xfc); while (cap_nxt && (defend_against_circular_linkedlist <= 48)) { - cap_id = do_pcibr_config_get(1, cfgw, cap_nxt, 1); + cap_id = do_pcibr_config_get(cfgw, cap_nxt, 1); if (cap_id == capability) { return ((cfg_p)((char *)cfgw + cap_nxt)); } - cap_nxt = (do_pcibr_config_get(1, cfgw, cap_nxt+1, 1) & 0xfc); + cap_nxt = (do_pcibr_config_get(cfgw, cap_nxt+1, 1) & 0xfc); defend_against_circular_linkedlist++; } @@ -1087,7 +938,7 @@ * with a particular PCI device. */ int -pcibr_slot_info_free(devfs_handle_t pcibr_vhdl, +pcibr_slot_info_free(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; @@ -1223,20 +1074,21 @@ * the base registers in the card. */ int -pcibr_slot_addr_space_init(devfs_handle_t pcibr_vhdl, +pcibr_slot_addr_space_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; bridge_t *bridge; - size_t align_slot; iopaddr_t mask; int nbars; int nfunc; int func; int win; int rc = 0; + int align; + int align_slot; pcibr_soft = pcibr_soft_get(pcibr_vhdl); @@ -1275,7 +1127,8 @@ * the entire "lo" area is only a * megabyte, total ... */ - align_slot = (slot < 2) ? 0x200000 : 0x100000; + align_slot = 0x100000; + align = align_slot; for (func = 0; func < nfunc; ++func) { cfg_p cfgw; @@ -1300,7 +1153,7 @@ cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; - if ((do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0) + if ((do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0) nbars = 2; else nbars = PCI_CFG_BASE_ADDRS; @@ -1333,23 +1186,24 @@ continue; /* already allocated */ } + align = (win) ? size : align_slot; + + if (align < _PAGESZ) + align = _PAGESZ; /* ie. 0x00004000 */ + switch (space) { case PCIIO_SPACE_IO: base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_window[win], PCIIO_SPACE_IO, - 0, size, align_slot); + 0, size, align); if (!base) rc = ENOSPC; break; case PCIIO_SPACE_MEM: - if ((do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4) & + if ((do_pcibr_config_get(wptr, (win * 4), 4) & PCI_BA_MEM_LOCATION) == PCI_BA_MEM_1MEG) { - int align = size; /* ie. 0x00001000 */ - - if (align < _PAGESZ) - align = _PAGESZ; /* ie. 0x00004000 */ /* allocate from 20-bit PCI space */ base = pcibr_bus_addr_alloc(pcibr_soft, @@ -1363,7 +1217,7 @@ base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_window[win], PCIIO_SPACE_MEM32, - 0, size, align_slot); + 0, size, align); if (!base) rc = ENOSPC; } @@ -1377,7 +1231,7 @@ PCIBR_DEVICE_TO_SLOT(pcibr_soft,slot), win, space)); } pcibr_info->f_window[win].w_base = base; - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4, base); + do_pcibr_config_set(wptr, (win * 4), 4, base); #if defined(SUPPORT_PRINTING_R_FORMAT) if (pcibr_debug_mask & PCIBR_DEBUG_BAR) { @@ -1405,26 +1259,22 @@ /* * Allocate space for the EXPANSION ROM - * NOTE: DO NOT DO THIS ON AN IOC3, - * as it blows the system away. */ base = size = 0; - if ((pcibr_soft->bs_slot[slot].bss_vendor_id != IOC3_VENDOR_ID_NUM) || - (pcibr_soft->bs_slot[slot].bss_device_id != IOC3_DEVICE_ID_NUM)) { - + { wptr = cfgw + PCI_EXPANSION_ROM / 4; - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4, 0xFFFFF000); - mask = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4); + do_pcibr_config_set(wptr, 0, 4, 0xFFFFF000); + mask = do_pcibr_config_get(wptr, 0, 4); if (mask & 0xFFFFF000) { size = mask & -mask; base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_rwindow, PCIIO_SPACE_MEM32, - 0, size, align_slot); + 0, size, align); if (!base) rc = ENOSPC; else { - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4, base); + do_pcibr_config_set(wptr, 0, 4, base); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "pcibr_slot_addr_space_init: slot=%d, func=%d, " "ROM in [0x%X..0x%X], allocated by pcibr\n", @@ -1435,7 +1285,7 @@ } pcibr_info->f_rbase = base; pcibr_info->f_rsize = size; - + /* * if necessary, update the board's * command register to enable decoding @@ -1449,7 +1299,7 @@ /* * The Adaptec 1160 FC Controller WAR #767995: * The part incorrectly ignores the upper 32 bits of a 64 bit - * address when decoding references to it's registers so to + * address when decoding references to its registers so to * keep it from responding to a bus cycle that it shouldn't * we only use I/O space to get at it's registers. Don't * enable memory space accesses on that PCI device. @@ -1463,7 +1313,7 @@ pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER; - pci_cfg_cmd_reg = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4); + pci_cfg_cmd_reg = do_pcibr_config_get(cfgw, PCI_CFG_COMMAND, 4); #if PCI_FBBE /* XXX- check here to see if dev can do fast-back-to-back */ if (!((pci_cfg_cmd_reg >> 16) & PCI_STAT_F_BK_BK_CAP)) @@ -1471,7 +1321,7 @@ #endif pci_cfg_cmd_reg &= 0xFFFF; if (pci_cfg_cmd_reg_add & ~pci_cfg_cmd_reg) - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4, + do_pcibr_config_set(cfgw, PCI_CFG_COMMAND, 4, pci_cfg_cmd_reg | pci_cfg_cmd_reg_add); } /* next func */ return(rc); @@ -1483,7 +1333,7 @@ */ int -pcibr_slot_device_init(devfs_handle_t pcibr_vhdl, +pcibr_slot_device_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; @@ -1525,8 +1375,6 @@ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pcibr_vhdl, "pcibr_slot_device_init: Device(%d): %R\n", slot, devreg, device_bits)); -#else - printk("pcibr_slot_device_init: Device(%d) 0x%x\n", slot, devreg); #endif return(0); } @@ -1536,7 +1384,7 @@ * Setup the host/guest relations for a PCI slot. */ int -pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl, +pcibr_slot_guest_info_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft; @@ -1605,18 +1453,17 @@ * card in this slot. */ int -pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl, +pcibr_slot_call_device_attach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags) { pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; - async_attach_t aa = NULL; int func; - devfs_handle_t xconn_vhdl, conn_vhdl; + vertex_hdl_t xconn_vhdl, conn_vhdl; #ifdef PIC_LATER - devfs_handle_t scsi_vhdl; + vertex_hdl_t scsi_vhdl; #endif int nfunc; int error_func; @@ -1639,7 +1486,6 @@ } xconn_vhdl = pcibr_soft->bs_conn; - aa = async_attach_get_info(xconn_vhdl); nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; @@ -1656,13 +1502,6 @@ conn_vhdl = pcibr_info->f_vertex; -#ifdef LATER - /* - * Activate if and when we support cdl. - */ - if (aa) - async_attach_add_info(conn_vhdl, aa); -#endif /* LATER */ error_func = pciio_device_attach(conn_vhdl, drv_flags); @@ -1728,7 +1567,7 @@ * card in this slot. */ int -pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl, +pcibr_slot_call_device_detach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags) { @@ -1736,7 +1575,7 @@ pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; int func; - devfs_handle_t conn_vhdl = GRAPH_VERTEX_NONE; + vertex_hdl_t conn_vhdl = GRAPH_VERTEX_NONE; int nfunc; int error_func; int error_slot = 0; @@ -1811,7 +1650,7 @@ * PCI card on the bus. */ int -pcibr_slot_attach(devfs_handle_t pcibr_vhdl, +pcibr_slot_attach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, @@ -1850,7 +1689,7 @@ * slot-specific freeing that needs to be done. */ int -pcibr_slot_detach(devfs_handle_t pcibr_vhdl, +pcibr_slot_detach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, @@ -1859,10 +1698,6 @@ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); int error; - /* Make sure that we do not detach a system critical function vertex */ - if(pcibr_is_slot_sys_critical(pcibr_vhdl, slot)) - return(PCI_IS_SYS_CRITICAL); - /* Call the device detach function */ error = (pcibr_slot_call_device_detach(pcibr_vhdl, slot, drv_flags)); if (error) { @@ -1892,61 +1727,6 @@ } /* - * pcibr_is_slot_sys_critical - * Check slot for any functions that are system critical. - * Return 1 if any are system critical or 0 otherwise. - * - * This function will always return 0 when called by - * pcibr_attach() because the system critical vertices - * have not yet been set in the hwgraph. - */ -int -pcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl, - pciio_slot_t slot) -{ - pcibr_soft_t pcibr_soft; - pcibr_info_h pcibr_infoh; - pcibr_info_t pcibr_info; - devfs_handle_t conn_vhdl = GRAPH_VERTEX_NONE; - int nfunc; - int func; - boolean_t is_sys_critical_vertex(devfs_handle_t); - - pcibr_soft = pcibr_soft_get(pcibr_vhdl); - if (!pcibr_soft) - return(EINVAL); - - if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) - return(EINVAL); - - nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; - pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; - - for (func = 0; func < nfunc; ++func) { - - pcibr_info = pcibr_infoh[func]; - if (!pcibr_info) - continue; - - if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) - continue; - - conn_vhdl = pcibr_info->f_vertex; - if (is_sys_critical_vertex(conn_vhdl)) { -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_WARNING "%v is a system critical device vertex\n", conn_vhdl); -#else - printk(KERN_WARNING "%p is a system critical device vertex\n", (void *)conn_vhdl); -#endif - return(1); - } - - } - - return(0); -} - -/* * pcibr_probe_slot_pic: read a config space word * while trapping any errors; return zero if * all went OK, or nonzero if there was an error. @@ -1984,57 +1764,6 @@ } /* - * pcibr_probe_slot_non_pic: read a config space word - * while trapping any errors; return zero if - * all went OK, or nonzero if there was an error. - * The value read, if any, is passed back - * through the valp parameter. - */ -static int -pcibr_probe_slot_non_pic(bridge_t *bridge, - cfg_p cfg, - unsigned *valp) -{ - int rv; - bridgereg_t b_old_enable = (bridgereg_t)0, b_new_enable = (bridgereg_t)0; - extern int badaddr_val(volatile void *, int, volatile void *); - - b_old_enable = bridge->b_int_enable; - b_new_enable = b_old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; - bridge->b_int_enable = b_new_enable; - - /* - * The xbridge doesn't clear b_err_int_view unless - * multi-err is cleared... - */ - if (is_xbridge(bridge)) { - if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) - bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; - } - - if (bridge->b_int_status & BRIDGE_IRR_PCI_GRP) { - bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR; - (void) bridge->b_wid_tflush; /* flushbus */ - } - rv = badaddr_val((void *) (((uint64_t)cfg) ^ 4), 4, valp); - /* - * The xbridge doesn't set master timeout in b_int_status - * here. Fortunately it's in error_interrupt_view. - */ - if (is_xbridge(bridge)) { - if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) { - bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; - rv = 1; /* unoccupied slot */ - } - } - bridge->b_int_enable = b_old_enable; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - - return(rv); -} - - -/* * pcibr_probe_slot: read a config space word * while trapping any errors; return zero if * all went OK, or nonzero if there was an error. @@ -2046,15 +1775,12 @@ cfg_p cfg, unsigned *valp) { - if ( is_pic(bridge) ) - return(pcibr_probe_slot_pic(bridge, cfg, valp)); - else - return(pcibr_probe_slot_non_pic(bridge, cfg, valp)); + return(pcibr_probe_slot_pic(bridge, cfg, valp)); } void -pcibr_device_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot) +pcibr_device_info_free(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pcibr_info_t pcibr_info; @@ -2079,9 +1805,9 @@ /* Disable memory and I/O BARs */ cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); - cmd_reg = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4); + cmd_reg = do_pcibr_config_get(cfgw, PCI_CFG_COMMAND, 4); cmd_reg &= (PCI_CMD_MEM_SPACE | PCI_CMD_IO_SPACE); - do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4, cmd_reg); + do_pcibr_config_set(cfgw, PCI_CFG_COMMAND, 4, cmd_reg); for (bar = 0; bar < PCI_CFG_BASE_ADDRS; bar++) { if (pcibr_info->f_window[bar].w_space == PCIIO_SPACE_NONE) @@ -2142,30 +1868,36 @@ pciio_space_t space, int start, int size, int align) { pciio_win_map_t win_map_p; + struct resource *root_resource = NULL; + iopaddr_t iopaddr = 0; switch (space) { case PCIIO_SPACE_IO: win_map_p = &pcibr_soft->bs_io_win_map; + root_resource = &pcibr_soft->bs_io_win_root_resource; break; case PCIIO_SPACE_MEM: win_map_p = &pcibr_soft->bs_swin_map; + root_resource = &pcibr_soft->bs_swin_root_resource; break; case PCIIO_SPACE_MEM32: win_map_p = &pcibr_soft->bs_mem_win_map; + root_resource = &pcibr_soft->bs_mem_win_root_resource; break; default: return 0; } - return pciio_device_win_alloc(win_map_p, + iopaddr = pciio_device_win_alloc(root_resource, win_info_p ? &win_info_p->w_win_alloc : NULL, start, size, align); + return(iopaddr); } @@ -2181,7 +1913,7 @@ * io_brick_tab[] array defined in ml/SN/iograph.c */ int -pcibr_widget_to_bus(devfs_handle_t pcibr_vhdl) +pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); xwidgetnum_t widget = pcibr_soft->bs_xid; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pciio.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pciio.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pciio.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pciio.c Wed Jul 23 18:29:00 2003 @@ -4,11 +4,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#define USRPCI 0 - #include #include #include @@ -30,27 +28,14 @@ #include #include #include -#include #include -#ifdef __ia64 -#define rmallocmap atemapalloc -#define rmfreemap atemapfree -#define rmfree atefree -#define rmalloc atealloc -#endif - #define DEBUG_PCIIO #undef DEBUG_PCIIO /* turn this on for yet more console output */ -#define GET_NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) -#define DO_DEL(ptr) (kfree(ptr)) - char pciio_info_fingerprint[] = "pciio_info"; -cdl_p pciio_registry = NULL; - int badaddr_val(volatile void *addr, int len, volatile void *ptr) { @@ -97,8 +82,6 @@ extern char master_baseio_wid; if (master_baseio_nasid < 0) { - nasid_t tmp; - master_baseio_nasid = ia64_sn_get_master_baseio_nasid(); if ( master_baseio_nasid >= 0 ) { @@ -109,13 +92,13 @@ } int -hub_dma_enabled(devfs_handle_t xconn_vhdl) +hub_dma_enabled(vertex_hdl_t xconn_vhdl) { return(0); } int -hub_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +hub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code) { return(0); } @@ -153,66 +136,64 @@ */ #if !defined(DEV_FUNC) -static pciio_provider_t *pciio_to_provider_fns(devfs_handle_t dev); +static pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev); #endif -pciio_piomap_t pciio_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); +pciio_piomap_t pciio_piomap_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); void pciio_piomap_free(pciio_piomap_t); caddr_t pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t); void pciio_piomap_done(pciio_piomap_t); -caddr_t pciio_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); -caddr_t pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); +caddr_t pciio_piotrans_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +caddr_t pciio_pio_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); -iopaddr_t pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); -void pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); +iopaddr_t pciio_piospace_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, size_t, size_t); +void pciio_piospace_free(vertex_hdl_t, pciio_space_t, iopaddr_t, size_t); -pciio_dmamap_t pciio_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +pciio_dmamap_t pciio_dmamap_alloc(vertex_hdl_t, device_desc_t, size_t, unsigned); void pciio_dmamap_free(pciio_dmamap_t); iopaddr_t pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); -alenlist_t pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned); void pciio_dmamap_done(pciio_dmamap_t); -iopaddr_t pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); -alenlist_t pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +iopaddr_t pciio_dmatrans_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, unsigned); void pciio_dmamap_drain(pciio_dmamap_t); -void pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); -void pciio_dmalist_drain(devfs_handle_t, alenlist_t); -iopaddr_t pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); +void pciio_dmaaddr_drain(vertex_hdl_t, paddr_t, size_t); +void pciio_dmalist_drain(vertex_hdl_t, alenlist_t); +iopaddr_t pciio_dma_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); -pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +pciio_intr_t pciio_intr_alloc(vertex_hdl_t, device_desc_t, pciio_intr_line_t, vertex_hdl_t); void pciio_intr_free(pciio_intr_t); int pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t); void pciio_intr_disconnect(pciio_intr_t); -devfs_handle_t pciio_intr_cpu_get(pciio_intr_t); +vertex_hdl_t pciio_intr_cpu_get(pciio_intr_t); void pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t); -void pciio_provider_startup(devfs_handle_t); -void pciio_provider_shutdown(devfs_handle_t); +void pciio_provider_startup(vertex_hdl_t); +void pciio_provider_shutdown(vertex_hdl_t); -pciio_endian_t pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); -pciio_priority_t pciio_priority_set(devfs_handle_t, pciio_priority_t); -devfs_handle_t pciio_intr_dev_get(pciio_intr_t); +pciio_endian_t pciio_endian_set(vertex_hdl_t, pciio_endian_t, pciio_endian_t); +pciio_priority_t pciio_priority_set(vertex_hdl_t, pciio_priority_t); +vertex_hdl_t pciio_intr_dev_get(pciio_intr_t); -devfs_handle_t pciio_pio_dev_get(pciio_piomap_t); +vertex_hdl_t pciio_pio_dev_get(pciio_piomap_t); pciio_slot_t pciio_pio_slot_get(pciio_piomap_t); pciio_space_t pciio_pio_space_get(pciio_piomap_t); iopaddr_t pciio_pio_pciaddr_get(pciio_piomap_t); ulong pciio_pio_mapsz_get(pciio_piomap_t); caddr_t pciio_pio_kvaddr_get(pciio_piomap_t); -devfs_handle_t pciio_dma_dev_get(pciio_dmamap_t); +vertex_hdl_t pciio_dma_dev_get(pciio_dmamap_t); pciio_slot_t pciio_dma_slot_get(pciio_dmamap_t); -pciio_info_t pciio_info_chk(devfs_handle_t); -pciio_info_t pciio_info_get(devfs_handle_t); -void pciio_info_set(devfs_handle_t, pciio_info_t); -devfs_handle_t pciio_info_dev_get(pciio_info_t); +pciio_info_t pciio_info_chk(vertex_hdl_t); +pciio_info_t pciio_info_get(vertex_hdl_t); +void pciio_info_set(vertex_hdl_t, pciio_info_t); +vertex_hdl_t pciio_info_dev_get(pciio_info_t); pciio_slot_t pciio_info_slot_get(pciio_info_t); pciio_function_t pciio_info_function_get(pciio_info_t); pciio_vendor_id_t pciio_info_vendor_id_get(pciio_info_t); pciio_device_id_t pciio_info_device_id_get(pciio_info_t); -devfs_handle_t pciio_info_master_get(pciio_info_t); +vertex_hdl_t pciio_info_master_get(pciio_info_t); arbitrary_info_t pciio_info_mfast_get(pciio_info_t); pciio_provider_t *pciio_info_pops_get(pciio_info_t); error_handler_f *pciio_info_efunc_get(pciio_info_t); @@ -223,30 +204,28 @@ iopaddr_t pciio_info_rom_base_get(pciio_info_t); size_t pciio_info_rom_size_get(pciio_info_t); -void pciio_init(void); -int pciio_attach(devfs_handle_t); +int pciio_attach(vertex_hdl_t); -void pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns); -void pciio_provider_unregister(devfs_handle_t); -pciio_provider_t *pciio_provider_fns_get(devfs_handle_t); +void pciio_provider_register(vertex_hdl_t, pciio_provider_t *pciio_fns); +void pciio_provider_unregister(vertex_hdl_t); +pciio_provider_t *pciio_provider_fns_get(vertex_hdl_t); int pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned); -void pciio_driver_unregister(char *driver_prefix); -devfs_handle_t pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +vertex_hdl_t pciio_device_register(vertex_hdl_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); -void pciio_device_unregister(devfs_handle_t); -pciio_info_t pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +void pciio_device_unregister(vertex_hdl_t); +pciio_info_t pciio_device_info_new(pciio_info_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); void pciio_device_info_free(pciio_info_t); -devfs_handle_t pciio_device_info_register(devfs_handle_t, pciio_info_t); -void pciio_device_info_unregister(devfs_handle_t, pciio_info_t); -int pciio_device_attach(devfs_handle_t, int); -int pciio_device_detach(devfs_handle_t, int); -void pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t); - -int pciio_reset(devfs_handle_t); -int pciio_write_gather_flush(devfs_handle_t); -int pciio_slot_inuse(devfs_handle_t); +vertex_hdl_t pciio_device_info_register(vertex_hdl_t, pciio_info_t); +void pciio_device_info_unregister(vertex_hdl_t, pciio_info_t); +int pciio_device_attach(vertex_hdl_t, int); +int pciio_device_detach(vertex_hdl_t, int); +void pciio_error_register(vertex_hdl_t, error_handler_f *, error_handler_arg_t); + +int pciio_reset(vertex_hdl_t); +int pciio_write_gather_flush(vertex_hdl_t); +int pciio_slot_inuse(vertex_hdl_t); /* ===================================================================== * Provider Function Location @@ -261,7 +240,7 @@ #if !defined(DEV_FUNC) static pciio_provider_t * -pciio_to_provider_fns(devfs_handle_t dev) +pciio_to_provider_fns(vertex_hdl_t dev) { pciio_info_t card_info; pciio_provider_t *provider_fns; @@ -316,7 +295,7 @@ */ pciio_piomap_t -pciio_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ +pciio_piomap_alloc(vertex_hdl_t dev, /* set up mapping for this device */ device_desc_t dev_desc, /* device descriptor */ pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ iopaddr_t addr, /* lowest address (or offset in window) */ @@ -354,7 +333,7 @@ } caddr_t -pciio_piotrans_addr(devfs_handle_t dev, /* translate for this device */ +pciio_piotrans_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ iopaddr_t addr, /* starting address (or offset in window) */ @@ -366,7 +345,7 @@ } caddr_t -pciio_pio_addr(devfs_handle_t dev, /* translate for this device */ +pciio_pio_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ iopaddr_t addr, /* starting address (or offset in window) */ @@ -410,7 +389,7 @@ } iopaddr_t -pciio_piospace_alloc(devfs_handle_t dev, /* Device requiring space */ +pciio_piospace_alloc(vertex_hdl_t dev, /* Device requiring space */ device_desc_t dev_desc, /* Device descriptor */ pciio_space_t space, /* MEM32/MEM64/IO */ size_t byte_count, /* Size of mapping */ @@ -423,7 +402,7 @@ } void -pciio_piospace_free(devfs_handle_t dev, /* Device freeing space */ +pciio_piospace_free(vertex_hdl_t dev, /* Device freeing space */ pciio_space_t space, /* Type of space */ iopaddr_t pciaddr, /* starting address */ size_t byte_count) @@ -440,7 +419,7 @@ */ pciio_dmamap_t -pciio_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ +pciio_dmamap_alloc(vertex_hdl_t dev, /* set up mappings for this device */ device_desc_t dev_desc, /* device descriptor */ size_t byte_count_max, /* max size of a mapping */ unsigned flags) @@ -465,15 +444,6 @@ (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); } -alenlist_t -pciio_dmamap_list(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ - alenlist_t alenlist, /* map this Address/Length List */ - unsigned flags) -{ - return DMAMAP_FUNC(pciio_dmamap, dmamap_list) - (CAST_DMAMAP(pciio_dmamap), alenlist, flags); -} - void pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) { @@ -482,7 +452,7 @@ } iopaddr_t -pciio_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ +pciio_dmatrans_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ paddr_t paddr, /* system physical address */ size_t byte_count, /* length */ @@ -492,18 +462,8 @@ (dev, dev_desc, paddr, byte_count, flags); } -alenlist_t -pciio_dmatrans_list(devfs_handle_t dev, /* translate for this device */ - device_desc_t dev_desc, /* device descriptor */ - alenlist_t palenlist, /* system address/length list */ - unsigned flags) -{ /* defined in dma.h */ - return DEV_FUNC(dev, dmatrans_list) - (dev, dev_desc, palenlist, flags); -} - iopaddr_t -pciio_dma_addr(devfs_handle_t dev, /* translate for this device */ +pciio_dma_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ paddr_t paddr, /* system physical address */ size_t byte_count, /* length */ @@ -553,14 +513,14 @@ } void -pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +pciio_dmaaddr_drain(vertex_hdl_t dev, paddr_t addr, size_t size) { DEV_FUNC(dev, dmaaddr_drain) (dev, addr, size); } void -pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list) +pciio_dmalist_drain(vertex_hdl_t dev, alenlist_t list) { DEV_FUNC(dev, dmalist_drain) (dev, list); @@ -577,10 +537,10 @@ * Return resource handle in intr_hdl. */ pciio_intr_t -pciio_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ +pciio_intr_alloc(vertex_hdl_t dev, /* which Crosstalk device */ device_desc_t dev_desc, /* device descriptor */ pciio_intr_line_t lines, /* INTR line(s) to attach */ - devfs_handle_t owner_dev) + vertex_hdl_t owner_dev) { /* owner of this interrupt */ return (pciio_intr_t) DEV_FUNC(dev, intr_alloc) (dev, dev_desc, lines, owner_dev); @@ -624,7 +584,7 @@ * Return a hwgraph vertex that represents the CPU currently * targeted by an interrupt. */ -devfs_handle_t +vertex_hdl_t pciio_intr_cpu_get(pciio_intr_t intr_hdl) { return INTR_FUNC(intr_hdl, intr_cpu_get) @@ -663,12 +623,12 @@ */ static pciio_info_t pciio_cardinfo_get( - devfs_handle_t pciio_vhdl, + vertex_hdl_t pciio_vhdl, pciio_slot_t pci_slot) { char namebuf[16]; pciio_info_t info = 0; - devfs_handle_t conn; + vertex_hdl_t conn; pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE); if (GRAPH_SUCCESS == @@ -699,22 +659,16 @@ /*ARGSUSED */ int pciio_error_handler( - devfs_handle_t pciio_vhdl, + vertex_hdl_t pciio_vhdl, int error_code, ioerror_mode_t mode, ioerror_t *ioerror) { pciio_info_t pciio_info; - devfs_handle_t pconn_vhdl; -#if USRPCI - devfs_handle_t usrpci_v; -#endif + vertex_hdl_t pconn_vhdl; pciio_slot_t slot; int retval; -#ifdef EHE_ENABLE - error_state_t e_state; -#endif /* EHE_ENABLE */ #if DEBUG && ERROR_DEBUG printk("%v: pciio_error_handler\n", pciio_vhdl); @@ -733,16 +687,6 @@ if (pciio_info && pciio_info->c_efunc) { pconn_vhdl = pciio_info_dev_get(pciio_info); -#ifdef EHE_ENABLE - e_state = error_state_get(pciio_vhdl); - - if (e_state == ERROR_STATE_ACTION) - (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); - - if (error_state_set(pconn_vhdl,e_state) == ERROR_RETURN_CODE_CANNOT_SET_STATE) - return(IOERROR_UNHANDLED); -#endif - retval = pciio_info->c_efunc (pciio_info->c_einfo, error_code, mode, ioerror); if (retval != IOERROR_UNHANDLED) @@ -770,49 +714,11 @@ pconn_vhdl = pciio_info_dev_get(pciio_info); -#ifdef EHE_ENABLE - e_state = error_state_get(pciio_vhdl); - - if (e_state == ERROR_STATE_ACTION) - (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); - - if (error_state_set(pconn_vhdl,e_state) == - ERROR_RETURN_CODE_CANNOT_SET_STATE) - return(IOERROR_UNHANDLED); -#endif /* EHE_ENABLE */ - retval = pciio_info->c_efunc (pciio_info->c_einfo, error_code, mode, ioerror); if (retval != IOERROR_UNHANDLED) return retval; } - -#if USRPCI - /* If the USRPCI driver is available and - * knows about this connection point, - * deliver the error to it. - * - * OK to use pconn_vhdl here, even though we - * have already UNREF'd it, since we know that - * it is not going away. - */ - pconn_vhdl = pciio_info_dev_get(pciio_info); - if (GRAPH_SUCCESS == hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) { - iopaddr_t busaddr; - IOERROR_GETVALUE(busaddr, ioerror, busaddr); - retval = usrpci_error_handler (usrpci_v, error_code, busaddr); - hwgraph_vertex_unref(usrpci_v); - if (retval != IOERROR_UNHANDLED) { - /* - * This unref is not needed. If this code is called often enough, - * the system will crash, due to vertex reference count reaching 0, - * causing vertex to be unallocated. -jeremy - * hwgraph_vertex_unref(pconn_vhdl); - */ - return retval; - } - } -#endif } } @@ -829,7 +735,7 @@ * Startup a crosstalk provider */ void -pciio_provider_startup(devfs_handle_t pciio_provider) +pciio_provider_startup(vertex_hdl_t pciio_provider) { DEV_FUNC(pciio_provider, provider_startup) (pciio_provider); @@ -839,7 +745,7 @@ * Shutdown a crosstalk provider */ void -pciio_provider_shutdown(devfs_handle_t pciio_provider) +pciio_provider_shutdown(vertex_hdl_t pciio_provider) { DEV_FUNC(pciio_provider, provider_shutdown) (pciio_provider); @@ -851,7 +757,7 @@ * how things will actually appear in memory. */ pciio_endian_t -pciio_endian_set(devfs_handle_t dev, +pciio_endian_set(vertex_hdl_t dev, pciio_endian_t device_end, pciio_endian_t desired_end) { @@ -880,7 +786,7 @@ * Specify PCI arbitration priority. */ pciio_priority_t -pciio_priority_set(devfs_handle_t dev, +pciio_priority_set(vertex_hdl_t dev, pciio_priority_t device_prio) { ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW)); @@ -893,7 +799,7 @@ * Read value of configuration register */ uint64_t -pciio_config_get(devfs_handle_t dev, +pciio_config_get(vertex_hdl_t dev, unsigned reg, unsigned size) { @@ -923,7 +829,7 @@ * Change value of configuration register */ void -pciio_config_set(devfs_handle_t dev, +pciio_config_set(vertex_hdl_t dev, unsigned reg, unsigned size, uint64_t value) @@ -953,7 +859,7 @@ * Issue a hardware reset to a card. */ int -pciio_reset(devfs_handle_t dev) +pciio_reset(vertex_hdl_t dev) { return DEV_FUNC(dev, reset) (dev); } @@ -962,19 +868,19 @@ * flush write gather buffers */ int -pciio_write_gather_flush(devfs_handle_t dev) +pciio_write_gather_flush(vertex_hdl_t dev) { return DEV_FUNC(dev, write_gather_flush) (dev); } -devfs_handle_t +vertex_hdl_t pciio_intr_dev_get(pciio_intr_t pciio_intr) { return (pciio_intr->pi_dev); } /****** Generic crosstalk pio interfaces ******/ -devfs_handle_t +vertex_hdl_t pciio_pio_dev_get(pciio_piomap_t pciio_piomap) { return (pciio_piomap->pp_dev); @@ -1011,7 +917,7 @@ } /****** Generic crosstalk dma interfaces ******/ -devfs_handle_t +vertex_hdl_t pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap) { return (pciio_dmamap->pd_dev); @@ -1026,7 +932,7 @@ /****** Generic pci slot information interfaces ******/ pciio_info_t -pciio_info_chk(devfs_handle_t pciio) +pciio_info_chk(vertex_hdl_t pciio) { arbitrary_info_t ainfo = 0; @@ -1035,7 +941,7 @@ } pciio_info_t -pciio_info_get(devfs_handle_t pciio) +pciio_info_get(vertex_hdl_t pciio) { pciio_info_t pciio_info; @@ -1051,18 +957,17 @@ #endif /* DEBUG_PCIIO */ if ((pciio_info != NULL) && - (pciio_info->c_fingerprint != pciio_info_fingerprint) - && (pciio_info->c_fingerprint != NULL)) { + (pciio_info->c_fingerprint != pciio_info_fingerprint) + && (pciio_info->c_fingerprint != NULL)) { - return((pciio_info_t)-1); /* Should panic .. */ + return((pciio_info_t)-1); /* Should panic .. */ } - return pciio_info; } void -pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info) +pciio_info_set(vertex_hdl_t pciio, pciio_info_t pciio_info) { if (pciio_info != NULL) pciio_info->c_fingerprint = pciio_info_fingerprint; @@ -1076,7 +981,7 @@ (arbitrary_info_t) pciio_info); } -devfs_handle_t +vertex_hdl_t pciio_info_dev_get(pciio_info_t pciio_info) { return (pciio_info->c_vertex); @@ -1106,7 +1011,7 @@ return (pciio_info->c_device); } -devfs_handle_t +vertex_hdl_t pciio_info_master_get(pciio_info_t pciio_info) { return (pciio_info->c_master); @@ -1172,47 +1077,12 @@ */ /* - * pciioinit: called once during device driver - * initializtion if this driver is configured into - * the system. - */ -void -pciio_init(void) -{ - cdl_p cp; - -#if DEBUG && ATTACH_DEBUG - printf("pciio_init\n"); -#endif - /* Allocate the registry. - * We might already have one. - * If we don't, go get one. - * MPness: someone might have - * set one up for us while we - * were not looking; use an atomic - * compare-and-swap to commit to - * using the new registry if and - * only if nobody else did first. - * If someone did get there first, - * toss the one we allocated back - * into the pool. - */ - if (pciio_registry == NULL) { - cp = cdl_new(EDGE_LBL_PCI, "vendor", "device"); - if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) { - cdl_del(cp); - } - } - ASSERT(pciio_registry != NULL); -} - -/* * pciioattach: called for each vertex in the graph * that is a PCI provider. */ /*ARGSUSED */ int -pciio_attach(devfs_handle_t pciio) +pciio_attach(vertex_hdl_t pciio) { #if DEBUG && ATTACH_DEBUG #if defined(SUPPORT_PRINTING_V_FORMAT) @@ -1228,7 +1098,7 @@ * Associate a set of pciio_provider functions with a vertex. */ void -pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns) +pciio_provider_register(vertex_hdl_t provider, pciio_provider_t *pciio_fns) { hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns); } @@ -1237,7 +1107,7 @@ * Disassociate a set of pciio_provider functions with a vertex. */ void -pciio_provider_unregister(devfs_handle_t provider) +pciio_provider_unregister(vertex_hdl_t provider) { arbitrary_info_t ainfo; @@ -1249,7 +1119,7 @@ * provider. */ pciio_provider_t * -pciio_provider_fns_get(devfs_handle_t provider) +pciio_provider_fns_get(vertex_hdl_t provider) { arbitrary_info_t ainfo = 0; @@ -1265,86 +1135,13 @@ char *driver_prefix, unsigned flags) { - /* a driver's init routine might call - * pciio_driver_register before the - * system calls pciio_init; so we - * make the init call ourselves here. - */ - if (pciio_registry == NULL) - pciio_init(); - - return cdl_add_driver(pciio_registry, - vendor_id, device_id, - driver_prefix, flags, NULL); -} - -/* - * Remove an initialization function. - */ -void -pciio_driver_unregister( - char *driver_prefix) -{ - /* before a driver calls unregister, - * it must have called register; so - * we can assume we have a registry here. - */ - ASSERT(pciio_registry != NULL); - - cdl_del_driver(pciio_registry, driver_prefix, NULL); -} - -/* - * Set the slot status for a device supported by the - * driver being registered. - */ -void -pciio_driver_reg_callback( - devfs_handle_t pconn_vhdl, - int key1, - int key2, - int error) -{ -} - -/* - * Set the slot status for a device supported by the - * driver being unregistered. - */ -void -pciio_driver_unreg_callback( - devfs_handle_t pconn_vhdl, - int key1, - int key2, - int error) -{ -} - -/* - * Call some function with each vertex that - * might be one of this driver's attach points. - */ -void -pciio_iterate(char *driver_prefix, - pciio_iter_f * func) -{ - /* a driver's init routine might call - * pciio_iterate before the - * system calls pciio_init; so we - * make the init call ourselves here. - */ - if (pciio_registry == NULL) - pciio_init(); - - ASSERT(pciio_registry != NULL); - - cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func); + return(0); } -devfs_handle_t +vertex_hdl_t pciio_device_register( - devfs_handle_t connectpt, /* vertex for /hw/.../pciio/%d */ - devfs_handle_t master, /* card's master ASIC (PCI provider) */ + vertex_hdl_t connectpt, /* vertex for /hw/.../pciio/%d */ + vertex_hdl_t master, /* card's master ASIC (PCI provider) */ pciio_slot_t slot, /* card's slot */ pciio_function_t func, /* card's func */ pciio_vendor_id_t vendor_id, @@ -1356,7 +1153,7 @@ } void -pciio_device_unregister(devfs_handle_t pconn) +pciio_device_unregister(vertex_hdl_t pconn) { DEV_FUNC(pconn,device_unregister)(pconn); } @@ -1364,14 +1161,14 @@ pciio_info_t pciio_device_info_new( pciio_info_t pciio_info, - devfs_handle_t master, + vertex_hdl_t master, pciio_slot_t slot, pciio_function_t func, pciio_vendor_id_t vendor_id, pciio_device_id_t device_id) { if (!pciio_info) - GET_NEW(pciio_info); + NEW(pciio_info); ASSERT(pciio_info != NULL); pciio_info->c_slot = slot; @@ -1396,14 +1193,14 @@ BZERO((char *)pciio_info,sizeof(pciio_info)); } -devfs_handle_t +vertex_hdl_t pciio_device_info_register( - devfs_handle_t connectpt, /* vertex at center of bus */ + vertex_hdl_t connectpt, /* vertex at center of bus */ pciio_info_t pciio_info) /* details about the connectpt */ { char name[32]; - devfs_handle_t pconn; - int device_master_set(devfs_handle_t, devfs_handle_t); + vertex_hdl_t pconn; + int device_master_set(vertex_hdl_t, vertex_hdl_t); pciio_slot_func_to_name(name, pciio_info->c_slot, @@ -1429,25 +1226,15 @@ */ device_master_set(pconn, pciio_info->c_master); - -#if USRPCI - /* - * Call into usrpci provider to let it initialize for - * the given slot. - */ - if (pciio_info->c_slot != PCIIO_SLOT_NONE) - usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot); -#endif - return pconn; } void -pciio_device_info_unregister(devfs_handle_t connectpt, +pciio_device_info_unregister(vertex_hdl_t connectpt, pciio_info_t pciio_info) { char name[32]; - devfs_handle_t pconn; + vertex_hdl_t pconn; if (!pciio_info) return; @@ -1470,7 +1257,7 @@ /* Add the pci card inventory information to the hwgraph */ static void -pciio_device_inventory_add(devfs_handle_t pconn_vhdl) +pciio_device_inventory_add(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); @@ -1488,7 +1275,7 @@ /*ARGSUSED */ int -pciio_device_attach(devfs_handle_t pconn, +pciio_device_attach(vertex_hdl_t pconn, int drv_flags) { pciio_info_t pciio_info; @@ -1507,92 +1294,18 @@ * pciio_init) have been called; so we * can assume here that we have a registry. */ - ASSERT(pciio_registry != NULL); - return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags)); + return(cdl_add_connpt(vendor_id, device_id, pconn, drv_flags)); } int -pciio_device_detach(devfs_handle_t pconn, +pciio_device_detach(vertex_hdl_t pconn, int drv_flags) { - pciio_info_t pciio_info; - pciio_vendor_id_t vendor_id; - pciio_device_id_t device_id; - - pciio_info = pciio_info_get(pconn); - - vendor_id = pciio_info->c_vendor; - device_id = pciio_info->c_device; - - /* we don't start attaching things until - * all the driver init routines (including - * pciio_init) have been called; so we - * can assume here that we have a registry. - */ - ASSERT(pciio_registry != NULL); - - return(cdl_del_connpt(pciio_registry, vendor_id, device_id, - pconn, drv_flags)); - -} - -/* SN2 */ -/* - * Allocate (if necessary) and initialize a PCI window mapping structure. - */ -pciio_win_map_t -pciio_device_win_map_new(pciio_win_map_t win_map, - size_t region_size, - size_t page_size) -{ - ASSERT((page_size & (page_size - 1)) == 0); - ASSERT((region_size & (page_size - 1)) == 0); - - if (win_map == NULL) - NEW(win_map); - - /* - * The map array tracks the free ``pages'' in the region. The worst - * case scenario is when every other page in the region is free -- - * e.i. maximum fragmentation. This leads to (max pages + 1) / 2 + 1 - * map entries. The first "+1" handles the divide by 2 rounding; the - * second handles the need for an end marker sentinel. - */ - win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1); - win_map->wm_page_size = page_size; - ASSERT(win_map->wm_map != NULL); - - return win_map; -} - -/* - * Free resources associated with a PCI window mapping structure. - */ -extern void -pciio_device_win_map_free(pciio_win_map_t win_map) -{ - rmfreemap(win_map->wm_map); - bzero(win_map, sizeof *win_map); + return(0); } /* - * Populate window map with specified free range. - */ -void -pciio_device_win_populate(pciio_win_map_t win_map, - iopaddr_t ioaddr, - size_t size) -{ - ASSERT((size & (win_map->wm_page_size - 1)) == 0); - ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0); - - rmfree(win_map->wm_map, - size / win_map->wm_page_size, - (unsigned long)ioaddr / win_map->wm_page_size); - -} -/* * Allocate space from the specified PCI window mapping resource. On * success record information about the allocation in the supplied window * allocation cookie (if non-NULL) and return the address of the allocated @@ -1609,94 +1322,36 @@ * and alignment. */ iopaddr_t -pciio_device_win_alloc(pciio_win_map_t win_map, +pciio_device_win_alloc(struct resource *root_resource, pciio_win_alloc_t win_alloc, size_t start, size_t size, size_t align) { - unsigned long base; -#ifdef PIC_LATER - ASSERT((size & (size - 1)) == 0); - ASSERT((align & (align - 1)) == 0); + struct resource *new_res; + int status = 0; - /* - * Convert size and alignment to pages. If size is greated than the - * requested alignment, we bump the alignment up to size; otherwise - * convert the size into a multiple of the alignment request. - */ - size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size; - align = align / win_map->wm_page_size; - if (size > align) - align = size; - else - size = (size + align - 1) & ~(align - 1); - - /* XXXX */ - base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP); - if (base == RMALLOC_FAIL) - return((iopaddr_t)NULL); -#else - int index_page, index_page_align; - int align_pages, size_pages; - int alloc_pages, free_pages; - int addr_align; - - /* Convert PCI bus alignment from bytes to pages */ - align_pages = align / win_map->wm_page_size; - - /* Convert PCI request from bytes to pages */ - size_pages = (size / win_map->wm_page_size) + - ((size % win_map->wm_page_size) ? 1 : 0); - - /* Align address with the larger of the size or the requested slot align */ - if (size_pages > align_pages) - align_pages = size_pages; - - /* - * Avoid wasting space by aligning - 1; this will prevent crossing - * another alignment boundary. - */ - alloc_pages = size_pages + (align_pages - 1); + new_res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); - /* Allocate PCI bus space in pages */ - index_page = (int) rmalloc(win_map->wm_map, - (size_t) alloc_pages); - - /* Error if no PCI bus address space available */ - if (!index_page) - return 0; - - /* PCI bus address index starts at 0 */ - index_page--; - - /* Align the page offset as requested */ - index_page_align = (index_page + (align_pages - 1)) - - ((index_page + (align_pages - 1)) % align_pages); - - free_pages = (align_pages - 1) - (index_page_align - index_page); - - /* Free unused PCI bus pages adjusting the index to start at 1 */ - rmfree(win_map->wm_map, - free_pages, - (index_page_align + 1) + size_pages); - - /* Return aligned PCI bus space in bytes */ - addr_align = (index_page_align * win_map->wm_page_size); - base = index_page; - size = alloc_pages - free_pages; -#endif /* PIC_LATER */ + status = allocate_resource( root_resource, new_res, + size, align /* Min start addr. */, + root_resource->end, align, + NULL, NULL); + if (status) { + kfree(new_res); + return((iopaddr_t) NULL); + } /* * If a window allocation cookie has been supplied, use it to keep * track of all the allocated space assigned to this window. */ if (win_alloc) { - win_alloc->wa_map = win_map; - win_alloc->wa_base = base; + win_alloc->wa_resource = new_res; + win_alloc->wa_base = new_res->start; win_alloc->wa_pages = size; } - return base * win_map->wm_page_size; + return new_res->start;; } /* @@ -1706,10 +1361,16 @@ void pciio_device_win_free(pciio_win_alloc_t win_alloc) { - if (win_alloc->wa_pages) - rmfree(win_alloc->wa_map->wm_map, - win_alloc->wa_pages, - win_alloc->wa_base); + + int status = 0; + + if (win_alloc->wa_resource) { + status = release_resource(win_alloc->wa_resource); + if (!status) + kfree(win_alloc->wa_resource); + else + BUG(); + } } /* @@ -1728,7 +1389,7 @@ * cooperating drivers, well, cooperate ... */ void -pciio_error_register(devfs_handle_t pconn, +pciio_error_register(vertex_hdl_t pconn, error_handler_f *efunc, error_handler_arg_t einfo) { @@ -1746,7 +1407,7 @@ * vhdl is the vertex for the slot */ int -pciio_slot_inuse(devfs_handle_t pconn_vhdl) +pciio_slot_inuse(vertex_hdl_t pconn_vhdl) { pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); @@ -1763,7 +1424,7 @@ } int -pciio_dma_enabled(devfs_handle_t pconn_vhdl) +pciio_dma_enabled(vertex_hdl_t pconn_vhdl) { return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl); } @@ -1777,7 +1438,7 @@ /* * These are complementary Linux interfaces that takes in a pci_dev * as the - * first arguement instead of devfs_handle_t. + * first arguement instead of vertex_hdl_t. */ iopaddr_t snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned); pciio_dmamap_t snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned); @@ -1800,7 +1461,7 @@ int *count_vchan0, int *count_vchan1) { - devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1); } @@ -1811,7 +1472,7 @@ pciio_endian_t device_end, pciio_endian_t desired_end) { - devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); return DEV_FUNC(dev, endian_set) (dev, device_end, desired_end); @@ -1825,7 +1486,7 @@ unsigned flags) { /* defined in dma.h */ - devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); /* * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be @@ -1842,7 +1503,7 @@ unsigned flags) { /* defined in dma.h */ - devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); /* * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pic.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/pic.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/pic.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/pic.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,51 +27,195 @@ #include #include #include -#include #include #include +extern char *bcopy(const char * src, char * dest, int count); + #define PCI_BUS_NO_1 1 -int pic_devflag = D_MP; +extern int pcibr_attach2(vertex_hdl_t, bridge_t *, vertex_hdl_t, int, pcibr_soft_t *); +extern void pcibr_driver_reg_callback(vertex_hdl_t, int, int, int); +extern void pcibr_driver_unreg_callback(vertex_hdl_t, int, int, int); -extern int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, int, pcibr_soft_t *); -extern void pcibr_driver_reg_callback(devfs_handle_t, int, int, int); -extern void pcibr_driver_unreg_callback(devfs_handle_t, int, int, int); +/* + * copy inventory_t from conn_v to peer_conn_v + */ +int +pic_bus1_inventory_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v) +{ + inventory_t *pinv, *peer_pinv; + + if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT, + (arbitrary_info_t *)&pinv) == GRAPH_SUCCESS) + { + NEW(peer_pinv); + bcopy((const char *)pinv, (char *)peer_pinv, sizeof(inventory_t)); + if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT, + (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) { + DEL(peer_pinv); + return 0; + } + return 1; + } + + printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ", (uint64_t)conn_v); + return 0; +} -void -pic_init(void) +/* + * copy xwidget_info_t from conn_v to peer_conn_v + */ +int +pic_bus1_widget_info_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v, + cnodeid_t xbow_peer) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pic_init()\n")); + xwidget_info_t widget_info, peer_widget_info; + char peer_path[256]; + vertex_hdl_t peer_hubv; + hubinfo_t peer_hub_info; + + /* get the peer hub's widgetid */ + peer_hubv = NODEPDA(xbow_peer)->node_vertex; + peer_hub_info = NULL; + hubinfo_get(peer_hubv, &peer_hub_info); + if (peer_hub_info == NULL) + return 0; + + if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET, + (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) { + NEW(peer_widget_info); + peer_widget_info->w_vertex = peer_conn_v; + peer_widget_info->w_id = widget_info->w_id; + peer_widget_info->w_master = peer_hubv; + peer_widget_info->w_masterid = peer_hub_info->h_widgetid; + /* structure copy */ + peer_widget_info->w_hwid = widget_info->w_hwid; + peer_widget_info->w_efunc = 0; + peer_widget_info->w_einfo = 0; + peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); + strcpy(peer_widget_info->w_name, peer_path); + + if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, + (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { + DEL(peer_widget_info); + return 0; + } + + xwidget_info_set(peer_conn_v, peer_widget_info); - xwidget_driver_register(PIC_WIDGET_PART_NUM_BUS0, - PIC_WIDGET_MFGR_NUM, - "pic_", - 0); + return 1; + } + + printk("pic_bus1_widget_info_dup: " + "cannot get INFO_LBL_XWIDGET from 0x%lx\n", (uint64_t)conn_v); + return 0; } +/* + * If this PIC is attached to two Cbricks ("dual-ported") then + * attach each bus to opposite Cbricks. + * + * If successful, return a new vertex suitable for attaching the PIC bus. + * If not successful, return zero and both buses will attach to the + * vertex passed into pic_attach(). + */ +vertex_hdl_t +pic_bus1_redist(nasid_t nasid, vertex_hdl_t conn_v) +{ + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + cnodeid_t xbow_peer = -1; + char pathname[256], peer_path[256], tmpbuf[256]; + char *p; + int rc; + vertex_hdl_t peer_conn_v; + int pos; + slabid_t slab; + + if (NODEPDA(cnode)->xbow_peer >= 0) { /* if dual-ported */ + /* create a path for this widget on the peer Cbrick */ + /* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */ + /* sprintf(pathname, "%v", conn_v); */ + xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer); + pos = hwgfs_generate_path(conn_v, tmpbuf, 256); + strcpy(pathname, &tmpbuf[pos]); + p = pathname + strlen("hw/module/001c01/slab/0/"); + + memset(tmpbuf, 0, 16); + format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF); + slab = geo_slab((NODEPDA(xbow_peer))->geoid); + sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); + + /* Look for vertex for this widget on the peer Cbrick. + * Expect GRAPH_NOT_FOUND. + */ + rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v); + if (GRAPH_SUCCESS == rc) + printk("pic_attach: found unexpected vertex: 0x%lx\n", + (uint64_t)peer_conn_v); + else if (GRAPH_NOT_FOUND != rc) { + printk("pic_attach: hwgraph_traverse unexpectedly" + " returned 0x%x\n", rc); + } else { + /* try to add the widget vertex to the peer Cbrick */ + rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v); + + if (GRAPH_SUCCESS != rc) + printk("pic_attach: hwgraph_path_add" + " failed with 0x%x\n", rc); + else { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_bus1_redist: added vertex %v\n", peer_conn_v)); + + /* Now hang appropiate stuff off of the new + * vertex. We bail out if we cannot add something. + * In that case, we don't remove the newly added + * vertex but that should be safe and we don't + * really expect the additions to fail anyway. + */ +#if 0 + if (!pic_bus1_inventory_dup(conn_v, peer_conn_v)) + return 0; + pic_bus1_device_desc_dup(conn_v, peer_conn_v); +#endif + if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer)) + return 0; + + return peer_conn_v; + } + } + } + return 0; +} + + int -pic_attach(devfs_handle_t conn_v) +pic_attach(vertex_hdl_t conn_v) { int rc; bridge_t *bridge0, *bridge1 = (bridge_t *)0; - devfs_handle_t pcibr_vhdl0, pcibr_vhdl1 = (devfs_handle_t)0; + vertex_hdl_t pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0; pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; + vertex_hdl_t conn_v0, conn_v1, peer_conn_v; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL, 0, sizeof(bridge_t), 0); -#ifdef PCI_BUS_NO_1 bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET); -#endif PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bridge0=0x%x, bridge1=0x%x\n", bridge0, bridge1)); + conn_v0 = conn_v1 = conn_v; + + /* If dual-ported then split the two PIC buses across both Cbricks */ + if ((peer_conn_v = (pic_bus1_redist(NASID_GET(bridge0), conn_v)))) + conn_v1 = peer_conn_v; + /* * Create the vertex for the PCI buses, which we * will also use to hold the pcibr_soft and @@ -84,12 +228,10 @@ * the Bridge registers themselves. */ /* FIXME: what should the hwgraph path look like ? */ - rc = hwgraph_path_add(conn_v, EDGE_LBL_PCIX_0, &pcibr_vhdl0); + rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); ASSERT(rc == GRAPH_SUCCESS); -#ifdef PCI_BUS_NO_1 - rc = hwgraph_path_add(conn_v, EDGE_LBL_PCIX_1, &pcibr_vhdl1); + rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); ASSERT(rc == GRAPH_SUCCESS); -#endif PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n", @@ -97,27 +239,17 @@ /* register pci provider array */ pciio_provider_register(pcibr_vhdl0, &pci_pic_provider); -#ifdef PCI_BUS_NO_1 pciio_provider_register(pcibr_vhdl1, &pci_pic_provider); -#endif pciio_provider_startup(pcibr_vhdl0); -#ifdef PCI_BUS_NO_1 pciio_provider_startup(pcibr_vhdl1); -#endif - pcibr_attach2(conn_v, bridge0, pcibr_vhdl0, 0, &bus0_soft); -#ifdef PCI_BUS_NO_1 - pcibr_attach2(conn_v, bridge1, pcibr_vhdl1, 1, &bus1_soft); -#endif + pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft); + pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft); /* save a pointer to the PIC's other bus's soft struct */ -#ifdef PCI_BUS_NO_1 bus0_soft->bs_peers_soft = bus1_soft; bus1_soft->bs_peers_soft = bus0_soft; -#else - bus0_soft->bs_peers_soft = (pcibr_soft_t)0; -#endif PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n", @@ -145,10 +277,8 @@ (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, (pciio_dmamap_free_f *) pcibr_dmamap_free, (pciio_dmamap_addr_f *) pcibr_dmamap_addr, - (pciio_dmamap_list_f *) pcibr_dmamap_list, (pciio_dmamap_done_f *) pcibr_dmamap_done, (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, - (pciio_dmatrans_list_f *) pcibr_dmatrans_list, (pciio_dmamap_drain_f *) pcibr_dmamap_drain, (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, (pciio_dmalist_drain_f *) pcibr_dmalist_drain, diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shub.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/shub.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shub.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/shub.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ #ident "$Revision: 1.167 $" @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,14 @@ } static inline void +shub_mmr_write_iospace(cnodeid_t cnode, shubreg_t reg, uint64_t val) +{ + int nasid = cnodeid_to_nasid(cnode); + + REMOTE_HUB_S(nasid, reg, val); +} + +static inline void shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val) { int nasid = cnodeid_to_nasid(cnode); @@ -118,6 +127,14 @@ return val; } +static inline uint64_t +shub_mmr_read_iospace(cnodeid_t cnode, shubreg_t reg) +{ + int nasid = cnodeid_to_nasid(cnode); + + return REMOTE_HUB_L(nasid, reg); +} + static inline uint32_t shub_mmr_read32(cnodeid_t cnode, shubreg_t reg) { @@ -182,12 +199,15 @@ { cnodeid_t cnode; uint64_t longarg; - devfs_handle_t d; int nasid; - if ((d = devfs_get_handle_from_inode(inode)) == NULL) +#ifdef CONFIG_HWGFS_FS + cnode = (cnodeid_t)file->f_dentry->d_fsdata; +#else + cnode = (cnodeid_t)file->private_data; +#endif + if (!cnode) return -ENODEV; - cnode = (cnodeid_t)hwgraph_fastinfo_get(d); switch (cmd) { case SNDRV_SHUB_CONFIGURE: @@ -231,3 +251,255 @@ struct file_operations shub_mon_fops = { ioctl: shubstats_ioctl, }; + +/* + * "linkstatd" kernel thread to export SGI Numalink + * stats via /proc/sgi_sn/linkstats + */ +static struct s_linkstats { + uint64_t hs_ni_sn_errors[2]; + uint64_t hs_ni_cb_errors[2]; + uint64_t hs_ni_retry_errors[2]; + int hs_ii_up; + uint64_t hs_ii_sn_errors; + uint64_t hs_ii_cb_errors; + uint64_t hs_ii_retry_errors; +} *sn_linkstats; + +static spinlock_t sn_linkstats_lock; +static unsigned long sn_linkstats_starttime; +static unsigned long sn_linkstats_samples; +static unsigned long sn_linkstats_overflows; +static unsigned long sn_linkstats_update_msecs; + +void +sn_linkstats_reset(unsigned long msecs) +{ + int cnode; + uint64_t iio_wstat; + uint64_t llp_csr_reg; + + spin_lock(&sn_linkstats_lock); + memset(sn_linkstats, 0, numnodes * sizeof(struct s_linkstats)); + for (cnode=0; cnode < numnodes; cnode++) { + shub_mmr_write(cnode, SH_NI0_LLP_ERR, 0L); + shub_mmr_write(cnode, SH_NI1_LLP_ERR, 0L); + shub_mmr_write_iospace(cnode, IIO_LLP_LOG, 0L); + + /* zero the II retry counter */ + iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); + iio_wstat &= 0xffffffffff00ffff; /* bits 23:16 */ + shub_mmr_write_iospace(cnode, IIO_WSTAT, iio_wstat); + + /* Check if the II xtalk link is working */ + llp_csr_reg = shub_mmr_read_iospace(cnode, IIO_LLP_CSR); + if (llp_csr_reg & IIO_LLP_CSR_IS_UP) + sn_linkstats[cnode].hs_ii_up = 1; + } + + sn_linkstats_update_msecs = msecs; + sn_linkstats_samples = 0; + sn_linkstats_overflows = 0; + sn_linkstats_starttime = jiffies; + spin_unlock(&sn_linkstats_lock); +} + +int +linkstatd_thread(void *unused) +{ + int cnode; + int overflows; + uint64_t reg[2]; + uint64_t iio_wstat = 0L; + ii_illr_u_t illr; + struct s_linkstats *lsp; + struct task_struct *tsk = current; + + daemonize(); + set_user_nice(tsk, 19); + sigfillset(&tsk->blocked); + strcpy(tsk->comm, "linkstatd"); + + while(1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(sn_linkstats_update_msecs * HZ / 1000); + + spin_lock(&sn_linkstats_lock); + + overflows = 0; + for (lsp=sn_linkstats, cnode=0; cnode < numnodes; cnode++, lsp++) { + reg[0] = shub_mmr_read(cnode, SH_NI0_LLP_ERR); + reg[1] = shub_mmr_read(cnode, SH_NI1_LLP_ERR); + if (lsp->hs_ii_up) { + illr = (ii_illr_u_t)shub_mmr_read_iospace(cnode, IIO_LLP_LOG); + iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); + } + + if (!overflows && ( + (reg[0] & SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK) == + SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK || + (reg[0] & SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK) == + SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK || + (reg[1] & SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK) == + SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK || + (reg[1] & SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK) == + SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK || + (lsp->hs_ii_up && illr.ii_illr_fld_s.i_sn_cnt == IIO_LLP_SN_MAX) || + (lsp->hs_ii_up && illr.ii_illr_fld_s.i_cb_cnt == IIO_LLP_CB_MAX))) { + overflows = 1; + } + +#define LINKSTAT_UPDATE(reg, cnt, mask, shift) cnt += (reg & mask) >> shift + + LINKSTAT_UPDATE(reg[0], lsp->hs_ni_sn_errors[0], + SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_MASK, + SH_NI0_LLP_ERR_RX_SN_ERR_COUNT_SHFT); + + LINKSTAT_UPDATE(reg[1], lsp->hs_ni_sn_errors[1], + SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_MASK, + SH_NI1_LLP_ERR_RX_SN_ERR_COUNT_SHFT); + + LINKSTAT_UPDATE(reg[0], lsp->hs_ni_cb_errors[0], + SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_MASK, + SH_NI0_LLP_ERR_RX_CB_ERR_COUNT_SHFT); + + LINKSTAT_UPDATE(reg[1], lsp->hs_ni_cb_errors[1], + SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_MASK, + SH_NI1_LLP_ERR_RX_CB_ERR_COUNT_SHFT); + + LINKSTAT_UPDATE(reg[0], lsp->hs_ni_retry_errors[0], + SH_NI0_LLP_ERR_RETRY_COUNT_MASK, + SH_NI0_LLP_ERR_RETRY_COUNT_SHFT); + + LINKSTAT_UPDATE(reg[1], lsp->hs_ni_retry_errors[1], + SH_NI1_LLP_ERR_RETRY_COUNT_MASK, + SH_NI1_LLP_ERR_RETRY_COUNT_SHFT); + + if (lsp->hs_ii_up) { + /* II sn and cb errors */ + lsp->hs_ii_sn_errors += illr.ii_illr_fld_s.i_sn_cnt; + lsp->hs_ii_cb_errors += illr.ii_illr_fld_s.i_cb_cnt; + lsp->hs_ii_retry_errors += (iio_wstat & 0x0000000000ff0000) >> 16; + + shub_mmr_write(cnode, SH_NI0_LLP_ERR, 0L); + shub_mmr_write(cnode, SH_NI1_LLP_ERR, 0L); + shub_mmr_write_iospace(cnode, IIO_LLP_LOG, 0L); + + /* zero the II retry counter */ + iio_wstat = shub_mmr_read_iospace(cnode, IIO_WSTAT); + iio_wstat &= 0xffffffffff00ffff; /* bits 23:16 */ + shub_mmr_write_iospace(cnode, IIO_WSTAT, iio_wstat); + } + } + + sn_linkstats_samples++; + if (overflows) + sn_linkstats_overflows++; + + spin_unlock(&sn_linkstats_lock); + } +} + +static char * +rate_per_minute(uint64_t val, uint64_t secs) +{ + static char buf[16]; + uint64_t a=0, b=0, c=0, d=0; + + if (secs) { + a = 60 * val / secs; + b = 60 * 10 * val / secs - (10 * a); + c = 60 * 100 * val / secs - (100 * a) - (10 * b); + d = 60 * 1000 * val / secs - (1000 * a) - (100 * b) - (10 * c); + } + sprintf(buf, "%4lu.%lu%lu%lu", a, b, c, d); + + return buf; +} + +int +sn_linkstats_get(char *page) +{ + int n = 0; + int cnode; + int nlport; + struct s_linkstats *lsp; + nodepda_t *npda; + uint64_t snsum = 0; + uint64_t cbsum = 0; + uint64_t retrysum = 0; + uint64_t snsum_ii = 0; + uint64_t cbsum_ii = 0; + uint64_t retrysum_ii = 0; + uint64_t secs; + + spin_lock(&sn_linkstats_lock); + secs = (jiffies - sn_linkstats_starttime) / HZ; + + n += sprintf(page, "# SGI Numalink stats v1 : %lu samples, %lu o/flows, update %lu msecs\n", + sn_linkstats_samples, sn_linkstats_overflows, sn_linkstats_update_msecs); + + n += sprintf(page+n, "%-37s %8s %8s %8s %8s\n", + "# Numalink", "sn errs", "cb errs", "cb/min", "retries"); + + for (lsp=sn_linkstats, cnode=0; cnode < numnodes; cnode++, lsp++) { + npda = NODEPDA(cnode); + + /* two NL links on each SHub */ + for (nlport=0; nlport < 2; nlport++) { + cbsum += lsp->hs_ni_cb_errors[nlport]; + snsum += lsp->hs_ni_sn_errors[nlport]; + retrysum += lsp->hs_ni_retry_errors[nlport]; + + /* avoid buffer overrun (should be using seq_read API) */ + if (numnodes > 64) + continue; + + n += sprintf(page + n, "/%s/link/%d %8lu %8lu %8s %8lu\n", + npda->hwg_node_name, nlport+1, lsp->hs_ni_sn_errors[nlport], + lsp->hs_ni_cb_errors[nlport], + rate_per_minute(lsp->hs_ni_cb_errors[nlport], secs), + lsp->hs_ni_retry_errors[nlport]); + } + + /* one II port on each SHub (may not be connected) */ + if (lsp->hs_ii_up) { + n += sprintf(page + n, "/%s/xtalk %8lu %8lu %8s %8lu\n", + npda->hwg_node_name, lsp->hs_ii_sn_errors, + lsp->hs_ii_cb_errors, rate_per_minute(lsp->hs_ii_cb_errors, secs), + lsp->hs_ii_retry_errors); + + snsum_ii += lsp->hs_ii_sn_errors; + cbsum_ii += lsp->hs_ii_cb_errors; + retrysum_ii += lsp->hs_ii_retry_errors; + } + } + + n += sprintf(page + n, "%-37s %8lu %8lu %8s %8lu\n", + "System wide NL totals", snsum, cbsum, + rate_per_minute(cbsum, secs), retrysum); + + n += sprintf(page + n, "%-37s %8lu %8lu %8s %8lu\n", + "System wide II totals", snsum_ii, cbsum_ii, + rate_per_minute(cbsum_ii, secs), retrysum_ii); + + spin_unlock(&sn_linkstats_lock); + + return n; +} + +static int __init +linkstatd_init(void) +{ + if (!ia64_platform_is("sn2")) + return -ENODEV; + + spin_lock_init(&sn_linkstats_lock); + sn_linkstats = kmalloc(numnodes * sizeof(struct s_linkstats), GFP_KERNEL); + sn_linkstats_reset(60000UL); /* default 60 second update interval */ + kernel_thread(linkstatd_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + + return 0; +} + +__initcall(linkstatd_init); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shub_intr.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/shub_intr.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shub_intr.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/shub_intr.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997, 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -30,7 +30,7 @@ /* ARGSUSED */ void -hub_intr_init(devfs_handle_t hubv) +hub_intr_init(vertex_hdl_t hubv) { } @@ -45,9 +45,9 @@ } static hub_intr_t -do_hub_intr_alloc(devfs_handle_t dev, +do_hub_intr_alloc(vertex_hdl_t dev, device_desc_t dev_desc, - devfs_handle_t owner_dev, + vertex_hdl_t owner_dev, int uncond_nothread) { cpuid_t cpu = 0; @@ -101,17 +101,17 @@ } hub_intr_t -hub_intr_alloc(devfs_handle_t dev, +hub_intr_alloc(vertex_hdl_t dev, device_desc_t dev_desc, - devfs_handle_t owner_dev) + vertex_hdl_t owner_dev) { return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 0)); } hub_intr_t -hub_intr_alloc_nothd(devfs_handle_t dev, +hub_intr_alloc_nothd(vertex_hdl_t dev, device_desc_t dev_desc, - devfs_handle_t owner_dev) + vertex_hdl_t owner_dev) { return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 1)); } @@ -188,18 +188,3 @@ ASSERT(rv == 0); intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED; } - - -/* - * Return a hwgraph vertex that represents the CPU currently - * targeted by an interrupt. - */ -devfs_handle_t -hub_intr_cpu_get(hub_intr_t intr_hdl) -{ - cpuid_t cpuid = intr_hdl->i_cpuid; - - ASSERT(cpuid != CPU_NONE); - - return(cpuid_to_vertex(cpuid)); -} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shuberror.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/shuberror.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shuberror.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/shuberror.c Wed Jul 23 18:28:59 2003 @@ -4,13 +4,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000,2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000,2002-2003 Silicon Graphics, Inc. All rights reserved. */ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -34,21 +36,18 @@ extern void hubni_eint_init(cnodeid_t cnode); extern void hubii_eint_init(cnodeid_t cnode); extern void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep); -int hubiio_crb_error_handler(devfs_handle_t hub_v, hubinfo_t hinfo); -int hubiio_prb_error_handler(devfs_handle_t hub_v, hubinfo_t hinfo); -extern void bte_crb_error_handler(devfs_handle_t hub_v, int btenum, int crbnum, ioerror_t *ioe, int bteop); +int hubiio_crb_error_handler(vertex_hdl_t hub_v, hubinfo_t hinfo); +int hubiio_prb_error_handler(vertex_hdl_t hub_v, hubinfo_t hinfo); +extern void bte_crb_error_handler(vertex_hdl_t hub_v, int btenum, int crbnum, ioerror_t *ioe, int bteop); +void print_crb_fields(int crb_num, ii_icrb0_a_u_t icrba, + ii_icrb0_b_u_t icrbb, ii_icrb0_c_u_t icrbc, + ii_icrb0_d_u_t icrbd, ii_icrb0_e_u_t icrbe); extern int maxcpus; +extern error_return_code_t error_state_set(vertex_hdl_t v,error_state_t new_state); #define HUB_ERROR_PERIOD (120 * HZ) /* 2 minutes */ -#ifdef BUS_INT_WAR -void sn_add_polled_interrupt(int irq, int interval); -void sn_delete_polled_interrupt(int irq); -extern int bus_int_war_ide_irq; -#endif - - void hub_error_clear(nasid_t nasid) { @@ -74,9 +73,7 @@ REMOTE_HUB_S(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)), prb.iprb_regval); } - REMOTE_HUB_S(nasid, IIO_IO_ERR_CLR, -1); - idsr = REMOTE_HUB_L(nasid, IIO_IIDSR); - REMOTE_HUB_S(nasid, IIO_IIDSR, (idsr & ~(IIO_IIDSR_SENT_MASK))); + REMOTE_HUB_S(nasid, IIO_IECLR, -1); } @@ -117,7 +114,6 @@ * Returns : None. */ - void hubii_eint_init(cnodeid_t cnode) { @@ -125,33 +121,41 @@ ii_iidsr_u_t hubio_eint; hubinfo_t hinfo; cpuid_t intr_cpu; - devfs_handle_t hub_v; + vertex_hdl_t hub_v; int bit_pos_to_irq(int bit); + ii_ilcsr_u_t ilcsr; - hub_v = (devfs_handle_t)cnodeid_to_vertex(cnode); + hub_v = (vertex_hdl_t)cnodeid_to_vertex(cnode); ASSERT_ALWAYS(hub_v); hubinfo_get(hub_v, &hinfo); ASSERT(hinfo); ASSERT(hinfo->h_cnodeid == cnode); + ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR); + if ((ilcsr.ii_ilcsr_fld_s.i_llp_stat & 0x2) == 0) { + /* + * HUB II link is not up. Disable LLP. Clear old errors. + * Enable interrupts to handle BTE errors. + */ + ilcsr.ii_ilcsr_fld_s.i_llp_en = 0; + REMOTE_HUB_S(hinfo->h_nasid, IIO_ILCSR, ilcsr.ii_ilcsr_regval); + } + /* Select a possible interrupt target where there is a free interrupt * bit and also reserve the interrupt bit for this IO error interrupt */ - intr_cpu = intr_heuristic(hub_v,0,-1,0,hub_v, + intr_cpu = intr_heuristic(hub_v,0,SGI_II_ERROR,0,hub_v, "HUB IO error interrupt",&bit); if (intr_cpu == CPU_NONE) { printk("hubii_eint_init: intr_reserve_level failed, cnode %d", cnode); return; } - rv = intr_connect_level(intr_cpu, bit, 0, NULL); - request_irq(bit + (intr_cpu << 8), hubii_eint_handler, 0, "SN_hub_error", (void *)hub_v); - irq_desc(bit + (intr_cpu << 8))->status |= SN2_IRQ_PER_HUB; -#ifdef BUS_INT_WAR - sn_add_polled_interrupt(bit + (intr_cpu << 8), (0.01 * HZ)); -#endif + rv = intr_connect_level(intr_cpu, SGI_II_ERROR, 0, NULL); + request_irq(SGI_II_ERROR, hubii_eint_handler, SA_SHIRQ, "SN_hub_error", (void *)hub_v); + irq_desc(bit)->status |= SN2_IRQ_PER_HUB; ASSERT_ALWAYS(rv >= 0); hubio_eint.ii_iidsr_regval = 0; hubio_eint.ii_iidsr_fld_s.i_enable = 1; @@ -167,18 +171,29 @@ void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep) { - devfs_handle_t hub_v; + vertex_hdl_t hub_v; hubinfo_t hinfo; ii_wstat_u_t wstat; hubreg_t idsr; + ii_ilcsr_u_t ilcsr; /* two levels of casting avoids compiler warning.!! */ - hub_v = (devfs_handle_t)(long)(arg); + hub_v = (vertex_hdl_t)(long)(arg); ASSERT(hub_v); hubinfo_get(hub_v, &hinfo); + idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_ICMR); +#if 0 + if (idsr & 0x1) { + /* ICMR bit is set .. we are getting into "Spurious Interrupts condition. */ + printk("Cnode %d II has seen the ICMR condition\n", hinfo->h_cnodeid); + printk("***** Please file PV with the above messages *****\n"); + /* panic("We have to panic to prevent further unknown states ..\n"); */ + } +#endif + /* * Identify the reason for error. */ @@ -218,10 +233,26 @@ * Note: we may never be able to print this, if the II talking * to Xbow which hosts the console is dead. */ - printk("Hub %d to Xtalk Link failed (II_ECRAZY) Reason: %s", - hinfo->h_cnodeid, reason); + ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR); + if (ilcsr.ii_ilcsr_fld_s.i_llp_en == 1) { /* Link is enabled */ + printk("Hub %d, cnode %d to Xtalk Link failed (II_ECRAZY) Reason: %s", + hinfo->h_nasid, hinfo->h_cnodeid, reason); + } } + + /* + * Before processing any interrupt related information, clear all + * error indication and reenable interrupts. This will prevent + * lost interrupts due to the interrupt handler scanning past a PRB/CRB + * which has not errorred yet and then the PRB/CRB goes into error. + * Note, PRB errors are cleared individually. + */ + REMOTE_HUB_S(hinfo->h_nasid, IIO_IECLR, 0xff0000); + idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_IIDSR) & ~IIO_IIDSR_SENT_MASK; + REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, idsr); + + /* * It's a toss as to which one among PRB/CRB to check first. * Current decision is based on the severity of the errors. @@ -232,14 +263,6 @@ */ (void)hubiio_crb_error_handler(hub_v, hinfo); (void)hubiio_prb_error_handler(hub_v, hinfo); - /* - * If we reach here, it indicates crb/prb handlers successfully - * handled the error. So, re-enable II to send more interrupt - * and return. - */ - REMOTE_HUB_S(hinfo->h_nasid, IIO_IECLR, 0xffffff); - idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_IIDSR) & ~IIO_IIDSR_SENT_MASK; - REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, idsr); } /* @@ -295,6 +318,105 @@ "Xtalk Error Packet" }; +void +print_crb_fields(int crb_num, ii_icrb0_a_u_t icrba, + ii_icrb0_b_u_t icrbb, ii_icrb0_c_u_t icrbc, + ii_icrb0_d_u_t icrbd, ii_icrb0_e_u_t icrbe) +{ + printk("CRB %d regA\n\t" + "a_iow 0x%x\n\t" + "valid0x%x\n\t" + "Address0x%lx\n\t" + "a_tnum 0x%x\n\t" + "a_sidn 0x%x\n", + crb_num, + icrba.a_iow, + icrba.a_valid, + icrba.a_addr, + icrba.a_tnum, + icrba.a_sidn); + printk("CRB %d regB\n\t" + "b_imsgtype 0x%x\n\t" + "b_imsg 0x%x\n" + "\tb_use_old 0x%x\n\t" + "b_initiator 0x%x\n\t" + "b_exc 0x%x\n" + "\tb_ackcnt 0x%x\n\t" + "b_resp 0x%x\n\t" + "b_ack 0x%x\n" + "\tb_hold 0x%x\n\t" + "b_wb 0x%x\n\t" + "b_intvn 0x%x\n" + "\tb_stall_ib 0x%x\n\t" + "b_stall_int 0x%x\n" + "\tb_stall_bte_0 0x%x\n\t" + "b_stall_bte_1 0x%x\n" + "\tb_error 0x%x\n\t" + "b_lnetuce 0x%x\n\t" + "b_mark 0x%x\n\t" + "b_xerr 0x%x\n", + crb_num, + icrbb.b_imsgtype, + icrbb.b_imsg, + icrbb.b_use_old, + icrbb.b_initiator, + icrbb.b_exc, + icrbb.b_ackcnt, + icrbb.b_resp, + icrbb.b_ack, + icrbb.b_hold, + icrbb.b_wb, + icrbb.b_intvn, + icrbb.b_stall_ib, + icrbb.b_stall_int, + icrbb.b_stall_bte_0, + icrbb.b_stall_bte_1, + icrbb.b_error, + icrbb.b_lnetuce, + icrbb.b_mark, + icrbb.b_xerr); + printk("CRB %d regC\n\t" + "c_source 0x%x\n\t" + "c_xtsize 0x%x\n\t" + "c_cohtrans 0x%x\n\t" + "c_btenum 0x%x\n\t" + "c_gbr 0x%x\n\t" + "c_doresp 0x%x\n\t" + "c_barrop 0x%x\n\t" + "c_suppl 0x%x\n", + crb_num, + icrbc.c_source, + icrbc.c_xtsize, + icrbc.c_cohtrans, + icrbc.c_btenum, + icrbc.c_gbr, + icrbc.c_doresp, + icrbc.c_barrop, + icrbc.c_suppl); + printk("CRB %d regD\n\t" + "d_bteaddr 0x%lx\n\t" + "d_bteop 0x%x\n\t" + "d_pripsc 0x%x\n\t" + "d_pricnt 0x%x\n\t" + "d_sleep 0x%x\n\t", + crb_num, + icrbd.d_bteaddr, + icrbd.d_bteop, + icrbd.d_pripsc, + icrbd.d_pricnt, + icrbd.d_sleep); + printk("CRB %d regE\n\t" + "icrbe_timeout 0x%x\n\t" + "icrbe_context 0x%x\n\t" + "icrbe_toutvld 0x%x\n\t" + "icrbe_ctxtvld 0x%x\n\t", + crb_num, + icrbe.icrbe_timeout, + icrbe.icrbe_context, + icrbe.icrbe_toutvld, + icrbe.icrbe_ctxtvld); +} + /* * hubiio_crb_error_handler * @@ -317,7 +439,7 @@ */ int -hubiio_crb_error_handler(devfs_handle_t hub_v, hubinfo_t hinfo) +hubiio_crb_error_handler(vertex_hdl_t hub_v, hubinfo_t hinfo) { cnodeid_t cnode; nasid_t nasid; @@ -335,6 +457,9 @@ cnode = NASID_TO_COMPACT_NODEID(nasid); /* + * XXX - Add locking for any recovery actions + */ + /* * Scan through all CRBs in the Hub, and handle the errors * in any of the CRBs marked. */ @@ -373,16 +498,11 @@ else /* b_initiator bit 2 gives BTE number */ bte_num = (icrbb.b_initiator & 0x4) >> 2; - /* >>> bte_crb_error_handler needs to be - * broken into two parts. The first should - * cleanup the CRB. The second should wait - * until all bte related CRB's are complete - * and then do the error reset. - */ + hubiio_crb_free(hinfo, i); + bte_crb_error_handler(hub_v, bte_num, i, &ioerror, icrbd.d_bteop); - hubiio_crb_free(hinfo, i); num_errors++; continue; } @@ -430,6 +550,86 @@ IOERROR_SETVALUE(&ioerror, tnum, icrba.a_tnum); } + if (icrbb.b_error) { + /* + * CRB 'i' has some error. Identify the type of error, + * and try to handle it. + * + */ + switch(icrbb.b_ecode) { + case IIO_ICRB_ECODE_PERR: + case IIO_ICRB_ECODE_WERR: + case IIO_ICRB_ECODE_AERR: + case IIO_ICRB_ECODE_PWERR: + case IIO_ICRB_ECODE_TOUT: + case IIO_ICRB_ECODE_XTERR: + printk("Shub II CRB %d: error %s on hub cnodeid: %d", + i, hubiio_crb_errors[icrbb.b_ecode], cnode); + /* + * Any sort of write error is mostly due + * bad programming (Note it's not a timeout.) + * So, invoke hub_iio_error_handler with + * appropriate information. + */ + IOERROR_SETVALUE(&ioerror,errortype,icrbb.b_ecode); + + /* Go through the error bit lookup phase */ + if (error_state_set(hub_v, ERROR_STATE_LOOKUP) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); + rc = hub_ioerror_handler( + hub_v, + DMA_WRITE_ERROR, + MODE_DEVERROR, + &ioerror); + if (rc == IOERROR_HANDLED) { + rc = hub_ioerror_handler( + hub_v, + DMA_WRITE_ERROR, + MODE_DEVREENABLE, + &ioerror); + }else { + printk("Unable to handle %s on hub %d", + hubiio_crb_errors[icrbb.b_ecode], + cnode); + /* panic; */ + } + /* Go to Next error */ + print_crb_fields(i, icrba, icrbb, icrbc, + icrbd, icrbe); + hubiio_crb_free(hinfo, i); + continue; + case IIO_ICRB_ECODE_PRERR: + case IIO_ICRB_ECODE_DERR: + printk("Shub II CRB %d: error %s on hub : %d", + i, hubiio_crb_errors[icrbb.b_ecode], cnode); + /* panic */ + default: + printk("Shub II CRB error (code : %d) on hub : %d", + icrbb.b_ecode, cnode); + /* panic */ + } + } + /* + * Error is not indicated via the errcode field + * Check other error indications in this register. + */ + if (icrbb.b_xerr) { + printk("Shub II CRB %d: Xtalk Packet with error bit set to hub %d", + i, cnode); + /* panic */ + } + if (icrbb.b_lnetuce) { + printk("Shub II CRB %d: Uncorrectable data error detected on data " + " from NUMAlink to node %d", + i, cnode); + /* panic */ + } + print_crb_fields(i, icrba, icrbb, icrbc, icrbd, icrbe); + + + + if (icrbb.b_error) { /* @@ -488,7 +688,7 @@ default: panic("Fatal error (code : %d) on hub : %d", - cnode); + icrbb.b_ecode, cnode); /*NOTREACHED*/ } @@ -568,7 +768,7 @@ * Cleanup involes freeing the PRB register */ static void -hubii_prb_handler(devfs_handle_t hub_v, hubinfo_t hinfo, int wnum) +hubii_prb_handler(vertex_hdl_t hub_v, hubinfo_t hinfo, int wnum) { nasid_t nasid; @@ -576,13 +776,13 @@ /* * Clear error bit by writing to IECLR register. */ - REMOTE_HUB_S(nasid, IIO_IO_ERR_CLR, (1 << wnum)); + REMOTE_HUB_S(nasid, IIO_IECLR, (1 << wnum)); /* * PIO Write to Widget 'i' got into an error. * Invoke hubiio_error_handler with this information. */ - printk( "Hub nasid %d got a PIO Write error from widget %d, cleaning up and continuing", - nasid, wnum); + printk( "Hub nasid %d got a PIO Write error from widget %d, " + "cleaning up and continuing", nasid, wnum); /* * XXX * It may be necessary to adjust IO PRB counter @@ -591,7 +791,7 @@ } int -hubiio_prb_error_handler(devfs_handle_t hub_v, hubinfo_t hinfo) +hubiio_prb_error_handler(vertex_hdl_t hub_v, hubinfo_t hinfo) { int wnum; nasid_t nasid; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shubio.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/shubio.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/shubio.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/shubio.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000,2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000,2002-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -30,8 +30,8 @@ #include -error_state_t error_state_get(devfs_handle_t v); -error_return_code_t error_state_set(devfs_handle_t v,error_state_t new_state); +error_state_t error_state_get(vertex_hdl_t v); +error_return_code_t error_state_set(vertex_hdl_t v,error_state_t new_state); /* @@ -42,7 +42,7 @@ /*ARGSUSED*/ int hub_xp_error_handler( - devfs_handle_t hub_v, + vertex_hdl_t hub_v, nasid_t nasid, int error_code, ioerror_mode_t mode, @@ -50,7 +50,7 @@ { /*REFERENCED*/ hubreg_t iio_imem; - devfs_handle_t xswitch; + vertex_hdl_t xswitch; error_state_t e_state; cnodeid_t cnode; @@ -148,7 +148,7 @@ */ int hub_ioerror_handler( - devfs_handle_t hub_v, + vertex_hdl_t hub_v, int error_code, int mode, struct io_error_s *ioerror) @@ -158,6 +158,7 @@ int retval = 0; /*REFERENCED*/ iopaddr_t p; + caddr_t cp; IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror); @@ -193,14 +194,14 @@ * This is typically true for user mode bus errors while * accessing I/O space. */ - IOERROR_GETVALUE(p,ioerror,vaddr); - if (p){ + IOERROR_GETVALUE(cp,ioerror,vaddr); + if (cp){ /* * If neither in small window nor in large window range, * outright reject it. */ - IOERROR_GETVALUE(p,ioerror,vaddr); - if (NODE_SWIN_ADDR(nasid, (paddr_t)p)){ + IOERROR_GETVALUE(cp,ioerror,vaddr); + if (NODE_SWIN_ADDR(nasid, (paddr_t)cp)){ iopaddr_t hubaddr; xwidgetnum_t widgetnum; iopaddr_t xtalkaddr; @@ -216,7 +217,7 @@ IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); - } else if (NODE_BWIN_ADDR(nasid, (paddr_t)p)){ + } else if (NODE_BWIN_ADDR(nasid, (paddr_t)cp)){ /* * Address corresponds to large window space. * Convert it to xtalk address. @@ -428,11 +429,6 @@ return retval; } -#define L_BITSMINOR 18 -#define L_MAXMAJ 0x1ff -#define emajor(x) (int )(((unsigned )(x)>>L_BITSMINOR) & L_MAXMAJ) -#define dev_is_vertex(dev) (emajor((dev_t)(dev)) == 0) - #define INFO_LBL_ERROR_STATE "error_state" #define v_error_state_get(v,s) \ @@ -454,12 +450,12 @@ * current state otherwise */ error_state_t -error_state_get(devfs_handle_t v) +error_state_get(vertex_hdl_t v) { error_state_t s; /* Check if we have a valid hwgraph vertex */ - if (!dev_is_vertex(v)) + if ( v == (vertex_hdl_t)0 ) return(ERROR_STATE_NONE); /* Get the labelled info hanging off the vertex which corresponds @@ -479,13 +475,13 @@ * ERROR_RETURN_CODE_SUCCESS otherwise */ error_return_code_t -error_state_set(devfs_handle_t v,error_state_t new_state) +error_state_set(vertex_hdl_t v,error_state_t new_state) { error_state_t old_state; boolean_t replace = B_TRUE; /* Check if we have a valid hwgraph vertex */ - if (!dev_is_vertex(v)) + if ( v == (vertex_hdl_t)0 ) return(ERROR_RETURN_CODE_GENERAL_FAILURE); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/xbow.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/xbow.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/xbow.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/xbow.c Wed Jul 23 18:28:59 2003 @@ -4,12 +4,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include #include +#include #include +#include #include #include #include @@ -18,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -44,8 +45,6 @@ #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) #define DEL(ptr) (kfree(ptr)) -int xbow_devflag = D_MP; - /* * This file supports the Xbow chip. Main functions: initializtion, * error handling, and GBR. @@ -59,9 +58,9 @@ typedef struct xbow_soft_s *xbow_soft_t; struct xbow_soft_s { - devfs_handle_t conn; /* our connection point */ - devfs_handle_t vhdl; /* xbow's private vertex */ - devfs_handle_t busv; /* the xswitch vertex */ + vertex_hdl_t conn; /* our connection point */ + vertex_hdl_t vhdl; /* xbow's private vertex */ + vertex_hdl_t busv; /* the xswitch vertex */ xbow_t *base; /* PIO pointer to crossbow chip */ char *name; /* hwgraph name */ @@ -89,36 +88,27 @@ */ void xbow_mlreset(xbow_t *); -void xbow_init(void); -int xbow_attach(devfs_handle_t); - -int xbow_open(devfs_handle_t *, int, int, cred_t *); -int xbow_close(devfs_handle_t, int, int, cred_t *); - -int xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); -int xbow_unmap(devfs_handle_t, vhandl_t *); -int xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); +int xbow_attach(vertex_hdl_t); int xbow_widget_present(xbow_t *, int); static int xbow_link_alive(xbow_t *, int); -devfs_handle_t xbow_widget_lookup(devfs_handle_t, int); +vertex_hdl_t xbow_widget_lookup(vertex_hdl_t, int); void xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); -void xbow_update_perf_counters(devfs_handle_t); -xbow_perf_link_t *xbow_get_perf_counters(devfs_handle_t); -int xbow_enable_perf_counter(devfs_handle_t, int, int, int); -xbow_link_status_t *xbow_get_llp_status(devfs_handle_t); -void xbow_update_llp_status(devfs_handle_t); - -int xbow_disable_llp_monitor(devfs_handle_t); -int xbow_enable_llp_monitor(devfs_handle_t); -int xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t, +void xbow_update_perf_counters(vertex_hdl_t); +xbow_perf_link_t *xbow_get_perf_counters(vertex_hdl_t); +int xbow_enable_perf_counter(vertex_hdl_t, int, int, int); +xbow_link_status_t *xbow_get_llp_status(vertex_hdl_t); +void xbow_update_llp_status(vertex_hdl_t); + +int xbow_disable_llp_monitor(vertex_hdl_t); +int xbow_enable_llp_monitor(vertex_hdl_t); +int xbow_prio_bw_alloc(vertex_hdl_t, xwidgetnum_t, xwidgetnum_t, unsigned long long, unsigned long long); static void xbow_setwidint(xtalk_intr_t); -void idbg_xbowregs(int64_t); xswitch_reset_link_f xbow_reset_link; @@ -127,6 +117,32 @@ xbow_reset_link, }; + +static int +xbow_mmap(struct file * file, struct vm_area_struct * vma) +{ + unsigned long phys_addr; + int error = 0; + + phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO; + error = io_remap_page_range(vma->vm_start, phys_addr, + vma->vm_end-vma->vm_start, + vma->vm_page_prot); + return(error); +} + +/* + * This is the file operation table for the pcibr driver. + * As each of the functions are implemented, put the + * appropriate function name below. + */ +struct file_operations xbow_fops = { + .owner = THIS_MODULE, + .mmap = xbow_mmap, +}; + /* * xbow_mlreset: called at mlreset time if the * platform specific code determines that there is @@ -144,39 +160,6 @@ { } -/* - * xbow_init: called with the rest of the device - * driver XXX_init routines. This platform *might* - * have a Crossbow chip, or even several, but it - * might have none. Register with the crosstalk - * generic provider so when we encounter the chip - * the right magic happens. - */ -void -xbow_init(void) -{ - -#if DEBUG && ATTACH_DEBUG - printk("xbow_init\n"); -#endif - - xwidget_driver_register(PXBOW_WIDGET_PART_NUM, - 0, /* XXBOW_WIDGET_MFGR_NUM, */ - "xbow_", - CDL_PRI_HI); /* attach before friends */ - - - xwidget_driver_register(XXBOW_WIDGET_PART_NUM, - 0, /* XXBOW_WIDGET_MFGR_NUM, */ - "xbow_", - CDL_PRI_HI); /* attach before friends */ - - xwidget_driver_register(XBOW_WIDGET_PART_NUM, - XBOW_WIDGET_MFGR_NUM, - "xbow_", - CDL_PRI_HI); /* attach before friends */ -} - #ifdef XBRIDGE_REGS_SIM /* xbow_set_simulated_regs: sets xbow regs as needed * for powering through the boot @@ -213,11 +196,11 @@ /*ARGSUSED */ int -xbow_attach(devfs_handle_t conn) +xbow_attach(vertex_hdl_t conn) { /*REFERENCED */ - devfs_handle_t vhdl; - devfs_handle_t busv; + vertex_hdl_t vhdl; + vertex_hdl_t busv; xbow_t *xbow; xbow_soft_t soft; int port; @@ -274,15 +257,14 @@ */ /* - * We need to teach xbow drivers to provide the right set of + * Register a xbow driver with devfs. * file ops. */ vhdl = NULL; - vhdl = hwgraph_register(conn, EDGE_LBL_XBOW, - 0, DEVFS_FL_AUTO_DEVNUM, - 0, 0, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, - /* &hcl_fops */ (void *)&vhdl, NULL); + vhdl = hwgraph_register(conn, EDGE_LBL_XBOW, 0, + DEVFS_FL_AUTO_DEVNUM, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + (struct file_operations *)&xbow_fops, (void *)xbow); if (!vhdl) { printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n", (void *)conn); @@ -299,7 +281,7 @@ soft->base = xbow; /* does the universe really need another macro? */ /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */ - hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); + /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */ #define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]" @@ -350,6 +332,14 @@ */ intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl); ASSERT(intr_hdl != NULL); + + { + int irq = ((hub_intr_t)intr_hdl)->i_bit; + int cpu = ((hub_intr_t)intr_hdl)->i_cpuid; + + intr_unreserve_level(cpu, irq); + ((hub_intr_t)intr_hdl)->i_bit = SGI_XBOW_ERROR; + } xtalk_intr_connect(intr_hdl, (intr_func_t) xbow_errintr_handler, @@ -357,19 +347,9 @@ (xtalk_intr_setfunc_t) xbow_setwidint, (void *) xbow); -#ifdef BUS_INT_WAR_NOT_YET - request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, - ((hub_intr_t)intr_hdl)->i_bit), - (intr_func_t)xbow_errintr_handler, 0, "XBOW error", + request_irq(SGI_XBOW_ERROR, (void *)xbow_errintr_handler, SA_SHIRQ, "XBOW error", (intr_arg_t) soft); - { - void sn_add_polled_interrupt(int, int); - sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, - ((hub_intr_t)intr_hdl)->i_bit), 5000); - } -#endif - /* * Enable xbow error interrupts @@ -439,50 +419,14 @@ return 0; /* attach successful */ } -/*ARGSUSED */ -int -xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) -{ - return 0; -} - -/*ARGSUSED */ -int -xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) -{ - return 0; -} - -/*ARGSUSED */ -int -xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) -{ - devfs_handle_t vhdl = dev_to_vhdl(dev); - xbow_soft_t soft = xbow_soft_get(vhdl); - int error; - - ASSERT(soft); - len = ctob(btoc(len)); - /* XXX- this ignores the offset!!! */ - error = v_mapphys(vt, (void *) soft->base, len); - return error; -} - -/*ARGSUSED */ -int -xbow_unmap(devfs_handle_t dev, vhandl_t *vt) -{ - return 0; -} - /* This contains special-case code for grio. There are plans to make * this general sometime in the future, but till then this should * be good enough. */ xwidgetnum_t -xbow_widget_num_get(devfs_handle_t dev) +xbow_widget_num_get(vertex_hdl_t dev) { - devfs_handle_t tdev; + vertex_hdl_t tdev; char devname[MAXDEVNAME]; xwidget_info_t xwidget_info; int i; @@ -512,58 +456,6 @@ return XWIDGET_NONE; } -int -xbow_ioctl(devfs_handle_t dev, - int cmd, - void *arg, - int flag, - struct cred *cr, - int *rvalp) -{ - devfs_handle_t vhdl; - int error = 0; - -#if defined (DEBUG) - int rc; - devfs_handle_t conn; - struct xwidget_info_s *xwidget_info; - xbow_soft_t xbow_soft; -#endif - *rvalp = 0; - - vhdl = dev_to_vhdl(dev); -#if defined (DEBUG) - xbow_soft = xbow_soft_get(vhdl); - conn = xbow_soft->conn; - - xwidget_info = xwidget_info_get(conn); - ASSERT_ALWAYS(xwidget_info != NULL); - - rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid); - ASSERT_ALWAYS(rc != 0); -#endif - switch (cmd) { - - case XBOWIOC_LLP_ERROR_ENABLE: - if ((error = xbow_enable_llp_monitor(vhdl)) != 0) - error = EINVAL; - - break; - - case XBOWIOC_LLP_ERROR_DISABLE: - - if ((error = xbow_disable_llp_monitor(vhdl)) != 0) - error = EINVAL; - - break; - - default: - break; - - } - return error; -} - /* * xbow_widget_present: See if a device is present * on the specified port of this crossbow. @@ -605,12 +497,12 @@ * specified. * If not found, return 0. */ -devfs_handle_t -xbow_widget_lookup(devfs_handle_t vhdl, +vertex_hdl_t +xbow_widget_lookup(vertex_hdl_t vhdl, int widgetnum) { xswitch_info_t xswitch_info; - devfs_handle_t conn; + vertex_hdl_t conn; xswitch_info = xswitch_info_get(vhdl); conn = xswitch_info_vhdl_get(xswitch_info, widgetnum); @@ -660,10 +552,6 @@ XTALK_ADDR_TO_UPPER(addr)); xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); -#ifdef BRINGUP2 -printk("xbow_intr_preset: xb_wid_int_upper 0x%lx xb_wid_int_lower 0x%lx\n", - (long)(((0xFF000000 & (vect << 24)) | (0x000F0000 & (targ << 16)) |XTALK_ADDR_TO_UPPER(addr))), (long)XTALK_ADDR_TO_LOWER(addr)); -#endif } #define XEM_ADD_STR(s) printk("%s", (s)) @@ -674,48 +562,14 @@ XEM_ADD_NVAR("ioe." #n, p); \ } -#ifdef LATER -static void -xem_add_ioe(ioerror_t *ioe) -{ - union tmp { - ushort stmp; - unsigned long long lltmp; - cpuid_t cputmp; - cnodeid_t cntmp; - iopaddr_t iotmp; - caddr_t catmp; - paddr_t patmp; - } tmp; - - XEM_ADD_IOEF(tmp.stmp, errortype); - XEM_ADD_IOEF(tmp.stmp, widgetnum); - XEM_ADD_IOEF(tmp.stmp, widgetdev); - XEM_ADD_IOEF(tmp.cputmp, srccpu); - XEM_ADD_IOEF(tmp.cntmp, srcnode); - XEM_ADD_IOEF(tmp.cntmp, errnode); - XEM_ADD_IOEF(tmp.iotmp, sysioaddr); - XEM_ADD_IOEF(tmp.iotmp, xtalkaddr); - XEM_ADD_IOEF(tmp.iotmp, busspace); - XEM_ADD_IOEF(tmp.iotmp, busaddr); - XEM_ADD_IOEF(tmp.catmp, vaddr); - XEM_ADD_IOEF(tmp.patmp, memaddr); - XEM_ADD_IOEF(tmp.catmp, epc); - XEM_ADD_IOEF(tmp.catmp, ef); - XEM_ADD_IOEF(tmp.stmp, tnum); -} - -#define XEM_ADD_IOE() (xem_add_ioe(ioe)) -#endif /* LATER */ - -int xbow_xmit_retry_errors = 0; +int xbow_xmit_retry_errors; int xbow_xmit_retry_error(xbow_soft_t soft, int port) { xswitch_info_t info; - devfs_handle_t vhdl; + vertex_hdl_t vhdl; widget_cfg_t *wid; widgetreg_t id; int part; @@ -865,7 +719,7 @@ link_pend &= ~XB_STAT_XMT_RTRY_ERR; } if (link_pend) { - devfs_handle_t xwidget_vhdl; + vertex_hdl_t xwidget_vhdl; char *xwidget_name; /* Get the widget name corresponding to the current @@ -917,12 +771,6 @@ XEM_ADD_VAR(link_status); XEM_ADD_VAR(link_aux_status); -#ifdef LATER - if (dump_ioe) { - XEM_ADD_IOE(); - dump_ioe = 0; - } -#endif #if !DEBUG } #endif @@ -987,8 +835,8 @@ xbow_soft_t soft = (xbow_soft_t) einfo; int port; - devfs_handle_t conn; - devfs_handle_t busv; + vertex_hdl_t conn; + vertex_hdl_t busv; xbow_t *xbow = soft->base; xbowreg_t wid_stat; @@ -1240,7 +1088,7 @@ } void -xbow_update_perf_counters(devfs_handle_t vhdl) +xbow_update_perf_counters(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; @@ -1268,7 +1116,7 @@ } xbow_perf_link_t * -xbow_get_perf_counters(devfs_handle_t vhdl) +xbow_get_perf_counters(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); xbow_perf_link_t *xbow_perf_link = xbow_soft->xbow_perflink; @@ -1277,7 +1125,7 @@ } int -xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter) +xbow_enable_perf_counter(vertex_hdl_t vhdl, int link, int mode, int counter) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; @@ -1331,7 +1179,7 @@ } xbow_link_status_t * -xbow_get_llp_status(devfs_handle_t vhdl) +xbow_get_llp_status(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; @@ -1340,7 +1188,7 @@ } void -xbow_update_llp_status(devfs_handle_t vhdl) +xbow_update_llp_status(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; @@ -1348,7 +1196,7 @@ xbwX_stat_t lnk_sts; xbow_aux_link_status_t aux_sts; int link; - devfs_handle_t xwidget_vhdl; + vertex_hdl_t xwidget_vhdl; char *xwidget_name; xbow = (xbow_t *) xbow_soft->base; @@ -1382,7 +1230,7 @@ } int -xbow_disable_llp_monitor(devfs_handle_t vhdl) +xbow_disable_llp_monitor(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); int port; @@ -1397,7 +1245,7 @@ } int -xbow_enable_llp_monitor(devfs_handle_t vhdl) +xbow_enable_llp_monitor(vertex_hdl_t vhdl) { xbow_soft_t xbow_soft = xbow_soft_get(vhdl); @@ -1407,7 +1255,7 @@ int -xbow_reset_link(devfs_handle_t xconn_vhdl) +xbow_reset_link(vertex_hdl_t xconn_vhdl) { xwidget_info_t widget_info; xwidgetnum_t port; @@ -1430,7 +1278,7 @@ xbow = XBOW_K1PTR; #else { - devfs_handle_t xbow_vhdl; + vertex_hdl_t xbow_vhdl; xbow_soft_t xbow_soft; hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl); @@ -1463,46 +1311,6 @@ return 0; } -/* - * Dump xbow registers. - * input parameter is either a pointer to - * the xbow chip or the vertex handle for - * an xbow vertex. - */ -void -idbg_xbowregs(int64_t regs) -{ - xbow_t *xbow; - int i; - xb_linkregs_t *link; - - xbow = (xbow_t *) regs; - -#ifdef LATER - qprintf("Printing xbow registers starting at 0x%x\n", xbow); - qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n", - xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper, - xbow->xb_wid_err_lower, xbow->xb_wid_control, - xbow->xb_wid_req_timeout); - qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n", - xbow->xb_wid_int_upper, xbow->xb_wid_int_lower, - xbow->xb_wid_err_cmdword, xbow->xb_wid_llp, - xbow->xb_wid_arb_reload); -#endif - - for (i = 8; i <= 0xf; i++) { - link = &xbow->xb_link(i); -#ifdef LATER - qprintf("Link %d registers\n", i); - qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n", - link->link_control, link->link_status, - link->link_arb_upper, link->link_arb_lower, - link->link_aux_status); -#endif - } -} - - #define XBOW_ARB_RELOAD_TICKS 25 /* granularity: 4 MB/s, max: 124 MB/s */ #define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS) @@ -1562,7 +1370,7 @@ * If bandwidth allocation is successful, return success else return failure. */ int -xbow_prio_bw_alloc(devfs_handle_t vhdl, +xbow_prio_bw_alloc(vertex_hdl_t vhdl, xwidgetnum_t src_wid, xwidgetnum_t dest_wid, unsigned long long old_alloc_bw, diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/xtalk.c linux2.4.21_itanium/arch/ia64/sn/io/sn2/xtalk.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/sn2/xtalk.c Wed Jul 23 18:21:04 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/sn2/xtalk.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -37,8 +37,6 @@ char widget_info_fingerprint[] = "widget_info"; -cdl_p xtalk_registry = NULL; - #define DEV_FUNC(dev,func) hub_##func #define CAST_PIOMAP(x) ((hub_piomap_t)(x)) #define CAST_DMAMAP(x) ((hub_dmamap_t)(x)) @@ -47,71 +45,70 @@ /* ===================================================================== * Function Table of Contents */ -xtalk_piomap_t xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned); +xtalk_piomap_t xtalk_piomap_alloc(vertex_hdl_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned); void xtalk_piomap_free(xtalk_piomap_t); caddr_t xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t); void xtalk_piomap_done(xtalk_piomap_t); -caddr_t xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned); -caddr_t xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned); +caddr_t xtalk_piotrans_addr(vertex_hdl_t, device_desc_t, iopaddr_t, size_t, unsigned); +caddr_t xtalk_pio_addr(vertex_hdl_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned); void xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *); caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); static caddr_t null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); -xtalk_dmamap_t xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +xtalk_dmamap_t xtalk_dmamap_alloc(vertex_hdl_t, device_desc_t, size_t, unsigned); void xtalk_dmamap_free(xtalk_dmamap_t); iopaddr_t xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t); alenlist_t xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned); void xtalk_dmamap_done(xtalk_dmamap_t); -iopaddr_t xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); -alenlist_t xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +iopaddr_t xtalk_dmatrans_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t xtalk_dmatrans_list(vertex_hdl_t, device_desc_t, alenlist_t, unsigned); void xtalk_dmamap_drain(xtalk_dmamap_t); -void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t); -void xtalk_dmalist_drain(devfs_handle_t, alenlist_t); -xtalk_intr_t xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t); -xtalk_intr_t xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t); +void xtalk_dmaaddr_drain(vertex_hdl_t, iopaddr_t, size_t); +void xtalk_dmalist_drain(vertex_hdl_t, alenlist_t); +xtalk_intr_t xtalk_intr_alloc(vertex_hdl_t, device_desc_t, vertex_hdl_t); +xtalk_intr_t xtalk_intr_alloc_nothd(vertex_hdl_t, device_desc_t, vertex_hdl_t); void xtalk_intr_free(xtalk_intr_t); int xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *); void xtalk_intr_disconnect(xtalk_intr_t); -devfs_handle_t xtalk_intr_cpu_get(xtalk_intr_t); -int xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *); -int xtalk_error_devenable(devfs_handle_t, int, int); -void xtalk_provider_startup(devfs_handle_t); -void xtalk_provider_shutdown(devfs_handle_t); -devfs_handle_t xtalk_intr_dev_get(xtalk_intr_t); +vertex_hdl_t xtalk_intr_cpu_get(xtalk_intr_t); +int xtalk_error_handler(vertex_hdl_t, int, ioerror_mode_t, ioerror_t *); +int xtalk_error_devenable(vertex_hdl_t, int, int); +void xtalk_provider_startup(vertex_hdl_t); +void xtalk_provider_shutdown(vertex_hdl_t); +vertex_hdl_t xtalk_intr_dev_get(xtalk_intr_t); xwidgetnum_t xtalk_intr_target_get(xtalk_intr_t); xtalk_intr_vector_t xtalk_intr_vector_get(xtalk_intr_t); iopaddr_t xtalk_intr_addr_get(struct xtalk_intr_s *); void *xtalk_intr_sfarg_get(xtalk_intr_t); -devfs_handle_t xtalk_pio_dev_get(xtalk_piomap_t); +vertex_hdl_t xtalk_pio_dev_get(xtalk_piomap_t); xwidgetnum_t xtalk_pio_target_get(xtalk_piomap_t); iopaddr_t xtalk_pio_xtalk_addr_get(xtalk_piomap_t); ulong xtalk_pio_mapsz_get(xtalk_piomap_t); caddr_t xtalk_pio_kvaddr_get(xtalk_piomap_t); -devfs_handle_t xtalk_dma_dev_get(xtalk_dmamap_t); +vertex_hdl_t xtalk_dma_dev_get(xtalk_dmamap_t); xwidgetnum_t xtalk_dma_target_get(xtalk_dmamap_t); -xwidget_info_t xwidget_info_chk(devfs_handle_t); -xwidget_info_t xwidget_info_get(devfs_handle_t); -void xwidget_info_set(devfs_handle_t, xwidget_info_t); -devfs_handle_t xwidget_info_dev_get(xwidget_info_t); +xwidget_info_t xwidget_info_chk(vertex_hdl_t); +xwidget_info_t xwidget_info_get(vertex_hdl_t); +void xwidget_info_set(vertex_hdl_t, xwidget_info_t); +vertex_hdl_t xwidget_info_dev_get(xwidget_info_t); xwidgetnum_t xwidget_info_id_get(xwidget_info_t); -devfs_handle_t xwidget_info_master_get(xwidget_info_t); +vertex_hdl_t xwidget_info_master_get(xwidget_info_t); xwidgetnum_t xwidget_info_masterid_get(xwidget_info_t); xwidget_part_num_t xwidget_info_part_num_get(xwidget_info_t); xwidget_mfg_num_t xwidget_info_mfg_num_get(xwidget_info_t); char *xwidget_info_name_get(xwidget_info_t); -void xtalk_init(void); -void xtalk_provider_register(devfs_handle_t, xtalk_provider_t *); -void xtalk_provider_unregister(devfs_handle_t); -xtalk_provider_t *xtalk_provider_fns_get(devfs_handle_t); +void xtalk_provider_register(vertex_hdl_t, xtalk_provider_t *); +void xtalk_provider_unregister(vertex_hdl_t); +xtalk_provider_t *xtalk_provider_fns_get(vertex_hdl_t); int xwidget_driver_register(xwidget_part_num_t, xwidget_mfg_num_t, char *, unsigned); void xwidget_driver_unregister(char *); -int xwidget_register(xwidget_hwid_t, devfs_handle_t, - xwidgetnum_t, devfs_handle_t, - xwidgetnum_t, async_attach_t); -int xwidget_unregister(devfs_handle_t); -void xwidget_reset(devfs_handle_t); -char *xwidget_name_get(devfs_handle_t); +int xwidget_register(xwidget_hwid_t, vertex_hdl_t, + xwidgetnum_t, vertex_hdl_t, + xwidgetnum_t); +int xwidget_unregister(vertex_hdl_t); +void xwidget_reset(vertex_hdl_t); +char *xwidget_name_get(vertex_hdl_t); #if !defined(DEV_FUNC) /* * There is more than one possible provider @@ -126,7 +123,7 @@ #define CAST_INTR(x) ((xtalk_intr_t)(x)) static xtalk_provider_t * -xwidget_to_provider_fns(devfs_handle_t xconn) +xwidget_to_provider_fns(vertex_hdl_t xconn) { xwidget_info_t widget_info; xtalk_provider_t *provider_fns; @@ -159,7 +156,7 @@ */ xtalk_piomap_t -xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ +xtalk_piomap_alloc(vertex_hdl_t dev, /* set up mapping for this device */ device_desc_t dev_desc, /* device descriptor */ iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ size_t byte_count, @@ -198,7 +195,7 @@ caddr_t -xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */ +xtalk_piotrans_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ iopaddr_t xtalk_addr, /* Crosstalk address */ size_t byte_count, /* map this many bytes */ @@ -209,7 +206,7 @@ } caddr_t -xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */ +xtalk_pio_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ iopaddr_t addr, /* starting address (or offset in window) */ size_t byte_count, /* map this many bytes */ @@ -326,7 +323,7 @@ */ xtalk_dmamap_t -xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ +xtalk_dmamap_alloc(vertex_hdl_t dev, /* set up mappings for this device */ device_desc_t dev_desc, /* device descriptor */ size_t byte_count_max, /* max size of a mapping */ unsigned flags) @@ -373,7 +370,7 @@ iopaddr_t -xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ +xtalk_dmatrans_addr(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ paddr_t paddr, /* system physical address */ size_t byte_count, /* length */ @@ -385,7 +382,7 @@ alenlist_t -xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */ +xtalk_dmatrans_list(vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ alenlist_t palenlist, /* system address/length list */ unsigned flags) @@ -402,14 +399,14 @@ } void -xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +xtalk_dmaaddr_drain(vertex_hdl_t dev, paddr_t addr, size_t size) { DEV_FUNC(dev, dmaaddr_drain) (dev, addr, size); } void -xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list) +xtalk_dmalist_drain(vertex_hdl_t dev, alenlist_t list) { DEV_FUNC(dev, dmalist_drain) (dev, list); @@ -426,9 +423,9 @@ * Return resource handle in intr_hdl. */ xtalk_intr_t -xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ +xtalk_intr_alloc(vertex_hdl_t dev, /* which Crosstalk device */ device_desc_t dev_desc, /* device descriptor */ - devfs_handle_t owner_dev) + vertex_hdl_t owner_dev) { /* owner of this interrupt */ return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc) (dev, dev_desc, owner_dev); @@ -440,9 +437,9 @@ * Return resource handle in intr_hdl. */ xtalk_intr_t -xtalk_intr_alloc_nothd(devfs_handle_t dev, /* which Crosstalk device */ +xtalk_intr_alloc_nothd(vertex_hdl_t dev, /* which Crosstalk device */ device_desc_t dev_desc, /* device descriptor */ - devfs_handle_t owner_dev) /* owner of this interrupt */ + vertex_hdl_t owner_dev) /* owner of this interrupt */ { return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd) (dev, dev_desc, owner_dev); @@ -492,11 +489,10 @@ * Return a hwgraph vertex that represents the CPU currently * targeted by an interrupt. */ -devfs_handle_t +vertex_hdl_t xtalk_intr_cpu_get(xtalk_intr_t intr_hdl) { - return INTR_FUNC(intr_hdl, intr_cpu_get) - (CAST_INTR(intr_hdl)); + return (vertex_hdl_t)0; } @@ -526,7 +522,7 @@ */ int xtalk_error_handler( - devfs_handle_t xconn, + vertex_hdl_t xconn, int error_code, ioerror_mode_t mode, ioerror_t *ioerror) @@ -555,7 +551,7 @@ #if defined(SUPPORT_PRINTING_V_FORMAT) printk(KERN_WARNING "Xbow at %v encountered Fatal error", xconn); #else - printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", xconn); + printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", (void *)xconn); #endif ioerror_dump("xtalk", error_code, mode, ioerror); @@ -563,7 +559,7 @@ } int -xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +xtalk_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code) { return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code); } @@ -577,7 +573,7 @@ * Startup a crosstalk provider */ void -xtalk_provider_startup(devfs_handle_t xtalk_provider) +xtalk_provider_startup(vertex_hdl_t xtalk_provider) { DEV_FUNC(xtalk_provider, provider_startup) (xtalk_provider); @@ -588,7 +584,7 @@ * Shutdown a crosstalk provider */ void -xtalk_provider_shutdown(devfs_handle_t xtalk_provider) +xtalk_provider_shutdown(vertex_hdl_t xtalk_provider) { DEV_FUNC(xtalk_provider, provider_shutdown) (xtalk_provider); @@ -598,22 +594,22 @@ * Enable a device on a xtalk widget */ void -xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum) +xtalk_widgetdev_enable(vertex_hdl_t xconn_vhdl, int devnum) { - DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum); + return; } /* * Shutdown a device on a xtalk widget */ void -xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum) +xtalk_widgetdev_shutdown(vertex_hdl_t xconn_vhdl, int devnum) { - DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum); + return; } int -xtalk_dma_enabled(devfs_handle_t xconn_vhdl) +xtalk_dma_enabled(vertex_hdl_t xconn_vhdl) { return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl); } @@ -623,7 +619,7 @@ */ /****** Generic crosstalk interrupt interfaces ******/ -devfs_handle_t +vertex_hdl_t xtalk_intr_dev_get(xtalk_intr_t xtalk_intr) { return (xtalk_intr->xi_dev); @@ -654,7 +650,7 @@ } /****** Generic crosstalk pio interfaces ******/ -devfs_handle_t +vertex_hdl_t xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap) { return (xtalk_piomap->xp_dev); @@ -686,7 +682,7 @@ /****** Generic crosstalk dma interfaces ******/ -devfs_handle_t +vertex_hdl_t xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap) { return (xtalk_dmamap->xd_dev); @@ -707,7 +703,7 @@ * if not, return NULL. */ xwidget_info_t -xwidget_info_chk(devfs_handle_t xwidget) +xwidget_info_chk(vertex_hdl_t xwidget) { arbitrary_info_t ainfo = 0; @@ -717,28 +713,18 @@ xwidget_info_t -xwidget_info_get(devfs_handle_t xwidget) +xwidget_info_get(vertex_hdl_t xwidget) { xwidget_info_t widget_info; widget_info = (xwidget_info_t) hwgraph_fastinfo_get(xwidget); -#ifdef LATER - if ((widget_info != NULL) && - (widget_info->w_fingerprint != widget_info_fingerprint)) -#ifdef SUPPORT_PRINTING_V_FORMAT - PRINT_PANIC("%v bad xwidget_info", xwidget); -#else - PRINT_PANIC("%x bad xwidget_info", xwidget); -#endif -#endif /* LATER */ - return (widget_info); } void -xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info) +xwidget_info_set(vertex_hdl_t xwidget, xwidget_info_t widget_info) { if (widget_info != NULL) widget_info->w_fingerprint = widget_info_fingerprint; @@ -753,11 +739,11 @@ (arbitrary_info_t) widget_info); } -devfs_handle_t +vertex_hdl_t xwidget_info_dev_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_dev_get: null xwidget_info"); return (xwidget_info->w_vertex); } @@ -765,16 +751,16 @@ xwidget_info_id_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_id_get: null xwidget_info"); return (xwidget_info->w_id); } -devfs_handle_t +vertex_hdl_t xwidget_info_master_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_master_get: null xwidget_info"); return (xwidget_info->w_master); } @@ -782,7 +768,7 @@ xwidget_info_masterid_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_masterid_get: null xwidget_info"); return (xwidget_info->w_masterid); } @@ -790,7 +776,7 @@ xwidget_info_part_num_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_part_num_get: null xwidget_info"); return (xwidget_info->w_hwid.part_num); } @@ -798,7 +784,7 @@ xwidget_info_mfg_num_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget_info"); + panic("xwidget_info_mfg_num_get: null xwidget_info"); return (xwidget_info->w_hwid.mfg_num); } /* Extract the widget name from the widget information @@ -808,49 +794,16 @@ xwidget_info_name_get(xwidget_info_t xwidget_info) { if (xwidget_info == NULL) - panic("null xwidget info"); + panic("xwidget_info_name_get: null xwidget_info"); return(xwidget_info->w_name); } /****** Generic crosstalk initialization interfaces ******/ /* - * One-time initialization needed for systems that support crosstalk. - */ -void -xtalk_init(void) -{ - cdl_p cp; - -#if DEBUG && ATTACH_DEBUG - printf("xtalk_init\n"); -#endif - /* Allocate the registry. - * We might already have one. - * If we don't, go get one. - * MPness: someone might have - * set one up for us while we - * were not looking; use an atomic - * compare-and-swap to commit to - * using the new registry if and - * only if nobody else did first. - * If someone did get there first, - * toss the one we allocated back - * into the pool. - */ - if (xtalk_registry == NULL) { - cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr"); - if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) { - cdl_del(cp); - } - } - ASSERT(xtalk_registry != NULL); -} - -/* * Associate a set of xtalk_provider functions with a vertex. */ void -xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns) +xtalk_provider_register(vertex_hdl_t provider, xtalk_provider_t *xtalk_fns) { hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns); } @@ -859,7 +812,7 @@ * Disassociate a set of xtalk_provider functions with a vertex. */ void -xtalk_provider_unregister(devfs_handle_t provider) +xtalk_provider_unregister(vertex_hdl_t provider) { hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL); } @@ -869,50 +822,19 @@ * provider. */ xtalk_provider_t * -xtalk_provider_fns_get(devfs_handle_t provider) +xtalk_provider_fns_get(vertex_hdl_t provider) { return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider)); } /* - * Announce a driver for a particular crosstalk part. - * Returns 0 on success or -1 on failure. Failure occurs if the - * specified hardware already has a driver. - */ -/*ARGSUSED4 */ -int -xwidget_driver_register(xwidget_part_num_t part_num, - xwidget_mfg_num_t mfg_num, - char *driver_prefix, - unsigned flags) -{ - /* a driver's init routine could call - * xwidget_driver_register before the - * system calls xtalk_init; so, we - * make the call here. - */ - if (xtalk_registry == NULL) - xtalk_init(); - - return cdl_add_driver(xtalk_registry, - part_num, mfg_num, - driver_prefix, flags, NULL); -} - -/* * Inform xtalk infrastructure that a driver is no longer available for * handling any widgets. */ void xwidget_driver_unregister(char *driver_prefix) { - /* before a driver calls unregister, - * it must have called registger; so we - * can assume we have a registry here. - */ - ASSERT(xtalk_registry != NULL); - - cdl_del_driver(xtalk_registry, driver_prefix, NULL); + return; } /* @@ -923,9 +845,6 @@ xtalk_iterate(char *driver_prefix, xtalk_iter_f *func) { - ASSERT(xtalk_registry != NULL); - - cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func); } /* @@ -939,11 +858,10 @@ */ int xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */ - devfs_handle_t widget, /* widget to initialize */ + vertex_hdl_t widget, /* widget to initialize */ xwidgetnum_t id, /* widget's target id (0..f) */ - devfs_handle_t master, /* widget's master vertex */ - xwidgetnum_t targetid, /* master's target id (9/a) */ - async_attach_t aa) + vertex_hdl_t master, /* widget's master vertex */ + xwidgetnum_t targetid) /* master's target id (9/a) */ { xwidget_info_t widget_info; char *s,devnm[MAXDEVNAME]; @@ -972,21 +890,11 @@ device_master_set(widget, master); - /* All the driver init routines (including - * xtalk_init) are called before we get into - * attaching devices, so we can assume we - * have a registry here. - */ - ASSERT(xtalk_registry != NULL); - /* * Add pointer to async attach info -- tear down will be done when * the particular descendant is done with the info. */ - if (aa) - async_attach_add_info(widget, aa); - - return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, + return cdl_add_connpt(hwid->part_num, hwid->mfg_num, widget, 0); } @@ -995,7 +903,7 @@ * Unregister the xtalk device and detach all its hwgraph namespace. */ int -xwidget_unregister(devfs_handle_t widget) +xwidget_unregister(vertex_hdl_t widget) { xwidget_info_t widget_info; xwidget_hwid_t hwid; @@ -1011,9 +919,6 @@ hwid = &(widget_info->w_hwid); - cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, - widget, 0); - /* Clean out the xwidget information */ (void)kfree(widget_info->w_name); BZERO((void *)widget_info, sizeof(widget_info)); @@ -1023,7 +928,7 @@ } void -xwidget_error_register(devfs_handle_t xwidget, +xwidget_error_register(vertex_hdl_t xwidget, error_handler_f *efunc, error_handler_arg_t einfo) { @@ -1039,37 +944,23 @@ * Issue a link reset to a widget. */ void -xwidget_reset(devfs_handle_t xwidget) +xwidget_reset(vertex_hdl_t xwidget) { xswitch_reset_link(xwidget); - } void -xwidget_gfx_reset(devfs_handle_t xwidget) +xwidget_gfx_reset(vertex_hdl_t xwidget) { - xwidget_info_t info; - - xswitch_reset_link(xwidget); - info = xwidget_info_get(xwidget); -#ifdef LATER - ASSERT_ALWAYS(info != NULL); -#endif - - /* - * Enable this for other architectures once we add widget_reset to the - * xtalk provider interface. - */ - DEV_FUNC(xtalk_provider, widget_reset) - (xwidget_info_master_get(info), xwidget_info_id_get(info)); + return; } #define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */ /* Get the canonical hwgraph name of xtalk widget */ char * -xwidget_name_get(devfs_handle_t xwidget_vhdl) +xwidget_name_get(vertex_hdl_t xwidget_vhdl) { xwidget_info_t info; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/io/xswitch.c linux2.4.21_itanium/arch/ia64/sn/io/xswitch.c --- linux2.4.21_itanium.org/arch/ia64/sn/io/xswitch.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/io/xswitch.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1992-1997,2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -23,8 +23,6 @@ #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) #define DEL(ptr) (kfree(ptr)) -int xswitch_devflag = D_MP; - /* * This file provides generic support for Crosstalk * Switches, in a way that insulates crosstalk providers @@ -45,9 +43,9 @@ #define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func static xswitch_provider_t * -xwidget_to_provider_fns(devfs_handle_t xconn) +xwidget_to_provider_fns(vertex_hdl_t xconn) { - devfs_handle_t busv; + vertex_hdl_t busv; xswitch_info_t xswitch_info; xswitch_provider_t provider_fns; @@ -75,27 +73,18 @@ struct xswitch_info_s { char *fingerprint; unsigned census; - devfs_handle_t vhdl[XSWITCH_CENSUS_PORTS]; - devfs_handle_t master_vhdl[XSWITCH_CENSUS_PORTS]; + vertex_hdl_t vhdl[XSWITCH_CENSUS_PORTS]; + vertex_hdl_t master_vhdl[XSWITCH_CENSUS_PORTS]; xswitch_provider_t *xswitch_fns; }; xswitch_info_t -xswitch_info_get(devfs_handle_t xwidget) +xswitch_info_get(vertex_hdl_t xwidget) { xswitch_info_t xswitch_info; xswitch_info = (xswitch_info_t) hwgraph_fastinfo_get(xwidget); -#ifdef LATER - if ((xswitch_info != NULL) && - (xswitch_info->fingerprint != xswitch_info_fingerprint)) -#ifdef SUPPORT_PRINTING_V_FORMAT - PRINT_PANIC("%v xswitch_info_get bad fingerprint", xwidget); -#else - PRINT_PANIC("%x xswitch_info_get bad fingerprint", xwidget); -#endif -#endif /* LATER */ return (xswitch_info); } @@ -103,7 +92,7 @@ void xswitch_info_vhdl_set(xswitch_info_t xswitch_info, xwidgetnum_t port, - devfs_handle_t xwidget) + vertex_hdl_t xwidget) { #if XSWITCH_CENSUS_PORT_MIN if (port < XSWITCH_CENSUS_PORT_MIN) @@ -115,15 +104,10 @@ xswitch_info->vhdl[port - XSWITCH_CENSUS_PORT_MIN] = xwidget; } -devfs_handle_t +vertex_hdl_t xswitch_info_vhdl_get(xswitch_info_t xswitch_info, xwidgetnum_t port) { -#ifdef LATER - if (xswitch_info == NULL) - PRINT_PANIC("xswitch_info_vhdl_get: null xswitch_info"); -#endif - #if XSWITCH_CENSUS_PORT_MIN if (port < XSWITCH_CENSUS_PORT_MIN) return GRAPH_VERTEX_NONE; @@ -142,7 +126,7 @@ void xswitch_info_master_assignment_set(xswitch_info_t xswitch_info, xwidgetnum_t port, - devfs_handle_t master_vhdl) + vertex_hdl_t master_vhdl) { #if XSWITCH_CENSUS_PORT_MIN if (port < XSWITCH_CENSUS_PORT_MIN) @@ -154,7 +138,7 @@ xswitch_info->master_vhdl[port - XSWITCH_CENSUS_PORT_MIN] = master_vhdl; } -devfs_handle_t +vertex_hdl_t xswitch_info_master_assignment_get(xswitch_info_t xswitch_info, xwidgetnum_t port) { @@ -169,14 +153,14 @@ } void -xswitch_info_set(devfs_handle_t xwidget, xswitch_info_t xswitch_info) +xswitch_info_set(vertex_hdl_t xwidget, xswitch_info_t xswitch_info) { xswitch_info->fingerprint = xswitch_info_fingerprint; hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) xswitch_info); } xswitch_info_t -xswitch_info_new(devfs_handle_t xwidget) +xswitch_info_new(vertex_hdl_t xwidget) { xswitch_info_t xswitch_info; @@ -202,7 +186,7 @@ } void -xswitch_provider_register(devfs_handle_t busv, +xswitch_provider_register(vertex_hdl_t busv, xswitch_provider_t * xswitch_fns) { xswitch_info_t xswitch_info = xswitch_info_get(busv); @@ -232,35 +216,8 @@ } int -xswitch_reset_link(devfs_handle_t xconn_vhdl) +xswitch_reset_link(vertex_hdl_t xconn_vhdl) { return DEV_FUNC(xconn_vhdl, reset_link) (xconn_vhdl); } - -/* Given a vertex handle to the xswitch get its logical - * id. - */ -int -xswitch_id_get(devfs_handle_t xconn_vhdl) -{ - arbitrary_info_t xbow_num; - graph_error_t rv; - - rv = hwgraph_info_get_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID,&xbow_num); - ASSERT(rv == GRAPH_SUCCESS); - return(xbow_num); -} - -/* Given a vertex handle to the xswitch set its logical - * id. - */ -void -xswitch_id_set(devfs_handle_t xconn_vhdl,int xbow_num) -{ - graph_error_t rv; - - rv = hwgraph_info_add_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID, - (arbitrary_info_t)xbow_num); - ASSERT(rv == GRAPH_SUCCESS); -} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/Makefile linux2.4.21_itanium/arch/ia64/sn/kernel/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/Makefile Wed Jul 23 18:28:59 2003 @@ -1,6 +1,6 @@ # arch/ia64/sn/kernel/Makefile # -# Copyright (C) 1999,2001-2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of version 2 of the GNU General Public License @@ -40,21 +40,15 @@ O_TARGET = sn.o -export-objs = sn_ksyms.o iomv.o +export-objs = sn_ksyms.o -subdir-$(CONFIG_IA64_SGI_SN1) = sn1 -subdir-$(CONFIG_IA64_SGI_SN2) = sn2 +subdir-y = sn2 -obj-y = probe.o setup.o sn_asm.o sv.o bte.o iomv.o -obj-$(CONFIG_IA64_SGI_SN1) += irq.o mca.o -obj-$(CONFIG_IA64_SGI_SN2) += irq.o mca.o +obj-y = probe.o setup.o sv.o bte.o +obj-y += irq.o mca.o idle.o +obj-y += sn2/sn2.o -obj-$(CONFIG_IA64_SGI_SN1) += sn1/sn1.o -obj-$(CONFIG_IA64_SGI_SN2) += sn2/sn2.o - -obj-$(CONFIG_IA64_SGI_AUTOTEST) += llsc4.o misctest.o obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_MODULES) += sn_ksyms.o -obj-$(CONFIG_IA64_SGI_SN_BRT) += bte_regr_test.o include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/bte.c linux2.4.21_itanium/arch/ia64/sn/kernel/bte.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/bte.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/bte.c Wed Jul 23 18:28:59 2003 @@ -1,7 +1,7 @@ /* * * - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -38,130 +38,157 @@ #include #include #include -#ifdef CONFIG_IA64_SGI_SN2 #include -#endif #include #include #include #include -#include +#include -int bte_offsets[] = { IIO_IBLS0, IIO_IBLS1 }; /* - * bte_init_node(nodepda, cnode) + * The base address of for each set of bte registers. + */ +static int bte_offsets[] = { IIO_IBLS0, IIO_IBLS1 }; + + +/************************************************************************ + * Block Transfer Engine copy related functions. * - * Initialize the nodepda structure with BTE base addresses and - * spinlocks. + ***********************************************************************/ + + +/* + * bte_copy(src, dest, len, mode, notification) * - * NOTE: The kernel parameter btetest will cause the initialization - * code to reserve blocks of physically contiguous memory to be - * used by the bte test module. + * Use the block transfer engine to move kernel memory from src to dest + * using the assigned mode. + * + * Paramaters: + * src - physical address of the transfer source. + * dest - physical address of the transfer destination. + * len - number of bytes to transfer from source to dest. + * mode - hardware defined. See reference information + * for IBCT0/1 in the SHUB Programmers Reference + * notification - kernel virtual address of the notification cache + * line. If NULL, the default is used and + * the bte_copy is synchronous. + * + * NOTE: This function requires src, dest, and len to + * be cacheline aligned. */ -void -bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) +bte_result_t +bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) { - int i; + int bte_to_use; + u64 transfer_size; + struct bteinfo_s *bte; + bte_result_t bte_status; + unsigned long irq_flags; - /* - * Indicate that all the block transfer engines on this node - * are available. - */ - for (i = 0; i < BTES_PER_NODE; i++) { -#ifdef CONFIG_IA64_SGI_SN2 - /* >>> Don't know why the 0x1800000L is here. Robin */ - mynodepda->bte_if[i].bte_base_addr = - (char *)LOCAL_MMR_ADDR(bte_offsets[i] | 0x1800000L); + BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n", + src, dest, len, mode, notification)); -#elif CONFIG_IA64_SGI_SN1 - mynodepda->bte_if[i].bte_base_addr = - (char *)LOCAL_HUB_ADDR(bte_offsets[i]); -#else -#error BTE Not defined for this hardware platform. -#endif + if (len == 0) { + return BTE_SUCCESS; + } - /* - * Initialize the notification and spinlock - * so the first transfer can occur. - */ - mynodepda->bte_if[i].most_rcnt_na = - &(mynodepda->bte_if[i].notify); - mynodepda->bte_if[i].notify = 0L; -#ifdef CONFIG_IA64_SGI_BTE_LOCKING - spin_lock_init(&mynodepda->bte_if[i].spinlock); -#endif /* CONFIG_IA64_SGI_BTE_LOCKING */ + ASSERT(!((len & L1_CACHE_MASK) || + (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK))); + ASSERT(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)); + + do { + local_irq_save(irq_flags); + + bte_to_use = 0; + /* Attempt to lock one of the BTE interfaces. */ + while ((bte_to_use < BTES_PER_NODE) && + BTE_LOCK_IF_AVAIL(bte_to_use)) { + bte_to_use++; + } + + if (bte_to_use < BTES_PER_NODE) { + break; + } + + local_irq_restore(irq_flags); + + if (!(mode & BTE_WACQUIRE)) { + return BTEFAIL_NOTAVAIL; + } - mynodepda->bte_if[i].bte_test_buf = - alloc_bootmem_node(NODE_DATA(cnode), BTE_MAX_XFER); + /* Wait until a bte is available. */ + udelay(10); + } while (1); + + bte = pda.cpu_bte_if[bte_to_use]; + BTE_PRINTKV(("Got a lock on bte %d\n", bte_to_use)); + + + if (notification == NULL) { + /* User does not want to be notified. */ + bte->most_rcnt_na = &bte->notify; + } else { + bte->most_rcnt_na = notification; } -} + /* Calculate the number of cache lines to transfer. */ + transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK); + /* Initialize the notification to a known value. */ + *bte->most_rcnt_na = -1L; -/* - * bte_reset_nasid(nasid_t) - * - * Does a soft reset of the BTEs on the specified nasid. - * This is followed by a one-line transfer from each of the - * virtual interfaces. - */ -void -bte_reset_nasid(nasid_t n) -{ - ii_ibcr_u_t ibcr; + /* Set the status reg busy bit and transfer length */ + BTE_PRINTKV(("IBLS - HUB_S(0x%p, 0x%lx)\n", + BTEREG_LNSTAT_ADDR, IBLS_BUSY | transfer_size)); + HUB_S(BTEREG_LNSTAT_ADDR, (IBLS_BUSY | transfer_size)); + + /* Set the source and destination registers */ + BTE_PRINTKV(("IBSA - HUB_S(0x%p, 0x%lx)\n", BTEREG_SRC_ADDR, + (TO_PHYS(src)))); + HUB_S(BTEREG_SRC_ADDR, (TO_PHYS(src))); + BTE_PRINTKV(("IBDA - HUB_S(0x%p, 0x%lx)\n", BTEREG_DEST_ADDR, + (TO_PHYS(dest)))); + HUB_S(BTEREG_DEST_ADDR, (TO_PHYS(dest))); + + /* Set the notification register */ + BTE_PRINTKV(("IBNA - HUB_S(0x%p, 0x%lx)\n", BTEREG_NOTIF_ADDR, + (TO_PHYS(__tpa(bte->most_rcnt_na))))); + HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(__tpa(bte->most_rcnt_na)))); + + + /* Initiate the transfer */ + BTE_PRINTK(("IBCT - HUB_S(0x%p, 0x%lx)\n", BTEREG_CTRL_ADDR, + BTE_VALID_MODE(mode))); + HUB_S(BTEREG_CTRL_ADDR, BTE_VALID_MODE(mode)); - ibcr.ii_ibcr_regval = REMOTE_HUB_L(n, IIO_IBCR); - ibcr.ii_ibcr_fld_s.i_soft_reset = 1; - REMOTE_HUB_S(n, IIO_IBCR, ibcr.ii_ibcr_regval); - - /* One line transfer on virtual interface 0 */ - REMOTE_HUB_S(n, IIO_IBLS_0, IBLS_BUSY | 1); - REMOTE_HUB_S(n, IIO_IBSA_0, TO_PHYS(__pa(&nodepda->bte_cleanup))); - REMOTE_HUB_S(n, IIO_IBDA_0, - TO_PHYS(__pa(&nodepda->bte_cleanup[4*L1_CACHE_BYTES]))); - REMOTE_HUB_S(n, IIO_IBNA_0, - TO_PHYS(__pa(&nodepda->bte_cleanup[4*L1_CACHE_BYTES]))); - REMOTE_HUB_S(n, IIO_IBCT_0, BTE_NOTIFY); - while (REMOTE_HUB_L(n, IIO_IBLS0)) { - /* >>> Need some way out in case of hang... */ + spin_unlock_irqrestore(&bte->spinlock, irq_flags); + + + if (notification != NULL) { + return BTE_SUCCESS; } - /* One line transfer on virtual interface 1 */ - REMOTE_HUB_S(n, IIO_IBLS_1, IBLS_BUSY | 1); - REMOTE_HUB_S(n, IIO_IBSA_1, TO_PHYS(__pa(nodepda->bte_cleanup))); - REMOTE_HUB_S(n, IIO_IBDA_1, - TO_PHYS(__pa(nodepda->bte_cleanup[4 * L1_CACHE_BYTES]))); - REMOTE_HUB_S(n, IIO_IBNA_1, - TO_PHYS(__pa(nodepda->bte_cleanup[5 * L1_CACHE_BYTES]))); - REMOTE_HUB_S(n, IIO_IBCT_1, BTE_NOTIFY); - while (REMOTE_HUB_L(n, IIO_IBLS1)) { - /* >>> Need some way out in case of hang... */ + while (*bte->most_rcnt_na == -1UL) { } -} -/* - * bte_init_cpu() - * - * Initialize the cpupda structure with pointers to the - * nodepda bte blocks. - * - */ -void -bte_init_cpu(void) -{ - /* Called by setup.c as each cpu is being added to the nodepda */ - if (local_node_data->active_cpu_count & 0x1) { - pda.cpu_bte_if[0] = &(nodepda->bte_if[0]); - pda.cpu_bte_if[1] = &(nodepda->bte_if[1]); + BTE_PRINTKV((" Delay Done. IBLS = 0x%lx, most_rcnt_na = 0x%lx\n", + HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na)); + + if (*bte->most_rcnt_na & IBLS_ERROR) { + bte_status = *bte->most_rcnt_na & ~IBLS_ERROR; + *bte->most_rcnt_na = 0L; } else { - pda.cpu_bte_if[0] = &(nodepda->bte_if[1]); - pda.cpu_bte_if[1] = &(nodepda->bte_if[0]); + bte_status = BTE_SUCCESS; } + BTE_PRINTK(("Returning status is 0x%lx and most_rcnt_na is 0x%lx\n", + HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na)); + + return bte_status; } @@ -198,15 +225,11 @@ char *bteBlock; if (len == 0) { - return (BTE_SUCCESS); + return BTE_SUCCESS; } -#ifdef CONFIG_IA64_SGI_BTE_LOCKING -#error bte_unaligned_copy() assumes single BTE selection in bte_copy(). -#else /* temporary buffer used during unaligned transfers */ - bteBlock = pda.cpu_bte_if[0]->bte_test_buf; -#endif + bteBlock = pda.cpu_bte_if[0]->scratch_buf; headBcopySrcOffset = src & L1_CACHE_MASK; destFirstCacheOffset = dest & L1_CACHE_MASK; @@ -271,15 +294,15 @@ headBteLen += footBteLen; } else if (footBcopyLen > 0) { rv = bte_copy(footBteSource, - __pa(bteBlock), + __tpa(bteBlock), footBteLen, mode, NULL); if (rv != BTE_SUCCESS) { - return (rv); + return rv; } memcpy(__va(footBcopyDest), - (char *)bteBlock, footBcopyLen); + (char *) bteBlock, footBcopyLen); } } else { footBcopyLen = 0; @@ -294,7 +317,7 @@ (len - headBcopyLen - footBcopyLen), mode, NULL); if (rv != BTE_SUCCESS) { - return (rv); + return rv; } } @@ -321,14 +344,93 @@ if (headBcopyLen > 0) { rv = bte_copy(headBteSource, - __pa(bteBlock), headBteLen, mode, NULL); + __tpa(bteBlock), headBteLen, mode, NULL); if (rv != BTE_SUCCESS) { - return (rv); + return rv; } - memcpy(__va(headBcopyDest), ((char *)bteBlock + + memcpy(__va(headBcopyDest), ((char *) bteBlock + headBcopySrcOffset), headBcopyLen); } - return (BTE_SUCCESS); + return BTE_SUCCESS; +} + + +/************************************************************************ + * Block Transfer Engine initialization functions. + * + ***********************************************************************/ + + +/* + * bte_init_node(nodepda, cnode) + * + * Initialize the nodepda structure with BTE base addresses and + * spinlocks. + */ +void +bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) +{ + int i; + + + /* + * Indicate that all the block transfer engines on this node + * are available. + */ + + /* + * Allocate one bte_recover_t structure per node. It holds + * the recovery lock for node. All the bte interface structures + * will point at this one bte_recover structure to get the lock. + */ + spin_lock_init(&mynodepda->bte_recovery_lock); + init_timer(&mynodepda->bte_recovery_timer); + mynodepda->bte_recovery_timer.function = bte_error_handler; + mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda; + + for (i = 0; i < BTES_PER_NODE; i++) { + /* >>> Don't know why the 0x1800000L is here. Robin */ + mynodepda->bte_if[i].bte_base_addr = + (char *) LOCAL_MMR_ADDR(bte_offsets[i] | 0x1800000L); + + /* + * Initialize the notification and spinlock + * so the first transfer can occur. + */ + mynodepda->bte_if[i].most_rcnt_na = + &(mynodepda->bte_if[i].notify); + mynodepda->bte_if[i].notify = 0L; + spin_lock_init(&mynodepda->bte_if[i].spinlock); + + mynodepda->bte_if[i].scratch_buf = + alloc_bootmem_node(NODE_DATA(cnode), BTE_MAX_XFER); + mynodepda->bte_if[i].bte_cnode = cnode; + mynodepda->bte_if[i].bte_error_count = 0; + mynodepda->bte_if[i].bte_num = i; + mynodepda->bte_if[i].cleanup_active = 0; + mynodepda->bte_if[i].bh_error = 0; + } + +} + +/* + * bte_init_cpu() + * + * Initialize the cpupda structure with pointers to the + * nodepda bte blocks. + * + */ +void +bte_init_cpu(void) +{ + /* Called by setup.c as each cpu is being added to the nodepda */ + if (local_node_data->active_cpu_count & 0x1) { + pda.cpu_bte_if[0] = &(nodepda->bte_if[0]); + pda.cpu_bte_if[1] = &(nodepda->bte_if[1]); + } else { + pda.cpu_bte_if[0] = &(nodepda->bte_if[1]); + pda.cpu_bte_if[1] = &(nodepda->bte_if[0]); + } } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/idle.c linux2.4.21_itanium/arch/ia64/sn/kernel/idle.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/idle.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/idle.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include + +void snidle(int state) { + if (state) { + if (pda.idle_flag == 0) { + /* + * Turn the activity LED off. + */ + set_led_bits(0, LED_CPU_ACTIVITY); + } + +#ifdef CONFIG_IA64_SGI_SN_SIM + if (IS_RUNNING_ON_SIMULATOR()) + SIMULATOR_SLEEP(); +#endif + + pda.idle_flag = 1; + } else { + /* + * Turn the activity LED on. + */ + set_led_bits(LED_CPU_ACTIVITY, LED_CPU_ACTIVITY); + + pda.idle_flag = 0; + } +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/irq.c linux2.4.21_itanium/arch/ia64/sn/kernel/irq.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/irq.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/irq.c Wed Jul 23 18:28:59 2003 @@ -1,7 +1,7 @@ /* - * Platform dependent support for SGI SN1 + * Platform dependent support for SGI SN * - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -32,12 +32,13 @@ * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ -#include #include #include +#include #include #include #include +#include #include #include #include @@ -49,18 +50,23 @@ #include #include #include -#ifdef ajmtestintr #include #include -#endif /* ajmtestintr */ #include #include #include #include #include #include +#include +#include +#include +#include int irq_to_bit_pos(int irq); +static void force_interrupt(int irq); +extern void pcibr_force_interrupt(pcibr_intr_t intr); +extern int sn_force_interrupt_flag; @@ -88,49 +94,11 @@ static void sn_ack_irq(unsigned int irq) { -#ifdef CONFIG_IA64_SGI_SN1 - int bit = -1; - unsigned long long intpend_val; - int subnode; -#endif -#ifdef CONFIG_IA64_SGI_SN2 unsigned long event_occurred, mask = 0; -#endif int nasid; irq = irq & 0xff; nasid = smp_physical_node_id(); -#ifdef CONFIG_IA64_SGI_SN1 - subnode = cpuid_to_subnode(smp_processor_id()); - if (irq == SGI_UART_IRQ) { - intpend_val = REMOTE_HUB_PI_L(nasid, subnode, PI_INT_PEND0); - if (intpend_val & (1L<> 8; - irq = irq & 0xff; + irq = SN_IVEC_FROM_IRQ(irq); - return(_sn_irq_desc[cpu] + irq); + return(_irq_desc + irq); } u8 sn_irq_to_vector(u8 irq) { - return(irq & 0xff); + return(irq); } unsigned int @@ -226,47 +175,24 @@ return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector)); } -void *kmalloc(size_t, int); - void sn_irq_init (void) { int i; irq_desc_t *base_desc = _irq_desc; - for (i=IA64_FIRST_DEVICE_VECTOR; i 118) bit = 118; -#ifdef CONFIG_IA64_SGI_SN1 - if (bit >= GFX_INTR_A && bit <= CC_PEND_B) { - return SGI_UART_IRQ; - } -#endif - return bit + BIT_TO_IRQ; } @@ -278,53 +204,183 @@ return bit; } -#ifdef ajmtestintr - -#include -struct timer_list intr_test_timer; -int intr_test_icount[NR_IRQS]; -struct intr_test_reg_struct { - pcibr_soft_t pcibr_soft; - int slot; +struct pcibr_intr_list_t { + struct pcibr_intr_list_t *next; + pcibr_intr_t intr; }; -struct intr_test_reg_struct intr_test_registered[NR_IRQS]; + +static struct pcibr_intr_list_t **pcibr_intr_list; void -intr_test_handle_timer(unsigned long data) { +register_pcibr_intr(int irq, pcibr_intr_t intr) { + struct pcibr_intr_list_t *p = kmalloc(sizeof(struct pcibr_intr_list_t), GFP_KERNEL); + struct pcibr_intr_list_t *list; + int cpu = SN_CPU_FROM_IRQ(irq); + + if (pcibr_intr_list == NULL) { + pcibr_intr_list = kmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS, GFP_KERNEL); + if (pcibr_intr_list == NULL) + pcibr_intr_list = vmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS); + if (pcibr_intr_list == NULL) panic("Could not allocate memory for pcibr_intr_list\n"); + memset( (void *)pcibr_intr_list, 0, sizeof(struct pcibr_intr_list_t *) * NR_IRQS); + } + if (pdacpu(cpu).sn_last_irq < irq) { + pdacpu(cpu).sn_last_irq = irq; + } + if (pdacpu(cpu).sn_first_irq > irq) pdacpu(cpu).sn_first_irq = irq; + if (!p) panic("Could not allocate memory for pcibr_intr_list_t\n"); + if ((list = pcibr_intr_list[irq])) { + while (list->next) list = list->next; + list->next = p; + p->next = NULL; + p->intr = intr; + } else { + pcibr_intr_list[irq] = p; + p->next = NULL; + p->intr = intr; + } +} + +void +force_polled_int(void) { int i; - bridge_t *bridge; + struct pcibr_intr_list_t *p; - for (i=0;ibs_intr[intr_test_registered[i].slot].bsi_xtalk_intr; - /* send interrupt */ - bridge = pcibr_soft->bs_base; - bridge->b_force_always[intr_test_registered[i].slot].intr = 1; + for (i=0; iintr){ + pcibr_force_interrupt(p->intr); + } + p = p->next; } } - del_timer(&intr_test_timer); - intr_test_timer.expires = jiffies + HZ/100; - add_timer(&intr_test_timer); } -void -intr_test_set_timer(void) { - intr_test_timer.expires = jiffies + HZ/100; - intr_test_timer.function = intr_test_handle_timer; - add_timer(&intr_test_timer); +static void +force_interrupt(int irq) { + struct pcibr_intr_list_t *p = pcibr_intr_list[irq]; + + while (p) { + if (p->intr) { + pcibr_force_interrupt(p->intr); + } + p = p->next; + } +} + +/* +Check for lost interrupts. If the PIC int_status reg. says that +an interrupt has been sent, but not handled, and the interrupt +is not pending in either the cpu irr regs or in the soft irr regs, +and the interrupt is not in service, then the interrupt may have +been lost. Force an interrupt on that pin. It is possible that +the interrupt is in flight, so we may generate a spurious interrupt, +but we should never miss a real lost interrupt. +*/ + +static void +sn_check_intr(int irq, pcibr_intr_t intr) { + unsigned long regval; + int irr_reg_num; + int irr_bit; + unsigned long irr_reg; + + + regval = intr->bi_soft->bs_base->p_int_status_64; + irr_reg_num = irq_to_vector(irq) / 64; + irr_bit = irq_to_vector(irq) % 64; + switch (irr_reg_num) { + case 0: + irr_reg = ia64_get_irr0(); + break; + case 1: + irr_reg = ia64_get_irr1(); + break; + case 2: + irr_reg = ia64_get_irr2(); + break; + case 3: + irr_reg = ia64_get_irr3(); + break; + } + if (!test_bit(irr_bit, &irr_reg) ) { + if (!test_bit(irq, pda.sn_soft_irr) ) { + if (!test_bit(irq, pda.sn_in_service_ivecs) ) { + regval &= 0xff; + if (intr->bi_ibits & regval & intr->bi_last_intr) { + regval &= ~(intr->bi_ibits & regval); + pcibr_force_interrupt(intr); + } + } + } + } + intr->bi_last_intr = regval; } void -intr_test_register_irq(int irq, pcibr_soft_t pcibr_soft, int slot) { - irq = irq & 0xff; - intr_test_registered[irq].pcibr_soft = pcibr_soft; - intr_test_registered[irq].slot = slot; +sn_lb_int_war_check(void) { + int i; + + if (pda.sn_first_irq == 0) return; + for (i=pda.sn_first_irq; + i <= pda.sn_last_irq; i++) { + struct pcibr_intr_list_t *p = pcibr_intr_list[i]; + if (p == NULL) { + continue; + } + while (p) { + sn_check_intr(i, p->intr); + p = p->next; + } + } +} + +static inline int +sn_get_next_bit(void) { + int i; + int bit; + + for (i = 3; i >= 0; i--) { + if (pda.sn_soft_irr[i] != 0) { + bit = (i * 64) + __ffs(pda.sn_soft_irr[i]); + __change_bit(bit, (volatile void *)pda.sn_soft_irr); + return(bit); + } + } + return IA64_SPURIOUS_INT_VECTOR; } void -intr_test_handle_intr(int irq, void *junk, struct pt_regs *morejunk) { - intr_test_icount[irq]++; - printk("RECEIVED %d INTERRUPTS ON IRQ %d\n",intr_test_icount[irq], irq); +sn_set_tpr(int vector) { + if (vector > IA64_LAST_DEVICE_VECTOR || vector < IA64_FIRST_DEVICE_VECTOR) { + ia64_set_tpr(vector); + } else { + ia64_set_tpr(IA64_LAST_DEVICE_VECTOR); + } +} + +static inline void +sn_get_all_ivr(void) { + int vector; + + vector = ia64_get_ivr(); + while (vector != IA64_SPURIOUS_INT_VECTOR) { + __set_bit(vector, (volatile void *)pda.sn_soft_irr); + ia64_eoi(); + if (vector > IA64_LAST_DEVICE_VECTOR) return; + vector = ia64_get_ivr(); + } +} + +int +sn_get_ivr(void) { + int vector; + + vector = sn_get_next_bit(); + if (vector == IA64_SPURIOUS_INT_VECTOR) { + sn_get_all_ivr(); + vector = sn_get_next_bit(); + } + return vector; } -#endif /* ajmtestintr */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/machvec.c linux2.4.21_itanium/arch/ia64/sn/kernel/machvec.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/machvec.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/machvec.c Wed Jul 23 18:28:59 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -30,30 +30,5 @@ * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ -#include - -#ifdef CONFIG_IA64_SGI_SN1 -#define MACHVEC_PLATFORM_NAME sn1 -#else CONFIG_IA64_SGI_SN1 #define MACHVEC_PLATFORM_NAME sn2 -#else -#error "unknown platform" -#endif - #include -#include -#include -void* -sn_mk_io_addr_MACRO - -dma_addr_t -sn_pci_map_single_MACRO - -int -sn_pci_map_sg_MACRO - -unsigned long -sn_virt_to_phys_MACRO - -void * -sn_phys_to_virt_MACRO diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/mca.c linux2.4.21_itanium/arch/ia64/sn/kernel/mca.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/mca.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/mca.c Wed Jul 23 18:28:59 2003 @@ -2,7 +2,7 @@ * File: mca.c * Purpose: SN specific MCA code. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -123,9 +123,7 @@ static void sn_cpei_timer_handler(unsigned long dummy) { sn_cpei_handler(-1, NULL, NULL); - del_timer(&sn_cpei_timer); - sn_cpei_timer.expires = jiffies + CPEI_INTERVAL; - add_timer(&sn_cpei_timer); + mod_timer(&sn_cpei_timer, jiffies + CPEI_INTERVAL); } void @@ -134,27 +132,3 @@ sn_cpei_timer.function = sn_cpei_timer_handler; add_timer(&sn_cpei_timer); } - - - - -#ifdef ajmtestceintr - -struct timer_list sn_ce_timer; - -void -sn_ce_timer_handler(long dummy) { - unsigned long *pi_ce_error_inject_reg = 0xc00000092fffff00; - - *pi_ce_error_inject_reg = 0x0000000000000100; - del_timer(&sn_ce_timer); - sn_ce_timer.expires = jiffies + CPEI_INTERVAL; - add_timer(&sn_ce_timer); -} - -sn_init_ce_timer() { - sn_ce_timer.expires = jiffies + CPEI_INTERVAL; - sn_ce_timer.function = sn_ce_timer_handler; - add_timer(&sn_ce_timer); -} -#endif /* ajmtestceintr */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/probe.c linux2.4.21_itanium/arch/ia64/sn/kernel/probe.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/probe.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/probe.c Wed Jul 23 18:28:59 2003 @@ -1,7 +1,7 @@ /* * Platform dependent support for IO probing. * - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/setup.c linux2.4.21_itanium/arch/ia64/sn/kernel/setup.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/setup.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/setup.c Wed Jul 23 18:28:59 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999,2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -69,21 +69,27 @@ #include #include #include - -#ifdef CONFIG_IA64_SGI_SN2 #include -#endif + +#define pxm_to_nasid(pxm) ((pxm)<<1) + +#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */ extern void bte_init_node (nodepda_t *, cnodeid_t); extern void bte_init_cpu (void); +extern void sn_timer_init(void); +extern unsigned long last_time_offset; +extern void (*ia64_mark_idle)(int); +extern void snidle(int); unsigned long sn_rtc_cycles_per_second; -unsigned long sn_rtc_usec_per_cyc; partid_t sn_partid = -1; char sn_system_serial_number_string[128]; u64 sn_partition_serial_number; +short physical_node_map[MAX_PHYSNODE_ID]; + /* * This is the address of the RRegs in the HSpace of the global * master. It is used by a hack in serial.c (serial_[in|out], @@ -92,21 +98,14 @@ * early_printk won't try to access the UART before * master_node_bedrock_address is properly calculated. */ -u64 master_node_bedrock_address = 0UL; +u64 master_node_bedrock_address; static void sn_init_pdas(char **); -extern struct irq_desc *_sn_irq_desc[]; - -#if defined(CONFIG_IA64_SGI_SN1) -extern synergy_da_t *Synergy_da_indr[]; -#endif static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; -#ifdef CONFIG_IA64_SGI_SN2 -irqpda_t *irqpdaindr[NR_CPUS]; -#endif /* CONFIG_IA64_SGI_SN2 */ +irqpda_t *irqpdaindr; /* @@ -133,29 +132,19 @@ * running in the simulator. Note that passing zeroes in DRIVE_INFO * is sufficient (the IDE driver will autodetect the drive geometry). */ +#ifdef CONFIG_IA64_GENERIC +extern char drive_info[4*16]; +#else char drive_info[4*16]; - -/** - * sn_map_nr - return the mem_map entry for a given kernel address - * @addr: kernel address to query - * - * Finds the mem_map entry for the kernel address given. Used by - * virt_to_page() (asm-ia64/page.h), among other things. - */ -unsigned long -sn_map_nr (void *addr) -{ - return MAP_NR_DISCONTIG(addr); -} +#endif /** * early_sn_setup - early setup routine for SN platforms * - * Sets up an intial console to aid debugging. Intended primarily - * for bringup, it's only called if %BRINGUP and %CONFIG_IA64_EARLY_PRINTK - * are turned on. See start_kernel() in init/main.c. + * Sets up an initial console to aid debugging. Intended primarily + * for bringup. See start_kernel() in init/main.c. */ -#if defined(CONFIG_IA64_EARLY_PRINTK) +#if defined(CONFIG_IA64_EARLY_PRINTK_SGI_SN) || defined(CONFIG_IA64_SGI_SN_SIM) void __init early_sn_setup(void) @@ -170,7 +159,7 @@ /* * Parse enough of the SAL tables to locate the SAL entry point. Since, console - * IO on SN2 is done via SAL calls, early_printk wont work without this. + * IO on SN2 is done via SAL calls, early_printk won't work without this. * * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c. * Any changes to those file may have to be made hereas well. @@ -193,21 +182,48 @@ } if ( IS_RUNNING_ON_SIMULATOR() ) { -#if defined(CONFIG_IA64_SGI_SN1) - master_node_bedrock_address = (u64)REMOTE_HSPEC_ADDR(get_nasid(), 0); -#else master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0); -#endif printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address); } } -#endif /* CONFIG_IA64_SGI_SN1 */ +#endif /* CONFIG_IA64_EARLY_PRINTK_SGI_SN */ #ifdef CONFIG_IA64_MCA extern int platform_intr_list[]; #endif extern nasid_t master_nasid; +static int shub_1_1_found __initdata; + + +/* + * sn_check_for_wars + * + * Set flag for enabling shub specific wars + */ + +static inline int __init +is_shub_1_1(int nasid) +{ + unsigned long id; + int rev; + + id = REMOTE_HUB_L(nasid, SH_SHUB_ID); + rev = (id & SH_SHUB_ID_REVISION_MASK) >> SH_SHUB_ID_REVISION_SHFT; + return rev <= 2; +} + +static void __init +sn_check_for_wars(void) +{ + int cnode; + + for (cnode=0; cnode< numnodes; cnode++) + if (is_shub_1_1(cnodeid_to_nasid(cnode))) + shub_1_1_found = 1; +} + + /** * sn_setup - SN platform setup routine @@ -221,8 +237,18 @@ sn_setup(char **cmdline_p) { long status, ticks_per_sec, drift; - int i; + int i, pxm; int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); + extern void io_sh_swapper(int, int); + extern nasid_t get_master_baseio_nasid(void); + extern void sn_cpu_init(void); + + MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY; + + memset(physical_node_map, -1, sizeof(physical_node_map)); + for (pxm=0; pxmthread.flags |= IA64_THREAD_FPEMU_NOPRINT; + sn_timer_init(); } /** @@ -332,19 +336,16 @@ if ((PDAADDR&~PAGE_MASK)+sizeof(pda_t) > PAGE_SIZE) panic("overflow of cpu_data page"); + memset(pda.cnodeid_to_nasid_table, -1, sizeof(pda.cnodeid_to_nasid_table)); + for (cnode=0; cnodeactive_cpu_count == 1) nodepda->node_first_cpu = cpuid; -#ifdef CONFIG_IA64_SGI_SN1 - { - int synergy; - synergy = cpu_physical_id_to_synergy(cpuphyid); - pda.p_subnodepda = &nodepdaindr[cnode]->snpda[synergy]; - } -#endif -#ifdef CONFIG_IA64_SGI_SN2 /* * We must use different memory allocators for first cpu (bootmem * allocator) than for the other cpus (regular allocator). */ if (cpuid == 0) - irqpdaindr[cpuid] = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t)); - else - irqpdaindr[cpuid] = page_address(alloc_pages_node(local_cnodeid(), GFP_KERNEL, get_order(sizeof(irqpda_t)))); + irqpdaindr = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t)); - memset(irqpdaindr[cpuid], 0, sizeof(irqpda_t)); - pda.p_irqpda = irqpdaindr[cpuid]; + memset(irqpdaindr, 0, sizeof(irqpda_t)); + irqpdaindr->irq_flags[SGI_PCIBR_ERROR] = SN2_IRQ_SHARED; + irqpdaindr->irq_flags[SGI_PCIBR_ERROR] |= SN2_IRQ_RESERVED; + irqpdaindr->irq_flags[SGI_II_ERROR] = SN2_IRQ_SHARED; + irqpdaindr->irq_flags[SGI_II_ERROR] |= SN2_IRQ_RESERVED; pda.pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR((slice < 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1 ) ); @@ -442,253 +438,9 @@ if (nodepda->node_first_cpu == cpuid) { int buddy_nasid; - buddy_nasid = cnodeid_to_nasid(local_cnodeid() == numnodes-1 ? 0 : local_cnodeid()+ 1); + buddy_nasid = cnodeid_to_nasid(numa_node_id() == numnodes-1 ? 0 : numa_node_id()+ 1); pda.pio_shub_war_cam_addr = (volatile unsigned long*)GLOBAL_MMR_ADDR(nasid, SH_PI_CAM_CONTROL); } -#ifdef BRINGUP2 - /* - * Zero out the counters used for counting MCAs - * ZZZZZ temp - */ - { - long *p; - p = (long*)LOCAL_MMR_ADDR(SH_XN_IILB_LB_CMP_ENABLE0); - *p = 0; - p = (long*)LOCAL_MMR_ADDR(SH_XN_IILB_LB_CMP_ENABLE1); - *p = 0; - } - -#endif -#endif - -#ifdef CONFIG_IA64_SGI_SN1 - pda.bedrock_rev_id = (volatile unsigned long *) LOCAL_HUB(LB_REV_ID); - if (cpuid_to_synergy(cpuid)) - /* CPU B */ - pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_B_ADDR; - else - /* CPU A */ - pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_A_ADDR; -#endif - - bte_init_cpu(); } - - -/** - * cnodeid_to_cpuid - convert a cnode to a cpuid of a cpu on the node. - * @cnode: node to get a cpuid from - * - * Returns -1 if no cpus exist on the node. - * NOTE:BRINGUP ZZZ This is NOT a good way to find cpus on the node. - * Need a better way!! - */ -int -cnodeid_to_cpuid(int cnode) { - int cpu; - - for (cpu = 0; cpu < smp_num_cpus; cpu++) - if (cpuid_to_cnodeid(cpu) == cnode) - break; - - if (cpu == smp_num_cpus) - cpu = -1; - - return cpu; -} - -/** - * get_cycles - return a non-decreasing timestamp - * - * On SN, we use an RTC read for this function - */ -cycles_t -get_cycles (void) -{ - return GET_RTC_COUNTER(); -} - -/** - * gettimeoffset - number of usecs elapsed since &xtime was last updated - * - * This function is used by do_gettimeofday() to determine the number - * of usecs that have elapsed since the last update to &xtime. On SN - * this is accomplished using the RTC built in to each Hub chip; each - * is guaranteed to be synchronized by the PROM, so a local read will - * suffice (get_cycles() does this for us). A snapshot of the RTC value - * is taken on every timer interrupt and this function more or less - * subtracts that snapshot value from the current value. - * - * Note that if a lot of processing was done during the last timer - * interrupt then &xtime may be some number of jiffies out of date. - * This function must account for that. - */ -unsigned long -gettimeoffset(void) -{ - unsigned long current_rtc_val, local_last_rtc_val; - unsigned long usec; - - local_last_rtc_val = last_rtc_val; - current_rtc_val = get_cycles(); - usec = last_itc_lost_usec; - - /* If the RTC has wrapped around, compensate */ - if (unlikely(current_rtc_val < local_last_rtc_val)) { - printk(KERN_NOTICE "RTC wrapped cpu:%d current:0x%lx last:0x%lx\n", - smp_processor_id(), current_rtc_val, - local_last_rtc_val); - current_rtc_val += RTC_MASK; - } - - usec += ((current_rtc_val - local_last_rtc_val)*sn_rtc_usec_per_cyc) >> - IA64_USEC_PER_CYC_SHIFT; - - /* - * usec is the number of microseconds into the current clock interval. Every - * clock tick, xtime is advanced by "tick" microseconds. If "usec" - * is allowed to get larger than "tick", the time value returned by gettimeofday - * will go backward. - */ - if (usec >= tick) - usec = tick-1; - - return usec; -} - -#ifdef II_PRTE_TLB_WAR -long iiprt_lock[16*64] __cacheline_aligned; /* allow for NASIDs up to 64 */ -#endif - -#ifdef BUS_INT_WAR - -#include -#include - -void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs); - -static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; - -#define IRQCPU(irq) ((irq)>>8) - -void -sn_add_polled_interrupt(int irq, int interval) -{ - unsigned long flags, irq_cnt; - sn_poll_entry_t *irq_list; - - irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries;; - - spin_lock_irqsave(&irq_lock, flags); - irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count; - irq_list[irq_cnt].irq = irq; - irq_list[irq_cnt].interval = interval; - irq_list[irq_cnt].tick = interval; - pdacpu(IRQCPU(irq)).pda_poll_entry_count++; - spin_unlock_irqrestore(&irq_lock, flags); - - -} - -void -sn_delete_polled_interrupt(int irq) -{ - unsigned long flags, i, irq_cnt; - sn_poll_entry_t *irq_list; - - irq_list = pdacpu(IRQCPU(irq)).pda_poll_entries; - - spin_lock_irqsave(&irq_lock, flags); - irq_cnt = pdacpu(IRQCPU(irq)).pda_poll_entry_count; - for (i=0; itick <= 0) { -#ifdef CONFIG_SHUB_1_0_SPECIFIC - irq_list->tick = irq_list->interval; -#else - irq_list->tick = sn_int_poll_ticks; -#endif - local_irq_save(flags); - ia64_handle_irq(irq_to_vector(irq_list->irq), 0); - local_irq_restore(flags); - } - } -} - -#define PROCFILENAME "sn_int_poll_ticks" - -static struct proc_dir_entry *proc_op; - - -static int -read_proc(char *buffer, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - - len += sprintf(buffer + len, "Poll hack: interval %ld ticks\n", sn_int_poll_ticks); - - if (len <= off+count) *eof = 1; - *start = buffer + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - -static int -write_proc (struct file *file, const char *userbuf, unsigned long count, void *data) -{ - extern long atoi(char *); - char buf[80]; - - if (copy_from_user(buf, userbuf, count < sizeof(buf) ? count : sizeof(buf))) - return -EFAULT; - - sn_int_poll_ticks = atoi(buf); - - return count; -} - - -int __init -sn_poll_init(void) -{ - if ((proc_op = create_proc_entry(PROCFILENAME, 0644, NULL)) == NULL) { - printk("%s: unable to create proc entry", PROCFILENAME); - return -1; - } - proc_op->read_proc = read_proc; - proc_op->write_proc = write_proc; - return 0; -} - -module_init(sn_poll_init); -#endif diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/Makefile linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/Makefile --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/Makefile Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/Makefile Wed Jul 23 18:28:59 2003 @@ -1,7 +1,7 @@ # # arch/ia64/sn/kernel/sn2/Makefile # -# Copyright (C) 1999,2001-2002 Silicon Graphics, Inc. All rights reserved. +# Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of version 2 of the GNU General Public License @@ -41,7 +41,9 @@ $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< O_TARGET = sn2.o +export-objs := io.o -obj-y = cache.o iomv.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o +obj-y = cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ + prominfo_proc.o timer.o include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/cache.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/cache.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/cache.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/cache.c Wed Jul 23 18:28:59 2003 @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. * */ @@ -24,6 +24,5 @@ sn_flush_all_caches(long flush_addr, long bytes) { flush_icache_range(flush_addr, flush_addr+bytes); + mb(); } - - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/io.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/io.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/io.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/io.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,91 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 Silicon Graphics, Inc. All rights reserved. + * + * The generic kernel requires function pointers to these routines, so + * we wrap the inlines from asm/ia64/sn/sn2/io.h here. + */ + +#include + +unsigned int +sn_inb (unsigned long port) +{ + return __sn_inb(port); +} + +unsigned int +sn_inw (unsigned long port) +{ + return __sn_inw(port); +} + +unsigned int +sn_inl (unsigned long port) +{ + return __sn_inl(port); +} + +void +sn_outb (unsigned char val, unsigned long port) +{ + __sn_outb(val, port); +} + +void +sn_outw (unsigned short val, unsigned long port) +{ + __sn_outw(val, port); +} + +void +sn_outl (unsigned int val, unsigned long port) +{ + __sn_outl(val, port); +} + +unsigned char +sn_readb (void *addr) +{ + return __sn_readb (addr); +} + +unsigned short +sn_readw (void *addr) +{ + return __sn_readw (addr); +} + +unsigned int +sn_readl (void *addr) +{ + return __sn_readl (addr); +} + +unsigned long +sn_readq (void *addr) +{ + return __sn_readq (addr); +} + + +/* define aliases: */ + +asm (".global __sn_inb, __sn_inw, __sn_inl"); +asm ("__sn_inb = sn_inb"); +asm ("__sn_inw = sn_inw"); +asm ("__sn_inl = sn_inl"); + +asm (".global __sn_outb, __sn_outw, __sn_outl"); +asm ("__sn_outb = sn_outb"); +asm ("__sn_outw = sn_outw"); +asm ("__sn_outl = sn_outl"); + +asm (".global __sn_readb, __sn_readw, __sn_readl, __sn_readq"); +asm ("__sn_readb = sn_readb"); +asm ("__sn_readw = sn_readw"); +asm ("__sn_readl = sn_readl"); +asm ("__sn_readq = sn_readq"); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/prominfo_proc.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/prominfo_proc.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/prominfo_proc.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/prominfo_proc.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,365 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * Module to export the system's Firmware Interface Tables, including + * PROM revision numbers, in /proc + */ +#include +#include +#include +#include +#include +#include +#include + +/* to lookup nasids */ +#include + +MODULE_DESCRIPTION("PROM version reporting for /proc"); +MODULE_AUTHOR("Chad Talbott"); +MODULE_LICENSE("GPL"); + +#undef DEBUG_PROMINFO + +#define TRACE_PROMINFO + +#if defined(DEBUG_PROMINFO) +# define DPRINTK(x...) printk(KERN_DEBUG x) +#else +# define DPRINTK(x...) +#endif + +#if defined(TRACE_PROMINFO) && defined(DEBUG_PROMINFO) +# if defined(__GNUC__) +# define TRACE() printk(KERN_DEBUG "%s:%d:%s\n", \ + __FILE__, __LINE__, __FUNCTION__) +# else +# define TRACE() printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__) +# endif +#else +# define TRACE() +#endif + +/* Sub-regions determined by bits in Node Offset */ +#define LB_PROM_SPACE 0x0000000700000000ul /* Local LB PROM */ + +#define FIT_SIGNATURE 0x2020205f5449465ful +/* Standard Intel FIT entry types */ +#define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */ +#define FIT_ENTRY_PAL_B 0x01 /* PAL_B entry */ +/* Entries 0x02 through 0x0D reserved by Intel */ +#define FIT_ENTRY_PAL_A_PROC 0x0E /* Processor-specific PAL_A entry */ +#define FIT_ENTRY_PAL_A 0x0F /* PAL_A entry, same as... */ +#define FIT_ENTRY_PAL_A_GEN 0x0F /* ...Generic PAL_A entry */ +#define FIT_ENTRY_UNUSED 0x7F /* Unused (reserved by Intel?) */ +/* OEM-defined entries range from 0x10 to 0x7E. */ +#define FIT_ENTRY_SAL_A 0x10 /* SAL_A entry */ +#define FIT_ENTRY_SAL_B 0x11 /* SAL_B entry */ +#define FIT_ENTRY_SALRUNTIME 0x12 /* SAL runtime entry */ +#define FIT_ENTRY_EFI 0x1F /* EFI entry */ +#define FIT_ENTRY_FPSWA 0x20 /* embedded fpswa entry */ +#define FIT_ENTRY_VMLINUX 0x21 /* embedded vmlinux entry */ + +#define FIT_MAJOR_SHIFT (32 + 8) +#define FIT_MAJOR_MASK ((1 << 8) - 1) +#define FIT_MINOR_SHIFT 32 +#define FIT_MINOR_MASK ((1 << 8) - 1) + +#define FIT_MAJOR(q) \ + ((unsigned) ((q) >> FIT_MAJOR_SHIFT) & FIT_MAJOR_MASK) +#define FIT_MINOR(q) \ + ((unsigned) ((q) >> FIT_MINOR_SHIFT) & FIT_MINOR_MASK) + +#define FIT_TYPE_SHIFT (32 + 16) +#define FIT_TYPE_MASK ((1 << 7) - 1) + +#define FIT_TYPE(q) \ + ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK) + +#define FIT_ENTRY(type, maj, min, size) \ + ((((unsigned long)(maj) & FIT_MAJOR_MASK) << FIT_MAJOR_SHIFT) | \ + (((unsigned long)(min) & FIT_MINOR_MASK) << FIT_MINOR_SHIFT) | \ + (((unsigned long)(type) & FIT_TYPE_MASK) << FIT_TYPE_SHIFT) | \ + (size)) + +struct fit_type_map_t { + unsigned char type; + const char *name; +}; + +static const struct fit_type_map_t fit_entry_types[] = { + { FIT_ENTRY_FIT_HEADER, "FIT Header" }, + { FIT_ENTRY_PAL_A_GEN, "Generic PAL_A" }, + { FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A" }, + { FIT_ENTRY_PAL_A, "PAL_A" }, + { FIT_ENTRY_PAL_B, "PAL_B" }, + { FIT_ENTRY_SAL_A, "SAL_A" }, + { FIT_ENTRY_SAL_B, "SAL_B" }, + { FIT_ENTRY_SALRUNTIME, "SAL runtime" }, + { FIT_ENTRY_EFI, "EFI" }, + { FIT_ENTRY_VMLINUX, "Embedded Linux" }, + { FIT_ENTRY_FPSWA, "Embedded FPSWA" }, + { FIT_ENTRY_UNUSED, "Unused" }, + { 0xff, "Error" }, +}; + +static const char * +fit_type_name(unsigned char type) +{ + struct fit_type_map_t const*mapp; + + for (mapp = fit_entry_types; mapp->type != 0xff; mapp++) + if (type == mapp->type) + return mapp->name; + + if ((type > FIT_ENTRY_PAL_A) && (type < FIT_ENTRY_UNUSED)) + return "OEM type"; + if ((type > FIT_ENTRY_PAL_B) && (type < FIT_ENTRY_PAL_A)) + return "Reserved"; + + return "Unknown type"; +} + +/* These two routines read the FIT table directly from the FLASH PROM + * on a specific node. The PROM can only be accessed using aligned 64 + * bit reads, so we do that and then shift and mask the result to get + * at each field. + */ +static int +dump_fit_entry(char *page, unsigned long *fentry) +{ + unsigned long q1, q2; + unsigned type; + + TRACE(); + + q1 = readq(fentry); + q2 = readq(fentry + 1); + type = FIT_TYPE(q2); + return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n", + type, + fit_type_name(type), + FIT_MAJOR(q2), FIT_MINOR(q2), + q1, + /* mult by sixteen to get size in bytes */ + (unsigned)q2 * 16); +} + +/* We assume that the fit table will be small enough that we can print + * the whole thing into one page. (This is true for our default 16kB + * pages -- each entry is about 60 chars wide when printed.) I read + * somewhere that the maximum size of the FIT is 128 entries, so we're + * OK except for 4kB pages (and no one is going to do that on SN + * anyway). + */ +static int +dump_fit(char *page, unsigned long *fit) +{ + unsigned long qw; + int nentries; + int fentry; + char *p; + + TRACE(); + + DPRINTK("dumping fit from %p\n", (void *)fit); + + qw = readq(fit); + DPRINTK("FIT signature: %016lx (%.8s)\n", qw, (char *)&qw); + if (qw != FIT_SIGNATURE) + printk(KERN_WARNING "Unrecognized FIT signature"); + + qw = readq(fit + 1); + nentries = (unsigned)qw; + DPRINTK("number of fit entries: %u\n", nentries); + /* check that we won't overflow the page -- see comment above */ + BUG_ON(nentries * 60 > PAGE_SIZE); + + p = page; + for (fentry = 0; fentry < nentries; fentry++) + /* each FIT entry is two 64 bit words */ + p += dump_fit_entry(p, fit + 2 * fentry); + + return p - page; +} + +static int +dump_version(char *page, unsigned long *fit) +{ + int nentries; + int fentry; + unsigned long qw; + + TRACE(); + + nentries = (unsigned)readq(fit + 1); + BUG_ON(nentries * 60 > PAGE_SIZE); + + for (fentry = 0; fentry < nentries; fentry++) { + qw = readq(fit + 2 * fentry + 1); + if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A) + return sprintf(page, "%x.%02x\n", + FIT_MAJOR(qw), FIT_MINOR(qw)); + } + return 0; +} + +/* same as in proc_misc.c */ +static int +proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, + int len) +{ + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +static int +read_version_entry(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + int len = 0; + + MOD_INC_USE_COUNT; + /* data holds the pointer to this node's FIT */ + len = dump_version(page, (unsigned long *)data); + len = proc_calc_metrics(page, start, off, count, eof, len); + MOD_DEC_USE_COUNT; + return len; +} + +static int +read_fit_entry(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + int len = 0; + + MOD_INC_USE_COUNT; + /* data holds the pointer to this node's FIT */ + len = dump_fit(page, (unsigned long *)data); + len = proc_calc_metrics(page, start, off, count, eof, len); + MOD_DEC_USE_COUNT; + + return len; +} + +/* this is a fake FIT that's used on the medusa simulator which + * doesn't usually run a complete PROM. + */ +#ifdef CONFIG_IA64_SGI_SN_SIM +static unsigned long fakefit[] = { + /* this is all we need to satisfy the code below */ + FIT_SIGNATURE, + FIT_ENTRY(FIT_ENTRY_FIT_HEADER, 0x02, 0x60, 2), + /* dump something arbitrary for + * /proc/sgi_prominfo/nodeX/version */ + 0xbadbeef00fa3ef17ul, + FIT_ENTRY(FIT_ENTRY_SAL_A, 0, 0x99, 0x100) +}; +#endif + +static unsigned long * +lookup_fit(int nasid) +{ + unsigned long *fitp; + unsigned long fit_paddr; + unsigned long *fit_vaddr; + +#ifdef CONFIG_IA64_SGI_SN_SIM + if (IS_RUNNING_ON_SIMULATOR()) + return fakefit; +#endif + + fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32); + DPRINTK("pointer to fit at %p\n", (void *)fitp); + fit_paddr = readq(fitp); + DPRINTK("fit pointer contains %lx\n", fit_paddr); + /* snag just the node-relative offset */ + fit_paddr &= ~0ul >> (63-35); + /* the pointer to the FIT is relative to IA-64 compatibility + * space. However, the PROM is mapped at a different offset + * in MMR space (both local and global) + */ + fit_paddr += 0x700000000; + fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr); + DPRINTK("fit at %p\n", (void *)fit_vaddr); + return fit_vaddr; +} + +/* module entry points */ +int __init prominfo_init(void); +void __exit prominfo_exit(void); + +module_init(prominfo_init); +module_exit(prominfo_exit); + +static struct proc_dir_entry **proc_entries; +static struct proc_dir_entry *sgi_prominfo_entry; + +#define NODE_NAME_LEN 11 + +int __init +prominfo_init(void) +{ + struct proc_dir_entry **entp; + cnodeid_t cnodeid; + nasid_t nasid; + char name[NODE_NAME_LEN]; + + if (!ia64_platform_is("sn2")) + return 0; + + TRACE(); + + DPRINTK("running on cpu %d\n", smp_processor_id()); + DPRINTK("numnodes %d\n", numnodes); + + proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *), + GFP_KERNEL); + + sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL); + + for (cnodeid = 0, entp = proc_entries; + cnodeid < numnodes; + cnodeid++, entp++) { + sprintf(name, "node%d", cnodeid); + *entp = proc_mkdir(name, sgi_prominfo_entry); + nasid = cnodeid_to_nasid(cnodeid); + create_proc_read_entry( + "fit", 0, *entp, read_fit_entry, + lookup_fit(nasid)); + create_proc_read_entry( + "version", 0, *entp, read_version_entry, + lookup_fit(nasid)); + } + + return 0; +} + +void __exit +prominfo_exit(void) +{ + struct proc_dir_entry **entp; + unsigned cnodeid; + char name[NODE_NAME_LEN]; + + TRACE(); + + for (cnodeid = 0, entp = proc_entries; + cnodeid < numnodes; + cnodeid++, entp++) { + remove_proc_entry("fit", *entp); + remove_proc_entry("version", *entp); + sprintf(name, "node%d", cnodeid); + remove_proc_entry(name, sgi_prominfo_entry); + } + remove_proc_entry("sgi_prominfo", NULL); + kfree(proc_entries); +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/ptc_deadlock.S linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/ptc_deadlock.S --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/ptc_deadlock.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/ptc_deadlock.S Wed Jul 23 18:28:59 2003 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include @@ -61,20 +61,22 @@ cmp.ne p6,p0=zeroval,scr2 (p6) br.cond.sptk 5b;; - tbit.nz p6,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK + tbit.nz p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK (p7) st8.rel [ptc1]=data1;; // Now write PTC1. +5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b + + tbit.nz p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK + mov psr.l=psrsave;; // Reenable IC srlz.i;; ////////////// END PHYSICAL MODE //////////////////// -(p6) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. +(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. -5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. - extr.u scr2=scr1,WRITECOUNT,7;;// PIO count - cmp.ne p6,p0=zeroval,scr2 -(p6) br.cond.sptk 5b - br.ret.sptk rp .endp sn2_ptc_deadlock_recovery_core diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/sn2_smp.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/sn2_smp.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/sn2_smp.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/sn2_smp.c Wed Jul 23 18:28:59 2003 @@ -1,7 +1,7 @@ /* * SN2 Platform specific SMP Support * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -79,296 +79,6 @@ return ws; } -static long use_tlb_hack; -static volatile unsigned long zz[1024] __attribute__((__aligned__(128))); -static inline long -get_itc(void) -{ - long ret; - __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret)); - return ret+1; -} - - - -#ifdef PTCG_WAR -/* - * The following structure is used to pass params thru smp_call_function - * to other cpus for flushing TLB ranges. - */ -typedef struct { - unsigned long start; - unsigned long end; - unsigned long nbits; - unsigned int rid; - atomic_t unfinished_count; - char fill[96]; -} ptc_params_t; - -#define NUMPTC 512 - -static ptc_params_t ptcParamArray[NUMPTC] __attribute__((__aligned__(128))); - -/* use separate cache lines on ptcParamsNextByCpu to avoid false sharing */ -static ptc_params_t *ptcParamsNextByCpu[NR_CPUS*16] __attribute__((__aligned__(128))); -static volatile ptc_params_t *ptcParamsEmpty __cacheline_aligned; - -/*REFERENCED*/ -static spinlock_t ptcParamsLock __cacheline_aligned = SPIN_LOCK_UNLOCKED; - -static int ptcInit = 0; -#ifdef PTCDEBUG -static int ptcParamsAllBusy = 0; /* debugging/statistics */ -static int ptcCountBacklog = 0; -static int ptcBacklog[NUMPTC+1]; -static char ptcParamsCounts[NR_CPUS][NUMPTC] __attribute__((__aligned__(128))); -static char ptcParamsResults[NR_CPUS][NUMPTC] __attribute__((__aligned__(128))); -#endif - -/* - * Make smp_send_flush_tlbsmp_send_flush_tlb() a weak reference, - * so that we get a clean compile with the ia64 patch without the - * actual SN1 specific code in arch/ia64/kernel/smp.c. - */ -extern void smp_send_flush_tlb (void) __attribute((weak)); - - -/** - * sn1_ptc_l_range - purge local translation cache - * @start: start of virtual address range - * @end: end of virtual address range - * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc)) - * - * Purges the range specified from the local processor's translation cache - * (as opposed to the translation registers). Note that more than the specified - * range *may* be cleared from the cache by some processors. - * - * This is probably not good enough, but I don't want to try to make it better - * until I get some statistics on a running system. At a minimum, we should only - * send IPIs to 1 processor in each TLB domain & have it issue a ptc.g on it's - * own FSB. Also, we only have to serialize per FSB, not globally. - * - * More likely, we will have to do some work to reduce the frequency of calls to - * this routine. - */ -static inline void -sn1_ptc_l_range(unsigned long start, unsigned long end, unsigned long nbits) -{ - do { - __asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory"); - start += (1UL << nbits); - } while (start < end); - ia64_srlz_d(); -} - -/** - * sn1_received_flush_tlb - cpu tlb flush routine - * - * Flushes the TLB of a given processor. - */ -void -sn1_received_flush_tlb(void) -{ - unsigned long start, end, nbits; - unsigned int rid, saved_rid; - int cpu = smp_processor_id(); - int result; - ptc_params_t *ptcParams; - - ptcParams = ptcParamsNextByCpu[cpu*16]; - if (ptcParams == ptcParamsEmpty) - return; - - do { - start = ptcParams->start; - saved_rid = (unsigned int) ia64_get_rr(start); - end = ptcParams->end; - nbits = ptcParams->nbits; - rid = ptcParams->rid; - - if (saved_rid != rid) { - ia64_set_rr(start, (unsigned long)rid); - ia64_srlz_d(); - } - - sn1_ptc_l_range(start, end, nbits); - - if (saved_rid != rid) - ia64_set_rr(start, (unsigned long)saved_rid); - - ia64_srlz_i(); - - result = atomic_dec(&ptcParams->unfinished_count); -#ifdef PTCDEBUG - { - int i = ptcParams-&ptcParamArray[0]; - ptcParamsResults[cpu][i] = (char) result; - ptcParamsCounts[cpu][i]++; - } -#endif /* PTCDEBUG */ - - if (++ptcParams == &ptcParamArray[NUMPTC]) - ptcParams = &ptcParamArray[0]; - - } while (ptcParams != ptcParamsEmpty); - - ptcParamsNextByCpu[cpu*16] = ptcParams; -} - -/** - * sn1_global_tlb_purge - flush a translation cache range on all processors - * @start: start of virtual address range to flush - * @end: end of virtual address range - * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc)) - * - * Flushes the translation cache of all processors from @start to @end. - */ -void -sn1_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) -{ - ptc_params_t *params; - ptc_params_t *next; - unsigned long irqflags; -#ifdef PTCDEBUG - ptc_params_t *nextnext; - int backlog = 0; -#endif - - if (smp_num_cpus == 1) { - sn1_ptc_l_range(start, end, nbits); - return; - } - - if (in_interrupt()) { - /* - * If at interrupt level and cannot get spinlock, - * then do something useful by flushing own tlbflush queue - * so as to avoid a possible deadlock. - */ - while (!spin_trylock(&ptcParamsLock)) { - local_irq_save(irqflags); - sn1_received_flush_tlb(); - local_irq_restore(irqflags); - udelay(10); /* take it easier on the bus */ - } - } else { - spin_lock(&ptcParamsLock); - } - - if (!ptcInit) { - int cpu; - ptcInit = 1; - memset(ptcParamArray, 0, sizeof(ptcParamArray)); - ptcParamsEmpty = &ptcParamArray[0]; - for (cpu=0; cpu= &ptcParamArray[0]) { - if (atomic_read(&ptr->unfinished_count) == 0) - break; - ++backlog; - } - - if (backlog) { - /* check the end of the array */ - ptr = &ptcParamArray[NUMPTC]; - while (--ptr > params) { - if (atomic_read(&ptr->unfinished_count) == 0) - break; - ++backlog; - } - } - ptcBacklog[backlog]++; - } -#endif /* PTCDEBUG */ - - /* wait for the next entry to clear...should be rare */ - if (atomic_read(&next->unfinished_count) > 0) { -#ifdef PTCDEBUG - ptcParamsAllBusy++; - - if (atomic_read(&nextnext->unfinished_count) == 0) { - if (atomic_read(&next->unfinished_count) > 0) { - panic("\nnonzero next zero nextnext %lx %lx\n", - (long)next, (long)nextnext); - } - } -#endif - - /* it could be this cpu that is behind */ - local_irq_save(irqflags); - sn1_received_flush_tlb(); - local_irq_restore(irqflags); - - /* now we know it's not this cpu, so just wait */ - while (atomic_read(&next->unfinished_count) > 0) { - barrier(); - } - } - - params->start = start; - params->end = end; - params->nbits = nbits; - params->rid = (unsigned int) ia64_get_rr(start); - atomic_set(¶ms->unfinished_count, smp_num_cpus); - - /* The atomic_set above can hit memory *after* the update - * to ptcParamsEmpty below, which opens a timing window - * that other cpus can squeeze into! - */ - mb(); - - /* everything is ready to process: - * -- global lock is held - * -- new entry + 1 is free - * -- new entry is set up - * so now: - * -- update the global next pointer - * -- unlock the global lock - * -- send IPI to notify other cpus - * -- process the data ourselves - */ - ptcParamsEmpty = next; - spin_unlock(&ptcParamsLock); - smp_send_flush_tlb(); - - local_irq_save(irqflags); - sn1_received_flush_tlb(); - local_irq_restore(irqflags); - - /* - * Since IPIs are polled event (for now), we need to wait til the - * TLB flush has started. - * wait for the flush to complete - */ - while (atomic_read(¶ms->unfinished_count) > 0) - barrier(); -} - -#endif /* PTCG_WAR */ /** @@ -384,19 +94,10 @@ void sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) { - int cnode, mycnode, nasid; + int cnode, mycnode, nasid, flushed=0; volatile unsigned long *ptc0, *ptc1; unsigned long flags=0, data0, data1; - long zzbase, zztime, zztime2; - /* - * Special case 1 cpu & 1 node. Use local purges. - */ -#ifdef PTCG_WAR - sn1_global_tlb_purge(start, end, nbits); - return; -#endif /* PTCG_WAR */ - data0 = (1UL<>8)<shared_mm || test_bit(cnode, current->node_history)) { nasid = cnodeid_to_nasid(cnode); ptc0 = CHANGE_NASID(nasid, ptc0); ptc1 = CHANGE_NASID(nasid, ptc1); pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1); + flushed = 1; } } - if (wait_piowc() & SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK) { - zz[zzbase+1]++; + if (flushed && (wait_piowc() & SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK)) { sn2_ptc_deadlock_recovery(data0, data1); } @@ -444,20 +134,8 @@ } while (start < end); - zz[zzbase+0] -= 0xffffffff00000000UL; - zztime2 = get_itc() - zztime2; spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); - zztime = get_itc() - zztime; - - zz[zzbase+6] += zztime; - if (zztime > zz[zzbase+7]) - zz[zzbase+7] = zztime; - - zz[zzbase+8] += zztime2; - if (zztime2 > zz[zzbase+9]) - zz[zzbase+9] = zztime2; - } /* @@ -480,7 +158,7 @@ ptc1 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1); piows = (long*)pda.pio_write_status_addr; - mycnode = local_cnodeid(); + mycnode = numa_node_id(); for (cnode = 0; cnode < numnodes; cnode++) { if (is_headless_node(cnode) || cnode == mycnode) @@ -511,16 +189,10 @@ void sn_send_IPI_phys(long physid, int vector, int delivery_mode) { - long nasid, slice; - long val; + long nasid, slice, val; + unsigned long flags=0; volatile long *p; -#if defined(BUS_INT_WAR) && defined(CONFIG_SHUB_1_0_SPECIFIC) - if (vector != ap_wakeup_vector && delivery_mode == IA64_IPI_DM_INT) { - return; - } -#endif - nasid = cpu_physical_id_to_nasid(physid); slice = cpu_physical_id_to_slice(physid); @@ -532,12 +204,15 @@ (0x000feeUL< - - -static struct proc_dir_entry *ptcg_stats; - -static int -ptcg_read_proc(char *buffer, char **start, off_t off, int count, int *eof, void *data) -{ - long cpu, *p, cnt; - int len = 0; - - p = (long*)LOCAL_MMR_ADDR(SH_DIAG_MSG_DATA7L); - len += sprintf(buffer + len, "PTCG Stats (option 0x%lx)\n", use_tlb_hack); - - len += sprintf(buffer + len, "%-14s", "CPU"); - for (cpu=0; cpucyc_per_usec : 0); - } - len += sprintf(buffer + len, "\n"); - - len += sprintf(buffer + len, "%-14s", "max-us"); - for (cpu=0; cpucyc_per_usec); - len += sprintf(buffer + len, "\n"); - - len += sprintf(buffer + len, "%-14s", "iaver-us"); - for (cpu=0; cpucyc_per_usec : 0); - } - len += sprintf(buffer + len, "\n"); - - len += sprintf(buffer + len, "%-14s", "imax-us"); - for (cpu=0; cpucyc_per_usec); - len += sprintf(buffer + len, "\n"); - - len += sprintf(buffer + len, "%-14s", "long-piowc"); - for (cpu=0; cpucount) len = count; - if (len<0) len = 0; - return len; -} - - -static int -ptcg_write_proc (struct file *file, const char *userbuf, unsigned long count, void *data) -{ - extern long atoi(char *); - char buf[80]; - long val; - long cpu; - long *p; - - if (copy_from_user(buf, userbuf, count < sizeof(buf) ? count : sizeof(buf))) - return -EFAULT; - - val = atoi(buf); - if (val&4) val |= 1; - use_tlb_hack = val; - - memset((void*)zz, 0, sizeof(zz)); - - for (cpu=0; cpuread_proc = ptcg_read_proc; - ptcg_stats->write_proc = ptcg_write_proc; - return 0; -} - -#include -module_init(sn2_ptcg_stats_init); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/sn_proc_fs.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/sn_proc_fs.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Wed Jul 23 18:28:59 2003 @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -31,6 +31,7 @@ * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include +#include #ifdef CONFIG_PROC_FS #include @@ -43,7 +44,7 @@ return sprintf(page, "%d\n", sn_local_partid()); } -struct proc_dir_entry * sgi_proc_dir = NULL; +static struct proc_dir_entry * sgi_proc_dir; void register_sn_partition_id(void) { @@ -96,4 +97,99 @@ } } +// Disable forced interrupts, but leave the code in, just in case. +int sn_force_interrupt_flag = 0; + +static int +sn_force_interrupt_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + if (sn_force_interrupt_flag) { + return sprintf(page, "Force interrupt is enabled\n"); + } + return sprintf(page, "Force interrupt is disabled\n"); +} + +static int +sn_force_interrupt_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + if (*buffer == '0') { + sn_force_interrupt_flag = 0; + } else { + sn_force_interrupt_flag = 1; + } + return 1; +} + +void +register_sn_force_interrupt(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = sn_force_interrupt_read_proc; + entry->write_proc = sn_force_interrupt_write_proc; + } +} + +extern int sn_linkstats_get(char *); +extern int sn_linkstats_reset(unsigned long); + +static int +sn_linkstats_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + + return sn_linkstats_get(page); +} + +static int +sn_linkstats_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char s[64]; + unsigned long msecs; + int e = count; + + if (copy_from_user(s, buffer, count < sizeof(s) ? count : sizeof(s))) + e = -EFAULT; + else { + if (sscanf(s, "%lu", &msecs) != 1 || msecs < 5) + /* at least 5 milliseconds between updates */ + e = -EINVAL; + else + sn_linkstats_reset(msecs); + } + + return e; +} + +void +register_sn_linkstats(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("linkstats", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = sn_linkstats_read_proc; + entry->write_proc = sn_linkstats_write_proc; + } +} + +void +register_sn_procfs(void) { + register_sn_partition_id(); + register_sn_serial_numbers(); + register_sn_force_interrupt(); + register_sn_linkstats(); +} + #endif /* CONFIG_PROC_FS */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/timer.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/timer.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn2/timer.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn2/timer.c Wed Jul 23 18:28:59 2003 @@ -0,0 +1,100 @@ +/* + * linux/arch/ia64/sn/kernel/sn2/timer.c + * + * Copyright (C) 2003 Silicon Graphics, Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +extern unsigned long sn_rtc_cycles_per_second; +static volatile unsigned long last_wall_rtc; + +/** + * gettimeoffset - number of usecs elapsed since &xtime was last updated + * + * This function is used by do_gettimeofday() to determine the number + * of usecs that have elapsed since the last update to &xtime. On SN + * this is accomplished using the RTC built in to each Hub chip; each + * is guaranteed to be synchronized by the PROM, so a local read will + * suffice (GET_RTC_COUNTER() does this for us). A snapshot of the RTC + * value is taken every time wall_jiffies is updated by the + * update_wall_time_hook (sn2_update_wall_time) which means we don't + * have to adjust for lost jiffies ticks or anything like that. + */ +extern unsigned long wall_jiffies; /* from kernel/timer.c */ + +static volatile long rtc_offset; +static long rtc_cycles_per_usec; +static long rtc_per_timer_tick; + +unsigned long +sn_gettimeoffset(void) +{ + long current_rtc, elapsed_rtc, old, new_offset; + + do { + old = rtc_offset; + current_rtc = GET_RTC_COUNTER(); + + /* + * Need to address wrapping here! + */ + elapsed_rtc = (long)(current_rtc - last_wall_rtc); + + /* + * This case is non lethal as the max() will take care of it. + */ +#if 0 + if (elapsed_rtc < 0) { + printk(KERN_ERR "sn_gettimeoffset(): time goes " + "backwards!\n current_rtc 0x%016lx, " + "last_wall_rtc 0x%016lx, elapsed %08lx, " + "offset %li\n", current_rtc, last_wall_rtc, + elapsed_rtc, max(elapsed_rtc, rtc_offset)/ + rtc_cycles_per_usec); + } +#endif + + new_offset = max(elapsed_rtc, old); + } while (cmpxchg(&rtc_offset, old, new_offset) != old); + + return new_offset / rtc_cycles_per_usec; +} + + +void sn2_update_wall_time(void) +{ + rtc_offset -= min(rtc_offset, rtc_per_timer_tick); + last_wall_rtc = GET_RTC_COUNTER(); +} + + +void sn2_reset_wall_time(void) +{ + rtc_offset = 0; + last_wall_rtc = GET_RTC_COUNTER(); +} + + +void __init +sn_timer_init(void) +{ + rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ; + rtc_cycles_per_usec = sn_rtc_cycles_per_second / 1000000; + + last_wall_rtc = GET_RTC_COUNTER(); + update_wall_time_hook = sn2_update_wall_time; + reset_wall_time_hook = sn2_reset_wall_time; + gettimeoffset = sn_gettimeoffset; +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn_ksyms.c linux2.4.21_itanium/arch/ia64/sn/kernel/sn_ksyms.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sn_ksyms.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sn_ksyms.c Wed Jul 23 18:28:59 2003 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. */ @@ -18,8 +18,8 @@ #include #include -#include -extern devfs_handle_t base_io_scsi_ctlr_vhdl[]; +#include +extern vertex_hdl_t base_io_scsi_ctlr_vhdl[]; #include extern cnodeid_t master_node_get(devfs_handle_t vhdl); #include @@ -31,9 +31,9 @@ * symbols referenced by the PCIBA module */ #include -#include #include #include +#include devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn); @@ -54,29 +54,26 @@ EXPORT_SYMBOL(sn_send_IPI_phys); /* symbols referenced by partitioning modules */ -#include +#include +EXPORT_SYMBOL(bte_copy); EXPORT_SYMBOL(bte_unaligned_copy); #include EXPORT_SYMBOL(ia64_sal); +EXPORT_SYMBOL(physical_node_map); -#ifdef CONFIG_IA64_SGI_SN2 #include EXPORT_SYMBOL(sal_lock); EXPORT_SYMBOL(sn_partid); EXPORT_SYMBOL(sn_local_partid); EXPORT_SYMBOL(sn_system_serial_number_string); EXPORT_SYMBOL(sn_partition_serial_number); -#endif + +EXPORT_SYMBOL(sn_mmiob); /* added by tduffy 04.08.01 to fix depmod issues */ #include -#ifdef BUS_INT_WAR -extern void sn_add_polled_interrupt(int, int); -extern void sn_delete_polled_interrupt(int); -EXPORT_SYMBOL(sn_add_polled_interrupt); -EXPORT_SYMBOL(sn_delete_polled_interrupt); -#endif - extern nasid_t master_nasid; EXPORT_SYMBOL(master_nasid); + +EXPORT_SYMBOL(sn_flush_all_caches); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/sn/kernel/sv.c linux2.4.21_itanium/arch/ia64/sn/kernel/sv.c --- linux2.4.21_itanium.org/arch/ia64/sn/kernel/sv.c Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/sn/kernel/sv.c Wed Jul 23 18:28:59 2003 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This implemenation of synchronization variables is heavily based on * one done by Steve Lord diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/tools/print_offsets.c linux2.4.21_itanium/arch/ia64/tools/print_offsets.c --- linux2.4.21_itanium.org/arch/ia64/tools/print_offsets.c Wed Jul 23 18:21:05 2003 +++ linux2.4.21_itanium/arch/ia64/tools/print_offsets.c Wed Jul 23 18:29:00 2003 @@ -10,7 +10,7 @@ * gets translated into an assembly file which, in turn, is processed * by awk to generate offsets.h. So if you make any changes to this * file, be sure to verify that the awk procedure still works (see - * prin_offsets.awk). + * print_offsets.awk). */ #include diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/arch/ia64/vmlinux.lds.S linux2.4.21_itanium/arch/ia64/vmlinux.lds.S --- linux2.4.21_itanium.org/arch/ia64/vmlinux.lds.S Wed Jul 23 18:21:02 2003 +++ linux2.4.21_itanium/arch/ia64/vmlinux.lds.S Wed Jul 23 18:28:55 2003 @@ -27,6 +27,7 @@ _text = .; _stext = .; + .text : AT(ADDR(.text) - PAGE_OFFSET) { *(.text.ivt) @@ -47,38 +48,48 @@ /* Exception table */ . = ALIGN(16); - __start___ex_table = .; __ex_table : AT(ADDR(__ex_table) - PAGE_OFFSET) - { *(__ex_table) } - __stop___ex_table = .; + { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } #if defined(CONFIG_IA64_GENERIC) /* Machine Vector */ . = ALIGN(16); - machvec_start = .; .machvec : AT(ADDR(.machvec) - PAGE_OFFSET) - { *(.machvec) } - machvec_end = .; + { + machvec_start = .; + *(.machvec) + machvec_end = .; + } #endif - __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : AT(ADDR(__ksymtab) - PAGE_OFFSET) - { *(__ksymtab) } - __stop___ksymtab = .; + { + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + } - __start___kallsyms = .; /* All kernel symbols for debugging */ __kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET) - { *(__kallsyms) } - __stop___kallsyms = .; + { + __start___kallsyms = .; /* All kernel symbols for debugging */ + *(__kallsyms) + __stop___kallsyms = .; + } /* Unwind info & table: */ . = ALIGN(8); .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - PAGE_OFFSET) { *(.IA_64.unwind_info*) } - ia64_unw_start = .; .IA_64.unwind : AT(ADDR(.IA_64.unwind) - PAGE_OFFSET) - { *(.IA_64.unwind*) } - ia64_unw_end = .; + { + ia64_unw_start = .; + *(.IA_64.unwind*) + ia64_unw_end = .; + } .rodata : AT(ADDR(.rodata) - PAGE_OFFSET) { *(.rodata) *(.rodata.*) } @@ -97,14 +108,18 @@ .data.init : AT(ADDR(.data.init) - PAGE_OFFSET) { *(.data.init) } . = ALIGN(16); - __setup_start = .; .setup.init : AT(ADDR(.setup.init) - PAGE_OFFSET) - { *(.setup.init) } - __setup_end = .; - __initcall_start = .; + { + __setup_start = .; + *(.setup.init) + __setup_end = .; + } .initcall.init : AT(ADDR(.initcall.init) - PAGE_OFFSET) - { *(.initcall.init) } - __initcall_end = .; + { + __initcall_start = .; + *(.initcall.init) + __initcall_end = .; + } . = ALIGN(PAGE_SIZE); __init_end = .; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/config.zx6000.test linux2.4.21_itanium/config.zx6000.test --- linux2.4.21_itanium.org/config.zx6000.test Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/config.zx6000.test Thu Jul 24 13:00:07 2003 @@ -0,0 +1,938 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_IA64=y +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_GENERIC is not set +# CONFIG_IA64_DIG is not set +# CONFIG_IA64_HP_SIM is not set +CONFIG_IA64_HP_ZX1=y +# CONFIG_IA64_SGI_SN1 is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_IA64_L1_CACHE_SHIFT=7 +CONFIG_IA64_MCA=y +CONFIG_PM=y +CONFIG_KCORE_ELF=y +CONFIG_FORCE_MAX_ZONEORDER=19 +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set +CONFIG_SMP=y +CONFIG_IA32_SUPPORT=y +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y +CONFIG_EFI_VARS=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_ACPI=y +CONFIG_ACPI_EFI=y +CONFIG_ACPI_INTERPRETER=y +CONFIG_ACPI_KERNEL_CONFIG=y + +# +# ACPI Support +# +CONFIG_ACPI_PCI=y +CONFIG_ACPI=y +CONFIG_ACPI_EFI=y +CONFIG_ACPI_BOOT=y +CONFIG_ACPI_BUS=y +CONFIG_ACPI_INTERPRETER=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=y +CONFIG_ACPI_PROCESSOR=y +# CONFIG_ACPI_THERMAL is not set +# CONFIG_ACPI_DEBUG is not set +CONFIG_PCI=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_STATS=y + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_BOOT=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA100=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_SC1200=y +# CONFIG_BLK_DEV_SVWKS is not set +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_PDC202XX=y +CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_BLK_DEV_ATARAID_SII is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_DEBUG_QUEUES=y +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +CONFIG_SCSI_AIC79XX=y +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_BUILD_FIRMWARE is not set +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_QLA2100 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +CONFIG_SCSI_NSP32=m +# CONFIG_SCSI_DEBUG is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +CONFIG_AMD8111_ETH=m +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TLAN is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_R8169=m +# CONFIG_SK98LIN is not set +# CONFIG_NET_BROADCOM is not set +CONFIG_TIGON3=y +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +CONFIG_INPUT=y +CONFIG_INPUT_KEYBDEV=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_HCDP=y +# CONFIG_SERIAL_ACPI is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +CONFIG_INPUT_SERIO=m +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_KCS=m +CONFIG_IPMI_WATCHDOG=m + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_PM_MYRINET=m +CONFIG_ETHERPM_RWCP=m +CONFIG_ETHERPM_NUNITS=4 +CONFIG_ETHERPM_INTRRP=y +CONFIG_PM_SHMEM=m +CONFIG_PM_MEMORY=y +# CONFIG_PM_RHiNET is not set +# CONFIG_SCx200_GPIO is not set +# CONFIG_INTEL_RNG is not set +CONFIG_AMD_PM768=m +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_EFI_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +# CONFIG_AGP_INTEL is not set +# CONFIG_AGP_I810 is not set +# CONFIG_AGP_VIA is not set +# CONFIG_AGP_AMD is not set +# CONFIG_AGP_AMD_8151 is not set +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_ALI is not set +# CONFIG_AGP_SWORKS is not set +# CONFIG_AGP_I460 is not set +CONFIG_AGP_HP_ZX1=y +CONFIG_DRM=y +CONFIG_DRM_OLD=y + +# +# DRM 4.0 drivers +# +CONFIG_DRM40_TDFX=y +# CONFIG_DRM40_GAMMA is not set +# CONFIG_DRM40_R128 is not set +# CONFIG_DRM40_RADEON is not set +# CONFIG_DRM40_I810 is not set +# CONFIG_DRM40_MGA is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +CONFIG_EXT3_FS=m +CONFIG_JBD=m +CONFIG_JBD_DEBUG=y +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +# CONFIG_HUGETLBFS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_TCP is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +CONFIG_USB_OHCI=y + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_MIDI is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_DEBUG is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set + +# +# Library routines +# +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +# CONFIG_IA64_GRANULE_16MB is not set +CONFIG_IA64_GRANULE_64MB=y +CONFIG_DEBUG_KERNEL=y +CONFIG_IA64_PRINT_HAZARDS=y +# CONFIG_DISABLE_VHPT is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_IA64_EARLY_PRINTK=y +CONFIG_IA64_EARLY_PRINTK_UART=y +CONFIG_IA64_EARLY_PRINTK_UART_BASE=0 +# CONFIG_IA64_EARLY_PRINTK_VGA is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/Config.help linux2.4.21_itanium/drivers/acpi/Config.help --- linux2.4.21_itanium.org/drivers/acpi/Config.help Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/Config.help Wed Jul 23 18:28:09 2003 @@ -0,0 +1,93 @@ +CONFIG_ACPI_ENABLE + Advanced Configuration and Power Interface (ACPI) support for + Linux requires an ACPI compliant platform (hardware/firmware), + and assumes the presence of OS-directed configuration and power + management (OSPM) software. This option will enlarge your + kernel by about 70K. + + Linux ACPI provides a robust functional replacement for several + legacy configuration and power management intefaces, including + the Plug-and-Play BIOS specification (PnP BIOS), the + MultiProcessor Specification (MPS), and the Advanced Power + Management (APM) specification. If both ACPI and APM support + are configured, whichever is loaded first shall be used. + + Add "acpi=off" to the kernel command line to disable this feature. + (Try "man bootparam" or see the documentation of your boot loader + about how to pass options to the kernel at boot time.) + + Add "acpi=ht-only" to the kernel command line to limit ACPI + support to processor enumeration only (see CONFIG_ACPI_HT_ONLY). + + ---------- + + The ACPI SourceForge project contains the latest source code, + documentation, tools, mailing list subscription, and other + information. This project is available at: + + + Linux support for ACPI is based on Intel Corporation's ACPI + Component Architecture (ACPI CA). For more information see: + + + ACPI is an open industry specification co-developed by Compaq, + Intel, Microsoft, Phoenix, and Toshiba. The specification is + available at: + + +CONFIG_ACPI_HT_ONLY + This option enables limited ACPI support -- just enough to + enumerate processors from the ACPI Multiple APIC Description + Table (MADT). Note that ACPI supports both logical (e.g. Hyper- + Threading) and physical processors, where the MultiProcessor + Specification (MPS) table only supports physical processors. + + Full ACPI support (CONFIG_ACPI) is preferred. Use this option + only if you wish to limit ACPI's role to processor enumeration. + +CONFIG_ACPI_AC + This driver adds support for the AC Adapter object, which indicates + whether a system is on AC, or not. Typically, only mobile systems + have this object, since desktops are always on AC. + +CONFIG_ACPI_BATTERY + This driver adds support for battery information through + /proc/acpi/battery. If you have a mobile system with a battery, + say Y. + +CONFIG_ACPI_BUTTON + This driver registers for events based on buttons, such as the + power, sleep, and lid switch. In the future, a daemon will read + /proc/acpi/event and perform user-defined actions such as shutting + down the system. Until then, you can cat it, and see output when + a button is pressed. + +CONFIG_ACPI_EC + This driver is required on some systems for the proper operation of + the battery and thermal drivers. If you are compiling for a + mobile system, say Y. + +CONFIG_ACPI_PROCESSOR + This driver installs ACPI as the idle handler for Linux, and uses + ACPI C2 and C3 processor states to save power, on systems that + support it. + +CONFIG_ACPI_THERMAL + This driver adds support for ACPI thermal zones. Most mobile and + some desktop systems support ACPI thermal zones. It is HIGHLY + recommended that this option be enabled, as your processor(s) + may be damaged without it. + +CONFIG_ACPI_FAN + This driver adds support for ACPI fan devices, allowing user-mode + applications to perform basic fan control (on, off, status). + +CONFIG_ACPI_SYSTEM + This driver will enable your system to shut down using ACPI, and + dump your ACPI DSDT table using /proc/acpi/dsdt. + +CONFIG_ACPI_DEBUG + The ACPI driver can optionally report errors with a great deal + of verbosity. Saying Y enables these statements. This will increase + your kernel size by around 50K. + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/Config.in linux2.4.21_itanium/drivers/acpi/Config.in --- linux2.4.21_itanium.org/drivers/acpi/Config.in Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/Config.in Wed Jul 23 18:28:08 2003 @@ -1,17 +1,126 @@ # -# ACPI configuration +# ACPI Configuration # -#mainmenu_option next_comment -#comment 'ACPI Configuration' -dep_bool ' ACPI Debug Statements' CONFIG_ACPI_DEBUG $CONFIG_ACPI -dep_tristate ' ACPI Bus Manager' CONFIG_ACPI_BUSMGR $CONFIG_ACPI +if [ "$CONFIG_X86" = "y" ]; then -dep_tristate ' System' CONFIG_ACPI_SYS $CONFIG_ACPI_BUSMGR $CONFIG_ACPI -dep_tristate ' Processor' CONFIG_ACPI_CPU $CONFIG_ACPI_BUSMGR $CONFIG_ACPI -dep_tristate ' Button' CONFIG_ACPI_BUTTON $CONFIG_ACPI_BUSMGR $CONFIG_ACPI -dep_tristate ' AC Adapter' CONFIG_ACPI_AC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI -dep_tristate ' Embedded Controller' CONFIG_ACPI_EC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI -dep_tristate ' Control Method Battery' CONFIG_ACPI_CMBATT $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC -dep_tristate ' Thermal' CONFIG_ACPI_THERMAL $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC -#endmenu + mainmenu_option next_comment + comment 'ACPI Support' + + if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then + choice 'ACPI Support' \ + "Enable CONFIG_ACPI_ENABLE \ + HyperThreading-Only CONFIG_ACPI_HT_ONLY \ + Disable CONFIG_ACPI_DISABLE" Disable + else + choice 'ACPI Support' \ + "Enable CONFIG_ACPI_ENABLE \ + Disable CONFIG_ACPI_DISABLE" Disable + fi + + if [ "$CONFIG_ACPI_ENABLE" = "y" ]; then + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS y + define_bool CONFIG_ACPI_INTERPRETER y + define_bool CONFIG_ACPI_EC y + define_bool CONFIG_ACPI_POWER y + if [ "$CONFIG_PCI" = "y" ]; then + define_bool CONFIG_ACPI_PCI y + fi + define_bool CONFIG_ACPI_SLEEP y + define_bool CONFIG_ACPI_SYSTEM y + tristate ' AC Adapter' CONFIG_ACPI_AC + tristate ' Battery' CONFIG_ACPI_BATTERY + tristate ' Button' CONFIG_ACPI_BUTTON + tristate ' Fan' CONFIG_ACPI_FAN + tristate ' Processor' CONFIG_ACPI_PROCESSOR + dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR + bool ' Debug Statements' CONFIG_ACPI_DEBUG + fi + + if [ "$CONFIG_ACPI_HT_ONLY" = "y" ]; then + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS n + define_bool CONFIG_ACPI_INTERPRETER n + define_bool CONFIG_ACPI_EC n + define_bool CONFIG_ACPI_PCI n + define_bool CONFIG_ACPI_POWER n + define_bool CONFIG_ACPI_SYSTEM n + define_bool CONFIG_ACPI_SLEEP n + define_bool CONFIG_ACPI_AC n + define_bool CONFIG_ACPI_BATTERY n + define_bool CONFIG_ACPI_BUTTON n + define_bool CONFIG_ACPI_FAN n + define_bool CONFIG_ACPI_PROCESSOR n + define_bool CONFIG_ACPI_THERMAL n + define_bool CONFIG_ACPI_DEBUG n + fi + + if [ "$CONFIG_ACPI_DISABLE" = "y" ]; then + define_bool CONFIG_ACPI n + define_bool CONFIG_ACPI_BOOT n + define_bool CONFIG_ACPI_BUS n + define_bool CONFIG_ACPI_INTERPRETER n + define_bool CONFIG_ACPI_EC n + define_bool CONFIG_ACPI_PCI n + define_bool CONFIG_ACPI_POWER n + define_bool CONFIG_ACPI_SYSTEM n + define_bool CONFIG_ACPI_SLEEP n + define_bool CONFIG_ACPI_AC n + define_bool CONFIG_ACPI_BATTERY n + define_bool CONFIG_ACPI_BUTTON n + define_bool CONFIG_ACPI_FAN n + define_bool CONFIG_ACPI_PROCESSOR n + define_bool CONFIG_ACPI_THERMAL n + define_bool CONFIG_ACPI_DEBUG n + fi + + endmenu + +fi + + +if [ "$CONFIG_IA64" = "y" ]; then + + if [ "$CONFIG_IA64_SGI_SN" = "y" ]; then + mainmenu_option next_comment + comment 'ACPI Support' + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_EFI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS n + define_bool CONFIG_ACPI_INTERPRETER n + define_bool CONFIG_ACPI_PCI n + define_bool CONFIG_ACPI_POWER n + define_bool CONFIG_ACPI_SYSTEM n + define_bool CONFIG_ACPI_BUTTON n + define_bool CONFIG_ACPI_FAN n + define_bool CONFIG_ACPI_PROCESSOR n + define_bool CONFIG_ACPI_THERMAL n + endmenu + fi + + if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + mainmenu_option next_comment + comment 'ACPI Support' + if [ "$CONFIG_PCI" = "y" ]; then + define_bool CONFIG_ACPI_PCI y + fi + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_EFI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS y + define_bool CONFIG_ACPI_INTERPRETER y + define_bool CONFIG_ACPI_POWER y + define_bool CONFIG_ACPI_SYSTEM y + tristate ' Button' CONFIG_ACPI_BUTTON + tristate ' Fan' CONFIG_ACPI_FAN + tristate ' Processor' CONFIG_ACPI_PROCESSOR + dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR + bool ' Debug Statements' CONFIG_ACPI_DEBUG + endmenu + fi + +fi diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/Makefile linux2.4.21_itanium/drivers/acpi/Makefile --- linux2.4.21_itanium.org/drivers/acpi/Makefile Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/Makefile Wed Jul 23 18:28:08 2003 @@ -4,51 +4,52 @@ O_TARGET := acpi.o -export-objs := acpi_ksyms.o - export ACPI_CFLAGS -ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include - -# -# CONFIG_ACPI_KERNEL_CONFIG is currently only IA64 -# -ifdef CONFIG_ACPI_KERNEL_CONFIG - ACPI_CFLAGS += -DCONFIG_ACPI_KERNEL_CONFIG_ONLY -endif - -acpi-subdirs := utilities dispatcher events hardware \ - executer namespace parser resources tables +ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include ifdef CONFIG_ACPI_DEBUG - ACPI_CFLAGS += -DACPI_DEBUG -Wno-unused -endif - -ifdef CONFIG_ACPI_DEBUGGER - ACPI_CFLAGS += -DENABLE_DEBUGGER - acpi-subdirs += debugger + ACPI_CFLAGS += -DACPI_DEBUG endif -EXTRA_CFLAGS += $(ACPI_CFLAGS) +EXTRA_CFLAGS += $(ACPI_CFLAGS) -mod-subdirs := ospm +export-objs := acpi_ksyms.o -subdir-$(CONFIG_ACPI) += $(acpi-subdirs) -subdir-$(CONFIG_ACPI_BUSMGR) += ospm +obj-y := acpi_ksyms.o -obj-$(CONFIG_ACPI) += driver.o os.o acpi_ksyms.o -obj-$(CONFIG_ACPI) += $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o) -ifdef CONFIG_ACPI_KERNEL_CONFIG - obj-$(CONFIG_ACPI) += acpiconf.o osconf.o +# +# ACPI Boot-Time Table Parsing +# +ifeq ($(CONFIG_ACPI_BOOT),y) + obj-y += tables.o endif -ifeq ($(CONFIG_ACPI_BUSMGR),y) - obj-y += ospm/ospm.o +# +# ACPI Core Subsystem (Interpreter) +# +ifeq ($(CONFIG_ACPI_INTERPRETER),y) + obj-y += osl.o utils.o + subdir-y += dispatcher events executer hardware namespace parser \ + resources tables utilities + obj-y += $(foreach dir,$(subdir-y),$(dir)/$(dir).o) endif -# commented out until we distribute it -ASG -#ifeq ($(CONFIG_KDB),y) -# obj-m += kdb/kdbm_acpi.o -#endif +# +# ACPI Bus and Device Drivers +# +ifeq ($(CONFIG_ACPI_BUS),y) + obj-y += bus.o + obj-$(CONFIG_ACPI_AC) += ac.o + obj-$(CONFIG_ACPI_BATTERY) += battery.o + obj-$(CONFIG_ACPI_BUTTON) += button.o + obj-$(CONFIG_ACPI_EC) += ec.o + obj-$(CONFIG_ACPI_FAN) += fan.o + obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o + obj-$(CONFIG_ACPI_POWER) += power.o + obj-$(CONFIG_ACPI_PROCESSOR) += processor.o + obj-$(CONFIG_ACPI_THERMAL) += thermal.o + obj-$(CONFIG_ACPI_SYSTEM) += system.o +endif include $(TOPDIR)/Rules.make diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/ac.c linux2.4.21_itanium/drivers/acpi/ac.c --- linux2.4.21_itanium.org/drivers/acpi/ac.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/ac.c Wed Jul 23 18:28:09 2003 @@ -0,0 +1,352 @@ +/* + * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_AC_COMPONENT +ACPI_MODULE_NAME ("acpi_ac") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +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, + }, +}; + +struct acpi_ac { + acpi_handle handle; + unsigned long state; +}; + + +/* -------------------------------------------------------------------------- + AC Adapter Management + -------------------------------------------------------------------------- */ + +static int +acpi_ac_get_state ( + struct acpi_ac *ac) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_ac_get_state"); + + if (!ac) + return_VALUE(-EINVAL); + + status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading AC Adapter state\n")); + ac->state = ACPI_AC_STATUS_UNKNOWN; + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#include +#include + +struct proc_dir_entry *acpi_ac_dir = NULL; + +static int +acpi_ac_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_read_state"); + + if (!ac || (off != 0)) + goto end; + + if (0 != acpi_ac_get_state(ac)) { + p += sprintf(p, "ERROR: Unable to read AC Adapter state\n"); + goto end; + } + + p += sprintf(p, "state: "); + switch (ac->state) { + case ACPI_AC_STATUS_OFFLINE: + p += sprintf(p, "off-line\n"); + break; + case ACPI_AC_STATUS_ONLINE: + p += sprintf(p, "on-line\n"); + break; + default: + p += sprintf(p, "unknown\n"); + break; + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_ac_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add_fs"); + + if (!acpi_ac_dir) { + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_ac_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'state' [R] */ + entry = create_proc_entry(ACPI_AC_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_AC_FILE_STATE)); + else { + entry->read_proc = acpi_ac_read_state; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_ac_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); + + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Model + -------------------------------------------------------------------------- */ + +void +acpi_ac_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_notify"); + + if (!ac) + return; + + if (0 != acpi_bus_get_device(ac->handle, &device)) + return_VOID; + + switch (event) { + case ACPI_AC_NOTIFY_STATUS: + acpi_ac_get_state(ac); + acpi_bus_generate_event(device, event, (u32) ac->state); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +int +acpi_ac_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add"); + + if (!device) + return_VALUE(-EINVAL); + + ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL); + if (!ac) + return_VALUE(-ENOMEM); + memset(ac, 0, sizeof(struct acpi_ac)); + + ac->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_AC_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_AC_CLASS); + acpi_driver_data(device) = ac; + + result = acpi_ac_get_state(ac); + if (0 != result) + goto end; + + result = acpi_ac_add_fs(device); + if (0 != result) + goto end; + + status = acpi_install_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), + ac->state?"on-line":"off-line"); + +end: + if (0 != result) { + acpi_ac_remove_fs(device); + kfree(ac); + } + + return_VALUE(result); +} + + +int +acpi_ac_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + ac = (struct acpi_ac *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_ac_remove_fs(device); + + kfree(ac); + + return_VALUE(0); +} + + +int __init +acpi_ac_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_init"); + + result = acpi_bus_register_driver(&acpi_ac_driver); + if (0 > result) { + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_ac_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_exit"); + + result = acpi_bus_unregister_driver(&acpi_ac_driver); + if (0 == result) + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_ac_init); +module_exit(acpi_ac_exit); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/acpi_bus.h linux2.4.21_itanium/drivers/acpi/acpi_bus.h --- linux2.4.21_itanium.org/drivers/acpi/acpi_bus.h Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/acpi_bus.h Wed Jul 23 18:28:09 2003 @@ -0,0 +1,321 @@ +/* + * acpi_bus.h - ACPI Bus Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 __ACPI_BUS_H__ +#define __ACPI_BUS_H__ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,4)) +#include +#define CONFIG_LDM +#endif + +#include "include/acpi.h" + + +/* TBD: Make dynamic */ +#define ACPI_MAX_HANDLES 10 +struct acpi_handle_list { + u32 count; + acpi_handle handles[ACPI_MAX_HANDLES]; +}; + + +/* acpi_utils.h */ +acpi_status acpi_extract_package (acpi_object *, acpi_buffer *, acpi_buffer *); +acpi_status acpi_evaluate (acpi_handle, acpi_string, acpi_object_list *, acpi_buffer *); +acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, unsigned long *); +acpi_status acpi_evaluate_reference (acpi_handle, acpi_string, acpi_object_list *, struct acpi_handle_list *); + + +#ifdef CONFIG_ACPI_BUS + +#include + +#define ACPI_BUS_FILE_ROOT "acpi" +extern struct proc_dir_entry *acpi_root_dir; +extern FADT_DESCRIPTOR acpi_fadt; + +enum acpi_bus_removal_type { + ACPI_BUS_REMOVAL_NORMAL = 0, + ACPI_BUS_REMOVAL_EJECT, + ACPI_BUS_REMOVAL_SUPRISE, + ACPI_BUS_REMOVAL_TYPE_COUNT +}; + +enum acpi_bus_device_type { + ACPI_BUS_TYPE_DEVICE = 0, + ACPI_BUS_TYPE_POWER, + ACPI_BUS_TYPE_PROCESSOR, + ACPI_BUS_TYPE_THERMAL, + ACPI_BUS_TYPE_SYSTEM, + ACPI_BUS_TYPE_POWER_BUTTON, + ACPI_BUS_TYPE_SLEEP_BUTTON, + ACPI_BUS_DEVICE_TYPE_COUNT +}; + +struct acpi_driver; +struct acpi_device; + + +/* + * ACPI Driver + * ----------- + */ + +typedef int (*acpi_op_add) (struct acpi_device *device); +typedef int (*acpi_op_remove) (struct acpi_device *device, int type); +typedef int (*acpi_op_lock) (struct acpi_device *device, int type); +typedef int (*acpi_op_start) (struct acpi_device *device); +typedef int (*acpi_op_stop) (struct acpi_device *device, int type); +typedef int (*acpi_op_suspend) (struct acpi_device *device, int state); +typedef int (*acpi_op_resume) (struct acpi_device *device, int state); +typedef int (*acpi_op_scan) (struct acpi_device *device); +typedef int (*acpi_op_bind) (struct acpi_device *device); + +struct acpi_device_ops { + acpi_op_add add; + acpi_op_remove remove; + acpi_op_lock lock; + acpi_op_start start; + acpi_op_stop stop; + acpi_op_suspend suspend; + acpi_op_resume resume; + acpi_op_scan scan; + acpi_op_bind bind; +}; + +struct acpi_driver { + struct list_head node; + char name[80]; + char class[80]; + int references; + char *ids; /* Supported Hardware IDs */ + struct acpi_device_ops ops; +}; + +enum acpi_blacklist_predicates +{ + all_versions, + less_than_or_equal, + equal, + greater_than_or_equal, +}; + +struct acpi_blacklist_item +{ + char oem_id[7]; + char oem_table_id[9]; + u32 oem_revision; + acpi_table_type table; + enum acpi_blacklist_predicates oem_revision_predicate; + char *reason; + u32 is_critical_error; +}; + + +/* + * ACPI Device + * ----------- + */ + +/* Status (_STA) */ + +struct acpi_device_status { + u32 present:1; + u32 enabled:1; + u32 show_in_ui:1; + u32 functional:1; + u32 battery_present:1; + u32 reserved:27; +}; + + +/* Flags */ + +struct acpi_device_flags { + u32 dynamic_status:1; + u32 hardware_id:1; + u32 compatible_ids:1; + u32 bus_address:1; + u32 unique_id:1; + u32 removable:1; + u32 ejectable:1; + u32 lockable:1; + u32 suprise_removal_ok:1; + u32 power_manageable:1; + u32 performance_manageable:1; + u32 reserved:21; +}; + + +/* File System */ + +struct acpi_device_dir { + struct proc_dir_entry *entry; +}; + +#define acpi_device_dir(d) ((d)->dir.entry) + + +/* Plug and Play */ + +typedef char acpi_bus_id[5]; +typedef unsigned long acpi_bus_address; +typedef char acpi_hardware_id[9]; +typedef char acpi_unique_id[9]; +typedef char acpi_device_name[40]; +typedef char acpi_device_class[20]; + +struct acpi_device_pnp { + acpi_bus_id bus_id; /* Object name */ + acpi_bus_address bus_address; /* _ADR */ + acpi_hardware_id hardware_id; /* _HID */ + acpi_unique_id unique_id; /* _UID */ + acpi_device_name device_name; /* Driver-determined */ + acpi_device_class device_class; /* " */ +}; + +#define acpi_device_bid(d) ((d)->pnp.bus_id) +#define acpi_device_adr(d) ((d)->pnp.bus_address) +#define acpi_device_hid(d) ((d)->pnp.hardware_id) +#define acpi_device_uid(d) ((d)->pnp.unique_id) +#define acpi_device_name(d) ((d)->pnp.device_name) +#define acpi_device_class(d) ((d)->pnp.device_class) + + +/* Power Management */ + +struct acpi_device_power_flags { + u32 explicit_get:1; /* _PSC present? */ + u32 power_resources:1; /* Power resources */ + u32 inrush_current:1; /* Serialize Dx->D0 */ + u32 wake_capable:1; /* Wakeup supported? */ + u32 wake_enabled:1; /* Enabled for wakeup */ + u32 power_removed:1; /* Optimize Dx->D0 */ + u32 reserved:26; +}; + +struct acpi_device_power_state { + struct { + u8 valid:1; + u8 explicit_set:1; /* _PSx present? */ + u8 reserved:6; + } flags; + int power; /* % Power (compared to D0) */ + int latency; /* Dx->D0 time (microseconds) */ + struct acpi_handle_list resources; /* Power resources referenced */ +}; + +struct acpi_device_power { + int state; /* Current state */ + struct acpi_device_power_flags flags; + struct acpi_device_power_state states[4]; /* Power states (D0-D3) */ +}; + + +/* Performance Management */ + +struct acpi_device_perf_flags { + u8 reserved:8; +}; + +struct acpi_device_perf_state { + struct { + u8 valid:1; + u8 reserved:7; + } flags; + u8 power; /* % Power (compared to P0) */ + u8 performance; /* % Performance ( " ) */ + int latency; /* Px->P0 time (microseconds) */ +}; + +struct acpi_device_perf { + int state; + struct acpi_device_perf_flags flags; + int state_count; + struct acpi_device_perf_state *states; +}; + + +/* Device */ + +struct acpi_device { + acpi_handle handle; + struct acpi_device *parent; + struct list_head children; + struct list_head node; + struct acpi_device_status status; + struct acpi_device_flags flags; + struct acpi_device_pnp pnp; + struct acpi_device_power power; + struct acpi_device_perf performance; + struct acpi_device_dir dir; + struct acpi_device_ops ops; + struct acpi_driver *driver; + void *driver_data; +#ifdef CONFIG_LDM + struct device dev; +#endif +}; + +#define acpi_driver_data(d) ((d)->driver_data) + + +/* + * Events + * ------ + */ + +struct acpi_bus_event { + struct list_head node; + acpi_device_class device_class; + acpi_bus_id bus_id; + u32 type; + u32 data; +}; + + +/* + * External Functions + */ + +int acpi_bus_get_device(acpi_handle, struct acpi_device **device); +int acpi_bus_get_status (struct acpi_device *device); +int acpi_bus_get_power (acpi_handle handle, int *state); +int acpi_bus_set_power (acpi_handle handle, int state); +int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data); +int acpi_bus_receive_event (struct acpi_bus_event *event); +int acpi_bus_register_driver (struct acpi_driver *driver); +int acpi_bus_unregister_driver (struct acpi_driver *driver); +int acpi_bus_scan (struct acpi_device *device); +int acpi_init (void); +void acpi_exit (void); + + +#endif /*CONFIG_ACPI_BUS*/ + +#endif /*__ACPI_BUS_H__*/ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/acpi_drivers.h linux2.4.21_itanium/drivers/acpi/acpi_drivers.h --- linux2.4.21_itanium.org/drivers/acpi/acpi_drivers.h Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/acpi_drivers.h Wed Jul 23 18:28:09 2003 @@ -0,0 +1,345 @@ +/* + * acpi_drivers.h ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 __ACPI_DRIVERS_H__ +#define __ACPI_DRIVERS_H__ + +#include +#include "acpi_bus.h" + + +#define ACPI_MAX_STRING 80 + + +/* -------------------------------------------------------------------------- + ACPI Bus + -------------------------------------------------------------------------- */ + +#define ACPI_BUS_COMPONENT 0x00010000 +#define ACPI_BUS_CLASS "system_bus" +#define ACPI_BUS_HID "ACPI_BUS" +#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver" +#define ACPI_BUS_DEVICE_NAME "System Bus" + + +/* -------------------------------------------------------------------------- + AC Adapter + -------------------------------------------------------------------------- */ + +#define ACPI_AC_COMPONENT 0x00020000 +#define ACPI_AC_CLASS "ac_adapter" +#define ACPI_AC_HID "ACPI0003" +#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver" +#define ACPI_AC_DEVICE_NAME "AC Adapter" +#define ACPI_AC_FILE_STATE "state" +#define ACPI_AC_NOTIFY_STATUS 0x80 +#define ACPI_AC_STATUS_OFFLINE 0x00 +#define ACPI_AC_STATUS_ONLINE 0x01 +#define ACPI_AC_STATUS_UNKNOWN 0xFF + + +/* -------------------------------------------------------------------------- + Battery + -------------------------------------------------------------------------- */ + +#define ACPI_BATTERY_COMPONENT 0x00040000 +#define ACPI_BATTERY_CLASS "battery" +#define ACPI_BATTERY_HID "PNP0C0A" +#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver" +#define ACPI_BATTERY_DEVICE_NAME "Battery" +#define ACPI_BATTERY_FILE_INFO "info" +#define ACPI_BATTERY_FILE_STATUS "state" +#define ACPI_BATTERY_FILE_ALARM "alarm" +#define ACPI_BATTERY_NOTIFY_STATUS 0x80 +#define ACPI_BATTERY_NOTIFY_INFO 0x81 +#define ACPI_BATTERY_UNITS_WATTS "mW" +#define ACPI_BATTERY_UNITS_AMPS "mA" + + +/* -------------------------------------------------------------------------- + Button + -------------------------------------------------------------------------- */ + +#define ACPI_BUTTON_COMPONENT 0x00080000 +#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" +#define ACPI_BUTTON_CLASS "button" +#define ACPI_BUTTON_FILE_INFO "info" +#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 +#define ACPI_BUTTON_NOTIFY_STATUS 0x80 + +#define ACPI_BUTTON_SUBCLASS_POWER "power" +#define ACPI_BUTTON_HID_POWER "PNP0C0C" +#define ACPI_BUTTON_HID_POWERF "ACPI_FPB" +#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)" +#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)" +#define ACPI_BUTTON_TYPE_POWER 0x01 +#define ACPI_BUTTON_TYPE_POWERF 0x02 + +#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" +#define ACPI_BUTTON_HID_SLEEP "PNP0C0E" +#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" +#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)" +#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)" +#define ACPI_BUTTON_TYPE_SLEEP 0x03 +#define ACPI_BUTTON_TYPE_SLEEPF 0x04 + +#define ACPI_BUTTON_SUBCLASS_LID "lid" +#define ACPI_BUTTON_HID_LID "PNP0C0D" +#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" +#define ACPI_BUTTON_TYPE_LID 0x05 + + +/* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ + +#define ACPI_EC_COMPONENT 0x00100000 +#define ACPI_EC_CLASS "embedded_controller" +#define ACPI_EC_HID "PNP0C09" +#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" +#define ACPI_EC_DEVICE_NAME "Embedded Controller" +#define ACPI_EC_FILE_INFO "info" + +#ifdef CONFIG_ACPI_EC + +int acpi_ec_init (void); +void acpi_ec_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Fan + -------------------------------------------------------------------------- */ + +#define ACPI_FAN_COMPONENT 0x00200000 +#define ACPI_FAN_CLASS "fan" +#define ACPI_FAN_HID "PNP0C0B" +#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver" +#define ACPI_FAN_DEVICE_NAME "Fan" +#define ACPI_FAN_FILE_STATE "state" +#define ACPI_FAN_NOTIFY_STATUS 0x80 + + +/* -------------------------------------------------------------------------- + PCI + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_PCI + +#define ACPI_PCI_COMPONENT 0x00400000 + +/* ACPI PCI Root Bridge (pci_root.c) */ + +#define ACPI_PCI_ROOT_CLASS "pci_bridge" +#define ACPI_PCI_ROOT_HID "PNP0A03" +#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver" +#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" + +int acpi_pci_root_init (void); +void acpi_pci_root_exit (void); + +/* ACPI PCI Interrupt Link (pci_link.c) */ + +#define ACPI_PCI_LINK_CLASS "pci_irq_routing" +#define ACPI_PCI_LINK_HID "PNP0C0F" +#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" +#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" +#define ACPI_PCI_LINK_FILE_INFO "info" +#define ACPI_PCI_LINK_FILE_STATUS "state" + +int acpi_pci_link_check (void); +int acpi_pci_link_get_irq (acpi_handle handle, int index); +int acpi_pci_link_init (void); +void acpi_pci_link_exit (void); + +/* ACPI PCI Interrupt Routing (pci_irq.c) */ + +int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus); + +/* ACPI PCI Device Binding (pci_bind.c) */ + +struct pci_bus; + +int acpi_pci_bind (struct acpi_device *device); +int acpi_pci_bind_root (struct acpi_device *device, acpi_pci_id *id, struct pci_bus *bus); + +#endif /*CONFIG_ACPI_PCI*/ + + +/* -------------------------------------------------------------------------- + Power Resource + -------------------------------------------------------------------------- */ + +#define ACPI_POWER_COMPONENT 0x00800000 +#define ACPI_POWER_CLASS "power_resource" +#define ACPI_POWER_HID "ACPI_PWR" +#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver" +#define ACPI_POWER_DEVICE_NAME "Power Resource" +#define ACPI_POWER_FILE_INFO "info" +#define ACPI_POWER_FILE_STATUS "state" +#define ACPI_POWER_RESOURCE_STATE_OFF 0x00 +#define ACPI_POWER_RESOURCE_STATE_ON 0x01 +#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF + +#ifdef CONFIG_ACPI_POWER + +int acpi_power_get_inferred_state (struct acpi_device *device); +int acpi_power_transition (struct acpi_device *device, int state); +int acpi_power_init (void); +void acpi_power_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Processor + -------------------------------------------------------------------------- */ + +#define ACPI_PROCESSOR_COMPONENT 0x01000000 +#define ACPI_PROCESSOR_CLASS "processor" +#define ACPI_PROCESSOR_HID "ACPI_CPU" +#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" +#define ACPI_PROCESSOR_DEVICE_NAME "Processor" +#define ACPI_PROCESSOR_FILE_INFO "info" +#define ACPI_PROCESSOR_FILE_POWER "power" +#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" +#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" +#define ACPI_PROCESSOR_FILE_LIMIT "limit" +#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 +#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 +#define ACPI_PROCESSOR_LIMIT_NONE 0x00 +#define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01 +#define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02 + +int acpi_processor_set_thermal_limit(acpi_handle handle, int type); + + +/* -------------------------------------------------------------------------- + System + -------------------------------------------------------------------------- */ + +#define ACPI_SYSTEM_COMPONENT 0x02000000 +#define ACPI_SYSTEM_CLASS "system" +#define ACPI_SYSTEM_HID "ACPI_SYS" +#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" +#define ACPI_SYSTEM_DEVICE_NAME "System" +#define ACPI_SYSTEM_FILE_INFO "info" +#define ACPI_SYSTEM_FILE_EVENT "event" +#define ACPI_SYSTEM_FILE_ALARM "alarm" +#define ACPI_SYSTEM_FILE_DSDT "dsdt" +#define ACPI_SYSTEM_FILE_FADT "fadt" +#define ACPI_SYSTEM_FILE_SLEEP "sleep" +#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" +#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" + +#ifdef CONFIG_ACPI_SYSTEM + +int acpi_system_init (void); +void acpi_system_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Thermal Zone + -------------------------------------------------------------------------- */ + +#define ACPI_THERMAL_COMPONENT 0x04000000 +#define ACPI_THERMAL_CLASS "thermal_zone" +#define ACPI_THERMAL_HID "ACPI_THM" +#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" +#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" +#define ACPI_THERMAL_FILE_STATE "state" +#define ACPI_THERMAL_FILE_TEMPERATURE "temperature" +#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points" +#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode" +#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency" +#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80 +#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81 +#define ACPI_THERMAL_NOTIFY_DEVICES 0x82 +#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 +#define ACPI_THERMAL_NOTIFY_HOT 0xF1 +#define ACPI_THERMAL_MODE_ACTIVE 0x00 +#define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" + + +/* -------------------------------------------------------------------------- + Debug Support + -------------------------------------------------------------------------- */ + +#define ACPI_DEBUG_RESTORE 0 +#define ACPI_DEBUG_LOW 1 +#define ACPI_DEBUG_MEDIUM 2 +#define ACPI_DEBUG_HIGH 3 +#define ACPI_DEBUG_DRIVERS 4 + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + +static inline void +acpi_set_debug ( + u32 flag) +{ + static u32 layer_save; + static u32 level_save; + + switch (flag) { + case ACPI_DEBUG_RESTORE: + acpi_dbg_layer = layer_save; + acpi_dbg_level = level_save; + break; + case ACPI_DEBUG_LOW: + case ACPI_DEBUG_MEDIUM: + case ACPI_DEBUG_HIGH: + case ACPI_DEBUG_DRIVERS: + layer_save = acpi_dbg_layer; + level_save = acpi_dbg_level; + break; + } + + switch (flag) { + case ACPI_DEBUG_LOW: + acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; + acpi_dbg_level = DEBUG_DEFAULT; + break; + case ACPI_DEBUG_MEDIUM: + acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; + acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS; + break; + case ACPI_DEBUG_HIGH: + acpi_dbg_layer = 0xFFFFFFFF; + acpi_dbg_level = 0xFFFFFFFF; + break; + case ACPI_DEBUG_DRIVERS: + acpi_dbg_layer = ACPI_ALL_DRIVERS; + acpi_dbg_level = 0xFFFFFFFF; + break; + } +} + + +#endif /*__ACPI_DRIVERS_H__*/ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/acpi_ksyms.c linux2.4.21_itanium/drivers/acpi/acpi_ksyms.c --- linux2.4.21_itanium.org/drivers/acpi/acpi_ksyms.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/acpi_ksyms.c Wed Jul 23 18:28:08 2003 @@ -1,64 +1,58 @@ /* - * ksyms.c - ACPI exported symbols + * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 1.1.1.2 $) * - * Copyright (C) 2000 Andrew Grover + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or 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. + * 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 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 #include -#include -#include -#include -#include -#include "acpi.h" -#include "acdebug.h" +#include "include/acpi.h" +#include "acpi_bus.h" -extern int acpi_in_debugger; -extern FADT_DESCRIPTOR acpi_fadt; -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("symbols") +#ifdef CONFIG_ACPI_INTERPRETER + +/* ACPI Debugger */ #ifdef ENABLE_DEBUGGER + +extern int acpi_in_debugger; + EXPORT_SYMBOL(acpi_in_debugger); EXPORT_SYMBOL(acpi_db_user_commands); -#endif + +#endif /* ENABLE_DEBUGGER */ + +/* ACPI Core Subsystem */ #ifdef ACPI_DEBUG +EXPORT_SYMBOL(acpi_dbg_layer); +EXPORT_SYMBOL(acpi_dbg_level); EXPORT_SYMBOL(acpi_ut_debug_print_raw); EXPORT_SYMBOL(acpi_ut_debug_print); EXPORT_SYMBOL(acpi_ut_status_exit); +EXPORT_SYMBOL(acpi_ut_value_exit); EXPORT_SYMBOL(acpi_ut_exit); EXPORT_SYMBOL(acpi_ut_trace); -#endif - -EXPORT_SYMBOL(acpi_gbl_FADT); - -EXPORT_SYMBOL(acpi_os_free); -EXPORT_SYMBOL(acpi_os_printf); -EXPORT_SYMBOL(acpi_os_callocate); -EXPORT_SYMBOL(acpi_os_sleep); -EXPORT_SYMBOL(acpi_os_stall); -EXPORT_SYMBOL(acpi_os_queue_for_execution); - -EXPORT_SYMBOL(acpi_dbg_layer); -EXPORT_SYMBOL(acpi_dbg_level); - -EXPORT_SYMBOL(acpi_format_exception); +#endif /*ACPI_DEBUG*/ EXPORT_SYMBOL(acpi_get_handle); EXPORT_SYMBOL(acpi_get_parent); @@ -69,7 +63,6 @@ EXPORT_SYMBOL(acpi_evaluate_object); EXPORT_SYMBOL(acpi_get_table); EXPORT_SYMBOL(acpi_get_firmware_table); - EXPORT_SYMBOL(acpi_install_notify_handler); EXPORT_SYMBOL(acpi_remove_notify_handler); EXPORT_SYMBOL(acpi_install_gpe_handler); @@ -78,40 +71,62 @@ EXPORT_SYMBOL(acpi_remove_address_space_handler); EXPORT_SYMBOL(acpi_install_fixed_event_handler); EXPORT_SYMBOL(acpi_remove_fixed_event_handler); - EXPORT_SYMBOL(acpi_acquire_global_lock); EXPORT_SYMBOL(acpi_release_global_lock); - EXPORT_SYMBOL(acpi_get_current_resources); EXPORT_SYMBOL(acpi_get_possible_resources); +EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_set_current_resources); - EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); - EXPORT_SYMBOL(acpi_get_timer_duration); EXPORT_SYMBOL(acpi_get_timer); +EXPORT_SYMBOL(acpi_get_sleep_type_data); +EXPORT_SYMBOL(acpi_get_register); +EXPORT_SYMBOL(acpi_set_register); +EXPORT_SYMBOL(acpi_enter_sleep_state); +EXPORT_SYMBOL(acpi_get_system_info); +EXPORT_SYMBOL(acpi_walk_namespace); + +/* ACPI OS Services Layer (acpi_osl.c) */ +EXPORT_SYMBOL(acpi_os_free); +EXPORT_SYMBOL(acpi_os_printf); +EXPORT_SYMBOL(acpi_os_sleep); +EXPORT_SYMBOL(acpi_os_stall); +EXPORT_SYMBOL(acpi_os_signal); +EXPORT_SYMBOL(acpi_os_queue_for_execution); EXPORT_SYMBOL(acpi_os_signal_semaphore); EXPORT_SYMBOL(acpi_os_create_semaphore); EXPORT_SYMBOL(acpi_os_delete_semaphore); EXPORT_SYMBOL(acpi_os_wait_semaphore); -EXPORT_SYMBOL(acpi_os_read_port); -EXPORT_SYMBOL(acpi_os_write_port); +/* ACPI Utilities (acpi_utils.c) */ + +EXPORT_SYMBOL(acpi_extract_package); +EXPORT_SYMBOL(acpi_evaluate); +EXPORT_SYMBOL(acpi_evaluate_integer); +EXPORT_SYMBOL(acpi_evaluate_reference); + +#endif /*CONFIG_ACPI_INTERPRETER*/ + +/* ACPI Bus Driver (acpi_bus.c) */ + +#ifdef CONFIG_ACPI_BUS + EXPORT_SYMBOL(acpi_fadt); -EXPORT_SYMBOL(acpi_hw_register_bit_access); -EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data); -EXPORT_SYMBOL(acpi_enter_sleep_state); -EXPORT_SYMBOL(acpi_get_system_info); -EXPORT_SYMBOL(acpi_leave_sleep_state); -EXPORT_SYMBOL(acpi_walk_namespace); -/*EXPORT_SYMBOL(acpi_save_state_mem);*/ -/*EXPORT_SYMBOL(acpi_save_state_disk);*/ -EXPORT_SYMBOL(acpi_hw_register_read); -EXPORT_SYMBOL(acpi_set_firmware_waking_vector); -EXPORT_SYMBOL(acpi_subsystem_status); +EXPORT_SYMBOL(acpi_root_dir); +EXPORT_SYMBOL(acpi_bus_get_device); +EXPORT_SYMBOL(acpi_bus_get_status); +EXPORT_SYMBOL(acpi_bus_get_power); +EXPORT_SYMBOL(acpi_bus_set_power); +EXPORT_SYMBOL(acpi_bus_generate_event); +EXPORT_SYMBOL(acpi_bus_receive_event); +EXPORT_SYMBOL(acpi_bus_register_driver); +EXPORT_SYMBOL(acpi_bus_unregister_driver); +EXPORT_SYMBOL(acpi_bus_scan); +EXPORT_SYMBOL(acpi_init); -EXPORT_SYMBOL(acpi_os_signal); +#endif /*CONFIG_ACPI_BUS*/ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/battery.c linux2.4.21_itanium/drivers/acpi/battery.c --- linux2.4.21_itanium.org/drivers/acpi/battery.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/battery.c Wed Jul 23 18:28:09 2003 @@ -0,0 +1,831 @@ +/* + * acpi_battery.c - ACPI Battery Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BATTERY_COMPONENT +ACPI_MODULE_NAME ("acpi_battery") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF + +#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" +#define ACPI_BATTERY_FORMAT_BST "NNNN" + +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, + }, +}; + +struct acpi_battery_status { + acpi_integer state; + acpi_integer present_rate; + acpi_integer remaining_capacity; + acpi_integer present_voltage; +}; + +struct acpi_battery_info { + acpi_integer power_unit; + acpi_integer design_capacity; + acpi_integer last_full_capacity; + acpi_integer battery_technology; + acpi_integer design_voltage; + acpi_integer design_capacity_warning; + acpi_integer design_capacity_low; + acpi_integer battery_capacity_granularity_1; + acpi_integer battery_capacity_granularity_2; + acpi_string model_number; + acpi_string serial_number; + acpi_string battery_type; + acpi_string oem_info; +}; + +struct acpi_battery_flags { + u8 present:1; /* Bay occupied? */ + u8 power_unit:1; /* 0=watts, 1=apms */ + u8 alarm:1; /* _BTP present? */ + u8 reserved:5; +}; + +struct acpi_battery_trips { + unsigned long warning; + unsigned long low; +}; + +struct acpi_battery { + acpi_handle handle; + struct acpi_battery_flags flags; + struct acpi_battery_trips trips; + unsigned long alarm; + struct acpi_battery_info *info; +}; + + +/* -------------------------------------------------------------------------- + Battery Management + -------------------------------------------------------------------------- */ + +static int +acpi_battery_get_info ( + struct acpi_battery *battery, + struct acpi_battery_info **bif) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), + ACPI_BATTERY_FORMAT_BIF}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_info"); + + if (!battery || !bif) + return_VALUE(-EINVAL); + + /* Evalute _BIF */ + + status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + kfree(buffer.pointer); + + if (0 == result) + (*bif) = (struct acpi_battery_info *) data.pointer; + + return_VALUE(result); +} + +static int +acpi_battery_get_status ( + struct acpi_battery *battery, + struct acpi_battery_status **bst) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), + ACPI_BATTERY_FORMAT_BST}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_status"); + + if (!battery || !bst) + return_VALUE(-EINVAL); + + /* Evalute _BST */ + + status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + kfree(buffer.pointer); + + if (0 == result) + (*bst) = (struct acpi_battery_status *) data.pointer; + + return_VALUE(result); +} + + +static int +acpi_battery_set_alarm ( + struct acpi_battery *battery, + unsigned long alarm) +{ + acpi_status status = 0; + acpi_object arg0 = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list = {1, &arg0}; + + ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); + + if (!battery) + return_VALUE(-EINVAL); + + if (!battery->flags.alarm) + return_VALUE(-ENODEV); + + arg0.integer.value = alarm; + + status = acpi_evaluate(battery->handle, "_BTP", &arg_list, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); + + battery->alarm = alarm; + + return_VALUE(0); +} + + +static int +acpi_battery_check ( + struct acpi_battery *battery) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_handle handle = NULL; + struct acpi_device *device = NULL; + struct acpi_battery_info *bif = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_check"); + + if (!battery) + return_VALUE(-EINVAL); + + result = acpi_bus_get_device(battery->handle, &device); + if (0 != result) + return_VALUE(result); + + result = acpi_bus_get_status(device); + if (0 != result) + return_VALUE(result); + + /* Insertion? */ + + if (!battery->flags.present && device->status.battery_present) { + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); + + /* Evalute _BIF to get certain static information */ + + result = acpi_battery_get_info(battery, &bif); + if (0 != result) + return_VALUE(result); + + battery->flags.power_unit = bif->power_unit; + battery->trips.warning = bif->design_capacity_warning; + battery->trips.low = bif->design_capacity_low; + kfree(bif); + + /* See if alarms are supported, and if so, set default */ + + status = acpi_get_handle(battery->handle, "_BTP", &handle); + if (ACPI_SUCCESS(status)) { + battery->flags.alarm = 1; + acpi_battery_set_alarm(battery, battery->trips.warning); + } + } + + /* Removal? */ + + else if (battery->flags.present && !device->status.battery_present) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); + } + + battery->flags.present = device->status.battery_present; + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#include +#include + +struct proc_dir_entry *acpi_battery_dir = NULL; + +static int +acpi_battery_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_info *bif = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_info"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Info (_BIF) */ + + result = acpi_battery_get_info(battery, &bif); + if ((0 != result) || !bif) { + p += sprintf(p, "ERROR: Unable to read battery information\n"); + goto end; + } + + units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design capacity: unknown\n"); + else + p += sprintf(p, "design capacity: %d %sh\n", + (u32) bif->design_capacity, units); + + if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "last full capacity: unknown\n"); + else + p += sprintf(p, "last full capacity: %d %sh\n", + (u32) bif->last_full_capacity, units); + + switch ((u32) bif->battery_technology) { + case 0: + p += sprintf(p, "battery technology: non-rechargeable\n"); + break; + case 1: + p += sprintf(p, "battery technology: rechargeable\n"); + break; + default: + p += sprintf(p, "battery technology: unknown\n"); + break; + } + + if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design voltage: unknown\n"); + else + p += sprintf(p, "design voltage: %d mV\n", + (u32) bif->design_voltage); + + p += sprintf(p, "design capacity warning: %d %sh\n", + (u32) bif->design_capacity_warning, units); + p += sprintf(p, "design capacity low: %d %sh\n", + (u32) bif->design_capacity_low, units); + p += sprintf(p, "capacity granularity 1: %d %sh\n", + (u32) bif->battery_capacity_granularity_1, units); + p += sprintf(p, "capacity granularity 2: %d %sh\n", + (u32) bif->battery_capacity_granularity_2, units); + p += sprintf(p, "model number: %s\n", + bif->model_number); + p += sprintf(p, "serial number: %s\n", + bif->serial_number); + p += sprintf(p, "battery type: %s\n", + bif->battery_type); + p += sprintf(p, "OEM info: %s\n", + bif->oem_info); + +end: + kfree(bif); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_status *bst = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_state"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Status (_BST) */ + + result = acpi_battery_get_status(battery, &bst); + if ((0 != result) || !bst) { + p += sprintf(p, "ERROR: Unable to read battery status\n"); + goto end; + } + + if (!(bst->state & 0x04)) + p += sprintf(p, "capacity state: ok\n"); + else + p += sprintf(p, "capacity state: critical\n"); + + if ((bst->state & 0x01) && (bst->state & 0x02)) + p += sprintf(p, "charging state: charging/discharging\n"); + else if (bst->state & 0x01) + p += sprintf(p, "charging state: discharging\n"); + else if (bst->state & 0x02) + p += sprintf(p, "charging state: charging\n"); + else + p += sprintf(p, "charging state: unknown\n"); + + if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present rate: unknown\n"); + else + p += sprintf(p, "present rate: %d %s\n", + (u32) bst->present_rate, units); + + if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "remaining capacity: unknown\n"); + else + p += sprintf(p, "remaining capacity: %d %sh\n", + (u32) bst->remaining_capacity, units); + + if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present voltage: unknown\n"); + else + p += sprintf(p, "present voltage: %d mV\n", + (u32) bst->present_voltage); + +end: + kfree(bst); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_alarm ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); + + if (!battery) + goto end; + + if (!battery->flags.present) { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Alarm */ + + p += sprintf(p, "alarm: "); + if (!battery->alarm) + p += sprintf(p, "unsupported\n"); + else + p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_write_alarm ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + char alarm_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); + + if (!battery || (count > sizeof(alarm_string) - 1)) + return_VALUE(-EINVAL); + + if (!battery->flags.present) + return_VALUE(-ENODEV); + + if (copy_from_user(alarm_string, buffer, count)) + return_VALUE(-EFAULT); + + alarm_string[count] = '\0'; + + result = acpi_battery_set_alarm(battery, + simple_strtoul(alarm_string, NULL, 0)); + if (0 != result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_battery_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); + + if (!acpi_battery_dir) { + acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_battery_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_INFO)); + else { + entry->read_proc = acpi_battery_read_info; + entry->data = acpi_driver_data(device); + } + + /* 'status' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_STATUS)); + else { + entry->read_proc = acpi_battery_read_state; + entry->data = acpi_driver_data(device); + } + + /* 'alarm' [R/W] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_ALARM)); + else { + entry->read_proc = acpi_battery_read_alarm; + entry->write_proc = acpi_battery_write_alarm; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_battery_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); + + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static void +acpi_battery_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_notify"); + + if (!battery) + return_VOID; + + if (0 != acpi_bus_get_device(handle, &device)) + return_VOID; + + switch (event) { + case ACPI_BATTERY_NOTIFY_STATUS: + case ACPI_BATTERY_NOTIFY_INFO: + acpi_battery_check(battery); + acpi_bus_generate_event(device, event, battery->flags.present); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +static int +acpi_battery_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add"); + + if (!device) + return_VALUE(-EINVAL); + + battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL); + if (!battery) + return_VALUE(-ENOMEM); + memset(battery, 0, sizeof(struct acpi_battery)); + + battery->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_BATTERY_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_BATTERY_CLASS); + acpi_driver_data(device) = battery; + + result = acpi_battery_check(battery); + if (0 != result) + goto end; + + result = acpi_battery_add_fs(device); + if (0 != result) + goto end; + + status = acpi_install_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present?"present":"absent"); + +end: + if (0 != result) { + acpi_battery_remove_fs(device); + kfree(battery); + } + + return_VALUE(result); +} + + +static int +acpi_battery_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + battery = (struct acpi_battery *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_battery_remove_fs(device); + + kfree(battery); + + return_VALUE(0); +} + + +static int __init +acpi_battery_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_init"); + + result = acpi_bus_register_driver(&acpi_battery_driver); + if (0 > result) { + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static void __exit +acpi_battery_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_exit"); + + result = acpi_bus_unregister_driver(&acpi_battery_driver); + if (0 == result) + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_battery_init); +module_exit(acpi_battery_exit); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/bus.c linux2.4.21_itanium/drivers/acpi/bus.c --- linux2.4.21_itanium.org/drivers/acpi/bus.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/bus.c Wed Jul 23 18:28:09 2003 @@ -0,0 +1,2197 @@ +/* + * acpi_bus.c - ACPI Bus Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" +#include "include/acinterp.h" /* for acpi_ex_eisa_id_to_string() */ + + +#define _COMPONENT ACPI_BUS_COMPONENT +ACPI_MODULE_NAME ("acpi_bus") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUS_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + +FADT_DESCRIPTOR acpi_fadt; +static u8 acpi_disabled; +struct acpi_device *acpi_root; +struct proc_dir_entry *acpi_root_dir; + +#define STRUCT_TO_INT(s) (*((int*)&s)) + +/* + * POLICY: If *anything* doesn't work, put it on the blacklist. + * If they are critical errors, mark it critical, and abort driver load. + */ +static struct acpi_blacklist_item acpi_blacklist[] __initdata = +{ + /* Portege 7020, BIOS 8.10 */ + {"TOSHIB", "7020CT ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 4030 */ + {"TOSHIB", "4030 ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 310/320, BIOS 7.1 */ + {"TOSHIB", "310 ", 0x19990511, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Seattle 2, old bios rev. */ + {"INTEL ", "440BX ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* ASUS K7M */ + {"ASUS ", "K7M ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Intel 810 Motherboard? */ + {"MNTRAL", "MO81010A", 0x00000012, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Compaq Presario 1700 */ + {"PTLTD ", " DSDT ", 0x06040000, ACPI_TABLE_DSDT, less_than_or_equal, "Multiple problems", 1}, + /* Sony FX120, FX140, FX150? */ + {"SONY ", "U0 ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1}, + /* Compaq Presario 800, Insyde BIOS */ + {"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, + /* IBM 600E - _ADR should return 7, but it returns 1 */ + {"IBM ", "TP600E ", 0x00000105, ACPI_TABLE_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, + {""} +}; + + +/* -------------------------------------------------------------------------- + Linux Driver Model (LDM) Support + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_LDM + +static int acpi_device_probe(struct device *dev); +static int acpi_device_remove(struct device *dev, u32 flags); +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, +}; + + +static int +acpi_device_probe ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_device_probe"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_remove ( + struct device *dev, + u32 flags) +{ + ACPI_FUNCTION_TRACE("acpi_device_remove"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_suspend ( + struct device *dev, + u32 state, + u32 stage) +{ + ACPI_FUNCTION_TRACE("acpi_device_suspend"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_resume ( + struct device *dev, + u32 stage) +{ + ACPI_FUNCTION_TRACE("acpi_device_resume"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + +#if 0 /* not used ATM */ +static int +acpi_platform_add ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_platform_add"); + + if (!dev) + return -EINVAL; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) added\n", + dev->name, dev->bus_id)); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_platform_remove ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_platform_add"); + + if (!dev) + return -EINVAL; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) removed\n", + dev->name, dev->bus_id)); + + /* TBD */ + + return_VALUE(0); +} +#endif /* unused */ + + +#endif /*CONFIG_LDM*/ + + +static int +acpi_device_register ( + struct acpi_device *device, + struct acpi_device *parent) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_device_register"); + + if (!device) + return_VALUE(-EINVAL); + +#ifdef CONFIG_LDM + sprintf(device->dev.name, "ACPI device %s:%s", + device->pnp.hardware_id, device->pnp.unique_id); + strncpy(device->dev.bus_id, device->pnp.bus_id, sizeof(acpi_bus_id)); + if (parent) + device->dev.parent = &parent->dev; + device->dev.driver = &acpi_bus_driver; + + result = device_register(&device->dev); +#endif /*CONFIG_LDM*/ + + return_VALUE(result); +} + + +static int +acpi_device_unregister ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_device_unregister"); + + if (!device) + return_VALUE(-EINVAL); + +#ifdef CONFIG_LDM + put_device(&device->dev); +#endif /*CONFIG_LDM*/ + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Device Management + -------------------------------------------------------------------------- */ + +static void +acpi_bus_data_handler ( + acpi_handle handle, + u32 function, + void *context) +{ + ACPI_FUNCTION_TRACE("acpi_bus_data_handler"); + + /* TBD */ + + return_VOID; +} + + +int +acpi_bus_get_device ( + acpi_handle handle, + struct acpi_device **device) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_bus_get_device"); + + if (!device) + return_VALUE(-EINVAL); + + /* TBD: Support fixed-feature devices */ + + status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device); + if (ACPI_FAILURE(status) || !*device) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context for object [%p]\n", + handle)); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +int +acpi_bus_get_status ( + struct acpi_device *device) +{ + acpi_status status = AE_OK; + unsigned long sta = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_status"); + + if (!device) + return_VALUE(-EINVAL); + + /* + * Evaluate _STA if present. + */ + if (device->flags.dynamic_status) { + status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + STRUCT_TO_INT(device->status) = (int) sta; + } + + /* + * Otherwise we assume the status of our parent (unless we don't + * have one, in which case status is implied). + */ + else if (device->parent) + device->status = device->parent->status; + else + STRUCT_TO_INT(device->status) = 0x0F; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", + device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status))); + + return_VALUE(0); +} + + +/* +static int +acpi_bus_create_device_fs (struct device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (device->dir.entry) + return_VALUE(-EEXIST); + + if (!device->parent) + device->dir.entry = proc_mkdir(device->pnp.bus_id, NULL); + else + device->dir.entry = proc_mkdir(device->pnp.bus_id, + device->parent->fs.entry); + + if (!device->dir.entry) { + printk(KERN_ERR PREFIX "Unable to create fs entry '%s'\n", + device->pnp.bus_id); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static int +acpi_bus_remove_device_fs (struct device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (!device->dir.entry) + return_VALUE(-ENODEV); + + if (!device->parent) + remove_proc_entry(device->pnp_bus_id, NULL); + else + remove_proc_entry(device->pnp.bus_id, device->parent->fs.entry); + + device->dir.entry = NULL; + + return_VALUE(0); +} +*/ + + +/* -------------------------------------------------------------------------- + Power Management + -------------------------------------------------------------------------- */ + +int +acpi_bus_get_power ( + acpi_handle handle, + int *state) +{ + int result = 0; + acpi_status status = 0; + struct acpi_device *device = NULL; + unsigned long psc = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_power"); + + result = acpi_bus_get_device(handle, &device); + if (0 != result) + return_VALUE(result); + + *state = ACPI_STATE_UNKNOWN; + + if (!device->flags.power_manageable) { + /* TBD: Non-recursive algorithm for walking up hierarchy */ + if (device->parent) + *state = device->parent->power.state; + else + *state = ACPI_STATE_D0; + } + else { + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.explicit_get) { + status = acpi_evaluate_integer(device->handle, "_PSC", + NULL, &psc); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + device->power.state = (int) psc; + } + else if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device); + if (0 != result) + return_VALUE(result); + } + + *state = device->power.state; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", + device->pnp.bus_id, device->power.state)); + + return_VALUE(0); +} + + +int +acpi_bus_set_power ( + acpi_handle handle, + int state) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + char object_name[5] = {'_','P','S','0'+state,'\0'}; + + ACPI_FUNCTION_TRACE("acpi_bus_set_power"); + + result = acpi_bus_get_device(handle, &device); + if (0 != result) + return_VALUE(result); + + if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) + return_VALUE(-EINVAL); + + /* Make sure this is a valid target state */ + + if (!device->flags.power_manageable) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); + return_VALUE(-ENODEV); + } + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); + return_VALUE(0); + } + if (!device->power.states[state].flags.valid) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state)); + return_VALUE(-ENODEV); + } + if (device->parent && (state < device->parent->power.state)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n")); + return_VALUE(-ENODEV); + } + + /* + * Transition Power + * ---------------- + * On transitions to a high-powered state we first apply power (via + * power resources) then evalute _PSx. Conversly for transitions to + * a lower-powered state. + */ + if (state < device->power.state) { + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (0 != result) + goto end; + } + if (device->power.states[state].flags.explicit_set) { + status = acpi_evaluate_object(device->handle, + object_name, NULL, NULL); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto end; + } + } + } + else { + if (device->power.states[state].flags.explicit_set) { + status = acpi_evaluate_object(device->handle, + object_name, NULL, NULL); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto end; + } + } + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (0 != result) + goto end; + } + } + +end: + if (0 != result) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n", + device->pnp.bus_id, state)); + else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n", + device->pnp.bus_id, state)); + + return_VALUE(result); +} + + +static int +acpi_bus_get_power_flags ( + struct acpi_device *device) +{ + acpi_status status = 0; + acpi_handle handle = 0; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags"); + + if (!device) + return -ENODEV; + + /* + * Power Management Flags + */ + status = acpi_get_handle(device->handle, "_PSC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.explicit_get = 1; + status = acpi_get_handle(device->handle, "_IRC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.inrush_current = 1; + status = acpi_get_handle(device->handle, "_PRW", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.wake_capable = 1; + + /* + * Enumerate supported power management states + */ + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { + struct acpi_device_power_state *ps = &device->power.states[i]; + char object_name[5] = {'_','P','R','0'+i,'\0'}; + + /* Evaluate "_PRx" to se if power resources are referenced */ + acpi_evaluate_reference(device->handle, object_name, NULL, + &ps->resources); + if (ps->resources.count) { + device->power.flags.power_resources = 1; + ps->flags.valid = 1; + } + + /* Evaluate "_PSx" to see if we can do explicit sets */ + object_name[2] = 'S'; + status = acpi_get_handle(device->handle, object_name, &handle); + if (ACPI_SUCCESS(status)) { + ps->flags.explicit_set = 1; + ps->flags.valid = 1; + } + + /* State is valid if we have some power control */ + if (ps->resources.count || ps->flags.explicit_set) + ps->flags.valid = 1; + + ps->power = -1; /* Unknown - driver assigned */ + ps->latency = -1; /* Unknown - driver assigned */ + } + + /* Set defaults for D0 and D3 states (always valid) */ + device->power.states[ACPI_STATE_D0].flags.valid = 1; + device->power.states[ACPI_STATE_D0].power = 100; + device->power.states[ACPI_STATE_D3].flags.valid = 1; + device->power.states[ACPI_STATE_D3].power = 0; + + /* + * System Power States + * ------------------- + */ + /* TBD: S1-S4 power state support and resource requirements. */ + /* + for (i=ACPI_STATE_S1; ihandle, name, NULL, + &state); + if (ACPI_FAILURE(status)) + continue; + } + */ + + /* TBD: System wake support and resource requirements. */ + + device->power.state = ACPI_STATE_UNKNOWN; + + return 0; +} + + +/* -------------------------------------------------------------------------- + Performance Management + -------------------------------------------------------------------------- */ + +static int +acpi_bus_get_perf_flags ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_get_perf_flags"); + + if (!device) + return -ENODEV; + + device->performance.state = ACPI_STATE_UNKNOWN; + + return 0; +} + + +/* -------------------------------------------------------------------------- + Event Management + -------------------------------------------------------------------------- */ + +static spinlock_t acpi_bus_event_lock = SPIN_LOCK_UNLOCKED; + +LIST_HEAD(acpi_bus_event_list); +DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); + +extern int event_is_open; + +int +acpi_bus_generate_event ( + struct acpi_device *device, + u8 type, + int data) +{ + struct acpi_bus_event *event = NULL; + u32 flags = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_generate_event"); + + if (!device) + return_VALUE(-EINVAL); + + /* drop event on the floor if no one's listening */ + if (!event_is_open) + return_VALUE(0); + + event = kmalloc(sizeof(struct acpi_bus_event), GFP_KERNEL); + if (!event) + return_VALUE(-ENOMEM); + + sprintf(event->device_class, "%s", device->pnp.device_class); + sprintf(event->bus_id, "%s", device->pnp.bus_id); + event->type = type; + event->data = data; + + spin_lock_irqsave(&acpi_bus_event_lock, flags); + list_add_tail(&event->node, &acpi_bus_event_list); + spin_unlock_irqrestore(&acpi_bus_event_lock, flags); + + wake_up_interruptible(&acpi_bus_event_queue); + + return_VALUE(0); +} + +int +acpi_bus_receive_event ( + struct acpi_bus_event *event) +{ + u32 flags = 0; + struct acpi_bus_event *entry = NULL; + + DECLARE_WAITQUEUE(wait, current); + + ACPI_FUNCTION_TRACE("acpi_bus_receive_event"); + + if (!event) + return -EINVAL; + + if (list_empty(&acpi_bus_event_list)) { + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&acpi_bus_event_queue, &wait); + + if (list_empty(&acpi_bus_event_list)) + schedule(); + + remove_wait_queue(&acpi_bus_event_queue, &wait); + set_current_state(TASK_RUNNING); + + if (signal_pending(current)) + return_VALUE(-ERESTARTSYS); + } + + spin_lock_irqsave(&acpi_bus_event_lock, flags); + entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); + if (entry) + list_del(&entry->node); + spin_unlock_irqrestore(&acpi_bus_event_lock, flags); + + if (!entry) + return_VALUE(-ENODEV); + + memcpy(event, entry, sizeof(struct acpi_bus_event)); + + kfree(entry); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Namespace Management + -------------------------------------------------------------------------- */ + +#define WALK_UP 0 +#define WALK_DOWN 1 + +typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*); + +#define HAS_CHILDREN(d) ((d)->children.next != &((d)->children)) +#define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children)) +#define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node)) + + +/** + * acpi_bus_walk + * ------------- + * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first) + * or up. Able to parse starting at any node in the namespace. Note that a + * callback return value of -ELOOP will terminate the walk. + * + * @start: starting point + * callback: function to call for every device encountered while parsing + * direction: direction to parse (up or down) + * @data: context for this search operation + */ +static int +acpi_bus_walk ( + struct acpi_device *start, + acpi_bus_walk_callback callback, + int direction, + void *data) +{ + int result = 0; + int level = 0; + struct acpi_device *device = NULL; + + if (!start || !callback) + return -EINVAL; + + device = start; + + /* + * Parse Namespace + * --------------- + * Parse a given subtree (specified by start) in the given direction. + * Walking 'up' simply means that we execute the callback on leaf + * devices prior to their parents (useful for things like removing + * or powering down a subtree). + */ + + while (device) { + + if (direction == WALK_DOWN) + if (-ELOOP == callback(device, level, data)) + break; + + /* Depth First */ + + if (HAS_CHILDREN(device)) { + device = NODE_TO_DEVICE(device->children.next); + ++level; + continue; + } + + if (direction == WALK_UP) + if (-ELOOP == callback(device, level, data)) + break; + + /* Now Breadth */ + + if (HAS_SIBLINGS(device)) { + device = NODE_TO_DEVICE(device->node.next); + continue; + } + + /* Scope Exhausted - Find Next */ + + while ((device = device->parent)) { + --level; + if (HAS_SIBLINGS(device)) { + device = NODE_TO_DEVICE(device->node.next); + break; + } + } + } + + if ((direction == WALK_UP) && (result == 0)) + callback(start, level, data); + + return result; +} + + +/* -------------------------------------------------------------------------- + Notification Handling + -------------------------------------------------------------------------- */ + +static int +acpi_bus_check_device ( + struct acpi_device *device, + int *status_changed) +{ + acpi_status status = 0; + struct acpi_device_status old_status; + + ACPI_FUNCTION_TRACE("acpi_bus_check_device"); + + if (!device) + return_VALUE(-EINVAL); + + if (status_changed) + *status_changed = 0; + + old_status = device->status; + + /* + * Make sure this device's parent is present before we go about + * messing with the device. + */ + if (device->parent && !device->parent->status.present) { + device->status = device->parent->status; + if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { + if (status_changed) + *status_changed = 1; + } + return_VALUE(0); + } + + status = acpi_bus_get_status(device); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) + return_VALUE(0); + + if (status_changed) + *status_changed = 1; + + /* + * Device Insertion/Removal + */ + if ((device->status.present) && !(old_status.present)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); + /* TBD: Handle device insertion */ + } + else if (!(device->status.present) && (old_status.present)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); + /* TBD: Handle device removal */ + } + + return_VALUE(0); +} + + +static int +acpi_bus_check_scope ( + struct acpi_device *device) +{ + int result = 0; + int status_changed = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_check_scope"); + + if (!device) + return_VALUE(-EINVAL); + + /* Status Change? */ + result = acpi_bus_check_device(device, &status_changed); + if (0 != result) + return_VALUE(result); + + if (!status_changed) + return_VALUE(0); + + /* + * TBD: Enumerate child devices within this device's scope and + * run acpi_bus_check_device()'s on them. + */ + + return_VALUE(0); +} + + +/** + * acpi_bus_notify + * --------------- + * Callback for all 'system-level' device notifications (values 0x00-0x7F). + */ +static void +acpi_bus_notify ( + acpi_handle handle, + u32 type, + void *data) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_notify"); + + if (0 != acpi_bus_get_device(handle, &device)) + return_VOID; + + switch (type) { + + case ACPI_NOTIFY_BUS_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n", + device->pnp.bus_id)); + result = acpi_bus_check_scope(device); + /* + * TBD: We'll need to outsource certain events to non-ACPI + * drivers via the device manager (device.c). + */ + break; + + case ACPI_NOTIFY_DEVICE_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n", + device->pnp.bus_id)); + result = acpi_bus_check_device(device, NULL); + /* + * TBD: We'll need to outsource certain events to non-ACPI + * drivers via the device manager (device.c). + */ + break; + + case ACPI_NOTIFY_DEVICE_WAKE: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD: Exactly what does 'light' mean? */ + break; + + case ACPI_NOTIFY_FREQUENCY_MISMATCH: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_BUS_MODE_MISMATCH: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_POWER_FAULT: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n", + type)); + break; + } + + return_VOID; +} + + +/* -------------------------------------------------------------------------- + Driver Management + -------------------------------------------------------------------------- */ + +static LIST_HEAD(acpi_bus_drivers); +static DECLARE_MUTEX(acpi_bus_drivers_lock); + + +/** + * acpi_bus_match + * -------------- + * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it + * matches the specified driver's criteria. + */ +static int +acpi_bus_match ( + struct acpi_device *device, + struct acpi_driver *driver) +{ + + if (!device || !driver) + return -EINVAL; + + if (device->flags.hardware_id) { + if (0 != strstr(driver->ids, device->pnp.hardware_id)) + return 0; + } + + if (device->flags.compatible_ids) { + acpi_status status = AE_OK; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_object *object = NULL; + char cid[256]; + + memset(cid, 0, sizeof(cid)); + + status = acpi_evaluate_object(device->handle, "_CID", NULL, + &buffer); + if (ACPI_FAILURE(status) || !buffer.pointer) + return -ENOENT; + + object = (acpi_object *) buffer.pointer; + + switch (object->type) { + case ACPI_TYPE_INTEGER: + acpi_ex_eisa_id_to_string((u32) object->integer.value, + cid); + break; + case ACPI_TYPE_STRING: + strncpy(cid, object->string.pointer, sizeof(cid) - 1); + break; + case ACPI_TYPE_PACKAGE: + /* TBD: Support CID packages */ + break; + } + + if (!cid[0]) + return -ENOENT; + + if (0 != strstr(driver->ids, cid)) + return 0; + } + + return -ENOENT; +} + + +/** + * acpi_bus_driver_init + * -------------------- + * Used to initialize a device via its device driver. Called whenever a + * driver is bound to a device. Invokes the driver's add() and start() ops. + */ +static int +acpi_bus_driver_init ( + struct acpi_device *device, + struct acpi_driver *driver) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_driver_init"); + + if (!device || !driver) + return_VALUE(-EINVAL); + + if (!driver->ops.add) + return_VALUE(-ENOSYS); + + result = driver->ops.add(device); + if (0 != result) { + device->driver = NULL; + acpi_driver_data(device) = NULL; + return_VALUE(result); + } + + /* + * TBD - Configuration Management: Assign resources to device based + * upon possible configuration and currently allocated resources. + */ + + if (driver->ops.start) { + result = driver->ops.start(device); + if ((0 != result) && (driver->ops.remove)) + driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + return_VALUE(result); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); + +#ifdef CONFIG_LDM + /* + * Update the device information (in the global device hierarchy) now + * that there's a driver bound to it. + */ + strncpy(device->dev.name, device->pnp.device_name, + sizeof(device->dev.name)); +#endif + + if (driver->ops.scan) { + driver->ops.scan(device); + } + + return_VALUE(0); +} + + +/** + * acpi_bus_attach + * ------------- + * Callback for acpi_bus_walk() used to find devices that match a specific + * driver's criteria and then attach the driver. + */ +static int +acpi_bus_attach ( + struct acpi_device *device, + int level, + void *data) +{ + int result = 0; + struct acpi_driver *driver = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_attach"); + + if (!device || !data) + return_VALUE(-EINVAL); + + driver = (struct acpi_driver *) data; + + if (device->driver) + return_VALUE(-EEXIST); + + if (!device->status.present) + return_VALUE(-ENODEV); + + result = acpi_bus_match(device, driver); + if (0 != result) + return_VALUE(result); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", + driver->name, device->pnp.bus_id)); + + result = acpi_bus_driver_init(device, driver); + if (0 != result) + return_VALUE(result); + + down(&acpi_bus_drivers_lock); + ++driver->references; + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/** + * acpi_bus_unattach + * ----------------- + * Callback for acpi_bus_walk() used to find devices that match a specific + * driver's criteria and unattach the driver. + */ +static int +acpi_bus_unattach ( + struct acpi_device *device, + int level, + void *data) +{ + int result = 0; + struct acpi_driver *driver = (struct acpi_driver *) data; + + ACPI_FUNCTION_TRACE("acpi_bus_unattach"); + + if (!device || !driver) + return_VALUE(-EINVAL); + + if (device->driver != driver) + return_VALUE(-ENOENT); + + if (!driver->ops.remove) + return_VALUE(-ENOSYS); + + result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + if (0 != result) + return_VALUE(result); + + device->driver = NULL; + acpi_driver_data(device) = NULL; + + down(&acpi_bus_drivers_lock); + driver->references--; + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/** + * acpi_bus_find_driver + * -------------------- + * Parses the list of registered drivers looking for a driver applicable for + * the specified device. + */ +static int +acpi_bus_find_driver ( + struct acpi_device *device) +{ + int result = -ENODEV; + struct list_head *entry = NULL; + struct acpi_driver *driver = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_find_driver"); + + if (!device || device->driver) + return_VALUE(-EINVAL); + + down(&acpi_bus_drivers_lock); + + list_for_each(entry, &acpi_bus_drivers) { + + driver = list_entry(entry, struct acpi_driver, node); + + if (0 != acpi_bus_match(device, driver)) + continue; + + result = acpi_bus_driver_init(device, driver); + if (0 == result) + ++driver->references; + + break; + } + + up(&acpi_bus_drivers_lock); + + return_VALUE(result); +} + + +/** + * acpi_bus_register_driver + * ------------------------ + * Registers a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and binds. + */ +int +acpi_bus_register_driver ( + struct acpi_driver *driver) +{ + ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); + + if (!driver) + return_VALUE(-EINVAL); + + down(&acpi_bus_drivers_lock); + list_add_tail(&driver->node, &acpi_bus_drivers); + up(&acpi_bus_drivers_lock); + + acpi_bus_walk(acpi_root, acpi_bus_attach, + WALK_DOWN, driver); + + return_VALUE(driver->references); +} + + +/** + * acpi_bus_unregister_driver + * -------------------------- + * Unregisters a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and unbinds. + */ +int +acpi_bus_unregister_driver ( + struct acpi_driver *driver) +{ + ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); + + if (!driver) + return_VALUE(-EINVAL); + + acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver); + + if (driver->references) + return_VALUE(driver->references); + + down(&acpi_bus_drivers_lock); + list_del(&driver->node); + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Device Enumeration + -------------------------------------------------------------------------- */ + +static int +acpi_bus_get_flags ( + struct acpi_device *device) +{ + acpi_status status = AE_OK; + acpi_handle temp = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_get_flags"); + + /* Presence of _STA indicates 'dynamic_status' */ + status = acpi_get_handle(device->handle, "_STA", &temp); + if (ACPI_SUCCESS(status)) + device->flags.dynamic_status = 1; + + /* Presence of _CID indicates 'compatible_ids' */ + status = acpi_get_handle(device->handle, "_CID", &temp); + if (ACPI_SUCCESS(status)) + device->flags.compatible_ids = 1; + + /* Presence of _RMV indicates 'removable' */ + status = acpi_get_handle(device->handle, "_RMV", &temp); + if (ACPI_SUCCESS(status)) + device->flags.removable = 1; + + /* Presence of _EJD|_EJ0 indicates 'ejectable' */ + status = acpi_get_handle(device->handle, "_EJD", &temp); + if (ACPI_SUCCESS(status)) + device->flags.ejectable = 1; + else { + status = acpi_get_handle(device->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) + device->flags.ejectable = 1; + } + + /* Presence of _LCK indicates 'lockable' */ + status = acpi_get_handle(device->handle, "_LCK", &temp); + if (ACPI_SUCCESS(status)) + device->flags.lockable = 1; + + /* Presence of _PS0|_PR0 indicates 'power manageable' */ + status = acpi_get_handle(device->handle, "_PS0", &temp); + if (ACPI_FAILURE(status)) + status = acpi_get_handle(device->handle, "_PR0", &temp); + if (ACPI_SUCCESS(status)) + device->flags.power_manageable = 1; + + /* TBD: Peformance management */ + + return_VALUE(0); +} + + +static int +acpi_bus_add ( + struct acpi_device **child, + struct acpi_device *parent, + acpi_handle handle, + int type) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + char bus_id[5] = {'?',0}; + acpi_buffer buffer = {sizeof(bus_id), bus_id}; + acpi_device_info info; + char *hid = NULL; + char *uid = NULL; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_add"); + + if (!child) + return_VALUE(-EINVAL); + + device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL); + if (!device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); + return_VALUE(-ENOMEM); + } + memset(device, 0, sizeof(struct acpi_device)); + + device->handle = handle; + device->parent = parent; + + memset(&info, 0, sizeof(acpi_device_info)); + + /* + * Bus ID + * ------ + * The device's Bus ID is simply the object name. + * TBD: Shouldn't this value be unique (within the ACPI namespace)? + */ + switch (type) { + case ACPI_BUS_TYPE_SYSTEM: + sprintf(device->pnp.bus_id, "%s", "ACPI"); + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + sprintf(device->pnp.bus_id, "%s", "PWRF"); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + sprintf(device->pnp.bus_id, "%s", "SLPF"); + break; + default: + acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); + /* Clean up trailing underscores (if any) */ + for (i = 3; i > 1; i--) { + if (bus_id[i] == '_') + bus_id[i] = '\0'; + else + break; + } + sprintf(device->pnp.bus_id, "%s", bus_id); + break; + } + + /* + * Flags + * ----- + * Get prior to calling acpi_bus_get_status() so we know whether + * or not _STA is present. Note that we only look for object + * handles -- cannot evaluate objects until we know the device is + * present and properly initialized. + */ + result = acpi_bus_get_flags(device); + if (0 != result) + goto end; + + /* + * Status + * ------ + * See if the device is present. We always assume that non-Device() + * objects (e.g. thermal zones, power resources, processors, etc.) are + * present, functioning, etc. (at least when parent object is present). + * Note that _STA has a different meaning for some objects (e.g. + * power resources) so we need to be careful how we use it. + */ + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + result = acpi_bus_get_status(device); + if (!result) + break; + if (!device->status.present) + result = -ENOENT; + goto end; + default: + STRUCT_TO_INT(device->status) = 0x0F; + break; + } + + /* + * Initialize Device + * ----------------- + * TBD: Synch with Core's enumeration/initialization process. + */ + + /* + * Hardware ID, Unique ID, & Bus Address + * ------------------------------------- + */ + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + status = acpi_get_object_info(handle, &info); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading device info\n")); + result = -ENODEV; + goto end; + } + /* Clean up info strings (not NULL terminated) */ + info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; + info.unique_id[sizeof(info.unique_id)-1] = '\0'; + if (info.valid & ACPI_VALID_HID) + hid = info.hardware_id; + if (info.valid & ACPI_VALID_UID) + uid = info.unique_id; + if (info.valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info.address; + device->flags.bus_address = 1; + } + break; + case ACPI_BUS_TYPE_POWER: + hid = ACPI_POWER_HID; + break; + case ACPI_BUS_TYPE_PROCESSOR: + hid = ACPI_PROCESSOR_HID; + break; + case ACPI_BUS_TYPE_SYSTEM: + hid = ACPI_SYSTEM_HID; + break; + case ACPI_BUS_TYPE_THERMAL: + hid = ACPI_THERMAL_HID; + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + hid = ACPI_BUTTON_HID_POWERF; + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + hid = ACPI_BUTTON_HID_SLEEPF; + break; + } + + /* + * \_SB + * ---- + * Fix for the system root bus device -- the only root-level device. + */ + if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { + hid = ACPI_BUS_HID; + sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME); + sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS); + } + + if (hid) { + sprintf(device->pnp.hardware_id, "%s", hid); + device->flags.hardware_id = 1; + } + if (uid) { + sprintf(device->pnp.unique_id, "%s", uid); + device->flags.unique_id = 1; + } + + /* + * Power Management + * ---------------- + */ + if (device->flags.power_manageable) { + result = acpi_bus_get_power_flags(device); + if (0 != result) + goto end; + } + + /* + * Performance Management + * ---------------------- + */ + if (device->flags.performance_manageable) { + result = acpi_bus_get_perf_flags(device); + if (0 != result) + goto end; + } + + /* + * Context + * ------- + * Attach this 'struct acpi_device' to the ACPI object. This makes + * resolutions from handle->device very efficient. Note that we need + * to be careful with fixed-feature devices as they all attach to the + * root object. + */ + switch (type) { + case ACPI_BUS_TYPE_POWER_BUTTON: + case ACPI_BUS_TYPE_SLEEP_BUTTON: + break; + default: + status = acpi_attach_data(device->handle, + acpi_bus_data_handler, device); + break; + } + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error attaching device data\n")); + result = -ENODEV; + goto end; + } + + /* + * Linkage + * ------- + * Link this device to its parent and siblings. + */ + INIT_LIST_HEAD(&device->children); + if (!device->parent) + INIT_LIST_HEAD(&device->node); + else + list_add_tail(&device->node, &device->parent->children); + +#ifdef CONFIG_ACPI_DEBUG + { + char *type_string = NULL; + char name[80] = {'?','\0'}; + acpi_buffer buffer = {sizeof(name), name}; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + type_string = "Device"; + break; + case ACPI_BUS_TYPE_POWER: + type_string = "Power Resource"; + break; + case ACPI_BUS_TYPE_PROCESSOR: + type_string = "Processor"; + break; + case ACPI_BUS_TYPE_SYSTEM: + type_string = "System"; + break; + case ACPI_BUS_TYPE_THERMAL: + type_string = "Thermal Zone"; + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + type_string = "Power Button"; + sprintf(name, "PWRB"); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + type_string = "Sleep Button"; + sprintf(name, "SLPB"); + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n", + type_string, name, handle)); + } +#endif /*CONFIG_ACPI_DEBUG*/ + + /* + * Global Device Hierarchy: + * ------------------------ + * Register this device with the global device hierarchy. + */ + acpi_device_register(device, parent); + + /* + * Bind _ADR-Based Devices + * ----------------------- + * If there's a a bus address (_ADR) then we utilize the parent's + * 'bind' function (if exists) to bind the ACPI- and natively- + * enumerated device representations. + */ + if (device->flags.bus_address) { + if (device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); + } + + /* + * Locate & Attach Driver + * ---------------------- + * If there's a hardware id (_HID) or compatible ids (_CID) we check + * to see if there's a driver installed for this kind of device. Note + * that drivers can install before or after a device in enumerated. + * + * TBD: Assumes LDM provides driver hot-plug capability. + */ + if (device->flags.hardware_id || device->flags.compatible_ids) + acpi_bus_find_driver(device); + +end: + if (0 != result) { + kfree(device); + return_VALUE(result); + } + + *child = device; + + return_VALUE(0); +} + + +static int +acpi_bus_remove ( + struct acpi_device *device, + int type) +{ + ACPI_FUNCTION_TRACE("acpi_bus_remove"); + + if (!device) + return_VALUE(-ENODEV); + + acpi_device_unregister(device); + + kfree(device); + + return_VALUE(0); +} + + +int +acpi_bus_scan ( + struct acpi_device *start) +{ + acpi_status status = AE_OK; + struct acpi_device *parent = NULL; + struct acpi_device *child = NULL; + acpi_handle phandle = 0; + acpi_handle chandle = 0; + acpi_object_type type = 0; + u32 level = 1; + + ACPI_FUNCTION_TRACE("acpi_bus_scan"); + + if (!start) + return_VALUE(-EINVAL); + + parent = start; + phandle = start->handle; + + /* + * Parse through the ACPI namespace, identify all 'devices', and + * create a new 'struct acpi_device' for each. + */ + while ((level > 0) && parent) { + + status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, + chandle, &chandle); + + /* + * If this scope is exhausted then move our way back up. + */ + if (ACPI_FAILURE(status)) { + level--; + chandle = phandle; + acpi_get_parent(phandle, &phandle); + if (parent->parent) + parent = parent->parent; + continue; + } + + status = acpi_get_type(chandle, &type); + if (ACPI_FAILURE(status)) + continue; + + /* + * If this is a scope object then parse it (depth-first). + */ + if (type == ACPI_TYPE_ANY) { + /* Hack to get around scope identity problem */ + status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + phandle = chandle; + chandle = 0; + } + continue; + } + + /* + * We're only interested in objects that we consider 'devices'. + */ + switch (type) { + case ACPI_TYPE_DEVICE: + type = ACPI_BUS_TYPE_DEVICE; + break; + case ACPI_TYPE_PROCESSOR: + type = ACPI_BUS_TYPE_PROCESSOR; + break; + case ACPI_TYPE_THERMAL: + type = ACPI_BUS_TYPE_THERMAL; + break; + case ACPI_TYPE_POWER: + type = ACPI_BUS_TYPE_POWER; + break; + default: + continue; + } + + status = acpi_bus_add(&child, parent, chandle, type); + if (ACPI_FAILURE(status)) + continue; + + /* + * If the device is present, enabled, and functioning then + * parse its scope (depth-first). Note that we need to + * represent absent devices to facilitate PnP notifications + * -- but only the subtree head (not all of its children, + * which will be enumerated when the parent is inserted). + * + * TBD: Need notifications and other detection mechanisms + * in place before we can fully implement this. + */ + if (child->status.present) { + status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, + 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + phandle = chandle; + chandle = 0; + parent = child; + } + } + } + + return_VALUE(0); +} + + +static int +acpi_bus_scan_fixed ( + struct acpi_device *root) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_scan"); + + if (!root) + return_VALUE(-ENODEV); + + /* + * Enumerate all fixed-feature devices. + */ + if (acpi_fadt.pwr_button == 0) + result = acpi_bus_add(&device, acpi_root, + ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_POWER_BUTTON); + + if (acpi_fadt.sleep_button == 0) + result = acpi_bus_add(&device, acpi_root, + ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_SLEEP_BUTTON); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Initialization/Cleanup + -------------------------------------------------------------------------- */ + +int __init +acpi_blacklisted(void) +{ + int i = 0; + int blacklisted = 0; + acpi_table_header table_header; + + while (acpi_blacklist[i].oem_id[0] != '\0') + { + if (!ACPI_SUCCESS(acpi_get_table_header(acpi_blacklist[i].table, 1, &table_header))) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_table_id, table_header.oem_table_id, 8)) { + i++; + continue; + } + + if ((acpi_blacklist[i].oem_revision_predicate == all_versions) + || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal + && table_header.oem_revision <= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal + && table_header.oem_revision >= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == equal + && table_header.oem_revision == acpi_blacklist[i].oem_revision)) { + + printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" " + "Revision 0x%x has a known ACPI BIOS problem.\n", + acpi_blacklist[i].oem_id, + acpi_blacklist[i].oem_table_id, + acpi_blacklist[i].oem_revision); + + printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n", + acpi_blacklist[i].reason, + (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable")); + + blacklisted = acpi_blacklist[i].is_critical_error; + break; + } + else { + i++; + } + } + + return blacklisted; +} + +static int __init +acpi_bus_init_irq (void) +{ + acpi_status status = AE_OK; + acpi_object arg = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list = {1, &arg}; + char *message = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_init_irq"); + + /* + * Let the system know what interrupt model we are using by + * evaluating the \_PIC object, if exists. + */ + + switch (acpi_irq_model) { + case ACPI_IRQ_MODEL_PIC: + message = "PIC"; + break; + case ACPI_IRQ_MODEL_IOAPIC: + message = "IOAPIC"; + break; + case ACPI_IRQ_MODEL_IOSAPIC: + message = "IOSAPIC"; + break; + default: + printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); + return_VALUE(-ENODEV); + } + + printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); + + arg.integer.value = acpi_irq_model; + + status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); + if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static int __init +acpi_bus_init (void) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt}; + int progress = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_init"); + + /* + * [0] Initailize the ACPI Core Subsystem. + */ + status = acpi_initialize_subsystem(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [1] Load the ACPI tables. + */ + status = acpi_load_tables(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [2] Check the blacklist + */ + if (acpi_blacklisted()) { + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [3] Get a separate copy of the FADT for use by other drivers. + */ + status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to get the FADT\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [4] Enable the ACPI Core Subsystem. + */ + status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n"); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "Interpreter enabled\n"); + + progress++; + + /* + * [5] Get the system interrupt model and evaluate \_PIC. + */ + result = acpi_bus_init_irq(); + if (0 != result) + goto end; + + progress++; + + /* + * [6] Register for all standard device notifications. + */ + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to register for device notifications\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [7] Create the root device. + */ + result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, + ACPI_BUS_TYPE_SYSTEM); + if (0 != result) + goto end; + + progress++; + + /* + * [8] Create the root file system. + */ + acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); + if (!acpi_root) { + result = -ENODEV; + goto end; + } + acpi_root_dir = acpi_device_dir(acpi_root); + + progress++; + + /* + * [9] Install drivers required for proper enumeration of the + * ACPI namespace. + */ + acpi_system_init(); /* ACPI System */ + acpi_power_init(); /* ACPI Bus Power Management */ +#ifdef CONFIG_ACPI_EC + acpi_ec_init(); /* ACPI Embedded Controller */ +#endif +#ifdef CONFIG_ACPI_PCI + acpi_pci_link_init(); /* ACPI PCI Interrupt Link */ + acpi_pci_root_init(); /* ACPI PCI Root Bridge */ +#endif + progress++; + + /* + * [10] Enumerate devices in the ACPI namespace. + */ + result = acpi_bus_scan_fixed(acpi_root); + if (0 != result) + goto end; + result = acpi_bus_scan(acpi_root); + if (0 != result) + goto end; + +end: + /* + * Clean up if anything went awry. + */ + if (0 != result) { + switch (progress) { + case 10: + case 9: remove_proc_entry("ACPI", NULL); + case 8: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + case 7: acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); + case 6: + case 5: + case 4: + case 3: + case 2: acpi_terminate(); + case 1: + case 0: + default: return_VALUE(-ENODEV); + } + } + + return_VALUE(0); +} + + +static void __exit +acpi_bus_exit (void) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_bus_exit"); + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, acpi_bus_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + +#ifdef CONFIG_ACPI_PCI + acpi_pci_root_exit(); + acpi_pci_link_exit(); +#endif +#ifdef CONFIG_ACPI_EC + acpi_ec_exit(); +#endif + acpi_power_exit(); + acpi_system_exit(); + + acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + + remove_proc_entry(ACPI_BUS_FILE_ROOT, NULL); + + status = acpi_terminate(); + if (ACPI_FAILURE(status)) + printk(KERN_ERR PREFIX "Unable to terminate the ACPI Interpreter\n"); + else + printk(KERN_ERR PREFIX "Interpreter disabled\n"); + + return_VOID; +} + + +int __init +acpi_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_init"); + + memset(&acpi_fadt, 0, sizeof(FADT_DESCRIPTOR)); + + printk(KERN_INFO PREFIX "Subsystem revision %08x\n", + ACPI_CA_VERSION); + + /* Initial core debug level excludes drivers, so include them now */ + acpi_set_debug(ACPI_DEBUG_LOW); + + if (acpi_disabled) { + printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n"); + return -ENODEV; + } + +#ifdef CONFIG_PM + if (PM_IS_ACTIVE()) { + printk(KERN_INFO PREFIX "APM is already active, exiting\n"); + return -ENODEV; + } +#endif + + result = acpi_bus_init(); + if (0 != result) + return_VALUE(result); + +#ifdef CONFIG_PM + pm_active = 1; +#endif + + return_VALUE(0); +} + + +void __exit +acpi_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_exit"); + +#ifdef CONFIG_PM + pm_active = 0; +#endif + + acpi_bus_exit(); + + return_VOID; +} + + +int __init +acpi_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "off", 3) == 0) + acpi_disabled = 1; + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); + } + return 1; +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +subsys_initcall(acpi_init); +#endif + +__setup("acpi=", acpi_setup); + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/button.c linux2.4.21_itanium/drivers/acpi/button.c --- linux2.4.21_itanium.org/drivers/acpi/button.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/button.c Wed Jul 23 18:28:09 2003 @@ -0,0 +1,420 @@ +/* + * acpi_button.c - ACPI Button Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BUTTON_COMPONENT +ACPI_MODULE_NAME ("acpi_button") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +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, + }, +}; + +struct acpi_button { + acpi_handle handle; + struct acpi_device *device; /* Fixed button kludge */ + u8 type; + unsigned long pushed; +}; + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#include +#include + +static struct proc_dir_entry *acpi_button_dir = NULL; + + +static int +acpi_button_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_button_read_info"); + + if (!button || !button->device) + goto end; + + p += sprintf(p, "type: %s\n", + acpi_device_name(button->device)); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_button_add_fs ( + struct acpi_device *device) +{ + static struct proc_dir_entry *power_entry; + static struct proc_dir_entry *sleep_entry; + static struct proc_dir_entry *lid_entry; + struct proc_dir_entry *entry = NULL; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add_fs"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + if (!acpi_button_dir) { + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + } + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + if (!power_entry) + power_entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + entry = power_entry; + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + if (!sleep_entry) + sleep_entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + entry = sleep_entry; + break; + case ACPI_BUTTON_TYPE_LID: + if (!lid_entry) + lid_entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + entry = lid_entry; + break; + } + + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->read_proc = acpi_button_read_info; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_button_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); + + if (!acpi_button_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_button_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +void +acpi_button_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + + ACPI_FUNCTION_TRACE("acpi_button_notify"); + + if (!button || !button->device) + return_VOID; + + switch (event) { + case ACPI_BUTTON_NOTIFY_STATUS: + acpi_bus_generate_event(button->device, event, ++button->pushed); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +acpi_status +acpi_button_notify_fixed ( + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + + ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); + + if (!button) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); + + return_ACPI_STATUS(AE_OK); +} + + +int +acpi_button_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add"); + + if (!device) + return_VALUE(-EINVAL); + + button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); + if (!button) + return_VALUE(-ENOMEM); + memset(button, 0, sizeof(struct acpi_button)); + + button->device = device; + button->handle = device->handle; + acpi_driver_data(device) = button; + + /* + * Determine the button type (via hid), as fixed-feature buttons + * need to be handled a bit differently than generic-space. + */ + if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) { + button->type = ACPI_BUTTON_TYPE_POWER; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_POWER); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { + button->type = ACPI_BUTTON_TYPE_POWERF; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_POWERF); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { + button->type = ACPI_BUTTON_TYPE_SLEEP; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_SLEEP); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) { + button->type = ACPI_BUTTON_TYPE_SLEEPF; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_SLEEPF); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { + button->type = ACPI_BUTTON_TYPE_LID; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_LID); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); + } + else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n", + acpi_device_hid(device))); + result = -ENODEV; + goto end; + } + + result = acpi_button_add_fs(device); + if (0 != result) + goto end; + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWERF: + status = acpi_install_fixed_event_handler ( + ACPI_EVENT_POWER_BUTTON, + acpi_button_notify_fixed, + button); + break; + case ACPI_BUTTON_TYPE_SLEEPF: + status = acpi_install_fixed_event_handler ( + ACPI_EVENT_SLEEP_BUTTON, + acpi_button_notify_fixed, + button); + break; + default: + status = acpi_install_notify_handler ( + button->handle, + ACPI_DEVICE_NOTIFY, + acpi_button_notify, + button); + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s [%s]\n", + acpi_device_name(device), acpi_device_bid(device)); + +end: + if (0 != result) { + acpi_button_remove_fs(device); + kfree(button); + } + + return_VALUE(result); +} + + +int +acpi_button_remove (struct acpi_device *device, int type) +{ + acpi_status status = 0; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + /* Unregister for device notifications. */ + switch (button->type) { + case ACPI_BUTTON_TYPE_POWERF: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); + break; + case ACPI_BUTTON_TYPE_SLEEPF: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); + break; + default: + status = acpi_remove_notify_handler(button->handle, + ACPI_DEVICE_NOTIFY, acpi_button_notify); + break; + } + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_button_remove_fs(device); + + kfree(button); + + return_VALUE(0); +} + + +static int __init +acpi_button_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_button_init"); + + result = acpi_bus_register_driver(&acpi_button_driver); + if (0 > result) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static void __exit +acpi_button_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_button_exit"); + + acpi_bus_unregister_driver(&acpi_button_driver); + + return_VOID; +} + + +module_init(acpi_button_init); +module_exit(acpi_button_exit); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/Makefile linux2.4.21_itanium/drivers/acpi/debugger/Makefile --- linux2.4.21_itanium.org/drivers/acpi/debugger/Makefile Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/Makefile Wed Jul 23 18:28:13 2003 @@ -1,11 +1,10 @@ # # Makefile for all Linux ACPI interpreter subdirectories -# EXCEPT for the ospm directory # O_TARGET := $(notdir $(CURDIR)).o -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) +obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbcmds.c linux2.4.21_itanium/drivers/acpi/debugger/dbcmds.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbcmds.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbcmds.c Wed Jul 23 18:28:12 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,21 +25,17 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" #include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #include "acresrc.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbcmds") + ACPI_MODULE_NAME ("dbcmds") /* @@ -47,7 +43,7 @@ * These object types map directly to the ACPI_TYPES */ -ARGUMENT_INFO acpi_db_object_types [] = +static ARGUMENT_INFO acpi_db_object_types [] = { {"ANY"}, {"NUMBERS"}, {"STRINGS"}, @@ -79,6 +75,8 @@ * DESCRIPTION: Check if this namespace object refers to the target object * that is passed in as the context value. * + * Note: Currently doesn't check subobjects within the Node's object + * ******************************************************************************/ acpi_status @@ -95,20 +93,13 @@ /* Check for match against the namespace node itself */ if (node == (void *) obj_desc) { - acpi_os_printf ("Object is a Node [%4.4s]\n", &node->name); + acpi_os_printf ("Object is a Node [%4.4s]\n", node->name.ascii); } /* Check for match against the object attached to the node */ - if (node->object == obj_desc) { - acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, &node->name); - } - - /* Check first child for a match */ - /* TBD: [Investigate] probably now obsolete with new datastructure */ - - if (node->child == (void *) obj_desc) { - acpi_os_printf ("Reference at Node->Child %p [%4.4s]\n", node, &node->name); + if (acpi_ns_get_attached_object (node) == obj_desc) { + acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, node->name.ascii); } return (AE_OK); @@ -136,11 +127,11 @@ /* Convert string to object pointer */ - obj_desc = (acpi_operand_object *) STRTOUL (object_arg, NULL, 16); + obj_desc = ACPI_TO_POINTER (ACPI_STRTOUL (object_arg, NULL, 16)); /* Search all nodes in namespace */ - acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_references, (void *) obj_desc, NULL); } @@ -227,7 +218,7 @@ /* Search all tables for the target type */ for (i = 0; i < NUM_ACPI_TABLES; i++) { - if (!STRNCMP (table_arg, acpi_gbl_acpi_table_data[i].signature, + if (!ACPI_STRNCMP (table_arg, acpi_gbl_acpi_table_data[i].signature, acpi_gbl_acpi_table_data[i].sig_length)) { /* Found the table, unload it */ @@ -279,14 +270,14 @@ /* Get and verify the breakpoint address */ - address = STRTOUL (location, NULL, 16); - if (address <= op->aml_offset) { - acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->aml_offset); + address = ACPI_STRTOUL (location, NULL, 16); + if (address <= op->common.aml_offset) { + acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->common.aml_offset); } /* Save breakpoint in current walk */ - walk_state->method_breakpoint = address; + walk_state->user_breakpoint = address; acpi_os_printf ("Breakpoint set at AML offset %X\n", address); } @@ -348,10 +339,9 @@ } if (statements) { - num_statements = STRTOUL (statements, NULL, 0); + num_statements = ACPI_STRTOUL (statements, NULL, 0); } - acpi_db_display_op (NULL, op, num_statements); } @@ -385,13 +375,13 @@ /* Check if numeric argument, must be a Node */ if ((start_arg[0] >= 0x30) && (start_arg[0] <= 0x39)) { - subtree_entry = (acpi_handle) STRTOUL (start_arg, NULL, 16); + subtree_entry = ACPI_TO_POINTER (ACPI_STRTOUL (start_arg, NULL, 16)); if (!acpi_os_readable (subtree_entry, sizeof (acpi_namespace_node))) { acpi_os_printf ("Address %p is invalid in this address space\n", subtree_entry); return; } - if (!VALID_DESCRIPTOR_TYPE ((subtree_entry), ACPI_DESC_TYPE_NAMED)) { + if (ACPI_GET_DESCRIPTOR_TYPE (subtree_entry) != ACPI_DESC_TYPE_NAMED) { acpi_os_printf ("Address %p is not a valid Named object\n", subtree_entry); return; } @@ -411,19 +401,18 @@ /* Now we can check for the depth argument */ if (depth_arg) { - max_depth = STRTOUL (depth_arg, NULL, 0); + max_depth = ACPI_STRTOUL (depth_arg, NULL, 0); } } - - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("ACPI Namespace (from %p subtree):\n", subtree_entry); /* Display the subtree */ - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, ACPI_UINT32_MAX, subtree_entry); - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); } @@ -450,24 +439,22 @@ u16 owner_id; - owner_id = (u16) STRTOUL (owner_arg, NULL, 0); - + owner_id = (u16) ACPI_STRTOUL (owner_arg, NULL, 0); /* Now we can check for the depth argument */ if (depth_arg) { - max_depth = STRTOUL (depth_arg, NULL, 0); + max_depth = ACPI_STRTOUL (depth_arg, NULL, 0); } - - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("ACPI Namespace by owner %X:\n", owner_id); /* Display the subtree */ - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, owner_id, subtree_entry); - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); } @@ -491,6 +478,7 @@ u32 value) { acpi_namespace_node *node; + acpi_status status; /* Translate name to an Named object */ @@ -508,7 +496,10 @@ /* Send the notify */ - acpi_ev_queue_notify_request (node, value); + status = acpi_ev_queue_notify_request (node, value); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not queue notify\n"); + } break; default: @@ -545,11 +536,12 @@ u32 value; acpi_walk_state *walk_state; acpi_operand_object *obj_desc; + acpi_status status; /* Validate Type_arg */ - STRUPR (type_arg); + ACPI_STRUPR (type_arg); type = type_arg[0]; if ((type != 'L') && (type != 'A')) { @@ -559,8 +551,8 @@ /* Get the index and value */ - index = STRTOUL (index_arg, NULL, 16); - value = STRTOUL (value_arg, NULL, 16); + index = ACPI_STRTOUL (index_arg, NULL, 16); + value = ACPI_STRTOUL (value_arg, NULL, 16); walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); if (!walk_state) { @@ -587,12 +579,16 @@ /* Set a method argument */ - if (index > MTH_NUM_ARGS) { + if (index > MTH_MAX_ARG) { acpi_os_printf ("Arg%d - Invalid argument name\n", index); return; } - acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state); + status = acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + obj_desc = walk_state->arguments[index].object; acpi_os_printf ("Arg%d: ", index); @@ -603,12 +599,16 @@ /* Set a method local */ - if (index > MTH_NUM_LOCALS) { + if (index > MTH_MAX_LOCAL) { acpi_os_printf ("Local%d - Invalid local variable name\n", index); return; } - acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state); + status = acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + obj_desc = walk_state->local_variables[index].object; acpi_os_printf ("Local%d: ", index); @@ -642,23 +642,22 @@ { acpi_operand_object *obj_desc; acpi_status status; - u32 buf_size; - NATIVE_CHAR buffer[64]; + acpi_buffer buffer; - obj_desc = ((acpi_namespace_node *)obj_handle)->object; - buf_size = sizeof (buffer) / sizeof (*buffer); + obj_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) obj_handle); /* Get and display the full pathname to this object */ - status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer); - + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname (obj_handle, &buffer); if (ACPI_FAILURE (status)) { acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); return (AE_OK); } - acpi_os_printf ("%32s", buffer); + acpi_os_printf ("%32s", buffer.pointer); + ACPI_MEM_FREE (buffer.pointer); /* Display short information about the object */ @@ -688,6 +687,10 @@ case ACPI_TYPE_BUFFER: acpi_os_printf (" Length %X", obj_desc->buffer.length); break; + + default: + /* Ignore other object types */ + break; } } @@ -714,7 +717,7 @@ NATIVE_CHAR *obj_type_arg, NATIVE_CHAR *display_count_arg) { - acpi_object_type8 type; + acpi_object_type type; /* Get the object type */ @@ -725,17 +728,17 @@ return (AE_OK); } - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace: \n", acpi_ut_get_type_name (type)); - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); /* Walk the namespace from the root */ - acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_specific_objects, (void *) &type, NULL); - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); return (AE_OK); } @@ -763,8 +766,7 @@ acpi_status status; NATIVE_CHAR *requested_name = (NATIVE_CHAR *) context; u32 i; - u32 buf_size; - NATIVE_CHAR buffer[96]; + acpi_buffer buffer; /* Check for a name match */ @@ -773,7 +775,7 @@ /* Wildcard support */ if ((requested_name[i] != '?') && - (requested_name[i] != ((NATIVE_CHAR *) (&((acpi_namespace_node *) obj_handle)->name))[i])) { + (requested_name[i] != ((acpi_namespace_node *) obj_handle)->name.ascii[i])) { /* No match, just exit */ return (AE_OK); @@ -783,16 +785,15 @@ /* Get the full pathname to this object */ - buf_size = sizeof (buffer) / sizeof (*buffer); - - status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname (obj_handle, &buffer); if (ACPI_FAILURE (status)) { acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); } - else { - acpi_os_printf ("%32s (%p) - %s\n", buffer, obj_handle, + acpi_os_printf ("%32s (%p) - %s\n", buffer.pointer, obj_handle, acpi_ut_get_type_name (((acpi_namespace_node *) obj_handle)->type)); + ACPI_MEM_FREE (buffer.pointer); } return (AE_OK); @@ -817,17 +818,17 @@ NATIVE_CHAR *name_arg) { - if (STRLEN (name_arg) > 4) { + if (ACPI_STRLEN (name_arg) > 4) { acpi_os_printf ("Name must be no longer than 4 characters\n"); return (AE_OK); } /* Walk the namespace from the root */ - acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_and_match_name, name_arg, NULL); - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); return (AE_OK); } @@ -849,6 +850,9 @@ acpi_db_set_scope ( NATIVE_CHAR *name) { + acpi_status status; + acpi_namespace_node *node; + if (!name || name[0] == 0) { acpi_os_printf ("Current scope: %s\n", acpi_gbl_db_scope_buf); @@ -857,19 +861,38 @@ acpi_db_prep_namestring (name); - /* TBD: [Future] Validate scope here */ if (name[0] == '\\') { - STRCPY (acpi_gbl_db_scope_buf, name); - STRCAT (acpi_gbl_db_scope_buf, "\\"); - } + /* Validate new scope from the root */ + + status = acpi_ns_get_node_by_path (name, acpi_gbl_root_node, ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_FAILURE (status)) { + goto error_exit; + } + ACPI_STRCPY (acpi_gbl_db_scope_buf, name); + ACPI_STRCAT (acpi_gbl_db_scope_buf, "\\"); + } else { - STRCAT (acpi_gbl_db_scope_buf, name); - STRCAT (acpi_gbl_db_scope_buf, "\\"); + /* Validate new scope relative to old scope */ + + status = acpi_ns_get_node_by_path (name, acpi_gbl_db_scope_node, ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_FAILURE (status)) { + goto error_exit; + } + + ACPI_STRCAT (acpi_gbl_db_scope_buf, name); + ACPI_STRCAT (acpi_gbl_db_scope_buf, "\\"); } + acpi_gbl_db_scope_node = node; acpi_os_printf ("New scope: %s\n", acpi_gbl_db_scope_buf); + return; + + +error_exit: + + acpi_os_printf ("Could not attach scope: %s, %s\n", name, acpi_format_exception (status)); } @@ -889,24 +912,25 @@ acpi_db_display_resources ( NATIVE_CHAR *object_arg) { -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 + acpi_operand_object *obj_desc; acpi_status status; acpi_buffer return_obj; - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_dbg_level |= ACPI_LV_RESOURCES; /* Convert string to object pointer */ - obj_desc = (acpi_operand_object *) STRTOUL (object_arg, NULL, 16); + obj_desc = ACPI_TO_POINTER (ACPI_STRTOUL (object_arg, NULL, 16)); /* Prepare for a return object of arbitrary size */ return_obj.pointer = acpi_gbl_db_buffer; return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - /* _PRT */ acpi_os_printf ("Evaluating _PRT\n"); @@ -950,10 +974,17 @@ status = acpi_get_current_resources (obj_desc, &return_obj); if (ACPI_FAILURE (status)) { acpi_os_printf ("Acpi_get_current_resources failed: %s\n", acpi_format_exception (status)); + goto get_prs; } else { - acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer); + acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); + } + + status = acpi_set_current_resources (obj_desc, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Acpi_set_current_resources failed: %s\n", acpi_format_exception (status)); + goto get_prs; } @@ -980,17 +1011,102 @@ } else { - acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer); + acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); } cleanup: - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); return; #endif } +typedef struct +{ + u32 nodes; + u32 objects; +} ACPI_INTEGRITY_INFO; + +/******************************************************************************* + * + * FUNCTION: Acpi_db_integrity_walk + * + * PARAMETERS: Callback from Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Examine one NS node for valid values. + * + ******************************************************************************/ + +acpi_status +acpi_db_integrity_walk ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_INTEGRITY_INFO *info = (ACPI_INTEGRITY_INFO *) context; + acpi_namespace_node *node = (acpi_namespace_node *) obj_handle; + acpi_operand_object *object; + + + info->nodes++; + if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { + acpi_os_printf ("Invalid Descriptor Type for Node %p, Type = %X\n", + node, ACPI_GET_DESCRIPTOR_TYPE (node)); + } + + if (node->type > INTERNAL_TYPE_MAX) { + acpi_os_printf ("Invalid Object Type for Node %p, Type = %X\n", + node, node->type); + } + + if (!acpi_ut_valid_acpi_name (node->name.integer)) { + acpi_os_printf ("Invalid Acpi_name for Node %p\n", node); + } + + object = acpi_ns_get_attached_object (node); + if (object) { + info->objects++; + if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf ("Invalid Descriptor Type for Object %p, Type = %X\n", + object, ACPI_GET_DESCRIPTOR_TYPE (object)); + } + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_check_integrity + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Check entire namespace for data structure integrity + * + ******************************************************************************/ + +void +acpi_db_check_integrity (void) +{ + ACPI_INTEGRITY_INFO info = {0,0}; + + /* Search all nodes in namespace */ + + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_integrity_walk, (void *) &info, NULL); + + acpi_os_printf ("Verified %d namespace nodes with %d Objects\n", info.nodes, info.objects); + +} + #endif /* ENABLE_DEBUGGER */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbdisasm.c linux2.4.21_itanium/drivers/acpi/debugger/dbdisasm.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbdisasm.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbdisasm.c Wed Jul 23 18:28:12 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -34,14 +34,13 @@ #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbdisasm") + ACPI_MODULE_NAME ("dbdisasm") -#define MAX_SHOW_ENTRY 128 #define BLOCK_PAREN 1 #define BLOCK_BRACE 2 #define DB_NO_OP_INFO " [%2.2d] " -#define DB_FULL_OP_INFO "%5.5X #%4.4X [%2.2d] " +#define DB_FULL_OP_INFO "%5.5X #%4.4hX [%2.2d] " NATIVE_CHAR *acpi_gbl_db_disasm_indent = "...."; @@ -64,17 +63,15 @@ acpi_parse_object *op) { - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_METHOD_OP: return (BLOCK_BRACE); - break; default: break; } return (BLOCK_PAREN); - } @@ -101,11 +98,23 @@ acpi_parse_object *op) { acpi_parse_object *target_op; + char *name; + if (op->common.flags & ACPI_PARSEOP_GENERIC) { + name = op->common.value.name; + if (name[0] == '\\') { + acpi_os_printf (" (Fully Qualified Pathname)"); + return (AE_OK); + } + } + else { + name = (char *) &op->named.name; + } + /* Search parent tree up to the root if necessary */ - target_op = acpi_ps_find (op, op->value.name, 0, 0); + target_op = acpi_ps_find (op, name, 0, 0); if (!target_op) { /* * Didn't find the name in the parse tree. This may be @@ -115,7 +124,6 @@ */ acpi_os_printf (" **** Path not found in parse tree"); } - else { /* The target was found, print the name and complete path */ @@ -136,8 +144,7 @@ { acpi_status status; acpi_namespace_node *node; - NATIVE_CHAR buffer[MAX_SHOW_ENTRY]; - u32 buffer_size = MAX_SHOW_ENTRY; + acpi_buffer buffer; u32 debug_level; @@ -148,12 +155,12 @@ /* Just get the Node out of the Op object */ - node = op->node; + node = op->common.node; if (!node) { /* Node not defined in this scope, look it up */ - status = acpi_ns_lookup (walk_state->scope_info, op->value.string, ACPI_TYPE_ANY, - IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); if (ACPI_FAILURE (status)) { /* @@ -167,18 +174,20 @@ /* Save it for next time. */ - op->node = node; + op->common.node = node; } /* Convert Named_desc/handle to a full pathname */ - status = acpi_ns_handle_to_pathname (node, &buffer_size, buffer); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname (node, &buffer); if (ACPI_FAILURE (status)) { acpi_os_printf ("****Could not get pathname****)"); goto exit; } - acpi_os_printf (" (Path %s)", buffer); + acpi_os_printf (" (Path %s)", buffer.pointer); + ACPI_MEM_FREE (buffer.pointer); exit: @@ -219,118 +228,116 @@ u32 j; - if (op) { - while (op) { - /* indentation */ - - depth_count = 0; - if (!acpi_gbl_db_opt_verbose) { - depth_count++; + if (!op) { + acpi_db_display_opcode (walk_state, op); + return; + } + + + while (op) { + /* Indentation */ + + depth_count = 0; + if (!acpi_gbl_db_opt_verbose) { + depth_count++; + } + + /* Determine the nesting depth of this argument */ + + for (depth = op->common.parent; depth; depth = depth->common.parent) { + arg = acpi_ps_get_arg (depth, 0); + while (arg && arg != origin) { + arg = arg->common.next; } - /* Determine the nesting depth of this argument */ + if (arg) { + break; + } - for (depth = op->parent; depth; depth = depth->parent) { - arg = acpi_ps_get_arg (depth, 0); - while (arg && arg != origin) { - arg = arg->next; - } + depth_count++; + } - if (arg) { - break; - } + /* Open a new block if we are nested further than last time */ - depth_count++; + if (depth_count > last_depth) { + VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth)); + for (i = 0; i < last_depth; i++) { + acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); } + if (acpi_db_block_type (op) == BLOCK_PAREN) { + acpi_os_printf ("(\n"); + } + else { + acpi_os_printf ("{\n"); + } + } - /* Open a new block if we are nested further than last time */ + /* Close a block if we are nested less than last time */ - if (depth_count > last_depth) { - VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth)); - for (i = 0; i < last_depth; i++) { + else if (depth_count < last_depth) { + for (j = last_depth; j >= (depth_count + 1); j--) { + VERBOSE_PRINT ((DB_NO_OP_INFO, (j - 1))); + for (i = 1; i < j; i++) { acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); } if (acpi_db_block_type (op) == BLOCK_PAREN) { - acpi_os_printf ("(\n"); + acpi_os_printf (")\n"); } else { - acpi_os_printf ("{\n"); + acpi_os_printf ("}\n"); } } + } - /* Close a block if we are nested less than last time */ - - else if (depth_count < last_depth) { - for (j = 0; j < (last_depth - depth_count); j++) { - VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - j)); - for (i = 0; i < (last_depth - j - 1); i++) { - acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); - } - - if (acpi_db_block_type (op) == BLOCK_PAREN) { - acpi_os_printf (")\n"); - } - else { - acpi_os_printf ("}\n"); - } - } - } - - /* In verbose mode, print the AML offset, opcode and depth count */ - - VERBOSE_PRINT ((DB_FULL_OP_INFO, (unsigned) op->aml_offset, op->opcode, depth_count)); + /* In verbose mode, print the AML offset, opcode and depth count */ + VERBOSE_PRINT ((DB_FULL_OP_INFO, (u32) op->common.aml_offset, + op->common.aml_opcode, depth_count)); - /* Indent the output according to the depth count */ - for (i = 0; i < depth_count; i++) { - acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); - } + /* Indent the output according to the depth count */ + for (i = 0; i < depth_count; i++) { + acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); + } - /* Now print the opcode */ + /* Now print the opcode */ - acpi_db_display_opcode (walk_state, op); + acpi_db_display_opcode (walk_state, op); - /* Resolve a name reference */ + /* Resolve a name reference */ - if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name) && - (op->parent) && - (acpi_gbl_db_opt_verbose)) { - acpi_ps_display_object_pathname (walk_state, op); - } + if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP && op->common.value.name) && + (op->common.parent) && + (acpi_gbl_db_opt_verbose)) { + (void) acpi_ps_display_object_pathname (walk_state, op); + } - acpi_os_printf ("\n"); + acpi_os_printf ("\n"); - /* Get the next node in the tree */ + /* Get the next node in the tree */ - op = acpi_ps_get_depth_next (origin, op); - last_depth = depth_count; + op = acpi_ps_get_depth_next (origin, op); + last_depth = depth_count; - num_opcodes--; - if (!num_opcodes) { - op = NULL; - } + num_opcodes--; + if (!num_opcodes) { + op = NULL; } + } - /* Close the last block(s) */ + /* Close the last block(s) */ - depth_count = last_depth -1; - for (i = 0; i < last_depth; i++) { - VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i)); - for (j = 0; j < depth_count; j++) { - acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); - } - acpi_os_printf ("}\n"); - depth_count--; + depth_count = last_depth -1; + for (i = 0; i < last_depth; i++) { + VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i)); + for (j = 0; j < depth_count; j++) { + acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); } - - } - - else { - acpi_db_display_opcode (walk_state, op); + acpi_os_printf ("}\n"); + depth_count--; } } @@ -352,7 +359,6 @@ NATIVE_CHAR *name) { u32 seg_count; - u8 do_dot = FALSE; if (!name) { @@ -360,21 +366,27 @@ return; } - if (acpi_ps_is_prefix_char (GET8 (name))) { - /* append prefix character */ + /* Handle all Scope Prefix operators */ + + while (acpi_ps_is_prefix_char (ACPI_GET8 (name))) { + /* Append prefix character */ - acpi_os_printf ("%1c", GET8 (name)); + acpi_os_printf ("%1c", ACPI_GET8 (name)); name++; } - switch (GET8 (name)) { + switch (ACPI_GET8 (name)) { + case 0: + seg_count = 0; + break; + case AML_DUAL_NAME_PREFIX: seg_count = 2; name++; break; case AML_MULTI_NAME_PREFIX_OP: - seg_count = (u32) GET8 (name + 1); + seg_count = (u32) ACPI_GET8 (name + 1); name += 2; break; @@ -383,19 +395,18 @@ break; } - while (seg_count--) { - /* append Name segment */ + while (seg_count) { + /* Append Name segment */ + + acpi_os_printf ("%4.4s", name); - if (do_dot) { - /* append dot */ + seg_count--; + if (seg_count) { + /* Not last name, append dot separator */ acpi_os_printf ("."); } - - acpi_os_printf ("%4.4s", name); - do_dot = TRUE; - - name += 4; + name += ACPI_NAME_SIZE; } } @@ -428,16 +439,15 @@ /* We are only interested in named objects */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (!(op_info->flags & AML_NSNODE)) { return; } - if (op_info->flags & AML_CREATE) { /* Field creation - check for a fully qualified namepath */ - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { @@ -445,9 +455,9 @@ } if ((name_path) && - (name_path->value.string) && - (name_path->value.string[0] == '\\')) { - acpi_db_display_namestring (name_path->value.string); + (name_path->common.value.string) && + (name_path->common.value.string[0] == '\\')) { + acpi_db_display_namestring (name_path->common.value.string); return; } } @@ -459,17 +469,17 @@ search = op; for (; ;) { - if (search->parent == prev) { + if (search->common.parent == prev) { break; } /* Go up one level */ - search = search->parent; + search = search->common.parent; } if (prev) { - op_info = acpi_ps_get_opcode_info (search->opcode); + op_info = acpi_ps_get_opcode_info (search->common.aml_opcode); if (!(op_info->flags & AML_FIELD)) { /* below root scope, append scope name */ @@ -480,7 +490,7 @@ } if (op_info->flags & AML_CREATE) { - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { @@ -488,11 +498,10 @@ } if ((name_path) && - (name_path->value.string)) { - acpi_os_printf ("%4.4s", name_path->value.string); + (name_path->common.value.string)) { + acpi_os_printf ("%4.4s", name_path->common.value.string); } } - else { name = acpi_ps_get_name (search); acpi_os_printf ("%4.4s", &name); @@ -536,134 +545,119 @@ if (!op) { acpi_os_printf (""); + return; } - /* op and arguments */ - switch (op->opcode) { - + switch (op->common.aml_opcode) { case AML_BYTE_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u8) 0x%2.2X", op->value.integer8); + acpi_os_printf ("(u8) 0x%2.2hX", op->common.value.integer8); } - else { - acpi_os_printf ("0x%2.2X", op->value.integer8); + acpi_os_printf ("0x%2.2hX", op->common.value.integer8); } - break; case AML_WORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u16) 0x%4.4X", op->value.integer16); + acpi_os_printf ("(u16) 0x%4.4hX", op->common.value.integer16); } - else { - acpi_os_printf ("0x%4.4X", op->value.integer16); + acpi_os_printf ("0x%4.4hX", op->common.value.integer16); } - break; case AML_DWORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u32) 0x%8.8X", op->value.integer32); + acpi_os_printf ("(u32) 0x%8.8X", op->common.value.integer32); } - else { - acpi_os_printf ("0x%8.8X", op->value.integer32); + acpi_os_printf ("0x%8.8X", op->common.value.integer32); } - break; case AML_QWORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->value.integer64.hi, - op->value.integer64.lo); + acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->common.value.integer64.hi, + op->common.value.integer64.lo); } - else { - acpi_os_printf ("0x%8.8X%8.8X", op->value.integer64.hi, - op->value.integer64.lo); + acpi_os_printf ("0x%8.8X%8.8X", op->common.value.integer64.hi, + op->common.value.integer64.lo); } - break; case AML_STRING_OP: - if (op->value.string) { - acpi_os_printf ("\"%s\"", op->value.string); + if (op->common.value.string) { + acpi_os_printf ("\"%s\"", op->common.value.string); } - else { acpi_os_printf ("<\"NULL STRING PTR\">"); } - break; case AML_INT_STATICSTRING_OP: - if (op->value.string) { - acpi_os_printf ("\"%s\"", op->value.string); + if (op->common.value.string) { + acpi_os_printf ("\"%s\"", op->common.value.string); } - else { acpi_os_printf ("\"\""); } - break; case AML_INT_NAMEPATH_OP: - acpi_db_display_namestring (op->value.name); + acpi_db_display_namestring (op->common.value.name); break; case AML_INT_NAMEDFIELD_OP: - acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_RESERVEDFIELD_OP: - acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_ACCESSFIELD_OP: - acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_BYTELIST_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->common.value.integer32); } - else { - acpi_os_printf ("0x%2.2X", op->value.integer32); + acpi_os_printf ("0x%2.2X", op->common.value.integer32); - byte_count = op->value.integer32; - byte_data = ((acpi_parse2_object *) op)->data; + byte_count = op->common.value.integer32; + byte_data = op->named.data; for (i = 0; i < byte_count; i++) { acpi_os_printf (", 0x%2.2X", byte_data[i]); } } - break; @@ -671,25 +665,25 @@ /* Just get the opcode name and print it */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); acpi_os_printf ("%s", op_info->name); #ifndef PARSER_ONLY - if ((op->opcode == AML_INT_RETURN_VALUE_OP) && + if ((op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) && + (walk_state) && (walk_state->results) && (walk_state->results->results.num_results)) { acpi_db_decode_internal_object (walk_state->results->results.obj_desc [walk_state->results->results.num_results-1]); } #endif - break; } if (!op_info) { /* If there is another element in the list, add a comma */ - if (op->next) { + if (op->common.next) { acpi_os_printf (","); } } @@ -697,19 +691,16 @@ /* * If this is a named opcode, print the associated name value */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (op && (op_info->flags & AML_NAMED)) { name = acpi_ps_get_name (op); acpi_os_printf (" %4.4s", &name); - if (acpi_gbl_db_opt_verbose) { - acpi_os_printf (" (Path \\"); - acpi_db_display_path (op); - acpi_os_printf (")"); + if ((acpi_gbl_db_opt_verbose) && (op->common.aml_opcode != AML_INT_NAMEDFIELD_OP)) { + (void) acpi_ps_display_object_pathname (walk_state, op); } } } - #endif /* ENABLE_DEBUGGER */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbdisply.c linux2.4.21_itanium/drivers/acpi/debugger/dbdisply.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbdisply.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbdisply.c Wed Jul 23 18:28:12 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,12 +25,10 @@ #include "acpi.h" -#include "acparser.h" #include "amlcode.h" #include "acdispat.h" #include "acnamesp.h" #include "acparser.h" -#include "acevents.h" #include "acinterp.h" #include "acdebug.h" @@ -39,7 +37,7 @@ #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbdisply") + ACPI_MODULE_NAME ("dbdisply") /****************************************************************************** @@ -61,7 +59,7 @@ void *obj_ptr; -#ifdef _IA16 +#if ACPI_MACHINE_WIDTH == 16 #include /* Have to handle 16-bit pointers of the form segment:offset */ @@ -75,8 +73,7 @@ /* Simple flat pointer */ - obj_ptr = (void *) STRTOUL (target, NULL, 16); - + obj_ptr = ACPI_TO_POINTER (ACPI_STRTOUL (target, NULL, 16)); #endif return (obj_ptr); @@ -102,16 +99,16 @@ const acpi_opcode_info *info; - info = acpi_ps_get_opcode_info (op->opcode); + info = acpi_ps_get_opcode_info (op->common.aml_opcode); acpi_os_printf ("Parser Op Descriptor:\n"); - acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode); + acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode); - DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name)); + ACPI_DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name)); - acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->value); - acpi_os_printf ("%20.20s : %p\n", "Parent", op->parent); - acpi_os_printf ("%20.20s : %p\n", "Next_op", op->next); + acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->common.value.arg); + acpi_os_printf ("%20.20s : %p\n", "Parent", op->common.parent); + acpi_os_printf ("%20.20s : %p\n", "Next_op", op->common.next); } @@ -136,6 +133,7 @@ { void *obj_ptr; acpi_namespace_node *node; + acpi_operand_object *obj_desc; u32 display = DB_BYTE_DISPLAY; NATIVE_CHAR buffer[80]; acpi_buffer ret_buf; @@ -150,7 +148,7 @@ /* Decode the output type */ if (output_type) { - STRUPR (output_type); + ACPI_STRUPR (output_type); if (output_type[0] == 'W') { display = DB_WORD_DISPLAY; } @@ -162,7 +160,6 @@ } } - ret_buf.length = sizeof (buffer); ret_buf.pointer = buffer; @@ -177,8 +174,10 @@ /* Decode the object type */ - if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_NAMED)) { - /* This is a Node */ + switch (ACPI_GET_DESCRIPTOR_TYPE (obj_ptr)) { + case ACPI_DESC_TYPE_NAMED: + + /* This is a namespace Node */ if (!acpi_os_readable (obj_ptr, sizeof (acpi_namespace_node))) { acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr); @@ -187,10 +186,11 @@ node = obj_ptr; goto dump_nte; - } - else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_INTERNAL)) { - /* This is an ACPI OBJECT */ + + case ACPI_DESC_TYPE_OPERAND: + + /* This is a ACPI OPERAND OBJECT */ if (!acpi_os_readable (obj_ptr, sizeof (acpi_operand_object))) { acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr); @@ -199,22 +199,27 @@ acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); acpi_ex_dump_object_descriptor (obj_ptr, 1); - } + break; - else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_PARSER)) { - /* This is an Parser Op object */ + + case ACPI_DESC_TYPE_PARSER: + + /* This is a Parser Op object */ if (!acpi_os_readable (obj_ptr, sizeof (acpi_parse_object))) { acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr); return; } - acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_parse_object), display, ACPI_UINT32_MAX); acpi_db_dump_parser_descriptor ((acpi_parse_object *) obj_ptr); - } + break; + + + default: + + /* Is not a recognizeable object */ - else { size = 16; if (acpi_os_readable (obj_ptr, 64)) { size = 64; @@ -223,12 +228,12 @@ /* Just dump some memory */ acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX); + break; } return; } - /* The parameter is a name string that must be resolved to a Named obj */ node = acpi_db_local_ns_lookup (target); @@ -257,15 +262,16 @@ acpi_ut_dump_buffer ((void *) node, sizeof (acpi_namespace_node), display, ACPI_UINT32_MAX); acpi_ex_dump_node (node, 1); - if (node->object) { - acpi_os_printf ("\n_attached Object (%p):\n", node->object); - if (!acpi_os_readable (node->object, sizeof (acpi_operand_object))) { - acpi_os_printf ("Invalid internal ACPI Object at address %p\n", node->object); + obj_desc = acpi_ns_get_attached_object (node); + if (obj_desc) { + acpi_os_printf ("\n_attached Object (%p):\n", obj_desc); + if (!acpi_os_readable (obj_desc, sizeof (acpi_operand_object))) { + acpi_os_printf ("Invalid internal ACPI Object at address %p\n", obj_desc); return; } - acpi_ut_dump_buffer ((void *) node->object, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); - acpi_ex_dump_object_descriptor (node->object, 1); + acpi_ut_dump_buffer ((void *) obj_desc, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); + acpi_ex_dump_object_descriptor (obj_desc, 1); } } @@ -290,6 +296,7 @@ if (!obj_desc) { + acpi_os_printf (" Uninitialized\n"); return; } @@ -298,8 +305,8 @@ switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: - acpi_os_printf (" %.8X%.8X", HIDWORD (obj_desc->integer.value), - LODWORD (obj_desc->integer.value)); + acpi_os_printf (" %8.8X%8.8X", ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; @@ -326,6 +333,11 @@ acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]); } break; + + + default: + /* No additional display for other types */ + break; } } @@ -358,29 +370,35 @@ return; } - /* Decode the object type */ - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_PARSER)) { + switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { + case ACPI_DESC_TYPE_PARSER: + acpi_os_printf (" "); - } + break; + + + case ACPI_DESC_TYPE_NAMED: - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { acpi_os_printf (" Name %4.4s Type-%s", - &((acpi_namespace_node *)obj_desc)->name, + ((acpi_namespace_node *)obj_desc)->name.ascii, acpi_ut_get_type_name (((acpi_namespace_node *) obj_desc)->type)); + if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_ARG) { acpi_os_printf (" [Method Arg]"); } if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_LOCAL) { acpi_os_printf (" [Method Local]"); } - } + break; + + + case ACPI_DESC_TYPE_OPERAND: - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { type = obj_desc->common.type; if (type > INTERNAL_TYPE_MAX) { - acpi_os_printf (" Type %x [Invalid Type]", type); + acpi_os_printf (" Type %hX [Invalid Type]", type); return; } @@ -406,10 +424,10 @@ break; case AML_LOCAL_OP: - acpi_os_printf ("[Local%d]", obj_desc->reference.offset); + acpi_os_printf ("[Local%d] ", obj_desc->reference.offset); if (walk_state) { obj_desc = walk_state->local_variables[obj_desc->reference.offset].object; - acpi_os_printf (" %p", obj_desc); + acpi_os_printf ("%p", obj_desc); acpi_db_decode_internal_object (obj_desc); } break; @@ -418,7 +436,7 @@ acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset); if (walk_state) { obj_desc = walk_state->arguments[obj_desc->reference.offset].object; - acpi_os_printf (" %p", obj_desc); + acpi_os_printf ("%p", obj_desc); acpi_db_decode_internal_object (obj_desc); } break; @@ -428,7 +446,7 @@ break; case AML_INDEX_OP: - acpi_os_printf ("[Index] "); + acpi_os_printf ("[Index] "); acpi_db_decode_internal_object (obj_desc->reference.object); break; @@ -444,10 +462,13 @@ acpi_db_decode_internal_object (obj_desc); break; } - } + break; + + + default: - else { acpi_os_printf (" "); + break; } acpi_os_printf ("\n"); @@ -494,18 +515,18 @@ } obj_desc = walk_state->method_desc; - node = walk_state->method_node; + node = walk_state->method_node; - num_args = obj_desc->method.param_count; + num_args = obj_desc->method.param_count; concurrency = obj_desc->method.concurrency; - acpi_os_printf ("Currently executing control method is [%4.4s]\n", &node->name); + acpi_os_printf ("Currently executing control method is [%4.4s]\n", node->name.ascii); acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency); root_op = start_op; - while (root_op->parent) { - root_op = root_op->parent; + while (root_op->common.parent) { + root_op = root_op->common.parent; } op = root_op; @@ -522,7 +543,7 @@ /* Decode the opcode */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); switch (op_info->class) { case AML_CLASS_ARGUMENT: if (count_remaining) { @@ -546,7 +567,6 @@ break; } - op = acpi_ps_get_depth_next (start_op, op); } @@ -587,9 +607,7 @@ obj_desc = walk_state->method_desc; node = walk_state->method_node; - - - acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name); + acpi_os_printf ("Local Variables for method [%4.4s]:\n", node->name.ascii); for (i = 0; i < MTH_NUM_LOCALS; i++) { obj_desc = walk_state->local_variables[i].object; @@ -629,12 +647,13 @@ } obj_desc = walk_state->method_desc; - node = walk_state->method_node; + node = walk_state->method_node; - num_args = obj_desc->method.param_count; + num_args = obj_desc->method.param_count; concurrency = obj_desc->method.concurrency; - acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", &node->name, num_args, concurrency); + acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", + node->name.ascii, num_args, concurrency); for (i = 0; i < num_args; i++) { obj_desc = walk_state->arguments[i].object; @@ -679,7 +698,8 @@ num_results = walk_state->results->results.num_results; } - acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", &node->name, num_results); + acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", + node->name.ascii, num_results); for (i = 0; i < num_results; i++) { obj_desc = walk_state->results->results.obj_desc[i]; @@ -704,7 +724,6 @@ void acpi_db_display_calling_tree (void) { - u32 i; acpi_walk_state *walk_state; acpi_namespace_node *node; @@ -716,13 +735,12 @@ } node = walk_state->method_node; - acpi_os_printf ("Current Control Method Call Tree\n"); - for (i = 0; walk_state; i++) { + while (walk_state) { node = walk_state->method_node; - acpi_os_printf (" [%4.4s]\n", &node->name); + acpi_os_printf (" [%4.4s]\n", node->name.ascii); walk_state = walk_state->next; } @@ -740,6 +758,10 @@ * * DESCRIPTION: Display the result of an AML opcode * + * Note: Curently only displays the result object if we are single stepping. + * However, this output may be useful in other contexts and could be enabled + * to do so if needed. + * ******************************************************************************/ void @@ -748,10 +770,8 @@ acpi_walk_state *walk_state) { - /* TBD: [Future] We don't always want to display the result. - * For now, only display if single stepping - * however, this output is very useful in other contexts also - */ + /* Only display if single stepping */ + if (!acpi_gbl_cm_single_step) { return; } @@ -781,7 +801,6 @@ acpi_walk_state *walk_state) { - if (!acpi_gbl_cm_single_step) { return; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbexec.c linux2.4.21_itanium/drivers/acpi/debugger/dbexec.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbexec.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbexec.c Wed Jul 23 18:28:12 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,23 +25,15 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbexec") + ACPI_MODULE_NAME ("dbexec") -db_method_info acpi_gbl_db_method_info; +static acpi_db_method_info acpi_gbl_db_method_info; /******************************************************************************* @@ -59,7 +51,7 @@ acpi_status acpi_db_execute_method ( - db_method_info *info, + acpi_db_method_info *info, acpi_buffer *return_obj) { acpi_status status; @@ -77,13 +69,12 @@ if (info->args && info->args[0]) { for (i = 0; info->args[i] && i < MTH_NUM_ARGS; i++) { params[i].type = ACPI_TYPE_INTEGER; - params[i].integer.value = STRTOUL (info->args[i], NULL, 16); + params[i].integer.value = ACPI_STRTOUL (info->args[i], NULL, 16); } param_objects.pointer = params; param_objects.count = i; } - else { /* Setup default parameters */ @@ -103,7 +94,6 @@ return_obj->pointer = acpi_gbl_db_buffer; return_obj->length = ACPI_DEBUG_BUFFER_SIZE; - /* Do the actual method execution */ status = acpi_evaluate_object (NULL, info->pathname, ¶m_objects, return_obj); @@ -129,7 +119,7 @@ void acpi_db_execute_setup ( - db_method_info *info) + acpi_db_method_info *info) { /* Catenate the current scope to the supplied name */ @@ -137,24 +127,24 @@ info->pathname[0] = 0; if ((info->name[0] != '\\') && (info->name[0] != '/')) { - STRCAT (info->pathname, acpi_gbl_db_scope_buf); + ACPI_STRCAT (info->pathname, acpi_gbl_db_scope_buf); } - STRCAT (info->pathname, info->name); + ACPI_STRCAT (info->pathname, info->name); acpi_db_prep_namestring (info->pathname); - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("Executing %s\n", info->pathname); if (info->flags & EX_SINGLE_STEP) { acpi_gbl_cm_single_step = TRUE; - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); } else { /* No single step, allow redirection to a file */ - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); } } @@ -174,13 +164,14 @@ ******************************************************************************/ u32 -acpi_db_get_outstanding_allocations (void) +acpi_db_get_outstanding_allocations ( + void) { - u32 i; u32 outstanding = 0; - #ifdef ACPI_DBG_TRACK_ALLOCATIONS + u32 i; + for (i = ACPI_MEM_LIST_FIRST_CACHE_LIST; i < ACPI_NUM_MEM_LISTS; i++) { outstanding += (acpi_gbl_memory_lists[i].total_allocated - @@ -248,7 +239,7 @@ allocations = acpi_db_get_outstanding_allocations () - previous_allocations; - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); if (allocations > 0) { acpi_os_printf ("Outstanding: %ld allocations after execution\n", @@ -271,7 +262,7 @@ } } - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); } @@ -288,12 +279,12 @@ * ******************************************************************************/ -void +void ACPI_SYSTEM_XFACE acpi_db_method_thread ( void *context) { acpi_status status; - db_method_info *info = context; + acpi_db_method_info *info = context; u32 i; acpi_buffer return_obj; @@ -311,7 +302,10 @@ /* Signal our completion */ - acpi_os_signal_semaphore (info->thread_gate, 1); + status = acpi_os_signal_semaphore (info->thread_gate, 1); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not signal debugger semaphore\n"); + } } @@ -344,15 +338,14 @@ /* Get the arguments */ - num_threads = STRTOUL (num_threads_arg, NULL, 0); - num_loops = STRTOUL (num_loops_arg, NULL, 0); + num_threads = ACPI_STRTOUL (num_threads_arg, NULL, 0); + num_loops = ACPI_STRTOUL (num_loops_arg, NULL, 0); if (!num_threads || !num_loops) { acpi_os_printf ("Bad argument: Threads %X, Loops %X\n", num_threads, num_loops); return; } - /* Create the synchronization semaphore */ status = acpi_os_create_semaphore (1, 0, &thread_gate); @@ -371,16 +364,17 @@ acpi_db_execute_setup (&acpi_gbl_db_method_info); - /* Create the threads */ acpi_os_printf ("Creating %X threads to execute %X times each\n", num_threads, num_loops); for (i = 0; i < (num_threads); i++) { - acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); + status = acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); + if (ACPI_FAILURE (status)) { + break; + } } - /* Wait for all threads to complete */ i = num_threads; @@ -391,11 +385,11 @@ /* Cleanup and exit */ - acpi_os_delete_semaphore (thread_gate); + (void) acpi_os_delete_semaphore (thread_gate); - acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("All threads (%X) have completed\n", num_threads); - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbfileio.c linux2.4.21_itanium/drivers/acpi/debugger/dbfileio.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbfileio.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbfileio.c Wed Jul 23 18:28:12 2003 @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,14 +28,12 @@ #include "acpi.h" #include "acdebug.h" #include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" #include "actables.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbfileio") + ACPI_MODULE_NAME ("dbfileio") /* @@ -64,7 +62,7 @@ * ******************************************************************************/ -acpi_object_type8 +acpi_object_type acpi_db_match_argument ( NATIVE_CHAR *user_argument, ARGUMENT_INFO *arguments) @@ -77,8 +75,8 @@ } for (i = 0; arguments[i].name; i++) { - if (STRSTR (arguments[i].name, user_argument) == arguments[i].name) { - return ((acpi_object_type8) i); + if (ACPI_STRSTR (arguments[i].name, user_argument) == arguments[i].name) { + return (i); } } @@ -141,7 +139,7 @@ acpi_gbl_debug_file = fopen (name, "w+"); if (acpi_gbl_debug_file) { acpi_os_printf ("Debug output file %s opened\n", name); - STRCPY (acpi_gbl_db_debug_filename, name); + ACPI_STRCPY (acpi_gbl_db_debug_filename, name); acpi_gbl_db_output_to_file = TRUE; } else { @@ -167,7 +165,7 @@ * ******************************************************************************/ -acpi_status +static acpi_status acpi_db_load_table( FILE *fp, acpi_table_header **table_ptr, @@ -200,11 +198,11 @@ /* We only support a limited number of table types */ - if (STRNCMP ((char *) table_header.signature, DSDT_SIG, 4) && - STRNCMP ((char *) table_header.signature, PSDT_SIG, 4) && - STRNCMP ((char *) table_header.signature, SSDT_SIG, 4)) { + if (ACPI_STRNCMP ((char *) table_header.signature, DSDT_SIG, 4) && + ACPI_STRNCMP ((char *) table_header.signature, PSDT_SIG, 4) && + ACPI_STRNCMP ((char *) table_header.signature, SSDT_SIG, 4)) { acpi_os_printf ("Table signature is invalid\n"); - DUMP_BUFFER (&table_header, sizeof (acpi_table_header)); + ACPI_DUMP_BUFFER (&table_header, sizeof (acpi_table_header)); return (AE_ERROR); } @@ -224,7 +222,7 @@ /* Copy the header to the buffer */ - MEMCPY (*table_ptr, &table_header, sizeof (table_header)); + ACPI_MEMCPY (*table_ptr, &table_header, sizeof (table_header)); /* Get the rest of the table */ @@ -275,7 +273,7 @@ acpi_table_desc table_info; - FUNCTION_TRACE ("Ae_local_load_table"); + ACPI_FUNCTION_TRACE ("Ae_local_load_table"); if (!table_ptr) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -285,7 +283,7 @@ table_info.pointer = table_ptr; - status = acpi_tb_install_table (NULL, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by Acpi_tb_get_table */ @@ -308,27 +306,14 @@ } -/******************************************************************************* - * - * FUNCTION: Acpi_db_load_acpi_table - * - * PARAMETERS: Filname - File where table is located - * - * RETURN: Status - * - * DESCRIPTION: Load an ACPI table from a file - * - ******************************************************************************/ - +#ifdef ACPI_APPLICATION acpi_status -acpi_db_load_acpi_table ( +acpi_db_get_acpi_table ( NATIVE_CHAR *filename) { -#ifdef ACPI_APPLICATION FILE *fp; - acpi_status status; u32 table_length; - + acpi_status status; /* Open the file */ @@ -350,25 +335,52 @@ return (status); } - /* Attempt to recognize and install the table */ + return (AE_OK); + } +#endif + +/******************************************************************************* + * + * FUNCTION: Acpi_db_load_acpi_table + * + * PARAMETERS: Filname - File where table is located + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a file + * + ******************************************************************************/ + +acpi_status +acpi_db_load_acpi_table ( + NATIVE_CHAR *filename) { +#ifdef ACPI_APPLICATION + acpi_status status; + + + status = acpi_db_get_acpi_table (filename); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Attempt to recognize and install the table */ status = ae_local_load_table (acpi_gbl_db_table_ptr); if (ACPI_FAILURE (status)) { - if (status == AE_EXIST) { + if (status == AE_ALREADY_EXISTS) { acpi_os_printf ("Table %4.4s is already installed\n", - &acpi_gbl_db_table_ptr->signature); + acpi_gbl_db_table_ptr->signature); } else { acpi_os_printf ("Could not install table, %s\n", acpi_format_exception (status)); } - acpi_os_free (acpi_gbl_db_table_ptr); 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); + acpi_gbl_db_table_ptr->signature, acpi_gbl_db_table_ptr); acpi_gbl_acpi_hardware_present = FALSE; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbhistry.c linux2.4.21_itanium/drivers/acpi/debugger/dbhistry.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbhistry.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbhistry.c Wed Jul 23 18:28:12 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,20 +25,12 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbhistry") + ACPI_MODULE_NAME ("dbhistry") #define HI_NO_HISTORY 0 @@ -54,11 +46,11 @@ } HISTORY_INFO; -HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; -u16 acpi_gbl_lo_history = 0; -u16 acpi_gbl_num_history = 0; -u16 acpi_gbl_next_history_index = 0; -u32 acpi_gbl_next_cmd_num = 1; +static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; +static u16 acpi_gbl_lo_history = 0; +static u16 acpi_gbl_num_history = 0; +static u16 acpi_gbl_next_history_index = 0; +static u32 acpi_gbl_next_cmd_num = 1; /******************************************************************************* @@ -78,10 +70,9 @@ NATIVE_CHAR *command_line) { - /* Put command into the next available slot */ - STRCPY (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command, command_line); + ACPI_STRCPY (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command, command_line); acpi_gbl_history_buffer[acpi_gbl_next_history_index].cmd_num = acpi_gbl_next_cmd_num; @@ -100,12 +91,10 @@ acpi_gbl_next_history_index = 0; } - acpi_gbl_next_cmd_num++; if (acpi_gbl_num_history < HISTORY_SIZE) { acpi_gbl_num_history++; } - } @@ -171,10 +160,9 @@ } else { - cmd_num = STRTOUL (command_num_arg, NULL, 0); + cmd_num = ACPI_STRTOUL (command_num_arg, NULL, 0); } - /* Search history buffer */ history_index = acpi_gbl_lo_history; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbinput.c linux2.4.21_itanium/drivers/acpi/debugger/dbinput.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbinput.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbinput.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,66 +25,20 @@ #include "acpi.h" -#include "acparser.h" -#include "actables.h" -#include "acnamesp.h" -#include "acinterp.h" #include "acdebug.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbinput") + ACPI_MODULE_NAME ("dbinput") /* - * Globals that are specific to the debugger - */ - -NATIVE_CHAR acpi_gbl_db_line_buf[80]; -NATIVE_CHAR acpi_gbl_db_parsed_buf[80]; -NATIVE_CHAR acpi_gbl_db_scope_buf[40]; -NATIVE_CHAR acpi_gbl_db_debug_filename[40]; -NATIVE_CHAR *acpi_gbl_db_args[DB_MAX_ARGS]; -NATIVE_CHAR *acpi_gbl_db_buffer = NULL; -NATIVE_CHAR *acpi_gbl_db_filename = NULL; -u8 acpi_gbl_db_output_to_file = FALSE; - -u32 acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2; -u32 acpi_gbl_db_console_debug_level = NORMAL_DEFAULT | ACPI_LV_TABLES; -u8 acpi_gbl_db_output_flags = DB_CONSOLE_OUTPUT; - - -u8 acpi_gbl_db_opt_tables = FALSE; -u8 acpi_gbl_db_opt_disasm = FALSE; -u8 acpi_gbl_db_opt_stats = FALSE; -u8 acpi_gbl_db_opt_parse_jit = FALSE; -u8 acpi_gbl_db_opt_verbose = TRUE; -u8 acpi_gbl_db_opt_ini_methods = TRUE; - -/* - * Statistic globals - */ -u16 acpi_gbl_obj_type_count[INTERNAL_TYPE_NODE_MAX+1]; -u16 acpi_gbl_node_type_count[INTERNAL_TYPE_NODE_MAX+1]; -u16 acpi_gbl_obj_type_count_misc; -u16 acpi_gbl_node_type_count_misc; -u32 acpi_gbl_num_nodes; -u32 acpi_gbl_num_objects; - - -u32 acpi_gbl_size_of_parse_tree; -u32 acpi_gbl_size_of_method_trees; -u32 acpi_gbl_size_of_node_entries; -u32 acpi_gbl_size_of_acpi_objects; - -/* * Top-level debugger commands. * * This list of commands must match the string table below it */ - enum acpi_ex_debugger_commands { CMD_NOT_FOUND = 0, @@ -109,6 +63,7 @@ CMD_HISTORY_EXE, CMD_HISTORY_LAST, CMD_INFORMATION, + CMD_INTEGRITY, CMD_INTO, CMD_LEVEL, CMD_LIST, @@ -139,7 +94,7 @@ #define CMD_FIRST_VALID 2 -const COMMAND_INFO acpi_gbl_db_commands[] = +static const COMMAND_INFO acpi_gbl_db_commands[] = { {"", 0}, {"", 0}, {"ALLOCATIONS", 0}, @@ -162,6 +117,7 @@ {"!", 1}, {"!!", 0}, {"INFORMATION", 0}, + {"INTEGRITY", 0}, {"INTO", 0}, {"LEVEL", 0}, {"LIST", 0}, @@ -224,13 +180,11 @@ } - /* * Parameter is the command class * * The idea here is to keep each class of commands smaller than a screenful */ - switch (help_type[0]) { case 'G': @@ -295,7 +249,7 @@ return; default: - acpi_os_printf ("Unrecognized Command Class: %x\n", help_type); + acpi_os_printf ("Unrecognized Command Class: %X\n", help_type); return; } } @@ -321,6 +275,7 @@ { NATIVE_CHAR *start; + /* At end of buffer? */ if (!string || !(*string)) @@ -328,7 +283,6 @@ return (NULL); } - /* Get rid of any spaces at the beginning */ if (*string == ' ') @@ -353,12 +307,10 @@ string++; } - if (!(*string)) { *next = NULL; } - else { *string = 0; @@ -392,11 +344,11 @@ NATIVE_CHAR *this; - STRCPY (acpi_gbl_db_parsed_buf, input_buffer); - STRUPR (acpi_gbl_db_parsed_buf); + ACPI_STRCPY (acpi_gbl_db_parsed_buf, input_buffer); + ACPI_STRUPR (acpi_gbl_db_parsed_buf); this = acpi_gbl_db_parsed_buf; - for (i = 0; i < DB_MAX_ARGS; i++) + for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++) { acpi_gbl_db_args[i] = acpi_db_get_next_token (this, &next); if (!acpi_gbl_db_args[i]) @@ -407,12 +359,11 @@ this = next; } - /* Uppercase the actual command */ if (acpi_gbl_db_args[0]) { - STRUPR (acpi_gbl_db_args[0]); + ACPI_STRUPR (acpi_gbl_db_args[0]); } count = i; @@ -451,7 +402,8 @@ for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) { - if (STRSTR (acpi_gbl_db_commands[i].name, user_command) == acpi_gbl_db_commands[i].name) + if (ACPI_STRSTR (acpi_gbl_db_commands[i].name, user_command) == + acpi_gbl_db_commands[i].name) { return (i); } @@ -572,7 +524,7 @@ break; case CMD_FIND: - acpi_db_find_name_in_namespace (acpi_gbl_db_args[1]); + status = acpi_db_find_name_in_namespace (acpi_gbl_db_args[1]); break; case CMD_GO: @@ -601,7 +553,6 @@ status = AE_CTRL_TRUE; } return (status); - break; case CMD_HISTORY_LAST: command_line = acpi_db_get_from_history (NULL); @@ -621,13 +572,14 @@ acpi_db_display_method_info (op); break; + case CMD_INTEGRITY: + acpi_db_check_integrity (); + break; + case CMD_INTO: if (op) { acpi_gbl_cm_single_step = TRUE; - -/* TBD: Must get current walk state */ - /* Acpi_gbl_Method_breakpoint = 0; */ return (AE_OK); } break; @@ -641,13 +593,13 @@ else if (param_count == 2) { temp = acpi_gbl_db_console_debug_level; - acpi_gbl_db_console_debug_level = STRTOUL (acpi_gbl_db_args[1], NULL, 16); + acpi_gbl_db_console_debug_level = ACPI_STRTOUL (acpi_gbl_db_args[1], NULL, 16); acpi_os_printf ("Debug Level for console output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_console_debug_level); } else { temp = acpi_gbl_db_debug_level; - acpi_gbl_db_debug_level = STRTOUL (acpi_gbl_db_args[1], NULL, 16); + acpi_gbl_db_debug_level = ACPI_STRTOUL (acpi_gbl_db_args[1], NULL, 16); acpi_os_printf ("Debug Level for file output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_debug_level); } break; @@ -673,7 +625,7 @@ break; case CMD_METHODS: - acpi_db_display_objects ("METHOD", acpi_gbl_db_args[1]); + status = acpi_db_display_objects ("METHOD", acpi_gbl_db_args[1]); break; case CMD_NAMESPACE: @@ -681,12 +633,13 @@ break; case CMD_NOTIFY: - temp = STRTOUL (acpi_gbl_db_args[2], NULL, 0); + temp = ACPI_STRTOUL (acpi_gbl_db_args[2], NULL, 0); acpi_db_send_notify (acpi_gbl_db_args[1], temp); break; case CMD_OBJECT: - acpi_db_display_objects (STRUPR (acpi_gbl_db_args[1]), acpi_gbl_db_args[2]); + ACPI_STRUPR (acpi_gbl_db_args[1]); + status = acpi_db_display_objects (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); break; case CMD_OPEN: @@ -718,19 +671,18 @@ break; case CMD_STATS: - acpi_db_display_statistics (acpi_gbl_db_args[1]); + status = acpi_db_display_statistics (acpi_gbl_db_args[1]); break; case CMD_STOP: - return (AE_AML_ERROR); - break; + return (AE_NOT_IMPLEMENTED); case CMD_TABLES: acpi_db_display_table_info (acpi_gbl_db_args[1]); break; case CMD_TERMINATE: - acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); acpi_ut_subsystem_shutdown (); /* TBD: [Restructure] Need some way to re-initialize without re-creating the semaphores! */ @@ -773,6 +725,7 @@ return (AE_CTRL_TERMINATE); case CMD_NOT_FOUND: + default: acpi_os_printf ("Unknown Command\n"); return (AE_CTRL_TRUE); } @@ -798,11 +751,12 @@ * ******************************************************************************/ -void +void ACPI_SYSTEM_XFACE acpi_db_execute_thread ( void *context) { acpi_status status = AE_OK; + acpi_status Mstatus; while (status != AE_CTRL_TERMINATE) @@ -810,9 +764,19 @@ acpi_gbl_method_executing = FALSE; acpi_gbl_step_to_next_call = FALSE; - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + Mstatus = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (Mstatus)) + { + return; + } + status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); - acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + + Mstatus = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (Mstatus)) + { + return; + } } } @@ -834,13 +798,11 @@ acpi_db_single_thread ( void) { - acpi_status status = AE_OK; - acpi_gbl_method_executing = FALSE; acpi_gbl_step_to_next_call = FALSE; - status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); + (void) acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); } @@ -872,23 +834,22 @@ { /* Force output to console until a command is entered */ - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); /* Different prompt if method is executing */ if (!acpi_gbl_method_executing) { - acpi_os_printf ("%1c ", DB_COMMAND_PROMPT); + acpi_os_printf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); } else { - acpi_os_printf ("%1c ", DB_EXECUTE_PROMPT); + acpi_os_printf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); } /* Get the user input line */ - acpi_os_get_line (acpi_gbl_db_line_buf); - + (void) acpi_os_get_line (acpi_gbl_db_line_buf); /* Check for single or multithreaded debug */ @@ -898,10 +859,18 @@ * Signal the debug thread that we have a command to execute, * and wait for the command to complete. */ - acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_READY); - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + status = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (status)) + { + return (status); + } + + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (status)) + { + return (status); + } } - else { /* Just call to the command line interpreter */ @@ -910,12 +879,11 @@ } } - /* * Only this thread (the original thread) should actually terminate the subsystem, * because all the semaphores are deleted during termination */ - acpi_terminate (); + status = acpi_terminate (); return (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbstats.c linux2.4.21_itanium/drivers/acpi/debugger/dbstats.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbstats.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbstats.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,19 +26,17 @@ #include #include -#include -#include #include #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbstats") + ACPI_MODULE_NAME ("dbstats") /* * Statistics subcommands */ -ARGUMENT_INFO acpi_db_stat_types [] = +static ARGUMENT_INFO acpi_db_stat_types [] = { {"ALLOCATIONS"}, {"OBJECTS"}, {"MEMORY"}, @@ -49,13 +47,13 @@ {NULL} /* Must be null terminated */ }; -#define CMD_ALLOCATIONS 0 -#define CMD_OBJECTS 1 -#define CMD_MEMORY 2 -#define CMD_MISC 3 -#define CMD_TABLES 4 -#define CMD_SIZES 5 -#define CMD_STACK 6 +#define CMD_STAT_ALLOCATIONS 0 +#define CMD_STAT_OBJECTS 1 +#define CMD_STAT_MEMORY 2 +#define CMD_STAT_MISC 3 +#define CMD_STAT_TABLES 4 +#define CMD_STAT_SIZES 5 +#define CMD_STAT_STACK 6 /******************************************************************************* @@ -67,9 +65,8 @@ * RETURN: None * * DESCRIPTION: Add this object to the global counts, by object type. - * Recursively handles subobjects and packages. - * - * [TBD] Restructure - remove recursion. + * Limited recursion handles subobjects and packages, and this + * is probably acceptable within the AML debugger only. * ******************************************************************************/ @@ -77,7 +74,6 @@ acpi_db_enumerate_object ( acpi_operand_object *obj_desc) { - u32 type; u32 i; @@ -91,22 +87,21 @@ acpi_gbl_num_objects++; - type = obj_desc->common.type; - if (type > INTERNAL_TYPE_NODE_MAX) + if (obj_desc->common.type > INTERNAL_TYPE_NODE_MAX) { acpi_gbl_obj_type_count_misc++; } else { - acpi_gbl_obj_type_count [type]++; + acpi_gbl_obj_type_count [obj_desc->common.type]++; } /* Count the sub-objects */ - switch (type) + switch (obj_desc->common.type) { case ACPI_TYPE_PACKAGE: - for (i = 0; i< obj_desc->package.count; i++) + for (i = 0; i < obj_desc->package.count; i++) { acpi_db_enumerate_object (obj_desc->package.elements[i]); } @@ -118,7 +113,15 @@ acpi_db_enumerate_object (obj_desc->device.addr_handler); break; + case ACPI_TYPE_BUFFER_FIELD: + if (acpi_ns_get_secondary_object (obj_desc)) + { + acpi_gbl_obj_type_count [ACPI_TYPE_BUFFER_FIELD]++; + } + break; + case ACPI_TYPE_REGION: + acpi_gbl_obj_type_count [INTERNAL_TYPE_REGION_FIELD ]++; acpi_db_enumerate_object (obj_desc->region.addr_handler); break; @@ -138,6 +141,9 @@ acpi_db_enumerate_object (obj_desc->thermal_zone.drv_handler); acpi_db_enumerate_object (obj_desc->thermal_zone.addr_handler); break; + + default: + break; } } @@ -172,7 +178,7 @@ acpi_gbl_num_nodes++; node = (acpi_namespace_node *) obj_handle; - obj_desc = ((acpi_namespace_node *) obj_handle)->object; + obj_desc = acpi_ns_get_attached_object (node); acpi_db_enumerate_object (obj_desc); @@ -227,7 +233,7 @@ * ******************************************************************************/ -acpi_status +void acpi_db_count_namespace_objects ( void) { @@ -244,10 +250,8 @@ acpi_gbl_node_type_count [i] = 0; } - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, FALSE, acpi_db_classify_one_object, NULL, NULL); - - return (AE_OK); } #endif @@ -271,8 +275,10 @@ { u32 i; u32 type; - u32 outstanding; u32 size; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + u32 outstanding; +#endif if (!acpi_gbl_DSDT) @@ -286,7 +292,7 @@ return (AE_OK); } - STRUPR (type_arg); + ACPI_STRUPR (type_arg); type = acpi_db_match_argument (type_arg, acpi_db_stat_types); if (type == (u32) -1) { @@ -298,14 +304,14 @@ switch (type) { #ifndef PARSER_ONLY - case CMD_ALLOCATIONS: + case CMD_STAT_ALLOCATIONS: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_ut_dump_allocation_info (); #endif break; #endif - case CMD_TABLES: + case CMD_STAT_TABLES: acpi_os_printf ("ACPI Table Information:\n\n"); if (acpi_gbl_DSDT) @@ -314,7 +320,7 @@ } break; - case CMD_OBJECTS: + case CMD_STAT_OBJECTS: #ifndef PARSER_ONLY @@ -338,7 +344,7 @@ #endif break; - case CMD_MEMORY: + case CMD_STAT_MEMORY: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_os_printf ("\n----Object and Cache Statistics---------------------------------------------\n"); @@ -368,11 +374,11 @@ if (acpi_gbl_memory_lists[i].object_size) { - size = ROUND_UP_TO_1K (outstanding * acpi_gbl_memory_lists[i].object_size); + size = ACPI_ROUND_UP_TO_1K (outstanding * acpi_gbl_memory_lists[i].object_size); } else { - size = ROUND_UP_TO_1K (acpi_gbl_memory_lists[i].current_total_size); + size = ACPI_ROUND_UP_TO_1K (acpi_gbl_memory_lists[i].current_total_size); } acpi_os_printf (" Mem: [Alloc Free Outstanding Size] % 7d % 7d % 7d % 7d Kb\n", @@ -384,7 +390,7 @@ break; - case CMD_MISC: + case CMD_STAT_MISC: acpi_os_printf ("\n_miscellaneous Statistics:\n\n"); acpi_os_printf ("Calls to Acpi_ps_find:.. ........% 7ld\n", acpi_gbl_ps_find_count); @@ -400,7 +406,7 @@ break; - case CMD_SIZES: + case CMD_STAT_SIZES: acpi_os_printf ("\n_internal object sizes:\n\n"); @@ -425,26 +431,33 @@ acpi_os_printf ("Notify_handler %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); acpi_os_printf ("Addr_handler %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); acpi_os_printf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); + acpi_os_printf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); acpi_os_printf ("\n"); - acpi_os_printf ("Parse_object %3d\n", sizeof (acpi_parse_object)); - acpi_os_printf ("Parse2_object %3d\n", sizeof (acpi_parse2_object)); + acpi_os_printf ("Parse_object %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); + acpi_os_printf ("Parse_object_named %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); + acpi_os_printf ("Parse_object_asl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); acpi_os_printf ("Operand_object %3d\n", sizeof (acpi_operand_object)); acpi_os_printf ("Namespace_node %3d\n", sizeof (acpi_namespace_node)); break; - case CMD_STACK: + case CMD_STAT_STACK: +#if defined(ACPI_DEBUG) - size = acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer; + size = (u32) (acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer); acpi_os_printf ("\n_subsystem Stack Usage:\n\n"); acpi_os_printf ("Entry Stack Pointer %X\n", acpi_gbl_entry_stack_pointer); acpi_os_printf ("Lowest Stack Pointer %X\n", acpi_gbl_lowest_stack_pointer); acpi_os_printf ("Stack Use %X (%d)\n", size, size); acpi_os_printf ("Deepest Procedure Nesting %d\n", acpi_gbl_deepest_nesting); +#endif + break; + + default: break; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbutils.c linux2.4.21_itanium/drivers/acpi/debugger/dbutils.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbutils.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbutils.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,9 +28,6 @@ #include "acparser.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" #include "acdispat.h" @@ -38,7 +35,7 @@ #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbutils") + ACPI_MODULE_NAME ("dbutils") /******************************************************************************* @@ -61,10 +58,8 @@ acpi_gbl_db_output_flags = (u8) output_flags; - if (output_flags & DB_REDIRECTABLE_OUTPUT) { - if (acpi_gbl_db_output_to_file) { - acpi_dbg_level = acpi_gbl_db_debug_level; - } + if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) && acpi_gbl_db_output_to_file) { + acpi_dbg_level = acpi_gbl_db_debug_level; } else { acpi_dbg_level = acpi_gbl_db_console_debug_level; @@ -92,7 +87,7 @@ acpi_os_printf ("\n_location %X:\n", address); acpi_dbg_level |= ACPI_LV_TABLES; - acpi_ut_dump_buffer ((u8 *) address, 64, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + acpi_ut_dump_buffer (ACPI_TO_POINTER (address), 64, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); } @@ -135,8 +130,9 @@ case ACPI_TYPE_INTEGER: - acpi_os_printf ("[Integer] = %8.8X%8.8X\n", HIDWORD (obj_desc->integer.value), - LODWORD (obj_desc->integer.value)); + acpi_os_printf ("[Integer] = %8.8X%8.8X\n", + ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; @@ -152,7 +148,7 @@ case ACPI_TYPE_BUFFER: - acpi_os_printf ("[Buffer] = "); + acpi_os_printf ("[Buffer] Length %.2X = ", obj_desc->buffer.length); acpi_ut_dump_buffer ((u8 *) obj_desc->buffer.pointer, obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT); break; @@ -215,7 +211,7 @@ return; } - STRUPR (name); + ACPI_STRUPR (name); /* Convert a leading forward slash to a backslash */ @@ -260,7 +256,7 @@ acpi_parse_object *root) { acpi_parse_object *op = root; - acpi_parse2_object *method; + acpi_parse_object *method; acpi_parse_object *search_op; acpi_parse_object *start_op; acpi_status status = AE_OK; @@ -268,15 +264,16 @@ acpi_walk_state *walk_state; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); acpi_os_printf ("Pass two parse ....\n"); - while (op) { - if (op->opcode == AML_METHOD_OP) { - method = (acpi_parse2_object *) op; + if (op->common.aml_opcode == AML_METHOD_OP) { + method = op; + + /* Create a new walk state for the parse */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); @@ -284,32 +281,32 @@ return (AE_NO_MEMORY); } + /* Init the Walk State */ walk_state->parser_state.aml = - walk_state->parser_state.aml_start = method->data; + walk_state->parser_state.aml_start = method->named.data; walk_state->parser_state.aml_end = - walk_state->parser_state.pkg_end = method->data + method->length; + walk_state->parser_state.pkg_end = method->named.data + method->named.length; walk_state->parser_state.start_scope = op; walk_state->descending_callback = acpi_ds_load1_begin_op; walk_state->ascending_callback = acpi_ds_load1_end_op; + /* Perform the AML parse */ status = acpi_ps_parse_aml (walk_state); - - base_aml_offset = (method->value.arg)->aml_offset + 1; - start_op = (method->value.arg)->next; + base_aml_offset = (method->common.value.arg)->common.aml_offset + 1; + start_op = (method->common.value.arg)->common.next; search_op = start_op; while (search_op) { - search_op->aml_offset += base_aml_offset; + search_op->common.aml_offset += base_aml_offset; search_op = acpi_ps_get_depth_next (start_op, search_op); } - } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { /* TBD: [Investigate] this isn't quite the right thing to do! */ /* * @@ -339,6 +336,9 @@ * * DESCRIPTION: Lookup a name in the ACPI namespace * + * Note: Currently begins search from the root. Could be enhanced to use + * the current prefix (scope) node as the search beginning point. + * ******************************************************************************/ acpi_namespace_node * @@ -360,21 +360,17 @@ return (NULL); } - /* Lookup the name */ - - /* TBD: [Investigate] what scope do we use? */ - /* Use the root scope for the start of the search */ - - status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, IMODE_EXECUTE, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, NULL, &node); - + /* + * Lookup the name. + * (Uses root node as the search starting point) + */ + status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); if (ACPI_FAILURE (status)) { acpi_os_printf ("Could not locate name: %s %s\n", name, acpi_format_exception (status)); } - ACPI_MEM_FREE (internal_path); - return (node); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/debugger/dbxface.c linux2.4.21_itanium/drivers/acpi/debugger/dbxface.c --- linux2.4.21_itanium.org/drivers/acpi/debugger/dbxface.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/debugger/dbxface.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,19 +25,14 @@ #include "acpi.h" -#include "acparser.h" #include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER - MODULE_NAME ("dbxface") + ACPI_MODULE_NAME ("dbxface") /******************************************************************************* @@ -64,30 +59,40 @@ acpi_status status = AE_OK; u32 original_debug_level; acpi_parse_object *display_op; + acpi_parse_object *parent_op; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* Is there a breakpoint set? */ + /* Check for single-step breakpoint */ - if (walk_state->method_breakpoint) { + if (walk_state->method_breakpoint && + (walk_state->method_breakpoint <= op->common.aml_offset)) { /* Check if the breakpoint has been reached or passed */ + /* Hit the breakpoint, resume single step, reset breakpoint */ - if (walk_state->method_breakpoint <= op->aml_offset) { - /* Hit the breakpoint, resume single step, reset breakpoint */ + acpi_os_printf ("***Break*** at AML offset %X\n", op->common.aml_offset); + acpi_gbl_cm_single_step = TRUE; + acpi_gbl_step_to_next_call = FALSE; + walk_state->method_breakpoint = 0; + } - acpi_os_printf ("***Break*** at AML offset %X\n", op->aml_offset); - acpi_gbl_cm_single_step = TRUE; - acpi_gbl_step_to_next_call = FALSE; - walk_state->method_breakpoint = 0; - } + /* Check for user breakpoint (Must be on exact Aml offset) */ + + else if (walk_state->user_breakpoint && + (walk_state->user_breakpoint == op->common.aml_offset)) { + acpi_os_printf ("***User_breakpoint*** at AML offset %X\n", op->common.aml_offset); + acpi_gbl_cm_single_step = TRUE; + acpi_gbl_step_to_next_call = FALSE; + walk_state->method_breakpoint = 0; } + /* * Check if this is an opcode that we are interested in -- * namely, opcodes that have arguments */ - if (op->opcode == AML_INT_NAMEDFIELD_OP) { + if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { return (AE_OK); } @@ -95,6 +100,9 @@ case AML_CLASS_UNKNOWN: case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ return (AE_OK); + + default: + /* All other opcodes -- continue */ break; } @@ -116,15 +124,41 @@ */ original_debug_level = acpi_dbg_level; acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); - next = op->next; - op->next = NULL; + next = op->common.next; + op->common.next = NULL; display_op = op; - if (op->parent) { - if ((op->parent->opcode == AML_IF_OP) || - (op->parent->opcode == AML_WHILE_OP)) { - display_op = op->parent; + parent_op = op->common.parent; + if (parent_op) { + if ((walk_state->control_state) && + (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { + /* + * We are executing the predicate of an IF or WHILE statement + * Search upwards for the containing IF or WHILE so that the + * entire predicate can be displayed. + */ + while (parent_op) { + if ((parent_op->common.aml_opcode == AML_IF_OP) || + (parent_op->common.aml_opcode == AML_WHILE_OP)) { + display_op = parent_op; + break; + } + parent_op = parent_op->common.parent; + } + } + else { + while (parent_op) { + if ((parent_op->common.aml_opcode == AML_IF_OP) || + (parent_op->common.aml_opcode == AML_ELSE_OP) || + (parent_op->common.aml_opcode == AML_SCOPE_OP) || + (parent_op->common.aml_opcode == AML_METHOD_OP) || + (parent_op->common.aml_opcode == AML_WHILE_OP)) { + break; + } + display_op = parent_op; + parent_op = parent_op->common.parent; + } } } @@ -132,23 +166,23 @@ acpi_db_display_op (walk_state, display_op, ACPI_UINT32_MAX); - if ((op->opcode == AML_IF_OP) || - (op->opcode == AML_WHILE_OP)) { + if ((op->common.aml_opcode == AML_IF_OP) || + (op->common.aml_opcode == AML_WHILE_OP)) { if (walk_state->control_state->common.value) { - acpi_os_printf ("Predicate was TRUE, executed block\n"); + acpi_os_printf ("Predicate = [True], IF block was executed\n"); } else { - acpi_os_printf ("Predicate is FALSE, skipping block\n"); + acpi_os_printf ("Predicate = [False], Skipping IF block\n"); } } - else if (op->opcode == AML_ELSE_OP) { - /* TBD */ + else if (op->common.aml_opcode == AML_ELSE_OP) { + acpi_os_printf ("Predicate = [False], ELSE block was executed\n"); } /* Restore everything */ - op->next = next; + op->common.next = next; acpi_os_printf ("\n"); acpi_dbg_level = original_debug_level; } @@ -159,13 +193,12 @@ return (AE_OK); } - /* * If we are executing a step-to-call command, * Check if this is a method call. */ if (acpi_gbl_step_to_next_call) { - if (op->opcode != AML_INT_METHODCALL_OP) { + if (op->common.aml_opcode != AML_INT_METHODCALL_OP) { /* Not a method call, just keep executing */ return (AE_OK); @@ -176,19 +209,16 @@ acpi_gbl_step_to_next_call = FALSE; } - /* * If the next opcode is a method call, we will "step over" it * by default. */ - if (op->opcode == AML_INT_METHODCALL_OP) { + if (op->common.aml_opcode == AML_INT_METHODCALL_OP) { acpi_gbl_cm_single_step = FALSE; /* No more single step while executing called method */ - /* Set the breakpoint on the call, it will stop execution as soon as we return */ - - /* TBD: [Future] don't kill the user breakpoint! */ + /* Set the breakpoint on/before the call, it will stop execution as soon as we return */ - walk_state->method_breakpoint = /* Op->Aml_offset + */ 1; /* Must be non-zero! */ + walk_state->method_breakpoint = 1; /* Must be non-zero! */ } @@ -204,8 +234,14 @@ if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) { /* Handshake with the front-end that gets user command lines */ - acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + status = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (status)) { + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (status)) { + return (status); + } } else { @@ -213,20 +249,20 @@ /* Force output to console until a command is entered */ - acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); /* Different prompt if method is executing */ if (!acpi_gbl_method_executing) { - acpi_os_printf ("%1c ", DB_COMMAND_PROMPT); + acpi_os_printf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); } else { - acpi_os_printf ("%1c ", DB_EXECUTE_PROMPT); + acpi_os_printf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); } /* Get the user input line */ - acpi_os_get_line (acpi_gbl_db_line_buf); + (void) acpi_os_get_line (acpi_gbl_db_line_buf); } status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, walk_state, op); @@ -252,20 +288,39 @@ * ******************************************************************************/ -int +acpi_status acpi_db_initialize (void) { + acpi_status status; /* Init globals */ - acpi_gbl_db_buffer = acpi_os_callocate (ACPI_DEBUG_BUFFER_SIZE); + acpi_gbl_db_buffer = NULL; + acpi_gbl_db_filename = NULL; + acpi_gbl_db_output_to_file = FALSE; + + acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2; + acpi_gbl_db_console_debug_level = NORMAL_DEFAULT | ACPI_LV_TABLES; + acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; + + acpi_gbl_db_opt_tables = FALSE; + acpi_gbl_db_opt_disasm = FALSE; + acpi_gbl_db_opt_stats = FALSE; + acpi_gbl_db_opt_verbose = TRUE; + acpi_gbl_db_opt_ini_methods = TRUE; + + acpi_gbl_db_buffer = acpi_os_allocate (ACPI_DEBUG_BUFFER_SIZE); + if (!acpi_gbl_db_buffer) { + return (AE_NO_MEMORY); + } + ACPI_MEMSET (acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE); /* Initial scope is the root */ acpi_gbl_db_scope_buf [0] = '\\'; acpi_gbl_db_scope_buf [1] = 0; - + acpi_gbl_db_scope_node = acpi_gbl_root_node; /* * If configured for multi-thread support, the debug executor runs in @@ -275,12 +330,24 @@ if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { /* These were created with one unit, grab it */ - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not get debugger mutex\n"); + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not get debugger mutex\n"); + return (status); + } /* Create the debug execution thread to execute commands */ - acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); + status = acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not start debugger thread\n"); + return (status); + } } if (!acpi_gbl_db_opt_verbose) { @@ -289,7 +356,7 @@ acpi_gbl_db_opt_stats = FALSE; } - return (0); + return (AE_OK); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/Makefile linux2.4.21_itanium/drivers/acpi/dispatcher/Makefile --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/Makefile Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/Makefile Wed Jul 23 18:28:09 2003 @@ -1,11 +1,10 @@ # # Makefile for all Linux ACPI interpreter subdirectories -# EXCEPT for the ospm directory # O_TARGET := $(notdir $(CURDIR)).o -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) +obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsfield.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsfield.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsfield.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsfield.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -33,7 +33,7 @@ #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsfield") + ACPI_MODULE_NAME ("dsfield") /******************************************************************************* @@ -65,14 +65,16 @@ acpi_namespace_node *node; acpi_status status; acpi_operand_object *obj_desc; + acpi_operand_object *second_desc = NULL; + u32 flags; - FUNCTION_TRACE ("Ds_create_buffer_field"); + ACPI_FUNCTION_TRACE ("Ds_create_buffer_field"); /* Get the Name_string argument */ - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { arg = acpi_ps_get_arg (op, 3); } else { @@ -86,12 +88,23 @@ } /* + * During the load phase, we want to enter the name of the field into + * the namespace. During the execute phase (when we evaluate the size + * operand), we want to lookup the name + */ + if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) { + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; + } + else { + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND; + } + + /* * Enter the Name_string into the namespace */ - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_DEF_ANY, IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, + INTERNAL_TYPE_DEF_ANY, ACPI_IMODE_LOAD_PASS1, + flags, walk_state, &(node)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -100,14 +113,15 @@ * for now, we will put it in the "op" object that the parser uses, so we * can get it again at the end of this scope */ - op->node = node; + op->common.node = node; /* * If there is no object attached to the node, this node was just created and * we need to create the field object. Otherwise, this was a lookup of an * existing node and we don't want to create the field object again. */ - if (node->object) { + obj_desc = acpi_ns_get_attached_object (node); + if (obj_desc) { return_ACPI_STATUS (AE_OK); } @@ -125,27 +139,21 @@ } /* - * Allocate a method object for this field unit - */ - obj_desc->buffer_field.extra = acpi_ut_create_internal_object ( - INTERNAL_TYPE_EXTRA); - if (!obj_desc->buffer_field.extra) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* * Remember location in AML stream of the field unit * opcode and operands -- since the buffer and index * operands must be evaluated. */ - obj_desc->buffer_field.extra->extra.aml_start = ((acpi_parse2_object *) op)->data; - obj_desc->buffer_field.extra->extra.aml_length = ((acpi_parse2_object *) op)->length; + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = op->named.data; + second_desc->extra.aml_length = op->named.length; obj_desc->buffer_field.node = node; - /* Attach constructed field descriptor to parent node */ + /* Attach constructed field descriptors to parent node */ status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD); + if (ACPI_FAILURE (status)) { + goto cleanup; + } cleanup: @@ -179,9 +187,10 @@ acpi_parse_object *arg) { acpi_status status; + acpi_integer position; - PROC_NAME("acpi_ds_get_field_names"); + ACPI_FUNCTION_TRACE_PTR ("Ds_get_field_names", info); /* First field starts at bit zero */ @@ -197,48 +206,75 @@ * 2) Access_as - changes the access mode * 3) Name - Enters a new named field into the namespace */ - switch (arg->opcode) { + switch (arg->common.aml_opcode) { case AML_INT_RESERVEDFIELD_OP: - info->field_bit_position += arg->value.size; + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; + + if (position > ACPI_UINT32_MAX) { + ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n")); + return_ACPI_STATUS (AE_SUPPORT); + } + + info->field_bit_position = (u32) position; break; case AML_INT_ACCESSFIELD_OP: /* - * Get a new Access_type and Access_attribute for all - * entries (until end or another Access_as keyword) + * Get a new Access_type and Access_attribute -- to be used for all + * field units that follow, until field end or another Access_as keyword. + * + * In Field_flags, preserve the flag bits other than the ACCESS_TYPE bits */ - info->field_flags = (u8) ((info->field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); + info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | + ((u8) (arg->common.value.integer32 >> 8))); + + info->attribute = (u8) (arg->common.value.integer32); break; case AML_INT_NAMEDFIELD_OP: - /* Enter a new field name into the namespace */ + /* Lookup the name */ status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name, - info->field_type, IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &info->field_node); + (NATIVE_CHAR *) &arg->named.name, + info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, + walk_state, &info->field_node); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + if (status != AE_ALREADY_EXISTS) { + return_ACPI_STATUS (status); + } + + ACPI_REPORT_ERROR (("Field name [%4.4s] already exists in current scope\n", + &arg->named.name)); + } + else { + arg->common.node = info->field_node; + info->field_bit_length = arg->common.value.size; + + /* Create and initialize an object for the new Field Node */ + + status = acpi_ex_prep_field_value (info); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - /* Create and initialize an object for the new Field Node */ + /* Keep track of bit position for the next field */ - info->field_bit_length = arg->value.size; + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; - status = acpi_ex_prep_field_value (info); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + if (position > ACPI_UINT32_MAX) { + ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", + &info->field_node->name)); + return_ACPI_STATUS (AE_SUPPORT); } - /* Keep track of bit position for the next field */ - info->field_bit_position += info->field_bit_length; break; @@ -246,12 +282,11 @@ default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n", - arg->opcode)); - return_ACPI_STATUS (AE_AML_ERROR); - break; + arg->common.aml_opcode)); + return_ACPI_STATUS (AE_AML_BAD_OPCODE); } - arg = arg->next; + arg = arg->common.next; } return_ACPI_STATUS (AE_OK); @@ -278,21 +313,21 @@ acpi_namespace_node *region_node, acpi_walk_state *walk_state) { - acpi_status status = AE_AML_ERROR; + acpi_status status; acpi_parse_object *arg; ACPI_CREATE_FIELD_INFO info; - FUNCTION_TRACE_PTR ("Ds_create_field", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_field", op); /* First arg is the name of the parent Op_region (must already exist) */ - arg = op->value.arg; + arg = op->common.value.arg; if (!region_node) { - status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, ®ion_node); + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name, + ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -300,15 +335,16 @@ /* Second arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; + info.attribute = 0; /* Each remaining arg is a Named Field */ info.field_type = INTERNAL_TYPE_REGION_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } @@ -316,6 +352,92 @@ /******************************************************************************* * + * FUNCTION: Acpi_ds_init_field_objects + * + * PARAMETERS: Op - Op containing the Field definition and args + * ` Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: For each "Field Unit" name in the argument list that is + * part of the field declaration, enter the name into the + * namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ds_init_field_objects ( + acpi_parse_object *op, + acpi_walk_state *walk_state) +{ + acpi_status status; + acpi_parse_object *arg = NULL; + acpi_namespace_node *node; + u8 type = 0; + + + ACPI_FUNCTION_TRACE_PTR ("Ds_init_field_objects", op); + + + switch (walk_state->opcode) { + case AML_FIELD_OP: + arg = acpi_ps_get_arg (op, 2); + type = INTERNAL_TYPE_REGION_FIELD; + break; + + case AML_BANK_FIELD_OP: + arg = acpi_ps_get_arg (op, 4); + type = INTERNAL_TYPE_BANK_FIELD; + break; + + case AML_INDEX_FIELD_OP: + arg = acpi_ps_get_arg (op, 3); + type = INTERNAL_TYPE_INDEX_FIELD; + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Walk the list of entries in the Field_list + */ + while (arg) { + /* Ignore OFFSET and ACCESSAS terms here */ + + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + status = acpi_ns_lookup (walk_state->scope_info, + (NATIVE_CHAR *) &arg->named.name, + type, ACPI_IMODE_LOAD_PASS1, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, + walk_state, &node); + if (ACPI_FAILURE (status)) { + if (status != AE_ALREADY_EXISTS) { + return_ACPI_STATUS (status); + } + + ACPI_REPORT_ERROR (("Field name [%4.4s] already exists in current scope\n", + &arg->named.name)); + + /* Name already exists, just ignore this error */ + + status = AE_OK; + } + + arg->common.node = node; + } + + /* Move to next field in the list */ + + arg = arg->common.next; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_ds_create_bank_field * * PARAMETERS: Op - Op containing the Field definition and args @@ -334,21 +456,21 @@ acpi_namespace_node *region_node, acpi_walk_state *walk_state) { - acpi_status status = AE_AML_ERROR; + acpi_status status; acpi_parse_object *arg; ACPI_CREATE_FIELD_INFO info; - FUNCTION_TRACE_PTR ("Ds_create_bank_field", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_bank_field", op); /* First arg is the name of the parent Op_region (must already exist) */ - arg = op->value.arg; + arg = op->common.value.arg; if (!region_node) { - status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, ®ion_node); + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name, + ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -356,30 +478,30 @@ /* Second arg is the Bank Register (must already exist) */ - arg = arg->next; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, &info.register_node); + arg = arg->common.next; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, + INTERNAL_TYPE_BANK_FIELD_DEFN, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Third arg is the Bank_value */ - arg = arg->next; - info.bank_value = arg->value.integer32; + arg = arg->common.next; + info.bank_value = arg->common.value.integer32; /* Fourth arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; /* Each remaining arg is a Named Field */ info.field_type = INTERNAL_TYPE_BANK_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } @@ -410,33 +532,33 @@ ACPI_CREATE_FIELD_INFO info; - FUNCTION_TRACE_PTR ("Ds_create_index_field", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_index_field", op); /* First arg is the name of the Index register (must already exist) */ - arg = op->value.arg; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - ACPI_TYPE_ANY, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, &info.register_node); + arg = op->common.value.arg; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Second arg is the data register (must already exist) */ - arg = arg->next; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, &info.data_register_node); + arg = arg->common.next; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, + INTERNAL_TYPE_INDEX_FIELD_DEFN, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Next arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; /* Each remaining arg is a Named Field */ @@ -444,7 +566,7 @@ info.field_type = INTERNAL_TYPE_INDEX_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsmethod.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsmethod.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsmethod.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsmethod.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -30,12 +30,10 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acdebug.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsmethod") + ACPI_MODULE_NAME ("dsmethod") /******************************************************************************* @@ -68,7 +66,7 @@ acpi_walk_state *walk_state; - FUNCTION_TRACE_PTR ("Ds_parse_method", obj_handle); + ACPI_FUNCTION_TRACE_PTR ("Ds_parse_method", obj_handle); /* Parameter Validation */ @@ -77,14 +75,13 @@ return_ACPI_STATUS (AE_NULL_ENTRY); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Parsing [%4.4s] **** Named_obj=%p\n", - (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle)); - + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** Named_obj=%p\n", + ((acpi_namespace_node *) obj_handle)->name.ascii, obj_handle)); /* Extract the method object from the method Node */ node = (acpi_namespace_node *) obj_handle; - obj_desc = node->object; + obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } @@ -112,13 +109,20 @@ /* Init new op with the method name and pointer back to the Node */ - acpi_ps_set_name (op, node->name); - op->node = node; + acpi_ps_set_name (op, node->name.integer); + op->common.node = node; + + /* + * Get a new Owner_id for objects created by this method. Namespace + * objects (such as Operation Regions) can be created during the + * first pass parse. + */ + owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); + obj_desc->method.owning_id = owner_id; /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -126,7 +130,7 @@ status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ + acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); } @@ -145,16 +149,11 @@ return_ACPI_STATUS (status); } - /* Get a new Owner_id for objects created by this method */ - - owner_id = acpi_ut_allocate_owner_id (OWNER_TYPE_METHOD); - obj_desc->method.owning_id = owner_id; - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n", - (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle, op)); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n", + ((acpi_namespace_node *) obj_handle)->name.ascii, obj_handle, op)); acpi_ps_delete_parse_tree (op); - return_ACPI_STATUS (status); } @@ -186,14 +185,13 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_PTR ("Ds_begin_method_execution", method_node); + ACPI_FUNCTION_TRACE_PTR ("Ds_begin_method_execution", method_node); if (!method_node) { return_ACPI_STATUS (AE_NULL_ENTRY); } - /* * If there is a concurrency limit on this method, we need to * obtain a unit from the method semaphore. @@ -221,13 +219,11 @@ WAIT_FOREVER); } - /* * Increment the method parse tree thread count since it has been * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; - return_ACPI_STATUS (status); } @@ -247,9 +243,9 @@ acpi_status acpi_ds_call_control_method ( - acpi_walk_list *walk_list, + ACPI_THREAD_STATE *thread, acpi_walk_state *this_walk_state, - acpi_parse_object *op) /* TBD: This operand is obsolete */ + acpi_parse_object *op) { acpi_status status; acpi_namespace_node *method_node; @@ -258,7 +254,7 @@ u32 i; - FUNCTION_TRACE_PTR ("Ds_call_control_method", this_walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_call_control_method", this_walk_state); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", this_walk_state->prev_op, this_walk_state)); @@ -284,14 +280,12 @@ return_ACPI_STATUS (status); } - /* 1) Parse: Create a new walk state for the preempting walk */ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, op, obj_desc, NULL); if (!next_walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); - goto cleanup; } /* Create and init a Root Node */ @@ -306,7 +300,7 @@ obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ + acpi_ds_delete_walk_state (next_walk_state); goto cleanup; } @@ -315,11 +309,10 @@ status = acpi_ps_parse_aml (next_walk_state); acpi_ps_delete_parse_tree (op); - /* 2) Execute: Create a new state for the preempting walk */ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, - NULL, obj_desc, walk_list); + NULL, obj_desc, thread); if (!next_walk_state) { status = AE_NO_MEMORY; goto cleanup; @@ -353,8 +346,8 @@ this_walk_state->num_operands = 0; - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n", - next_walk_state)); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Starting nested execution, newstate=%p\n", next_walk_state)); return_ACPI_STATUS (AE_OK); @@ -362,7 +355,7 @@ /* On error, we must delete the new walk state */ cleanup: - acpi_ds_terminate_control_method (next_walk_state); + (void) acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); return_ACPI_STATUS (status); @@ -390,7 +383,7 @@ acpi_status status; - FUNCTION_TRACE_PTR ("Ds_restart_control_method", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_restart_control_method", walk_state); if (return_desc) { @@ -405,7 +398,6 @@ return_ACPI_STATUS (status); } } - else { /* * Delete the return value if it will not be used by the @@ -413,7 +405,6 @@ */ acpi_ut_remove_reference (return_desc); } - } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, @@ -421,7 +412,6 @@ walk_state->method_call_op, return_desc, walk_state->return_used, walk_state->results, walk_state)); - return_ACPI_STATUS (AE_OK); } @@ -446,12 +436,17 @@ { acpi_operand_object *obj_desc; acpi_namespace_node *method_node; + acpi_status status; - FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state); - /* The method object should be stored in the walk state */ + if (!walk_state) { + return (AE_BAD_PARAMETER); + } + + /* The current method object was saved in the walk state */ obj_desc = walk_state->method_desc; if (!obj_desc) { @@ -467,14 +462,22 @@ * If this is the last thread executing the method, * we have additional cleanup to perform */ - acpi_ut_acquire_mutex (ACPI_MTX_PARSER); - + status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { - acpi_os_signal_semaphore ( - walk_state->method_desc->method.semaphore, 1); + status = acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not signal method semaphore\n")); + status = AE_OK; + + /* Ignore error and continue cleanup */ + } } /* Decrement the thread count on the method parse tree */ @@ -493,7 +496,11 @@ * Delete any namespace entries created immediately underneath * the method */ - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + if (method_node->child) { acpi_ns_delete_namespace_subtree (method_node); } @@ -503,11 +510,14 @@ * the namespace */ acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - acpi_ut_release_mutex (ACPI_MTX_PARSER); - return_ACPI_STATUS (AE_OK); + status = acpi_ut_release_mutex (ACPI_MTX_PARSER); + return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsmthdat.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsmthdat.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsmthdat.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsmthdat.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,15 +25,13 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" -#include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsmthdat") + ACPI_MODULE_NAME ("dsmthdat") /******************************************************************************* @@ -49,49 +47,48 @@ * This allows Ref_of and De_ref_of to work properly for these * special data types. * + * NOTES: Walk_state fields are initialized to zero by the + * ACPI_MEM_CALLOCATE(). + * + * A pseudo-Namespace Node is assigned to each argument and local + * so that Ref_of() can return a pointer to the Node. + * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_init ( acpi_walk_state *walk_state) { u32 i; - FUNCTION_TRACE ("Ds_method_data_init"); + ACPI_FUNCTION_TRACE ("Ds_method_data_init"); - /* - * Walk_state fields are initialized to zero by the - * ACPI_MEM_CALLOCATE(). - * - * An Node is assigned to each argument and local so - * that Ref_of() can return a pointer to the Node. - */ /* Init the method arguments */ for (i = 0; i < MTH_NUM_ARGS; i++) { - MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name, + ACPI_MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name, NAMEOF_ARG_NTE); - walk_state->arguments[i].name |= (i << 24); - walk_state->arguments[i].data_type = ACPI_DESC_TYPE_NAMED; - walk_state->arguments[i].type = ACPI_TYPE_ANY; - walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; + walk_state->arguments[i].name.integer |= (i << 24); + walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].type = ACPI_TYPE_ANY; + walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; } /* Init the method locals */ for (i = 0; i < MTH_NUM_LOCALS; i++) { - MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name, + ACPI_MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name, NAMEOF_LOCAL_NTE); - walk_state->local_variables[i].name |= (i << 24); - walk_state->local_variables[i].data_type = ACPI_DESC_TYPE_NAMED; - walk_state->local_variables[i].type = ACPI_TYPE_ANY; - walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; + walk_state->local_variables[i].name.integer |= (i << 24); + walk_state->local_variables[i].descriptor = ACPI_DESC_TYPE_NAMED; + walk_state->local_variables[i].type = ACPI_TYPE_ANY; + walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -101,64 +98,50 @@ * * PARAMETERS: Walk_state - Current walk state object * - * RETURN: Status + * RETURN: None * * DESCRIPTION: Delete method locals and arguments. Arguments are only * deleted if this method was called from another method. * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_delete_all ( acpi_walk_state *walk_state) { u32 index; - acpi_operand_object *object; - FUNCTION_TRACE ("Ds_method_data_delete_all"); + ACPI_FUNCTION_TRACE ("Ds_method_data_delete_all"); - /* Delete the locals */ - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting local variables in %p\n", walk_state)); + /* Detach the locals */ for (index = 0; index < MTH_NUM_LOCALS; index++) { - object = walk_state->local_variables[index].object; - if (object) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n", index, object)); - - /* Remove first */ + if (walk_state->local_variables[index].object) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n", + index, walk_state->local_variables[index].object)); - walk_state->local_variables[index].object = NULL; + /* Detach object (if present) and remove a reference */ - /* Was given a ref when stored */ - - acpi_ut_remove_reference (object); - } + acpi_ns_detach_object (&walk_state->local_variables[index]); + } } - - /* Delete the arguments */ - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting arguments in %p\n", walk_state)); + /* Detach the arguments */ for (index = 0; index < MTH_NUM_ARGS; index++) { - object = walk_state->arguments[index].object; - if (object) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", index, object)); - - /* Remove first */ - - walk_state->arguments[index].object = NULL; + if (walk_state->arguments[index].object) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", + index, walk_state->arguments[index].object)); - /* Was given a ref when stored */ + /* Detach object (if present) and remove a reference */ - acpi_ut_remove_reference (object); + acpi_ns_detach_object (&walk_state->arguments[index]); } } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -172,7 +155,9 @@ * * RETURN: Status * - * DESCRIPTION: Initialize arguments for a method + * DESCRIPTION: Initialize arguments for a method. The parameter list is a list + * of ACPI operand objects, either null terminated or whose length + * is defined by Max_param_count. * ******************************************************************************/ @@ -183,11 +168,10 @@ acpi_walk_state *walk_state) { acpi_status status; - u32 mindex; - u32 pindex; + u32 index = 0; - FUNCTION_TRACE_PTR ("Ds_method_data_init_args", params); + ACPI_FUNCTION_TRACE_PTR ("Ds_method_data_init_args", params); if (!params) { @@ -197,106 +181,90 @@ /* Copy passed parameters into the new method stack frame */ - for (pindex = mindex = 0; - (mindex < MTH_NUM_ARGS) && (pindex < max_param_count); - mindex++) { - if (params[pindex]) { - /* - * A valid parameter. - * Set the current method argument to the - * Params[Pindex++] argument object descriptor - */ - status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex, - params[pindex], walk_state); - if (ACPI_FAILURE (status)) { - break; - } - - pindex++; + while ((index < MTH_NUM_ARGS) && (index < max_param_count) && params[index]) { + /* + * A valid parameter. + * Store the argument in the method/walk descriptor + */ + status = acpi_ds_store_object_to_local (AML_ARG_OP, index, params[index], + walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - else { - break; - } + index++; } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", pindex)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", index)); return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_get_entry + * FUNCTION: Acpi_ds_method_data_get_node * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - Which local_var or argument to get - * Entry - Pointer to where a pointer to the stack - * entry is returned. + * Index - Which local_var or argument whose type + * to get * Walk_state - Current walk state object * - * RETURN: Status - * - * DESCRIPTION: Get the address of the object entry given by Opcode:Index + * RETURN: Get the Node associated with a local or arg. * ******************************************************************************/ acpi_status -acpi_ds_method_data_get_entry ( +acpi_ds_method_data_get_node ( u16 opcode, u32 index, acpi_walk_state *walk_state, - acpi_operand_object ***entry) + acpi_namespace_node **node) { - - FUNCTION_TRACE_U32 ("Ds_method_data_get_entry", index); + ACPI_FUNCTION_TRACE ("Ds_method_data_get_node"); /* - * Get the requested object. - * The stack "Opcode" is either a Local_variable or an Argument + * Method Locals and Arguments are supported */ switch (opcode) { - case AML_LOCAL_OP: if (index > MTH_MAX_LOCAL) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local_var index %d is invalid (max %d)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local index %d is invalid (max %d)\n", index, MTH_MAX_LOCAL)); - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS (AE_AML_INVALID_INDEX); } - *entry = (acpi_operand_object **) - &walk_state->local_variables[index].object; - break; + /* Return a pointer to the pseudo-node */ + *node = &walk_state->local_variables[index]; + break; case AML_ARG_OP: if (index > MTH_MAX_ARG) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n", index, MTH_MAX_ARG)); - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS (AE_AML_INVALID_INDEX); } - *entry = (acpi_operand_object **) - &walk_state->arguments[index].object; - break; + /* Return a pointer to the pseudo-node */ + *node = &walk_state->arguments[index]; + break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode)); - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS (AE_AML_BAD_OPCODE); } - return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_set_entry + * FUNCTION: Acpi_ds_method_data_set_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get @@ -310,22 +278,22 @@ ******************************************************************************/ acpi_status -acpi_ds_method_data_set_entry ( +acpi_ds_method_data_set_value ( u16 opcode, u32 index, acpi_operand_object *object, acpi_walk_state *walk_state) { acpi_status status; - acpi_operand_object **entry; + acpi_namespace_node *node; - FUNCTION_TRACE ("Ds_method_data_set_entry"); + ACPI_FUNCTION_TRACE ("Ds_method_data_set_value"); - /* Get a pointer to the stack entry to set */ + /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -336,8 +304,7 @@ /* Install the object into the stack entry */ - *entry = object; - + node->object = object; return_ACPI_STATUS (AE_OK); } @@ -351,105 +318,43 @@ * to get * Walk_state - Current walk state object * - * RETURN: Data type of selected Arg or Local - * Used only in Exec_monadic2()/Type_op. + * RETURN: Data type of current value of the selected Arg or Local * ******************************************************************************/ -acpi_object_type8 +acpi_object_type acpi_ds_method_data_get_type ( u16 opcode, u32 index, acpi_walk_state *walk_state) { acpi_status status; - acpi_operand_object **entry; + acpi_namespace_node *node; acpi_operand_object *object; - FUNCTION_TRACE ("Ds_method_data_get_type"); + ACPI_FUNCTION_TRACE ("Ds_method_data_get_type"); - /* Get a pointer to the requested stack entry */ + /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { return_VALUE ((ACPI_TYPE_NOT_FOUND)); } - /* Get the object from the method stack */ - - object = *entry; - - /* Get the object type */ + /* Get the object */ + object = acpi_ns_get_attached_object (node); if (!object) { - /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */ - return_VALUE (ACPI_TYPE_ANY); - } - - return_VALUE (object->common.type); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ds_method_data_get_node - * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - Which local_var or argument whose type - * to get - * Walk_state - Current walk state object - * - * RETURN: Get the Node associated with a local or arg. - * - ******************************************************************************/ + /* Uninitialized local/arg, return TYPE_ANY */ -acpi_namespace_node * -acpi_ds_method_data_get_node ( - u16 opcode, - u32 index, - acpi_walk_state *walk_state) -{ - acpi_namespace_node *node = NULL; - - - FUNCTION_TRACE ("Ds_method_data_get_node"); - - - switch (opcode) { - - case AML_LOCAL_OP: - - if (index > MTH_MAX_LOCAL) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local index %d is invalid (max %d)\n", - index, MTH_MAX_LOCAL)); - return_PTR (node); - } - - node = &walk_state->local_variables[index]; - break; - - - case AML_ARG_OP: - - if (index > MTH_MAX_ARG) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n", - index, MTH_MAX_ARG)); - return_PTR (node); - } - - node = &walk_state->arguments[index]; - break; - - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode)); - break; + return_VALUE (ACPI_TYPE_ANY); } + /* Get the object type */ - return_PTR (node); + return_VALUE (object->common.type); } @@ -479,11 +384,11 @@ acpi_operand_object **dest_desc) { acpi_status status; - acpi_operand_object **entry; + acpi_namespace_node *node; acpi_operand_object *object; - FUNCTION_TRACE ("Ds_method_data_get_value"); + ACPI_FUNCTION_TRACE ("Ds_method_data_get_value"); /* Validate the object descriptor */ @@ -493,24 +398,22 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } + /* Get the namespace node for the arg/local */ - /* Get a pointer to the requested method stack entry */ - - status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* Get the object from the method stack */ - - object = *entry; + /* Get the object from the node */ + object = node->object; /* Examine the returned object, it must be valid. */ if (!object) { /* - * Index points to uninitialized object stack value. + * Index points to uninitialized object. * This means that either 1) The expected argument was * not passed to the method, or 2) A local variable * was referenced by the method (via the ASL) @@ -519,25 +422,25 @@ switch (opcode) { case AML_ARG_OP: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at entry %p\n", - index, entry)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at node %p\n", + index, node)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG); - break; case AML_LOCAL_OP: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at entry %p\n", - index, entry)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at node %p\n", + index, node)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); - break; + + default: + return_ACPI_STATUS (AE_AML_INTERNAL); } } - /* - * Index points to initialized and valid object stack value. + * The Index points to an initialized and valid object. * Return an additional reference to the object */ *dest_desc = object; @@ -555,56 +458,56 @@ * Index - Which local_var or argument to delete * Walk_state - Current walk state object * - * RETURN: Status + * RETURN: None * * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts * a null into the stack slot after the object is deleted. * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_delete_value ( u16 opcode, u32 index, acpi_walk_state *walk_state) { acpi_status status; - acpi_operand_object **entry; + acpi_namespace_node *node; acpi_operand_object *object; - FUNCTION_TRACE ("Ds_method_data_delete_value"); + ACPI_FUNCTION_TRACE ("Ds_method_data_delete_value"); - /* Get a pointer to the requested entry */ + /* Get the namespace node for the arg/local */ - status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + return_VOID; } - /* Get the current entry in this slot k */ + /* Get the associated object */ - object = *entry; + object = acpi_ns_get_attached_object (node); /* * Undefine the Arg or Local by setting its descriptor * pointer to NULL. Locals/Args can contain both * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs */ - *entry = NULL; + node->object = NULL; if ((object) && - (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) { + (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) { /* - * There is a valid object in this slot + * There is a valid object. * Decrement the reference count by one to balance the - * increment when the object was stored in the slot. + * increment when the object was stored. */ acpi_ut_remove_reference (object); } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -614,14 +517,14 @@ * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to set - * Src_desc - Value to be stored + * Obj_desc - Value to be stored * Walk_state - Current walk state * * RETURN: Status * - * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed + * DESCRIPTION: Store a value in an Arg or Local. The Obj_desc is installed * as the new value for the Arg or Local and the reference count - * for Src_desc is incremented. + * for Obj_desc is incremented. * ******************************************************************************/ @@ -629,45 +532,45 @@ acpi_ds_store_object_to_local ( u16 opcode, u32 index, - acpi_operand_object *src_desc, + acpi_operand_object *obj_desc, acpi_walk_state *walk_state) { acpi_status status; - acpi_operand_object **entry; + acpi_namespace_node *node; + acpi_operand_object *current_obj_desc; - FUNCTION_TRACE ("Ds_method_data_set_value"); + ACPI_FUNCTION_TRACE ("Ds_store_object_to_local"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", - opcode, index, src_desc)); + opcode, index, obj_desc)); /* Parameter validation */ - if (!src_desc) { + if (!obj_desc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } + /* Get the namespace node for the arg/local */ - /* Get a pointer to the requested method stack entry */ - - status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { - goto cleanup; + return_ACPI_STATUS (status); } - if (*entry == src_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", src_desc)); - goto cleanup; + current_obj_desc = acpi_ns_get_attached_object (node); + if (current_obj_desc == obj_desc) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", obj_desc)); + return_ACPI_STATUS (status); } - /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do * an indirect store! */ - if (*entry) { + if (current_obj_desc) { /* * Check for an indirect store if an argument * contains an object reference (stored as an Node). @@ -685,36 +588,24 @@ * Weird, but true. */ if ((opcode == AML_ARG_OP) && - (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { + (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) == ACPI_DESC_TYPE_NAMED)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Arg (%p) is an Obj_ref(Node), storing in %p\n", - src_desc, *entry)); + "Arg (%p) is an Obj_ref(Node), storing in node %p\n", + obj_desc, current_obj_desc)); /* Detach an existing object from the Node */ - acpi_ns_detach_object ((acpi_namespace_node *) *entry); + acpi_ns_detach_object ((acpi_namespace_node *) current_obj_desc); /* * Store this object into the Node - * (do the indirect store) + * (perform the indirect store) */ - status = acpi_ns_attach_object ((acpi_namespace_node *) *entry, src_desc, - src_desc->common.type); + status = acpi_ns_attach_object ((acpi_namespace_node *) current_obj_desc, + obj_desc, obj_desc->common.type); return_ACPI_STATUS (status); } - -#ifdef ACPI_ENABLE_IMPLICIT_CONVERSION - /* - * Perform "Implicit conversion" of the new object to the type of the - * existing object - */ - status = acpi_ex_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } -#endif - /* * Delete the existing object * before storing the new one @@ -722,27 +613,14 @@ acpi_ds_method_data_delete_value (opcode, index, walk_state); } - /* - * Install the Obj_stack descriptor (*Src_desc) into + * Install the Obj_stack descriptor (*Obj_desc) into * the descriptor for the Arg or Local. * Install the new object in the stack entry * (increments the object reference count by one) */ - status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* Normal exit */ - - return_ACPI_STATUS (AE_OK); - - - /* Error exit */ - -cleanup: - + status = acpi_ds_method_data_set_value (opcode, index, obj_desc, walk_state); return_ACPI_STATUS (status); } + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsobject.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsobject.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsobject.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsobject.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,11 +28,10 @@ #include "acparser.h" #include "amlcode.h" #include "acdispat.h" -#include "acinterp.h" #include "acnamesp.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsobject") + ACPI_MODULE_NAME ("dsobject") /******************************************************************************* @@ -47,11 +46,11 @@ * RETURN: Status * * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object - * within the namespace. + * within the namespace. * * Currently, the only objects that require initialization are: * 1) Methods - * 2) Op Regions + * 2) Operation Regions * ******************************************************************************/ @@ -62,18 +61,14 @@ void *context, void **return_value) { - acpi_object_type8 type; + acpi_object_type type; acpi_status status; acpi_init_walk_info *info = (acpi_init_walk_info *) context; - u8 table_revision; - PROC_NAME ("Ds_init_one_object"); + ACPI_FUNCTION_NAME ("Ds_init_one_object"); - info->object_count++; - table_revision = info->table_desc->pointer->revision; - /* * We are only interested in objects owned by the table that * was just loaded @@ -83,16 +78,21 @@ return (AE_OK); } + info->object_count++; /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type (obj_handle); switch (type) { - case ACPI_TYPE_REGION: - acpi_ds_initialize_region (obj_handle); + status = acpi_ds_initialize_region (obj_handle); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n", + obj_handle, ((acpi_namespace_node *) obj_handle)->name.ascii, + acpi_format_exception (status))); + } info->op_region_count++; break; @@ -109,9 +109,11 @@ /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. + * TBD: This is really for possible future support of integer width + * on a per-table basis. Currently, we just use a global for the width. */ - if (table_revision == 1) { - ((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; + if (info->table_desc->pointer->revision == 1) { + ((acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; } /* @@ -121,7 +123,7 @@ status = acpi_ds_parse_method (obj_handle); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", - obj_handle, (char*)&((acpi_namespace_node *)obj_handle)->name, + obj_handle, ((acpi_namespace_node *) obj_handle)->name.ascii, acpi_format_exception (status))); /* This parse failed, but we will continue parsing more methods */ @@ -134,8 +136,16 @@ * for every execution since there isn't much overhead */ acpi_ns_delete_namespace_subtree (obj_handle); + acpi_ns_delete_namespace_by_owner (((acpi_namespace_node *) obj_handle)->object->method.owning_id); + break; + + + case ACPI_TYPE_DEVICE: + + info->device_count++; break; + default: break; } @@ -152,12 +162,13 @@ * * FUNCTION: Acpi_ds_initialize_objects * - * PARAMETERS: None + * PARAMETERS: Table_desc - Descriptor for parent ACPI table + * Start_node - Root of subtree to be initialized. * * RETURN: Status * - * DESCRIPTION: Walk the entire namespace and perform any necessary - * initialization on the objects found therein + * DESCRIPTION: Walk the namespace starting at "Start_node" and perform any + * necessary initialization on the objects found therein * ******************************************************************************/ @@ -170,35 +181,35 @@ acpi_init_walk_info info; - FUNCTION_TRACE ("Ds_initialize_objects"); + ACPI_FUNCTION_TRACE ("Ds_initialize_objects"); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Parsing Methods:")); - info.method_count = 0; info.op_region_count = 0; info.object_count = 0; + info.device_count = 0; info.table_desc = table_desc; - /* Walk entire namespace from the supplied root */ status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, acpi_ds_init_one_object, &info, NULL); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed, %s\n", + acpi_format_exception (status))); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, - "\n%d Control Methods found and parsed (%d nodes total)\n", - info.method_count, info.object_count)); - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Control Methods found\n", info.method_count)); + "\n_table [%4.4s] - %hd Objects with %hd Devices %hd Methods %hd Regions\n", + table_desc->pointer->signature, info.object_count, + info.device_count, info.method_count, info.op_region_count)); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Op Regions found\n", info.op_region_count)); + "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count)); return_ACPI_STATUS (AE_OK); } @@ -208,9 +219,10 @@ * * FUNCTION: Acpi_ds_init_object_from_op * - * PARAMETERS: Op - Parser op used to init the internal object + * PARAMETERS: Walk_state - Current walk state + * Op - Parser op used to init the internal object * Opcode - AML opcode associated with the object - * Obj_desc - Namespace object to be initialized + * Ret_obj_desc - Namespace object to be initialized * * RETURN: Status * @@ -227,15 +239,11 @@ u16 opcode, acpi_operand_object **ret_obj_desc) { - acpi_status status; - acpi_parse_object *arg; - acpi_parse2_object *byte_list; - acpi_operand_object *arg_desc; const acpi_opcode_info *op_info; acpi_operand_object *obj_desc; - PROC_NAME ("Ds_init_object_from_op"); + ACPI_FUNCTION_NAME ("Ds_init_object_from_op"); obj_desc = *ret_obj_desc; @@ -246,100 +254,41 @@ return (AE_TYPE); } - - /* Get and prepare the first argument */ + /* Perform per-object initialization */ switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: - /* First arg is a number */ - - acpi_ds_create_operand (walk_state, op->value.arg, 0); - arg_desc = walk_state->operands [walk_state->num_operands - 1]; - acpi_ds_obj_stack_pop (1, walk_state); - - /* Resolve the object (could be an arg or local) */ - - status = acpi_ex_resolve_to_value (&arg_desc, walk_state); - if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (arg_desc); - return (status); - } - - /* We are expecting a number */ - - if (arg_desc->common.type != ACPI_TYPE_INTEGER) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Expecting number, got obj: %p type %X\n", - arg_desc, arg_desc->common.type)); - acpi_ut_remove_reference (arg_desc); - return (AE_TYPE); - } - - /* Get the value, delete the internal object */ - - obj_desc->buffer.length = (u32) arg_desc->integer.value; - acpi_ut_remove_reference (arg_desc); - - /* Allocate the buffer */ - - if (obj_desc->buffer.length == 0) { - obj_desc->buffer.pointer = NULL; - REPORT_WARNING (("Buffer created with zero length in AML\n")); - break; - } - - else { - obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( - obj_desc->buffer.length); - - if (!obj_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } - } - /* - * Second arg is the buffer data (optional) Byte_list can be either - * individual bytes or a string initializer. + * Defer evaluation of Buffer Term_arg operand */ - arg = op->value.arg; /* skip first arg */ - - byte_list = (acpi_parse2_object *) arg->next; - if (byte_list) { - if (byte_list->opcode != AML_INT_BYTELIST_OP) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got: %p\n", - byte_list)); - return (AE_TYPE); - } - - MEMCPY (obj_desc->buffer.pointer, byte_list->data, - obj_desc->buffer.length); - } - + 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: /* - * When called, an internal package object has already been built and - * is pointed to by Obj_desc. Acpi_ds_build_internal_object builds another - * internal package object, so remove reference to the original so - * that it is deleted. Error checking is done within the remove - * reference function. + * Defer evaluation of Package Term_arg operand */ - acpi_ut_remove_reference (obj_desc); - status = acpi_ds_build_internal_object (walk_state, op, ret_obj_desc); + 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: - obj_desc->integer.value = op->value.integer; + + obj_desc->integer.value = op->common.value.integer; break; case ACPI_TYPE_STRING: - obj_desc->string.pointer = op->value.string; - obj_desc->string.length = STRLEN (op->value.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 @@ -376,22 +325,21 @@ default: /* Constants, Literals, etc.. */ - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* Node was saved in Op */ - obj_desc->reference.node = op->node; + 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_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n", obj_desc->common.type)); break; @@ -403,9 +351,10 @@ /***************************************************************************** * - * FUNCTION: Acpi_ds_build_internal_simple_obj + * FUNCTION: Acpi_ds_build_internal_object * - * PARAMETERS: Op - Parser object to be translated + * PARAMETERS: Walk_state - Current walk state + * Op - Parser object to be translated * Obj_desc_ptr - Where the ACPI internal object is returned * * RETURN: Status @@ -415,96 +364,76 @@ * ****************************************************************************/ -static acpi_status -acpi_ds_build_internal_simple_obj ( +acpi_status +acpi_ds_build_internal_object ( acpi_walk_state *walk_state, acpi_parse_object *op, acpi_operand_object **obj_desc_ptr) { acpi_operand_object *obj_desc; - acpi_object_type8 type; acpi_status status; - u32 length; char *name; - FUNCTION_TRACE ("Ds_build_internal_simple_obj"); + ACPI_FUNCTION_TRACE ("Ds_build_internal_object"); - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* - * This is an object reference. If The name was - * previously looked up in the NS, it is stored in this op. + * This is an object reference. If this name was + * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ - if (!op->node) { - status = acpi_ns_lookup (walk_state->scope_info, - op->value.string, ACPI_TYPE_ANY, - IMODE_EXECUTE, - NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, - NULL, - (acpi_namespace_node **)&(op->node)); + if (!op->common.node) { + status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, + (acpi_namespace_node **) &(op->common.node)); if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { name = NULL; - acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name); - - if (name) { - REPORT_WARNING (("Reference %s at AML %X not found\n", - name, op->aml_offset)); + status = acpi_ns_externalize_name (ACPI_UINT32_MAX, op->common.value.string, NULL, &name); + if (ACPI_SUCCESS (status)) { + ACPI_REPORT_WARNING (("Reference %s at AML %X not found\n", + name, op->common.aml_offset)); ACPI_MEM_FREE (name); } - else { - REPORT_WARNING (("Reference %s at AML %X not found\n", - op->value.string, op->aml_offset)); + ACPI_REPORT_WARNING (("Reference %s at AML %X not found\n", + op->common.value.string, op->common.aml_offset)); } *obj_desc_ptr = NULL; } - else { return_ACPI_STATUS (status); } } } - - /* - * The reference will be a Reference - * TBD: [Restructure] unless we really need a separate - * type of INTERNAL_TYPE_REFERENCE change - * Acpi_ds_map_opcode_to_data_type to handle this case - */ - type = INTERNAL_TYPE_REFERENCE; - } - else { - type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL); } - /* Create and init the internal ACPI object */ - obj_desc = acpi_ut_create_internal_object (type); + obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type); if (!obj_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_object_from_op (walk_state, op, op->opcode, &obj_desc); + status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); } *obj_desc_ptr = obj_desc; - return_ACPI_STATUS (AE_OK); } /***************************************************************************** * - * FUNCTION: Acpi_ds_build_internal_package_obj + * FUNCTION: Acpi_ds_build_internal_buffer_obj * * PARAMETERS: Op - Parser object to be translated * Obj_desc_ptr - Where the ACPI internal object is returned @@ -517,114 +446,211 @@ ****************************************************************************/ acpi_status -acpi_ds_build_internal_package_obj ( +acpi_ds_build_internal_buffer_obj ( acpi_walk_state *walk_state, acpi_parse_object *op, + u32 buffer_length, acpi_operand_object **obj_desc_ptr) { acpi_parse_object *arg; acpi_operand_object *obj_desc; - acpi_status status = AE_OK; + acpi_parse_object *byte_list; + u32 byte_list_length = 0; - FUNCTION_TRACE ("Ds_build_internal_package_obj"); + ACPI_FUNCTION_TRACE ("Ds_build_internal_buffer_obj"); - obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE); - *obj_desc_ptr = obj_desc; - if (!obj_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - if (op->opcode == AML_VAR_PACKAGE_OP) { + obj_desc = *obj_desc_ptr; + if (obj_desc) { /* - * Variable length package parameters are evaluated JIT + * We are evaluating a Named buffer object "Name (xxxx, Buffer)". + * The buffer object already exists (from the NS node) */ - return_ACPI_STATUS (AE_OK); } + else { + /* Create a new buffer object */ - /* The first argument must be the package length */ - - arg = op->value.arg; - obj_desc->package.count = arg->value.integer32; + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + *obj_desc_ptr = obj_desc; + if (!obj_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } /* - * Allocate the array of pointers (ptrs to the - * individual objects) Add an extra pointer slot so - * that the list is always null terminated. + * Second arg is the buffer data (optional) Byte_list can be either + * individual bytes or a string initializer. In either case, a + * Byte_list appears in the AML. */ - obj_desc->package.elements = ACPI_MEM_CALLOCATE ( - (obj_desc->package.count + 1) * sizeof (void *)); + arg = op->common.value.arg; /* skip first arg */ - if (!obj_desc->package.elements) { - acpi_ut_delete_object_desc (obj_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } + byte_list = arg->named.next; + if (byte_list) { + if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Expecting bytelist, got AML opcode %X in op %p\n", + byte_list->common.aml_opcode, byte_list)); - obj_desc->package.next_element = obj_desc->package.elements; + acpi_ut_remove_reference (obj_desc); + return (AE_TYPE); + } + + byte_list_length = byte_list->common.value.integer32; + } /* - * Now init the elements of the package + * The buffer length (number of bytes) will be the larger of: + * 1) The specified buffer length and + * 2) The length of the initializer byte list */ - arg = arg->next; - while (arg) { - if (arg->opcode == AML_PACKAGE_OP) { - status = acpi_ds_build_internal_package_obj (walk_state, arg, - obj_desc->package.next_element); - } + obj_desc->buffer.length = buffer_length; + if (byte_list_length > buffer_length) { + obj_desc->buffer.length = byte_list_length; + } - else { - status = acpi_ds_build_internal_simple_obj (walk_state, arg, - obj_desc->package.next_element); - } + /* Allocate the buffer */ - obj_desc->package.next_element++; - arg = arg->next; + if (obj_desc->buffer.length == 0) { + obj_desc->buffer.pointer = NULL; + ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n")); + return_ACPI_STATUS (AE_OK); } - obj_desc->package.flags |= AOPOBJ_DATA_VALID; - return_ACPI_STATUS (status); + obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( + obj_desc->buffer.length); + if (!obj_desc->buffer.pointer) { + acpi_ut_delete_object_desc (obj_desc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Initialize buffer from the Byte_list (if present) */ + + if (byte_list) { + ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data, + byte_list_length); + } + + obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; + op->common.node = (acpi_namespace_node *) obj_desc; + return_ACPI_STATUS (AE_OK); } /***************************************************************************** * - * FUNCTION: Acpi_ds_build_internal_object + * FUNCTION: Acpi_ds_build_internal_package_obj * * PARAMETERS: Op - Parser object to be translated * Obj_desc_ptr - Where the ACPI internal object is returned * * RETURN: Status * - * DESCRIPTION: Translate a parser Op object to the equivalent namespace - * object + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object * ****************************************************************************/ acpi_status -acpi_ds_build_internal_object ( +acpi_ds_build_internal_package_obj ( acpi_walk_state *walk_state, acpi_parse_object *op, + u32 package_length, acpi_operand_object **obj_desc_ptr) { - acpi_status status; + acpi_parse_object *arg; + acpi_parse_object *parent; + acpi_operand_object *obj_desc = NULL; + u32 package_list_length; + acpi_status status = AE_OK; + u32 i; - switch (op->opcode) { - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: + ACPI_FUNCTION_TRACE ("Ds_build_internal_package_obj"); - status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr); - break; + /* Find the parent of a possibly nested package */ - default: + parent = op->common.parent; + while ((parent->common.aml_opcode == AML_PACKAGE_OP) || + (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { + parent = parent->common.parent; + } - status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr); - break; + obj_desc = *obj_desc_ptr; + if (obj_desc) { + /* + * We are evaluating a Named package object "Name (xxxx, Package)". + * Get the existing package object from the NS node + */ + } + else { + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE); + *obj_desc_ptr = obj_desc; + if (!obj_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + obj_desc->package.node = parent->common.node; + } + + obj_desc->package.count = package_length; + + /* Count the number of items in the package list */ + + package_list_length = 0; + arg = op->common.value.arg; + arg = arg->common.next; + while (arg) { + package_list_length++; + arg = arg->common.next; + } + + /* + * The package length (number of elements) will be the greater + * of the specified length and the length of the initializer list + */ + if (package_list_length > package_length) { + obj_desc->package.count = package_list_length; } - return (status); + /* + * Allocate the pointer array (array of pointers to the + * individual objects). Add an extra pointer slot so + * that the list is always null terminated. + */ + obj_desc->package.elements = ACPI_MEM_CALLOCATE ( + ((ACPI_SIZE) obj_desc->package.count + 1) * sizeof (void *)); + + if (!obj_desc->package.elements) { + acpi_ut_delete_object_desc (obj_desc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Now init the elements of the package + */ + i = 0; + arg = op->common.value.arg; + arg = arg->common.next; + while (arg) { + if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { + /* Object (package or buffer) is already built */ + + obj_desc->package.elements[i] = ACPI_CAST_PTR (acpi_operand_object, arg->common.node); + } + else { + status = acpi_ds_build_internal_object (walk_state, arg, + &obj_desc->package.elements[i]); + } + + i++; + arg = arg->common.next; + } + + obj_desc->package.flags |= AOPOBJ_DATA_VALID; + op->common.node = (acpi_namespace_node *) obj_desc; + return_ACPI_STATUS (status); } @@ -651,7 +677,7 @@ acpi_operand_object *obj_desc; - FUNCTION_TRACE_PTR ("Ds_create_node", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_node", op); /* @@ -659,11 +685,11 @@ * parts of the table, we can arrive here twice. Only init * the named object node the first time through */ - if (node->object) { + if (acpi_ns_get_attached_object (node)) { return_ACPI_STATUS (AE_OK); } - if (!op->value.arg) { + if (!op->common.value.arg) { /* No arguments, there is nothing to do */ return_ACPI_STATUS (AE_OK); @@ -671,7 +697,7 @@ /* Build an internal object for the argument(s) */ - status = acpi_ds_build_internal_object (walk_state, op->value.arg, &obj_desc); + status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -680,9 +706,9 @@ node->type = obj_desc->common.type; - /* Init obj */ + /* Attach obj to node */ - status = acpi_ns_attach_object (node, obj_desc, (u8) node->type); + status = acpi_ns_attach_object (node, obj_desc, node->type); /* Remove local reference to the object */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsopcode.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsopcode.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsopcode.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsopcode.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -32,96 +32,70 @@ #include "acinterp.h" #include "acnamesp.h" #include "acevents.h" -#include "actables.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsopcode") + ACPI_MODULE_NAME ("dsopcode") /***************************************************************************** * - * FUNCTION: Acpi_ds_get_buffer_field_arguments + * FUNCTION: Acpi_ds_execute_arguments * - * PARAMETERS: Obj_desc - A valid Buffer_field object + * PARAMETERS: Node - Parent NS node + * Aml_length - Length of executable AML + * Aml_start - Pointer to the AML * * RETURN: Status. * - * DESCRIPTION: Get Buffer_field Buffer and Index. This implements the late - * evaluation of these field attributes. + * DESCRIPTION: Late execution of region or field arguments * ****************************************************************************/ acpi_status -acpi_ds_get_buffer_field_arguments ( - acpi_operand_object *obj_desc) +acpi_ds_execute_arguments ( + acpi_namespace_node *node, + acpi_namespace_node *scope_node, + u32 aml_length, + u8 *aml_start) { - acpi_operand_object *extra_desc; - acpi_namespace_node *node; - acpi_parse_object *op; - acpi_parse_object *field_op; acpi_status status; - acpi_table_desc *table_desc; + acpi_parse_object *op; acpi_walk_state *walk_state; + acpi_parse_object *arg; - FUNCTION_TRACE_PTR ("Ds_get_buffer_field_arguments", obj_desc); - - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS (AE_OK); - } - - - /* Get the AML pointer (method object) and Buffer_field node */ - - extra_desc = obj_desc->buffer_field.extra; - node = obj_desc->buffer_field.node; - - DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Field]")); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Buffer_field JIT Init\n", - (char*)&node->name)); + ACPI_FUNCTION_TRACE ("Acpi_ds_execute_arguments"); /* - * Allocate a new parser op to be the root of the parsed - * Op_region tree + * Allocate a new parser op to be the root of the parsed tree */ - op = acpi_ps_alloc_op (AML_SCOPE_OP); + op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP); if (!op) { - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the Node for use in Acpi_ps_parse_aml */ - op->node = acpi_ns_get_parent_object (node); - - /* Get a handle to the parent ACPI table */ - - status = acpi_tb_handle_to_object (node->owner_id, &table_desc); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + op->common.node = scope_node; /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start, - extra_desc->extra.aml_length, NULL, NULL, 1); + status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, + aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ + acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); } - /* TBD: No Walk flags?? */ - walk_state->parse_flags = 0; - /* Pass1: Parse the entire Buffer_field declaration */ + /* Pass1: Parse the entire declaration */ status = acpi_ps_parse_aml (walk_state); if (ACPI_FAILURE (status)) { @@ -129,182 +103,228 @@ return_ACPI_STATUS (status); } - /* Get and init the actual Field_unit Op created above */ - - field_op = op->value.arg; - op->node = node; - + /* Get and init the Op created above */ - field_op = op->value.arg; - field_op->node = node; + arg = op->common.value.arg; + op->common.node = node; + arg->common.node = node; acpi_ps_delete_parse_tree (op); - /* Evaluate the address and length arguments for the Op_region */ + /* Evaluate the address and length arguments for the Buffer Field */ - op = acpi_ps_alloc_op (AML_SCOPE_OP); + op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP); if (!op) { - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } - op->node = acpi_ns_get_parent_object (node); + op->common.node = scope_node; /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start, - extra_desc->extra.aml_length, NULL, NULL, 3); + status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, + aml_length, NULL, NULL, 3); if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ + acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); } status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); - - /* - * The pseudo-method object is no longer needed since the region is - * now initialized - */ - acpi_ut_remove_reference (obj_desc->buffer_field.extra); - obj_desc->buffer_field.extra = NULL; - return_ACPI_STATUS (status); } /***************************************************************************** * - * FUNCTION: Acpi_ds_get_region_arguments + * FUNCTION: Acpi_ds_get_buffer_field_arguments * - * PARAMETERS: Obj_desc - A valid region object + * PARAMETERS: Obj_desc - A valid Buffer_field object * * RETURN: Status. * - * DESCRIPTION: Get region address and length. This implements the late - * evaluation of these region attributes. + * DESCRIPTION: Get Buffer_field Buffer and Index. This implements the late + * evaluation of these field attributes. * ****************************************************************************/ acpi_status -acpi_ds_get_region_arguments ( +acpi_ds_get_buffer_field_arguments ( acpi_operand_object *obj_desc) { - acpi_operand_object *extra_desc = NULL; + acpi_operand_object *extra_desc; acpi_namespace_node *node; - acpi_parse_object *op; - acpi_parse_object *region_op; acpi_status status; - acpi_table_desc *table_desc; - acpi_walk_state *walk_state; - FUNCTION_TRACE_PTR ("Ds_get_region_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ds_get_buffer_field_arguments", obj_desc); - if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS (AE_OK); } + /* Get the AML pointer (method object) and Buffer_field node */ - /* Get the AML pointer (method object) and region node */ + extra_desc = acpi_ns_get_secondary_object (obj_desc); + node = obj_desc->buffer_field.node; - extra_desc = obj_desc->region.extra; - node = obj_desc->region.node; + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Field]")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Buffer_field JIT Init\n", + node->name.ascii)); - DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Operation Region]")); + /* Execute the AML code for the Term_arg arguments */ - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Op_region Init at AML %p\n", - (char*)&node->name, extra_desc->extra.aml_start)); + status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node), + extra_desc->extra.aml_length, extra_desc->extra.aml_start); + return_ACPI_STATUS (status); +} - /* - * Allocate a new parser op to be the root of the parsed - * Op_region tree - */ - op = acpi_ps_alloc_op (AML_SCOPE_OP); - if (!op) { - return (AE_NO_MEMORY); - } - /* Save the Node for use in Acpi_ps_parse_aml */ +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_buffer_arguments + * + * PARAMETERS: Obj_desc - A valid Bufferobject + * + * RETURN: Status. + * + * DESCRIPTION: Get Buffer length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ****************************************************************************/ - op->node = acpi_ns_get_parent_object (node); +acpi_status +acpi_ds_get_buffer_arguments ( + acpi_operand_object *obj_desc) +{ + acpi_namespace_node *node; + acpi_status status; - /* Get a handle to the parent ACPI table */ - status = acpi_tb_handle_to_object (node->owner_id, &table_desc); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + ACPI_FUNCTION_TRACE_PTR ("Ds_get_buffer_arguments", obj_desc); - /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - op, NULL, NULL); - if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS (AE_OK); } - status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start, - extra_desc->extra.aml_length, NULL, NULL, 1); - if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ - return_ACPI_STATUS (status); + /* Get the Buffer node */ + + node = obj_desc->buffer.node; + if (!node) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "No pointer back to NS node in buffer %p\n", obj_desc)); + return_ACPI_STATUS (AE_AML_INTERNAL); } - /* TBD: No Walk flags?? */ + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer JIT Init\n")); - walk_state->parse_flags = 0; + /* Execute the AML code for the Term_arg arguments */ - /* Parse the entire Op_region declaration, creating a parse tree */ + status = acpi_ds_execute_arguments (node, node, + obj_desc->buffer.aml_length, obj_desc->buffer.aml_start); + return_ACPI_STATUS (status); +} - status = acpi_ps_parse_aml (walk_state); - if (ACPI_FAILURE (status)) { - acpi_ps_delete_parse_tree (op); - return_ACPI_STATUS (status); - } - /* Get and init the actual Region_op created above */ +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_package_arguments + * + * PARAMETERS: Obj_desc - A valid Packageobject + * + * RETURN: Status. + * + * DESCRIPTION: Get Package length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ****************************************************************************/ - region_op = op->value.arg; - op->node = node; +acpi_status +acpi_ds_get_package_arguments ( + acpi_operand_object *obj_desc) +{ + acpi_namespace_node *node; + acpi_status status; - region_op = op->value.arg; - region_op->node = node; - acpi_ps_delete_parse_tree (op); + ACPI_FUNCTION_TRACE_PTR ("Ds_get_package_arguments", obj_desc); - /* Evaluate the address and length arguments for the Op_region */ - op = acpi_ps_alloc_op (AML_SCOPE_OP); - if (!op) { - return (AE_NO_MEMORY); + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS (AE_OK); } - op->node = acpi_ns_get_parent_object (node); + /* Get the Package node */ - /* Create and initialize a new parser state */ + node = obj_desc->package.node; + if (!node) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "No pointer back to NS node in package %p\n", obj_desc)); + return_ACPI_STATUS (AE_AML_INTERNAL); + } - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - op, NULL, NULL); - if (!walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package JIT Init\n")); + + /* Execute the AML code for the Term_arg arguments */ + + status = acpi_ds_execute_arguments (node, node, + obj_desc->package.aml_length, obj_desc->package.aml_start); + return_ACPI_STATUS (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_region_arguments + * + * PARAMETERS: Obj_desc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ****************************************************************************/ + +acpi_status +acpi_ds_get_region_arguments ( + acpi_operand_object *obj_desc) +{ + acpi_namespace_node *node; + acpi_status status; + acpi_operand_object *extra_desc; + + + ACPI_FUNCTION_TRACE_PTR ("Ds_get_region_arguments", obj_desc); + + + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS (AE_OK); } - status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start, - extra_desc->extra.aml_length, NULL, NULL, 3); - if (ACPI_FAILURE (status)) { - /* TBD: delete walk state */ - return_ACPI_STATUS (status); + extra_desc = acpi_ns_get_secondary_object (obj_desc); + if (!extra_desc) { + return_ACPI_STATUS (AE_NOT_EXIST); } - status = acpi_ps_parse_aml (walk_state); - acpi_ps_delete_parse_tree (op); + /* Get the Region node */ + + node = obj_desc->region.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Operation Region]")); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Op_region Init at AML %p\n", + node->name.ascii, extra_desc->extra.aml_start)); + + status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node), + extra_desc->extra.aml_length, extra_desc->extra.aml_start); return_ACPI_STATUS (status); } @@ -317,7 +337,7 @@ * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Front end to Ev_initialize_region * ****************************************************************************/ @@ -334,301 +354,276 @@ /* Namespace is NOT locked */ status = acpi_ev_initialize_region (obj_desc, FALSE); - return (status); } /***************************************************************************** * - * FUNCTION: Acpi_ds_eval_buffer_field_operands + * FUNCTION: Acpi_ds_init_buffer_field * - * PARAMETERS: Op - A valid Buffer_field Op object + * PARAMETERS: Aml_opcode - Create_xxx_field + * Obj_desc - Buffer_field object + * Buffer_desc - Host Buffer + * Offset_desc - Offset into buffer + * Length - Length of field (CREATE_FIELD_OP only) + * Result - Where to store the result * * RETURN: Status * - * DESCRIPTION: Get Buffer_field Buffer and Index - * Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk - * - * ACPI SPECIFICATION REFERENCES: - * Each of the Buffer Field opcodes is defined as specified in in-line - * comments below. For each one, use the following definitions. - * - * Def_bit_field := Bit_field_op Src_buf Bit_idx Destination - * Def_byte_field := Byte_field_op Src_buf Byte_idx Destination - * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string - * Def_dWord_field := DWord_field_op Src_buf Byte_idx Destination - * Def_word_field := Word_field_op Src_buf Byte_idx Destination - * Bit_index := Term_arg=>Integer - * Byte_index := Term_arg=>Integer - * Destination := Name_string - * Num_bits := Term_arg=>Integer - * Source_buf := Term_arg=>Buffer + * DESCRIPTION: Perform actual initialization of a buffer field * ****************************************************************************/ acpi_status -acpi_ds_eval_buffer_field_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op) +acpi_ds_init_buffer_field ( + u16 aml_opcode, + acpi_operand_object *obj_desc, + acpi_operand_object *buffer_desc, + acpi_operand_object *offset_desc, + acpi_operand_object *length_desc, + acpi_operand_object *result_desc) { - acpi_status status; - acpi_operand_object *obj_desc; - acpi_namespace_node *node; - acpi_parse_object *next_op; u32 offset; u32 bit_offset; u32 bit_count; u8 field_flags; - acpi_operand_object *res_desc = NULL; - acpi_operand_object *cnt_desc = NULL; - acpi_operand_object *off_desc = NULL; - acpi_operand_object *src_desc = NULL; - - - FUNCTION_TRACE_PTR ("Ds_eval_buffer_field_operands", op); - - - /* - * This is where we evaluate the address and length fields of the - * Create_xxx_field declaration - */ - node = op->node; - - /* Next_op points to the op that holds the Buffer */ - - next_op = op->value.arg; - - /* Acpi_evaluate/create the address and length operands */ + acpi_status status; - status = acpi_ds_create_operands (walk_state, next_op); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - obj_desc = acpi_ns_get_attached_object (node); - if (!obj_desc) { - return_ACPI_STATUS (AE_NOT_EXIST); - } + ACPI_FUNCTION_TRACE_PTR ("Ds_init_buffer_field", obj_desc); - /* Resolve the operands */ + /* Host object must be a Buffer */ - status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); - DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE, acpi_ps_get_opcode_name (op->opcode), - walk_state->num_operands, "after Acpi_ex_resolve_operands"); - - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n", - acpi_ps_get_opcode_name (op->opcode), status)); + if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Target of Create Field is not a Buffer object - %s\n", + acpi_ut_get_type_name (buffer_desc->common.type))); + status = AE_AML_OPERAND_TYPE; goto cleanup; } - /* Get the operands */ - - if (AML_CREATE_FIELD_OP == op->opcode) { - res_desc = walk_state->operands[3]; - cnt_desc = walk_state->operands[2]; - } - else { - res_desc = walk_state->operands[2]; - } - - off_desc = walk_state->operands[1]; - src_desc = walk_state->operands[0]; - - - offset = (u32) off_desc->integer.value; - /* - * If Res_desc is a Name, it will be a direct name pointer after - * Acpi_ex_resolve_operands() + * The last parameter to all of these opcodes (Result_desc) started + * out as a Name_string, and should therefore now be a NS node + * after resolution in Acpi_ex_resolve_operands(). */ - if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination must be a Node\n", - acpi_ps_get_opcode_name (op->opcode))); + if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination must be a NS Node\n", + acpi_ps_get_opcode_name (aml_opcode))); status = AE_AML_OPERAND_TYPE; goto cleanup; } + offset = (u32) offset_desc->integer.value; + /* * Setup the Bit offsets and counts, according to the opcode */ - switch (op->opcode) { - - /* Def_create_field */ - + switch (aml_opcode) { case AML_CREATE_FIELD_OP: /* Offset is in bits, count is in bits */ - bit_offset = offset; - bit_count = (u32) cnt_desc->integer.value; - field_flags = ACCESS_BYTE_ACC; + bit_offset = offset; + bit_count = (u32) length_desc->integer.value; + field_flags = AML_FIELD_ACCESS_BYTE; break; - - /* Def_create_bit_field */ - case AML_CREATE_BIT_FIELD_OP: /* Offset is in bits, Field is one bit */ - bit_offset = offset; - bit_count = 1; - field_flags = ACCESS_BYTE_ACC; + bit_offset = offset; + bit_count = 1; + field_flags = AML_FIELD_ACCESS_BYTE; break; - - /* Def_create_byte_field */ - case AML_CREATE_BYTE_FIELD_OP: /* Offset is in bytes, field is one byte */ - bit_offset = 8 * offset; - bit_count = 8; - field_flags = ACCESS_BYTE_ACC; + bit_offset = 8 * offset; + bit_count = 8; + field_flags = AML_FIELD_ACCESS_BYTE; break; - - /* Def_create_word_field */ - case AML_CREATE_WORD_FIELD_OP: /* Offset is in bytes, field is one word */ - bit_offset = 8 * offset; - bit_count = 16; - field_flags = ACCESS_WORD_ACC; + bit_offset = 8 * offset; + bit_count = 16; + field_flags = AML_FIELD_ACCESS_WORD; break; - - /* Def_create_dWord_field */ - case AML_CREATE_DWORD_FIELD_OP: /* Offset is in bytes, field is one dword */ - bit_offset = 8 * offset; - bit_count = 32; - field_flags = ACCESS_DWORD_ACC; + bit_offset = 8 * offset; + bit_count = 32; + field_flags = AML_FIELD_ACCESS_DWORD; break; - - /* Def_create_qWord_field */ - case AML_CREATE_QWORD_FIELD_OP: /* Offset is in bytes, field is one qword */ - bit_offset = 8 * offset; - bit_count = 64; - field_flags = ACCESS_QWORD_ACC; + bit_offset = 8 * offset; + bit_count = 64; + field_flags = AML_FIELD_ACCESS_QWORD; break; - default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Internal error - unknown field creation opcode %02x\n", - op->opcode)); + "Unknown field creation opcode %02x\n", + aml_opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } + /* Entire field must fit within the current length of the buffer */ + + if ((bit_offset + bit_count) > + (8 * (u32) buffer_desc->buffer.length)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Field size %d exceeds Buffer size %d (bits)\n", + bit_offset + bit_count, 8 * (u32) buffer_desc->buffer.length)); + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + /* - * Setup field according to the object type + * Initialize areas of the field object that are common to all fields + * For Field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE) */ - switch (src_desc->common.type) { + status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0, + bit_offset, bit_count); + if (ACPI_FAILURE (status)) { + goto cleanup; + } - /* Source_buff := Term_arg=>Buffer */ + obj_desc->buffer_field.buffer_obj = buffer_desc; - case ACPI_TYPE_BUFFER: + /* Reference count for Buffer_desc inherits Obj_desc count */ - if ((bit_offset + bit_count) > - (8 * (u32) src_desc->buffer.length)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field size %d exceeds Buffer size %d (bits)\n", - bit_offset + bit_count, 8 * (u32) src_desc->buffer.length)); - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } + buffer_desc->common.reference_count = (u16) (buffer_desc->common.reference_count + + obj_desc->common.reference_count); - /* - * Initialize areas of the field object that are common to all fields - * For Field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE) - */ - status = acpi_ex_prep_common_field_object (obj_desc, field_flags, - bit_offset, bit_count); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } +cleanup: - obj_desc->buffer_field.buffer_obj = src_desc; + /* Always delete the operands */ - /* Reference count for Src_desc inherits Obj_desc count */ + acpi_ut_remove_reference (offset_desc); + acpi_ut_remove_reference (buffer_desc); - src_desc->common.reference_count = (u16) (src_desc->common.reference_count + - obj_desc->common.reference_count); + if (aml_opcode == AML_CREATE_FIELD_OP) { + acpi_ut_remove_reference (length_desc); + } - break; + /* On failure, delete the result descriptor */ + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (result_desc); /* Result descriptor */ + } + else { + /* Now the address and length are valid for this Buffer_field */ - /* Improper object type */ + obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; + } - default: + return_ACPI_STATUS (status); +} - if ((src_desc->common.type > (u8) INTERNAL_TYPE_REFERENCE) || !acpi_ut_valid_object_type (src_desc->common.type)) /* TBD: This line MUST be a single line until Acpi_src can handle it (block deletion) */ { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Tried to create field in invalid object type %X\n", - src_desc->common.type)); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Tried to create field in improper object type - %s\n", - acpi_ut_get_type_name (src_desc->common.type))); - } +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_buffer_field_operands + * + * PARAMETERS: Walk_state - Current walk + * Op - A valid Buffer_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get Buffer_field Buffer and Index + * Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk + * + ****************************************************************************/ - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } +acpi_status +acpi_ds_eval_buffer_field_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op) +{ + acpi_status status; + acpi_operand_object *obj_desc; + acpi_namespace_node *node; + acpi_parse_object *next_op; - if (AML_CREATE_FIELD_OP == op->opcode) { - /* Delete object descriptor unique to Create_field */ + ACPI_FUNCTION_TRACE_PTR ("Ds_eval_buffer_field_operands", op); - acpi_ut_remove_reference (cnt_desc); - cnt_desc = NULL; - } + /* + * This is where we evaluate the address and length fields of the + * Create_xxx_field declaration + */ + node = op->common.node; + + /* Next_op points to the op that holds the Buffer */ -cleanup: + next_op = op->common.value.arg; - /* Always delete the operands */ + /* Evaluate/create the address and length operands */ - acpi_ut_remove_reference (off_desc); - acpi_ut_remove_reference (src_desc); + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (AML_CREATE_FIELD_OP == op->opcode) { - acpi_ut_remove_reference (cnt_desc); + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { + return_ACPI_STATUS (AE_NOT_EXIST); } - /* On failure, delete the result descriptor */ + /* Resolve the operands */ + + status = acpi_ex_resolve_operands (op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + + ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name (op->common.aml_opcode), + walk_state->num_operands, "after Acpi_ex_resolve_operands"); if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (res_desc); /* Result descriptor */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n", + acpi_ps_get_opcode_name (op->common.aml_opcode), status)); + + return_ACPI_STATUS (status); } + /* Initialize the Buffer Field */ + + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + /* NOTE: Slightly different operands for this opcode */ + + status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc, + walk_state->operands[0], walk_state->operands[1], + walk_state->operands[2], walk_state->operands[3]); + } else { - /* Now the address and length are valid for this Buffer_field */ + /* All other, Create_xxx_field opcodes */ - obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; + status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc, + walk_state->operands[0], walk_state->operands[1], + NULL, walk_state->operands[2]); } return_ACPI_STATUS (status); @@ -639,7 +634,8 @@ * * FUNCTION: Acpi_ds_eval_region_operands * - * PARAMETERS: Op - A valid region Op object + * PARAMETERS: Walk_state - Current walk + * Op - A valid region Op object * * RETURN: Status * @@ -660,23 +656,23 @@ acpi_parse_object *next_op; - FUNCTION_TRACE_PTR ("Ds_eval_region_operands", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_eval_region_operands", op); /* * This is where we evaluate the address and length fields of the Op_region declaration */ - node = op->node; + node = op->common.node; /* Next_op points to the op that holds the Space_iD */ - next_op = op->value.arg; + next_op = op->common.value.arg; /* Next_op points to address op */ - next_op = next_op->next; + next_op = next_op->common.next; - /* Acpi_evaluate/create the address and length operands */ + /* Evaluate/create the address and length operands */ status = acpi_ds_create_operands (walk_state, next_op); if (ACPI_FAILURE (status)) { @@ -685,16 +681,15 @@ /* Resolve the length and address operands to numbers */ - status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + status = acpi_ex_resolve_operands (op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE, - acpi_ps_get_opcode_name (op->opcode), + ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name (op->common.aml_opcode), 1, "after Acpi_ex_resolve_operands"); - obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { return_ACPI_STATUS (AE_NOT_EXIST); @@ -718,9 +713,9 @@ obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value; acpi_ut_remove_reference (operand_desc); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Rgn_obj %p Addr %8.8X%8.8X Len %X\n", - obj_desc, HIDWORD(obj_desc->region.address), LODWORD(obj_desc->region.address), + obj_desc, + ACPI_HIDWORD (obj_desc->region.address), ACPI_LODWORD (obj_desc->region.address), obj_desc->region.length)); /* Now the address and length are valid for this opregion */ @@ -731,6 +726,101 @@ } +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_data_object_operands + * + * PARAMETERS: Walk_state - Current walk + * Op - A valid Data_object Op object + * Obj_desc - Data_object + * + * RETURN: Status + * + * DESCRIPTION: Get the operands and complete the following data objec types: + * Buffer + * Package + * + ****************************************************************************/ + +acpi_status +acpi_ds_eval_data_object_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op, + acpi_operand_object *obj_desc) +{ + acpi_status status; + acpi_operand_object *arg_desc; + u32 length; + + + ACPI_FUNCTION_TRACE ("Ds_eval_data_object_operands"); + + + /* The first operand (for all of these data objects) is the length */ + + status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_ex_resolve_operands (walk_state->opcode, + &(walk_state->operands [walk_state->num_operands -1]), + walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Extract length operand */ + + arg_desc = walk_state->operands [walk_state->num_operands - 1]; + length = (u32) arg_desc->integer.value; + + /* Cleanup for length operand */ + + status = acpi_ds_obj_stack_pop (1, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + acpi_ut_remove_reference (arg_desc); + + /* + * Create the actual data object + */ + switch (op->common.aml_opcode) { + case AML_BUFFER_OP: + + status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc); + break; + + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc); + break; + + default: + return_ACPI_STATUS (AE_AML_BAD_OPCODE); + } + + if (ACPI_SUCCESS (status)) { + /* + * Return the object in the Walk_state, unless the parent is a package -- + * in this case, the return object will be stored in the parse tree + * for the package. + */ + if ((!op->common.parent) || + ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && + (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) && + (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + walk_state->result_obj = obj_desc; + } + } + + return_ACPI_STATUS (status); +} + + /******************************************************************************* * * FUNCTION: Acpi_ds_exec_begin_control_op @@ -754,13 +844,13 @@ acpi_generic_state *control_state; - PROC_NAME ("Ds_exec_begin_control_op"); + ACPI_FUNCTION_NAME ("Ds_exec_begin_control_op"); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, - op->opcode, walk_state)); + op->common.aml_opcode, walk_state)); - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_IF_OP: case AML_WHILE_OP: @@ -774,19 +864,19 @@ status = AE_NO_MEMORY; break; } - - acpi_ut_push_generic_state (&walk_state->control_state, control_state); - /* * Save a pointer to the predicate for multiple executions * of a loop */ - walk_state->control_state->control.aml_predicate_start = - walk_state->parser_state.aml - 1; - /* TBD: can this be removed? */ - /*Acpi_ps_pkg_length_encoding_size (GET8 (Walk_state->Parser_state->Aml));*/ - break; + control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1; + control_state->control.package_end = walk_state->parser_state.pkg_end; + control_state->control.opcode = op->common.aml_opcode; + + + /* Push the control state on this walk's control stack */ + acpi_ut_push_generic_state (&walk_state->control_state, control_state); + break; case AML_ELSE_OP: @@ -799,12 +889,10 @@ break; - case AML_RETURN_OP: break; - default: break; } @@ -825,7 +913,6 @@ * DESCRIPTION: Handles all control ops encountered during control method * execution. * - * ******************************************************************************/ acpi_status @@ -837,10 +924,10 @@ acpi_generic_state *control_state; - PROC_NAME ("Ds_exec_end_control_op"); + ACPI_FUNCTION_NAME ("Ds_exec_end_control_op"); - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_IF_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); @@ -890,17 +977,17 @@ case AML_RETURN_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "[RETURN_OP] Op=%p Arg=%p\n",op, op->value.arg)); + "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ - if (op->value.arg) { + if (op->common.value.arg) { /* Return statement has an immediate operand */ - status = acpi_ds_create_operands (walk_state, op->value.arg); + status = acpi_ds_create_operands (walk_state, op->common.value.arg); if (ACPI_FAILURE (status)) { return (status); } @@ -922,7 +1009,6 @@ */ walk_state->return_desc = walk_state->operands[0]; } - else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { /* @@ -934,18 +1020,17 @@ * * Allow references created by the Index operator to return unchanged. */ - if (VALID_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc [0], ACPI_DESC_TYPE_INTERNAL) && + if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) && ((walk_state->results->results.obj_desc [0])->common.type == INTERNAL_TYPE_REFERENCE) && ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) { - status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } + status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } } walk_state->return_desc = walk_state->results->results.obj_desc [0]; } - else { /* No return operand */ @@ -979,7 +1064,7 @@ /* Call up to the OS service layer to handle this */ - acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); + status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); /* If and when it returns, all done. */ @@ -987,43 +1072,47 @@ case AML_BREAK_OP: + case AML_CONTINUE_OP: /* ACPI 2.0 */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Break to end of current package, Op=%p\n", op)); - /* TBD: update behavior for ACPI 2.0 */ + /* Pop and delete control states until we find a while */ - /* - * As per the ACPI specification: - * "The break operation causes the current package - * execution to complete" - * "Break -- Stop executing the current code package - * at this point" - * - * Returning AE_FALSE here will cause termination of - * the current package, and execution will continue one - * level up, starting with the completion of the parent Op. - */ - status = AE_CTRL_FALSE; - break; + while (walk_state->control_state && + (walk_state->control_state->control.opcode != AML_WHILE_OP)) { + control_state = acpi_ut_pop_generic_state (&walk_state->control_state); + acpi_ut_delete_generic_state (control_state); + } + /* No while found? */ - case AML_CONTINUE_OP: /* ACPI 2.0 */ + if (!walk_state->control_state) { + return (AE_AML_NO_WHILE); + } + + /* Was: Walk_state->Aml_last_while = Walk_state->Control_state->Control.Aml_predicate_start; */ - status = AE_NOT_IMPLEMENTED; + walk_state->aml_last_while = walk_state->control_state->control.package_end; + + /* Return status depending on opcode */ + + if (op->common.aml_opcode == AML_BREAK_OP) { + status = AE_CTRL_BREAK; + } + else { + status = AE_CTRL_CONTINUE; + } break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n", - op->opcode, op)); + op->common.aml_opcode, op)); status = AE_AML_BAD_OPCODE; break; } - return (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsutils.c linux2.4.21_itanium/drivers/acpi/dispatcher/dsutils.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dsutils.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dsutils.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -33,7 +33,7 @@ #include "acdebug.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dsutils") + ACPI_MODULE_NAME ("dsutils") /******************************************************************************* @@ -58,7 +58,7 @@ const acpi_opcode_info *parent_info; - FUNCTION_TRACE_PTR ("Ds_is_result_used", op); + ACPI_FUNCTION_TRACE_PTR ("Ds_is_result_used", op); /* Must have both an Op and a Result Object */ @@ -68,29 +68,25 @@ return_VALUE (TRUE); } - /* * If there is no parent, the result can't possibly be used! * (An executing method typically has no parent, since each * method is parsed separately) However, a method that is * invoked from another method has a parent. */ - if (!op->parent) { + if (!op->common.parent) { return_VALUE (FALSE); } - /* * Get info on the parent. The root Op is AML_SCOPE */ - - parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op)); return_VALUE (FALSE); } - /* * Decide what to do with the result based on the parent. If * the parent opcode will not use the result, delete the object. @@ -98,78 +94,90 @@ * as an operand later. */ switch (parent_info->class) { - /* - * In these cases, the parent will never use the return object - */ - case AML_CLASS_CONTROL: /* IF, ELSE, WHILE only */ + case AML_CLASS_CONTROL: - switch (op->parent->opcode) { + switch (op->common.parent->common.aml_opcode) { case AML_RETURN_OP: /* Never delete the return value associated with a return opcode */ - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result used, [RETURN] opcode=%X Op=%p\n", op->opcode, op)); - return_VALUE (TRUE); - break; + goto result_used; case AML_IF_OP: case AML_WHILE_OP: /* * If we are executing the predicate AND this is the predicate op, - * we will use the return value! + * we will use the return value */ - if ((walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) && + if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) && (walk_state->control_state->control.predicate_op == op)) { - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result used as a predicate, [IF/WHILE] opcode=%X Op=%p\n", - op->opcode, op)); - return_VALUE (TRUE); + goto result_used; } + break; + default: + /* Ignore other control opcodes */ break; } + /* The general control opcode returns no result */ - /* Fall through to not used case below */ + goto result_not_used; - case AML_CLASS_NAMED_OBJECT: /* Scope, method, etc. */ case AML_CLASS_CREATE: /* * These opcodes allow Term_arg(s) as operands and therefore - * method calls. The result is used. + * the operands can be method calls. The result is used. */ - if ((op->parent->opcode == AML_REGION_OP) || - (op->parent->opcode == AML_CREATE_FIELD_OP) || - (op->parent->opcode == AML_CREATE_BIT_FIELD_OP) || - (op->parent->opcode == AML_CREATE_BYTE_FIELD_OP) || - (op->parent->opcode == AML_CREATE_WORD_FIELD_OP) || - (op->parent->opcode == AML_CREATE_DWORD_FIELD_OP) || - (op->parent->opcode == AML_CREATE_QWORD_FIELD_OP)) { - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result used, [Region or Create_field] opcode=%X Op=%p\n", - op->opcode, op)); - return_VALUE (TRUE); + goto result_used; + + + case AML_CLASS_NAMED_OBJECT: + + if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || + (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) { + /* + * These opcodes allow Term_arg(s) as operands and therefore + * the operands can be method calls. The result is used. + */ + goto result_used; } - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result not used, Parent opcode=%X Op=%p\n", op->opcode, op)); + goto result_not_used; - return_VALUE (FALSE); - break; - /* - * In all other cases. the parent will actually use the return - * object, so keep it. - */ default: - break; + + /* + * In all other cases. the parent will actually use the return + * object, so keep it. + */ + goto result_used; } + +result_used: + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", + acpi_ps_get_opcode_name (op->common.aml_opcode), + acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op)); + return_VALUE (TRUE); + + +result_not_used: + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", + acpi_ps_get_opcode_name (op->common.aml_opcode), + acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op)); + + return_VALUE (FALSE); + } @@ -200,7 +208,7 @@ acpi_status status; - FUNCTION_TRACE_PTR ("Ds_delete_result_if_not_used", result_obj); + ACPI_FUNCTION_TRACE_PTR ("Ds_delete_result_if_not_used", result_obj); if (!op) { @@ -250,29 +258,29 @@ u32 arg_index) { acpi_status status = AE_OK; + acpi_status status2; NATIVE_CHAR *name_string; u32 name_length; - acpi_object_type8 data_type; acpi_operand_object *obj_desc; acpi_parse_object *parent_op; u16 opcode; - u32 flags; - operating_mode interpreter_mode; + acpi_interpreter_mode interpreter_mode; const acpi_opcode_info *op_info; + char *name; - FUNCTION_TRACE_PTR ("Ds_create_operand", arg); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_operand", arg); /* A valid name must be looked up in the namespace */ - if ((arg->opcode == AML_INT_NAMEPATH_OP) && - (arg->value.string)) { + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + (arg->common.value.string)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg)); /* Get the entire name string from the AML stream */ - status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->value.buffer, + status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer, &name_string, &name_length); if (ACPI_FAILURE (status)) { @@ -290,46 +298,41 @@ * IMODE_EXECUTE) in order to support the creation of * namespace objects during the execution of control methods. */ - parent_op = arg->parent; - op_info = acpi_ps_get_opcode_info (parent_op->opcode); + parent_op = arg->common.parent; + op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode); if ((op_info->flags & AML_NSNODE) && - (parent_op->opcode != AML_INT_METHODCALL_OP) && - (parent_op->opcode != AML_REGION_OP) && - (parent_op->opcode != AML_INT_NAMEPATH_OP)) { + (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) && + (parent_op->common.aml_opcode != AML_REGION_OP) && + (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) { /* Enter name into namespace if not found */ - interpreter_mode = IMODE_LOAD_PASS2; + interpreter_mode = ACPI_IMODE_LOAD_PASS2; } else { /* Return a failure if name not found */ - interpreter_mode = IMODE_EXECUTE; + interpreter_mode = ACPI_IMODE_EXECUTE; } status = acpi_ns_lookup (walk_state->scope_info, name_string, ACPI_TYPE_ANY, interpreter_mode, - NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, walk_state, - (acpi_namespace_node **) &obj_desc); - - /* Free the namestring created above */ - - ACPI_MEM_FREE (name_string); - + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &obj_desc)); /* * The only case where we pass through (ignore) a NOT_FOUND * error is for the Cond_ref_of opcode. */ if (status == AE_NOT_FOUND) { - if (parent_op->opcode == AML_COND_REF_OF_OP) { + if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) { /* * For the Conditional Reference op, it's OK if * the name is not found; We just need a way to * indicate this to the interpreter, set the * object to the root */ - obj_desc = (acpi_operand_object *) acpi_gbl_root_node; + obj_desc = ACPI_CAST_PTR (acpi_operand_object, acpi_gbl_root_node); status = AE_OK; } @@ -340,13 +343,20 @@ */ status = AE_AML_NAME_NOT_FOUND; - /* TBD: Externalize Name_string and print */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Object name was not found in namespace\n")); + name = NULL; + status2 = acpi_ns_externalize_name (ACPI_UINT32_MAX, name_string, NULL, &name); + if (ACPI_SUCCESS (status2)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Object name [%s] was not found in namespace\n", name)); + ACPI_MEM_FREE (name); + } } } + /* Free the namestring created above */ + + ACPI_MEM_FREE (name_string); + /* Check status from the lookup */ if (ACPI_FAILURE (status)) { @@ -359,14 +369,14 @@ if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); } else { /* Check for null name case */ - if (arg->opcode == AML_INT_NAMEPATH_OP) { + if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* * If the name is null, this means that this is an * optional result parameter that was not specified @@ -376,30 +386,25 @@ opcode = AML_ZERO_OP; /* Has no arguments! */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg)); - - /* - * TBD: [Investigate] anything else needed for the - * zero op lvalue? - */ } else { - opcode = arg->opcode; + opcode = arg->common.aml_opcode; } + /* Get the object type of the argument */ - /* Get the data type of the argument */ - - data_type = acpi_ds_map_opcode_to_data_type (opcode, &flags); - if (data_type == INTERNAL_TYPE_INVALID) { + op_info = acpi_ps_get_opcode_info (opcode); + if (op_info->object_type == INTERNAL_TYPE_INVALID) { return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } - if (flags & OP_HAS_RETURN_VALUE) { + if (op_info->flags & AML_HAS_RETVAL) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Argument previously created, already stacked \n")); - DEBUGGER_EXEC (acpi_db_display_argument_object (walk_state->operands [walk_state->num_operands - 1], walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object ( + walk_state->operands [walk_state->num_operands - 1], walk_state)); /* * Use value that was already previously returned @@ -415,13 +420,11 @@ acpi_format_exception (status))); return_ACPI_STATUS (status); } - } - else { /* Create an ACPI_INTERNAL_OBJECT for the argument */ - obj_desc = acpi_ut_create_internal_object (data_type); + obj_desc = acpi_ut_create_internal_object (op_info->object_type); if (!obj_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -434,7 +437,7 @@ acpi_ut_delete_object_desc (obj_desc); return_ACPI_STATUS (status); } - } + } /* Put the operand object on the object stack */ @@ -443,7 +446,7 @@ return_ACPI_STATUS (status); } - DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); } return_ACPI_STATUS (AE_OK); @@ -474,7 +477,7 @@ u32 arg_count = 0; - FUNCTION_TRACE_PTR ("Ds_create_operands", first_arg); + ACPI_FUNCTION_TRACE_PTR ("Ds_create_operands", first_arg); /* For all arguments in the list... */ @@ -491,7 +494,7 @@ /* Move on to next argument, if any */ - arg = arg->next; + arg = arg->common.next; arg_count++; } @@ -504,7 +507,7 @@ * pop everything off of the operand stack and delete those * objects */ - acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state); + (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n", (arg_count + 1), acpi_format_exception (status))); @@ -534,18 +537,13 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_PTR ("Ds_resolve_operands", walk_state); + 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 */ - - /* - * TBD: [Investigate] Note from previous parser: - * Ref_of problem with Acpi_ex_resolve_to_value() conversion. - */ 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)) { @@ -556,263 +554,3 @@ return_ACPI_STATUS (status); } - -/******************************************************************************* - * - * FUNCTION: Acpi_ds_map_opcode_to_data_type - * - * PARAMETERS: Opcode - AML opcode to map - * Out_flags - Additional info about the opcode - * - * RETURN: The ACPI type associated with the opcode - * - * DESCRIPTION: Convert a raw AML opcode to the associated ACPI data type, - * if any. If the opcode returns a value as part of the - * intepreter execution, a flag is returned in Out_flags. - * - ******************************************************************************/ - -acpi_object_type8 -acpi_ds_map_opcode_to_data_type ( - u16 opcode, - u32 *out_flags) -{ - acpi_object_type8 data_type = INTERNAL_TYPE_INVALID; - const acpi_opcode_info *op_info; - u32 flags = 0; - - - PROC_NAME ("Ds_map_opcode_to_data_type"); - - - op_info = acpi_ps_get_opcode_info (opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - /* Unknown opcode */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown AML opcode: %x\n", opcode)); - return (data_type); - } - - -/* - * TBD: Use op class - */ - - switch (op_info->type) { - - case AML_TYPE_LITERAL: - - switch (opcode) { - case AML_BYTE_OP: - case AML_WORD_OP: - case AML_DWORD_OP: - case AML_QWORD_OP: - - data_type = ACPI_TYPE_INTEGER; - break; - - - case AML_STRING_OP: - - data_type = ACPI_TYPE_STRING; - break; - - case AML_INT_NAMEPATH_OP: - data_type = INTERNAL_TYPE_REFERENCE; - break; - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown (type LITERAL) AML opcode: %x\n", opcode)); - break; - } - break; - - - case AML_TYPE_DATA_TERM: - - switch (opcode) { - case AML_BUFFER_OP: - - data_type = ACPI_TYPE_BUFFER; - break; - - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - data_type = ACPI_TYPE_PACKAGE; - break; - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown (type DATA_TERM) AML opcode: %x\n", opcode)); - break; - } - break; - - - case AML_TYPE_CONSTANT: - case AML_TYPE_METHOD_ARGUMENT: - case AML_TYPE_LOCAL_VARIABLE: - - data_type = INTERNAL_TYPE_REFERENCE; - break; - - - case AML_TYPE_EXEC_1A_0T_1R: - case AML_TYPE_EXEC_1A_1T_1R: - case AML_TYPE_EXEC_2A_0T_1R: - case AML_TYPE_EXEC_2A_1T_1R: - case AML_TYPE_EXEC_2A_2T_1R: - case AML_TYPE_EXEC_3A_1T_1R: - case AML_TYPE_EXEC_6A_0T_1R: - case AML_TYPE_RETURN: - - flags = OP_HAS_RETURN_VALUE; - data_type = ACPI_TYPE_ANY; - break; - - - case AML_TYPE_METHOD_CALL: - - flags = OP_HAS_RETURN_VALUE; - data_type = ACPI_TYPE_METHOD; - break; - - - case AML_TYPE_NAMED_FIELD: - case AML_TYPE_NAMED_SIMPLE: - case AML_TYPE_NAMED_COMPLEX: - case AML_TYPE_NAMED_NO_OBJ: - - data_type = acpi_ds_map_named_opcode_to_data_type (opcode); - break; - - - case AML_TYPE_EXEC_1A_0T_0R: - case AML_TYPE_EXEC_2A_0T_0R: - case AML_TYPE_EXEC_3A_0T_0R: - case AML_TYPE_EXEC_1A_1T_0R: - case AML_TYPE_CONTROL: - - /* No mapping needed at this time */ - - break; - - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unimplemented data type opcode: %x\n", opcode)); - break; - } - - /* Return flags to caller if requested */ - - if (out_flags) { - *out_flags = flags; - } - - return (data_type); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ds_map_named_opcode_to_data_type - * - * PARAMETERS: Opcode - The Named AML opcode to map - * - * RETURN: The ACPI type associated with the named opcode - * - * DESCRIPTION: Convert a raw Named AML opcode to the associated data type. - * Named opcodes are a subsystem of the AML opcodes. - * - ******************************************************************************/ - -acpi_object_type8 -acpi_ds_map_named_opcode_to_data_type ( - u16 opcode) -{ - acpi_object_type8 data_type; - - - FUNCTION_ENTRY (); - - - /* Decode Opcode */ - - switch (opcode) { - case AML_SCOPE_OP: - data_type = INTERNAL_TYPE_SCOPE; - break; - - case AML_DEVICE_OP: - data_type = ACPI_TYPE_DEVICE; - break; - - case AML_THERMAL_ZONE_OP: - data_type = ACPI_TYPE_THERMAL; - break; - - case AML_METHOD_OP: - data_type = ACPI_TYPE_METHOD; - break; - - case AML_POWER_RES_OP: - data_type = ACPI_TYPE_POWER; - break; - - case AML_PROCESSOR_OP: - data_type = ACPI_TYPE_PROCESSOR; - break; - - case AML_FIELD_OP: /* Field_op */ - data_type = INTERNAL_TYPE_FIELD_DEFN; - break; - - case AML_INDEX_FIELD_OP: /* Index_field_op */ - data_type = INTERNAL_TYPE_INDEX_FIELD_DEFN; - break; - - case AML_BANK_FIELD_OP: /* Bank_field_op */ - data_type = INTERNAL_TYPE_BANK_FIELD_DEFN; - break; - - case AML_INT_NAMEDFIELD_OP: /* NO CASE IN ORIGINAL */ - data_type = ACPI_TYPE_ANY; - break; - - case AML_NAME_OP: /* Name_op - special code in original */ - case AML_INT_NAMEPATH_OP: - data_type = ACPI_TYPE_ANY; - break; - - case AML_ALIAS_OP: - data_type = INTERNAL_TYPE_ALIAS; - break; - - case AML_MUTEX_OP: - data_type = ACPI_TYPE_MUTEX; - break; - - case AML_EVENT_OP: - data_type = ACPI_TYPE_EVENT; - break; - - case AML_DATA_REGION_OP: - case AML_REGION_OP: - data_type = ACPI_TYPE_REGION; - break; - - - default: - data_type = ACPI_TYPE_ANY; - break; - - } - - return (data_type); -} - - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswexec.c linux2.4.21_itanium/drivers/acpi/dispatcher/dswexec.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswexec.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dswexec.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -35,12 +35,12 @@ #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dswexec") + ACPI_MODULE_NAME ("dswexec") /* - * Dispatch tables for opcode classes + * Dispatch table for opcode classes */ -ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = { +static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = { acpi_ex_opcode_1A_0T_0R, acpi_ex_opcode_1A_0T_1R, acpi_ex_opcode_1A_1T_0R, @@ -68,17 +68,17 @@ acpi_status acpi_ds_get_predicate_value ( acpi_walk_state *walk_state, - u32 has_result_obj) { + acpi_operand_object *result_obj) { acpi_status status = AE_OK; acpi_operand_object *obj_desc; - FUNCTION_TRACE_PTR ("Ds_get_predicate_value", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_get_predicate_value", walk_state); walk_state->control_state->common.state = 0; - if (has_result_obj) { + if (result_obj) { status = acpi_ds_result_pop (&obj_desc, walk_state); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -88,7 +88,6 @@ return_ACPI_STATUS (status); } } - else { status = acpi_ds_create_operand (walk_state, walk_state->op, 0); if (ACPI_FAILURE (status)) { @@ -110,7 +109,6 @@ return_ACPI_STATUS (AE_AML_NO_OPERAND); } - /* * Result of predicate evaluation currently must * be a number @@ -124,7 +122,6 @@ goto cleanup; } - /* Truncate the predicate to 32-bits if necessary */ acpi_ex_truncate_for32bit_table (obj_desc, walk_state); @@ -136,7 +133,6 @@ if (obj_desc->integer.value) { walk_state->control_state->common.value = TRUE; } - else { /* * Predicate is FALSE, we will just toss the @@ -149,12 +145,12 @@ cleanup: - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%pn", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", walk_state->control_state->common.value, walk_state->op)); /* Break to debugger to display result */ - DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); /* * Delete the predicate result object (we know that @@ -162,7 +158,7 @@ */ acpi_ut_remove_reference (obj_desc); - walk_state->control_state->common.state = CONTROL_NORMAL; + walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; return_ACPI_STATUS (status); } @@ -192,7 +188,7 @@ u32 opcode_class; - FUNCTION_TRACE_PTR ("Ds_exec_begin_op", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_exec_begin_op", walk_state); op = walk_state->op; @@ -204,8 +200,18 @@ op = *out_op; walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->opcode = op->common.aml_opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + + if (acpi_ns_opens_scope (walk_state->op_info->object_type)) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", + acpi_ut_get_type_name (walk_state->op_info->object_type), op)); + + status = acpi_ds_scope_stack_pop (walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } } if (op == walk_state->origin) { @@ -223,11 +229,11 @@ */ if ((walk_state->control_state) && (walk_state->control_state->common.state == - CONTROL_CONDITIONAL_EXECUTING)) { + ACPI_CONTROL_CONDITIONAL_EXECUTING)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n", op, walk_state)); - walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING; + walk_state->control_state->common.state = ACPI_CONTROL_PREDICATE_EXECUTING; /* Save start of predicate */ @@ -239,7 +245,7 @@ /* We want to send namepaths to the load code */ - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { opcode_class = AML_CLASS_NAMED_OBJECT; } @@ -260,7 +266,7 @@ case AML_CLASS_NAMED_OBJECT: - if (walk_state->walk_type == WALK_METHOD) { + if (walk_state->walk_type == ACPI_WALK_METHOD) { /* * Found a named object declaration during method * execution; we must enter this object into the @@ -271,19 +277,16 @@ status = acpi_ds_load2_begin_op (walk_state, NULL); } - - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { status = acpi_ds_result_stack_push (walk_state); } - break; - /* most operators with arguments */ - case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: + /* most operators with arguments */ /* Start a new result/operand state */ status = acpi_ds_result_stack_push (walk_state); @@ -329,7 +332,7 @@ u32 i; - FUNCTION_TRACE_PTR ("Ds_exec_end_op", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_exec_end_op", walk_state); op = walk_state->op; @@ -337,11 +340,11 @@ op_class = walk_state->op_info->class; if (op_class == AML_CLASS_UNKNOWN) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->opcode)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode)); return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } - first_arg = op->value.arg; + first_arg = op->common.value.arg; /* Init the walk state */ @@ -349,22 +352,19 @@ walk_state->return_desc = NULL; walk_state->result_obj = NULL; - /* Call debugger for single step support (DEBUG build only) */ - DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class)); - DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);}); - + ACPI_DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class)); + ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);}); - switch (op_class) { /* Decode the Opcode Class */ - case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ + switch (op_class) { + case AML_CLASS_ARGUMENT: /* constants, literals, etc. -- do nothing */ break; - /* most operators with arguments */ - case AML_CLASS_EXECUTE: + case AML_CLASS_EXECUTE: /* most operators with arguments */ /* Build resolved operand stack */ @@ -385,37 +385,26 @@ status = acpi_ex_resolve_operands (walk_state->opcode, &(walk_state->operands [walk_state->num_operands -1]), walk_state); - if (ACPI_FAILURE (status)) { - /* TBD: must pop and delete operands */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "[%s]: Could not resolve operands, %s\n", - acpi_ps_get_opcode_name (walk_state->opcode), acpi_format_exception (status))); + if (ACPI_SUCCESS (status)) { + ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name (walk_state->opcode), + walk_state->num_operands, "after Ex_resolve_operands"); /* - * On error, we must delete all the operands and clear the - * operand stack + * Dispatch the request to the appropriate interpreter handler + * routine. There is one routine per opcode "type" based upon the + * number of opcode arguments and return type. */ - for (i = 0; i < walk_state->num_operands; i++) { - acpi_ut_remove_reference (walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - - walk_state->num_operands = 0; - goto cleanup; + status = acpi_gbl_op_type_dispatch [op_type] (walk_state); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "[%s]: Could not resolve operands, %s\n", + acpi_ps_get_opcode_name (walk_state->opcode), + acpi_format_exception (status))); } - DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE, acpi_ps_get_opcode_name (walk_state->opcode), - walk_state->num_operands, "after Ex_resolve_operands"); - - /* - * Dispatch the request to the appropriate interpreter handler - * routine. There is one routine per opcode "type" based upon the - * number of opcode arguments and return type. - */ - status = acpi_gbl_op_type_dispatch [op_type] (walk_state); - - - /* Delete argument objects and clear the operand stack */ + /* Always delete the argument objects and clear the operand stack */ for (i = 0; i < walk_state->num_operands; i++) { /* @@ -425,7 +414,6 @@ acpi_ut_remove_reference (walk_state->operands[i]); walk_state->operands[i] = NULL; } - walk_state->num_operands = 0; /* @@ -448,8 +436,11 @@ /* 1 Operand, 0 External_result, 0 Internal_result */ status = acpi_ds_exec_end_control_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } - acpi_ds_result_stack_pop (walk_state); + status = acpi_ds_result_stack_pop (walk_state); break; @@ -467,7 +458,7 @@ /* Next_op points to first argument op */ - next_op = next_op->next; + next_op = next_op->common.next; /* * Get the method's arguments and put them on the operand stack @@ -478,10 +469,9 @@ } /* - * Since the operands will be passed to another - * control method, we must resolve all local - * references here (Local variables, arguments - * to *this* method, etc.) + * Since the operands will be passed to another control method, + * we must resolve all local references here (Local variables, + * arguments to *this* method, etc.) */ status = acpi_ds_resolve_operands (walk_state); if (ACPI_FAILURE (status)) { @@ -499,7 +489,6 @@ * especially the operand count! */ return_ACPI_STATUS (status); - break; case AML_TYPE_CREATE_FIELD: @@ -516,16 +505,63 @@ break; + case AML_TYPE_CREATE_OBJECT: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing Create_object (Buffer/Package) Op=%p\n", op)); + + switch (op->common.parent->common.aml_opcode) { + case AML_NAME_OP: + + /* + * Put the Node on the object stack (Contains the ACPI Name of + * this object) + */ + walk_state->operands[0] = (void *) op->common.parent->common.node; + walk_state->num_operands = 1; + + status = acpi_ds_create_node (walk_state, op->common.parent->common.node, op->common.parent); + if (ACPI_FAILURE (status)) { + break; + } + + /* Fall through */ + /*lint -fallthrough */ + + case AML_INT_EVAL_SUBTREE_OP: + + status = acpi_ds_eval_data_object_operands (walk_state, op, + acpi_ns_get_attached_object (op->common.parent->common.node)); + break; + + default: + + status = acpi_ds_eval_data_object_operands (walk_state, op, NULL); + break; + } + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (ACPI_SUCCESS (status) && + walk_state->result_obj) { + status = acpi_ds_result_push (walk_state->result_obj, walk_state); + } + break; + + case AML_TYPE_NAMED_FIELD: case AML_TYPE_NAMED_COMPLEX: case AML_TYPE_NAMED_SIMPLE: + case AML_TYPE_NAMED_NO_OBJ: status = acpi_ds_load2_end_op (walk_state); if (ACPI_FAILURE (status)) { break; } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing Op_region Address/Length Op=%p\n", op)); @@ -539,23 +575,26 @@ break; + case AML_TYPE_UNDEFINED: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Undefined opcode type Op=%p\n", op)); return_ACPI_STATUS (AE_NOT_IMPLEMENTED); - break; case AML_TYPE_BOGUS: - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Internal opcode=%X type Op=%p\n", + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Internal opcode=%X type Op=%p\n", walk_state->opcode, op)); break; + default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n", - op_class, op_type, op->opcode, op)); + op_class, op_type, op->common.aml_opcode, op)); status = AE_NOT_IMPLEMENTED; break; @@ -563,8 +602,8 @@ } /* - * ACPI 2.0 support for 64-bit integers: - * Truncate numeric result value if we are executing from a 32-bit ACPI table + * ACPI 2.0 support for 64-bit integers: Truncate numeric + * result value if we are executing from a 32-bit ACPI table */ acpi_ex_truncate_for32bit_table (walk_state->result_obj, walk_state); @@ -575,9 +614,9 @@ if ((walk_state->control_state) && (walk_state->control_state->common.state == - CONTROL_PREDICATE_EXECUTING) && + ACPI_CONTROL_PREDICATE_EXECUTING) && (walk_state->control_state->control.predicate_op == op)) { - status = acpi_ds_get_predicate_value (walk_state, !! walk_state->result_obj); + status = acpi_ds_get_predicate_value (walk_state, walk_state->result_obj); walk_state->result_obj = NULL; } @@ -586,7 +625,7 @@ if (walk_state->result_obj) { /* Break to debugger to display result */ - DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj, walk_state)); /* * Delete the result op if and only if: @@ -598,10 +637,7 @@ /* Always clear the object stack */ - /* TBD: [Investigate] Clear stack of return value, - but don't delete it */ walk_state->num_operands = 0; - return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswload.c linux2.4.21_itanium/drivers/acpi/dispatcher/dswload.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswload.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dswload.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -34,7 +34,7 @@ #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dswload") + ACPI_MODULE_NAME ("dswload") /******************************************************************************* @@ -77,7 +77,6 @@ default: return (AE_BAD_PARAMETER); - break; } return (AE_OK); @@ -106,27 +105,31 @@ acpi_parse_object *op; acpi_namespace_node *node; acpi_status status; - acpi_object_type8 data_type; + acpi_object_type object_type; NATIVE_CHAR *path; - PROC_NAME ("Ds_load1_begin_op"); + ACPI_FUNCTION_NAME ("Ds_load1_begin_op"); op = walk_state->op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); + if (op && (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP)) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); + } + /* We are only interested in opcodes that have an associated name */ - if (walk_state->op) { - if (!(walk_state->op_info->flags & AML_NAMED)) { + if (op) { + if (!(walk_state->op_info->flags & AML_NAMED)) { *out_op = op; return (AE_OK); } /* Check if this object has already been installed in the namespace */ - if (op->node) { + if (op->common.node) { *out_op = op; return (AE_OK); } @@ -136,25 +139,18 @@ /* Map the raw opcode into an internal object type */ - data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode); - + object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); - - - if (walk_state->opcode == AML_SCOPE_OP) { - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); - } + "State=%p Op=%p Type=%X\n", walk_state, op, object_type)); /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that involve * arguments to the opcode must be created as we go back up the parse tree later. */ - status = acpi_ns_lookup (walk_state->scope_info, path, data_type, - IMODE_LOAD_PASS1, NS_NO_UPSEARCH, walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, path, object_type, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH, walk_state, &(node)); if (ACPI_FAILURE (status)) { return (status); @@ -171,13 +167,13 @@ /* Initialize */ - ((acpi_parse2_object *)op)->name = node->name; + op->named.name = node->name.integer; /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ - op->node = node; + op->common.node = node; acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op); *out_op = op; @@ -205,10 +201,11 @@ acpi_walk_state *walk_state) { acpi_parse_object *op; - acpi_object_type8 data_type; + acpi_object_type object_type; + acpi_status status = AE_OK; - PROC_NAME ("Ds_load1_end_op"); + ACPI_FUNCTION_NAME ("Ds_load1_end_op"); op = walk_state->op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); @@ -216,35 +213,51 @@ /* We are only interested in opcodes that have an associated name */ - if (!(walk_state->op_info->flags & AML_NAMED)) { + if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { return (AE_OK); } - /* Get the type to determine if we should pop the scope */ + /* Get the object type to determine if we should pop the scope */ + + object_type = walk_state->op_info->object_type; - data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + if (walk_state->op_info->flags & AML_FIELD) { + if (walk_state->opcode == AML_FIELD_OP || + walk_state->opcode == AML_BANK_FIELD_OP || + walk_state->opcode == AML_INDEX_FIELD_OP) { + status = acpi_ds_init_field_objects (op, walk_state); + } + return (status); + } + + + if (op->common.aml_opcode == AML_REGION_OP) { + status = acpi_ex_create_region (op->named.data, op->named.length, + (ACPI_ADR_SPACE_TYPE) ((op->common.value.arg)->common.value.integer), walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } - if (op->opcode == AML_NAME_OP) { - /* For Name opcode, check the argument */ + if (op->common.aml_opcode == AML_NAME_OP) { + /* For Name opcode, get the object type from the argument */ - if (op->value.arg) { - data_type = acpi_ds_map_opcode_to_data_type ( - (op->value.arg)->opcode, NULL); - ((acpi_namespace_node *)op->node)->type = - (u8) data_type; + if (op->common.value.arg) { + object_type = (acpi_ps_get_opcode_info ((op->common.value.arg)->common.aml_opcode))->object_type; + op->common.node->type = (u8) object_type; } } /* Pop the scope stack */ - if (acpi_ns_opens_scope (data_type)) { + if (acpi_ns_opens_scope (object_type)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", - acpi_ut_get_type_name (data_type), op)); + acpi_ut_get_type_name (object_type), op)); - acpi_ds_scope_stack_pop (walk_state); + status = acpi_ds_scope_stack_pop (walk_state); } - return (AE_OK); + return (status); } @@ -270,28 +283,21 @@ acpi_parse_object *op; acpi_namespace_node *node; acpi_status status; - acpi_object_type8 data_type; + acpi_object_type object_type; NATIVE_CHAR *buffer_ptr; - void *original = NULL; - PROC_NAME ("Ds_load2_begin_op"); + ACPI_FUNCTION_NAME ("Ds_load2_begin_op"); + op = walk_state->op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); - if (op) { /* We only care about Namespace opcodes here */ - if (!(walk_state->op_info->flags & AML_NSOPCODE) && - walk_state->opcode != AML_INT_NAMEPATH_OP) { - return (AE_OK); - } - - /* TBD: [Restructure] Temp! same code as in psparse */ - - if (!(walk_state->op_info->flags & AML_NAMED)) { + if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) || + (!(walk_state->op_info->flags & AML_NAMED))) { return (AE_OK); } @@ -301,7 +307,7 @@ if (walk_state->opcode == AML_INT_NAMEPATH_OP) { /* For Namepath op, get the path string */ - buffer_ptr = op->value.string; + buffer_ptr = op->common.value.string; if (!buffer_ptr) { /* No name, just exit */ @@ -311,20 +317,21 @@ else { /* Get name from the op */ - buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name; + buffer_ptr = (NATIVE_CHAR *) &op->named.name; } } else { + /* Get the namestring from the raw AML */ + buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state); } + /* Map the opcode into an internal object type */ - /* Map the raw opcode into an internal object type */ - - data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode); + object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%x\n", walk_state, op, data_type)); + "State=%p Op=%p Type=%X\n", walk_state, op, object_type)); if (walk_state->opcode == AML_FIELD_OP || @@ -333,23 +340,24 @@ node = NULL; status = AE_OK; } - else if (walk_state->opcode == AML_INT_NAMEPATH_OP) { /* * The Name_path is an object reference to an existing object. Don't enter the * name into the namespace, but look it up for use later */ - status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type, - IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); } - else { - if (op && op->node) { - original = op->node; - node = op->node; + /* All other opcodes */ + + if (op && op->common.node) { + /* This op/node was previously entered into the namespace */ + + node = op->common.node; - if (acpi_ns_opens_scope (data_type)) { - status = acpi_ds_scope_stack_push (node, data_type, walk_state); + if (acpi_ns_opens_scope (object_type)) { + status = acpi_ds_scope_stack_push (node, object_type, walk_state); if (ACPI_FAILURE (status)) { return (status); } @@ -363,8 +371,8 @@ * as we go downward in the parse tree. Any necessary subobjects that involve * arguments to the opcode must be created as we go back up the parse tree later. */ - status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type, - IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type, + ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, walk_state, &(node)); } if (ACPI_SUCCESS (status)) { @@ -376,26 +384,21 @@ return (AE_NO_MEMORY); } - /* Initialize */ + /* Initialize the new op */ - ((acpi_parse2_object *)op)->name = node->name; - *out_op = op; + if (node) { + op->named.name = node->name.integer; + } + if (out_op) { + *out_op = op; + } } /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ - op->node = node; - - if (original) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %p\n", original, node)); - - if (original != node) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Lookup match error: old %p new %p\n", original, node)); - } - } + op->common.node = node; } return (status); @@ -423,18 +426,18 @@ { acpi_parse_object *op; acpi_status status = AE_OK; - acpi_object_type8 data_type; + acpi_object_type object_type; acpi_namespace_node *node; acpi_parse_object *arg; acpi_namespace_node *new_node; u32 i; - PROC_NAME ("Ds_load2_end_op"); + ACPI_FUNCTION_NAME ("Ds_load2_end_op"); op = walk_state->op; - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); - + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", + walk_state->op_info->name, op, walk_state)); /* Only interested in opcodes that have namespace objects */ @@ -442,11 +445,11 @@ return (AE_OK); } - if (op->opcode == AML_SCOPE_OP) { + if (op->common.aml_opcode == AML_SCOPE_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Ending scope Op=%p State=%p\n", op, walk_state)); - if (((acpi_parse2_object *)op)->name == -1) { + if (op->named.name == ACPI_UINT16_MAX) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n", op, walk_state)); return (AE_OK); @@ -454,13 +457,13 @@ } - data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + object_type = walk_state->op_info->object_type; /* * Get the Node/name from the earlier lookup * (It was saved in the *op structure) */ - node = op->node; + node = op->common.node; /* * Put the Node on the object stack (Contains the ACPI Name of @@ -471,11 +474,14 @@ /* Pop the scope stack */ - if (acpi_ns_opens_scope (data_type)) { - + if (acpi_ns_opens_scope (object_type)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", - acpi_ut_get_type_name (data_type), op)); - acpi_ds_scope_stack_pop (walk_state); + acpi_ut_get_type_name (object_type), op)); + + status = acpi_ds_scope_stack_pop (walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } } /* @@ -508,11 +514,11 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Create-Load [%s] State=%p Op=%p Named_obj=%p\n", - acpi_ps_get_opcode_name (op->opcode), walk_state, op, node)); + acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node)); /* Decode the opcode */ - arg = op->value.arg; + arg = op->common.value.arg; switch (walk_state->op_info->type) { case AML_TYPE_CREATE_FIELD: @@ -527,24 +533,25 @@ case AML_TYPE_NAMED_FIELD: - arg = op->value.arg; - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_INDEX_FIELD_OP: - status = acpi_ds_create_index_field (op, (acpi_handle) arg->node, + status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node, walk_state); break; - case AML_BANK_FIELD_OP: - status = acpi_ds_create_bank_field (op, arg->node, walk_state); + status = acpi_ds_create_bank_field (op, arg->common.node, walk_state); break; - case AML_FIELD_OP: - status = acpi_ds_create_field (op, arg->node, walk_state); + status = acpi_ds_create_field (op, arg->common.node, walk_state); + break; + + default: + /* All NAMED_FIELD opcodes must be handled above */ break; } break; @@ -557,31 +564,27 @@ goto cleanup; } - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_PROCESSOR_OP: status = acpi_ex_create_processor (walk_state); break; - case AML_POWER_RES_OP: status = acpi_ex_create_power_resource (walk_state); break; - case AML_MUTEX_OP: status = acpi_ex_create_mutex (walk_state); break; - case AML_EVENT_OP: status = acpi_ex_create_event (walk_state); break; - case AML_DATA_REGION_OP: status = acpi_ex_create_table_region (walk_state); @@ -597,7 +600,6 @@ status = AE_OK; goto cleanup; - break; } /* Delete operands */ @@ -612,24 +614,23 @@ case AML_TYPE_NAMED_COMPLEX: - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_METHOD_OP: /* - * Method_op Pkg_length Names_string Method_flags Term_list + * Method_op Pkg_length Name_string Method_flags Term_list */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "LOADING-Method: State=%p Op=%p Named_obj=%p\n", walk_state, op, node)); - if (!node->object) { + if (!acpi_ns_get_attached_object (node)) { status = acpi_ds_create_operands (walk_state, arg); if (ACPI_FAILURE (status)) { goto cleanup; } - status = acpi_ex_create_method (((acpi_parse2_object *) op)->data, - ((acpi_parse2_object *) op)->length, - walk_state); + status = acpi_ex_create_method (op->named.data, + op->named.length, walk_state); } break; @@ -639,9 +640,21 @@ * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. * (We must save the address of the AML of the address and length operands) */ - status = acpi_ex_create_region (((acpi_parse2_object *) op)->data, - ((acpi_parse2_object *) op)->length, - (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state); + /* + * If we have a valid region, initialize it + * Namespace is NOT locked at this point. + */ + status = acpi_ev_initialize_region (acpi_ns_get_attached_object (node), FALSE); + if (ACPI_FAILURE (status)) { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == status) { + status = AE_OK; + } + } break; @@ -649,6 +662,11 @@ status = acpi_ds_create_node (walk_state, node, op); break; + + + default: + /* All NAMED_COMPLEX opcodes must be handled above */ + break; } break; @@ -668,21 +686,24 @@ /* * Lookup the method name and save the Node */ - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - ACPI_TYPE_ANY, IMODE_LOAD_PASS2, - NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); if (ACPI_SUCCESS (status)) { - /* TBD: has name already been resolved by here ??*/ - - /* TBD: [Restructure] Make sure that what we found is indeed a method! */ - /* We didn't search for a method on purpose, to see if the name would resolve! */ + /* + * Make sure that what we found is indeed a method + * We didn't search for a method on purpose, to see if the name would resolve + */ + if (new_node->type != ACPI_TYPE_METHOD) { + status = AE_AML_OPERAND_TYPE; + } /* We could put the returned object (Node) on the object stack for later, but * for now, we will put it in the "op" object that the parser uses, so we * can get it again at the end of this scope */ - op->node = new_node; + op->common.node = new_node; } break; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswscope.c linux2.4.21_itanium/drivers/acpi/dispatcher/dswscope.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswscope.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dswscope.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -30,7 +30,7 @@ #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dswscope") + ACPI_MODULE_NAME ("dswscope") #define STACK_POP(head) head @@ -53,7 +53,7 @@ { acpi_generic_state *scope_info; - PROC_NAME ("Ds_scope_stack_clear"); + ACPI_FUNCTION_NAME ("Ds_scope_stack_clear"); while (walk_state->scope_info) { @@ -84,26 +84,26 @@ acpi_status acpi_ds_scope_stack_push ( acpi_namespace_node *node, - acpi_object_type8 type, + acpi_object_type type, acpi_walk_state *walk_state) { acpi_generic_state *scope_info; - FUNCTION_TRACE ("Ds_scope_stack_push"); + ACPI_FUNCTION_TRACE ("Ds_scope_stack_push"); if (!node) { /* Invalid scope */ - REPORT_ERROR (("Ds_scope_stack_push: null scope passed\n")); + ACPI_REPORT_ERROR (("Ds_scope_stack_push: null scope passed\n")); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Make sure object type is valid */ if (!acpi_ex_validate_object_type (type)) { - REPORT_WARNING (("Ds_scope_stack_push: type code out of range\n")); + ACPI_REPORT_WARNING (("Ds_scope_stack_push: type code out of range\n")); } @@ -152,7 +152,7 @@ acpi_generic_state *scope_info; - FUNCTION_TRACE ("Ds_scope_stack_pop"); + ACPI_FUNCTION_TRACE ("Ds_scope_stack_pop"); /* diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswstate.c linux2.4.21_itanium/drivers/acpi/dispatcher/dswstate.c --- linux2.4.21_itanium.org/drivers/acpi/dispatcher/dswstate.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/dispatcher/dswstate.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,14 +25,12 @@ #include "acpi.h" -#include "amlcode.h" #include "acparser.h" #include "acdispat.h" #include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_DISPATCHER - MODULE_NAME ("dswstate") + ACPI_MODULE_NAME ("dswstate") /******************************************************************************* @@ -57,7 +55,7 @@ acpi_generic_state *state; - PROC_NAME ("Ds_result_insert"); + ACPI_FUNCTION_NAME ("Ds_result_insert"); state = walk_state->results; @@ -116,7 +114,7 @@ acpi_generic_state *state; - PROC_NAME ("Ds_result_remove"); + ACPI_FUNCTION_NAME ("Ds_result_remove"); state = walk_state->results; @@ -126,13 +124,12 @@ return (AE_NOT_EXIST); } - if (index >= OBJ_NUM_OPERANDS) { + if (index >= OBJ_MAX_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index out of range: %X State=%p Num=%X\n", index, walk_state, state->results.num_results)); } - /* Check for a valid result object */ if (!state->results.obj_desc [index]) { @@ -181,7 +178,7 @@ acpi_generic_state *state; - PROC_NAME ("Ds_result_pop"); + ACPI_FUNCTION_NAME ("Ds_result_pop"); state = walk_state->results; @@ -237,11 +234,11 @@ acpi_operand_object **object, acpi_walk_state *walk_state) { - u32 index; + NATIVE_UINT index; acpi_generic_state *state; - PROC_NAME ("Ds_result_pop_from_bottom"); + ACPI_FUNCTION_NAME ("Ds_result_pop_from_bottom"); state = walk_state->results; @@ -251,7 +248,6 @@ return (AE_NOT_EXIST); } - if (!state->results.num_results) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state)); return (AE_AML_NO_RETURN_VALUE); @@ -273,7 +269,7 @@ if (!*object) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n", - walk_state, state->results.num_results, index)); + walk_state, state->results.num_results, (u32) index)); return (AE_AML_NO_RETURN_VALUE); } @@ -307,7 +303,7 @@ acpi_generic_state *state; - PROC_NAME ("Ds_result_push"); + ACPI_FUNCTION_NAME ("Ds_result_push"); state = walk_state->results; @@ -329,7 +325,6 @@ return (AE_BAD_PARAMETER); } - state->results.obj_desc [state->results.num_results] = object; state->results.num_results++; @@ -360,7 +355,7 @@ { acpi_generic_state *state; - PROC_NAME ("Ds_result_stack_push"); + ACPI_FUNCTION_NAME ("Ds_result_stack_push"); state = acpi_ut_create_generic_state (); @@ -396,7 +391,7 @@ { acpi_generic_state *state; - PROC_NAME ("Ds_result_stack_pop"); + ACPI_FUNCTION_NAME ("Ds_result_stack_pop"); /* Check for stack underflow */ @@ -440,7 +435,7 @@ u32 i; - FUNCTION_TRACE_PTR ("Ds_obj_stack_delete_all", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_obj_stack_delete_all", walk_state); /* The stack size is configurable, but fixed */ @@ -474,7 +469,7 @@ void *object, acpi_walk_state *walk_state) { - PROC_NAME ("Ds_obj_stack_push"); + ACPI_FUNCTION_NAME ("Ds_obj_stack_push"); /* Check for stack overflow */ @@ -519,7 +514,7 @@ acpi_operand_object **object, acpi_walk_state *walk_state) { - PROC_NAME ("Ds_obj_stack_pop_object"); + ACPI_FUNCTION_NAME ("Ds_obj_stack_pop_object"); /* Check for stack underflow */ @@ -580,7 +575,7 @@ { u32 i; - PROC_NAME ("Ds_obj_stack_pop"); + ACPI_FUNCTION_NAME ("Ds_obj_stack_pop"); for (i = 0; i < pop_count; i++) { @@ -628,7 +623,7 @@ u32 i; acpi_operand_object *obj_desc; - PROC_NAME ("Ds_obj_stack_pop_and_delete"); + ACPI_FUNCTION_NAME ("Ds_obj_stack_pop_and_delete"); for (i = 0; i < pop_count; i++) { @@ -679,7 +674,7 @@ acpi_walk_state *walk_state) { - FUNCTION_TRACE_PTR ("Ds_obj_stack_get_value", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_obj_stack_get_value", walk_state); /* Can't do it if the stack is empty */ @@ -694,7 +689,6 @@ return_PTR (NULL); } - return_PTR (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) - index]); } @@ -704,31 +698,31 @@ * * FUNCTION: Acpi_ds_get_current_walk_state * - * PARAMETERS: Walk_list - Get current active state for this walk list + * PARAMETERS: Thread - Get current active state for this Thread * * RETURN: Pointer to the current walk state * * DESCRIPTION: Get the walk state that is at the head of the list (the "current" - * walk state. + * walk state.) * ******************************************************************************/ acpi_walk_state * acpi_ds_get_current_walk_state ( - acpi_walk_list *walk_list) + ACPI_THREAD_STATE *thread) { - PROC_NAME ("Ds_get_current_walk_state"); + ACPI_FUNCTION_NAME ("Ds_get_current_walk_state"); - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Ds_get_current_walk_state, =%p\n", - walk_list->walk_state)); - - if (!walk_list) { + if (!thread) { return (NULL); } - return (walk_list->walk_state); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Ds_get_current_walk_state, =%p\n", + thread->walk_state_list)); + + return (thread->walk_state_list); } @@ -748,13 +742,13 @@ void acpi_ds_push_walk_state ( acpi_walk_state *walk_state, - acpi_walk_list *walk_list) + ACPI_THREAD_STATE *thread) { - FUNCTION_TRACE ("Ds_push_walk_state"); + ACPI_FUNCTION_TRACE ("Ds_push_walk_state"); - walk_state->next = walk_list->walk_state; - walk_list->walk_state = walk_state; + walk_state->next = thread->walk_state_list; + thread->walk_state_list = walk_state; return_VOID; } @@ -776,25 +770,25 @@ acpi_walk_state * acpi_ds_pop_walk_state ( - acpi_walk_list *walk_list) + ACPI_THREAD_STATE *thread) { acpi_walk_state *walk_state; - FUNCTION_TRACE ("Ds_pop_walk_state"); + ACPI_FUNCTION_TRACE ("Ds_pop_walk_state"); - walk_state = walk_list->walk_state; + walk_state = thread->walk_state_list; if (walk_state) { /* Next walk state becomes the current walk state */ - walk_list->walk_state = walk_state->next; + thread->walk_state_list = walk_state->next; /* * Don't clear the NEXT field, this serves as an indicator * that there is a parent WALK STATE - * Walk_state->Next = NULL; + * NO: Walk_state->Next = NULL; */ } @@ -807,12 +801,12 @@ * FUNCTION: Acpi_ds_create_walk_state * * PARAMETERS: Origin - Starting point for this walk - * Walk_list - Owning walk list + * Thread - Current thread state * * RETURN: Pointer to the new walk state. * - * DESCRIPTION: Allocate and initialize a new walk state. The current walk state - * is set to this new state. + * DESCRIPTION: Allocate and initialize a new walk state. The current walk + * state is set to this new state. * ******************************************************************************/ @@ -821,13 +815,13 @@ acpi_owner_id owner_id, acpi_parse_object *origin, acpi_operand_object *mth_desc, - acpi_walk_list *walk_list) + ACPI_THREAD_STATE *thread) { acpi_walk_state *walk_state; acpi_status status; - FUNCTION_TRACE ("Ds_create_walk_state"); + ACPI_FUNCTION_TRACE ("Ds_create_walk_state"); walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK); @@ -839,7 +833,7 @@ walk_state->owner_id = owner_id; walk_state->origin = origin; walk_state->method_desc = mth_desc; - walk_state->walk_list = walk_list; + walk_state->thread = thread; /* Init the method args/local */ @@ -856,8 +850,8 @@ /* Put the new state at the head of the walk list */ - if (walk_list) { - acpi_ds_push_walk_state (walk_state, walk_list); + if (thread) { + acpi_ds_push_walk_state (walk_state, thread); } return_PTR (walk_state); @@ -892,7 +886,7 @@ acpi_parse_state *parser_state = &walk_state->parser_state; - FUNCTION_TRACE ("Ds_init_aml_walk"); + ACPI_FUNCTION_TRACE ("Ds_init_aml_walk"); walk_state->parser_state.aml = @@ -901,7 +895,6 @@ walk_state->parser_state.pkg_end = aml_start + aml_length; /* The Next_op of the Next_walk will be the beginning of the method */ - /* TBD: [Restructure] -- obsolete? */ walk_state->next_op = NULL; walk_state->params = params; @@ -914,11 +907,10 @@ if (method_node) { walk_state->parser_state.start_node = method_node; - walk_state->walk_type = WALK_METHOD; + walk_state->walk_type = ACPI_WALK_METHOD; walk_state->method_node = method_node; walk_state->method_desc = acpi_ns_get_attached_object (method_node); - /* Push start scope on scope stack and make it current */ status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state); @@ -928,13 +920,15 @@ /* Init the method arguments */ - acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state); + status = acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - else { /* Setup the current scope */ - parser_state->start_node = parser_state->start_op->node; + parser_state->start_node = parser_state->start_op->common.node; if (parser_state->start_node) { /* Push start scope on scope stack and make it current */ @@ -946,9 +940,8 @@ } } - acpi_ds_init_callbacks (walk_state, pass_number); - - return_ACPI_STATUS (AE_OK); + status = acpi_ds_init_callbacks (walk_state, pass_number); + return_ACPI_STATUS (status); } #endif @@ -972,7 +965,7 @@ acpi_generic_state *state; - FUNCTION_TRACE_PTR ("Ds_delete_walk_state", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ds_delete_walk_state", walk_state); if (!walk_state) { @@ -984,7 +977,6 @@ return; } - if (walk_state->parser_state.scope) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state)); } @@ -1038,7 +1030,7 @@ acpi_ds_delete_walk_state_cache ( void) { - FUNCTION_TRACE ("Ds_delete_walk_state_cache"); + ACPI_FUNCTION_TRACE ("Ds_delete_walk_state_cache"); acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/ec.c linux2.4.21_itanium/drivers/acpi/ec.c --- linux2.4.21_itanium.org/drivers/acpi/ec.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/ec.c Wed Jul 23 18:28:08 2003 @@ -0,0 +1,736 @@ +/* + * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_EC_COMPONENT +ACPI_MODULE_NAME ("acpi_ec") + +#define PREFIX "ACPI: " + + +#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ +#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ +#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ + +#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ +#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ + +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ +#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ + +#define ACPI_EC_COMMAND_READ 0x80 +#define ACPI_EC_COMMAND_WRITE 0x81 +#define ACPI_EC_COMMAND_QUERY 0x84 + +static int acpi_ec_add (struct acpi_device *device); +static int acpi_ec_remove (struct acpi_device *device, int type); +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, + }, +}; + +struct acpi_ec { + acpi_handle handle; + unsigned long gpe_bit; + unsigned long status_port; + unsigned long command_port; + unsigned long data_port; + unsigned long global_lock; + spinlock_t lock; +}; + + +/* -------------------------------------------------------------------------- + Transaction Management + -------------------------------------------------------------------------- */ + +static int +acpi_ec_wait ( + struct acpi_ec *ec, + u8 event) +{ + u8 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; + + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ + switch (event) { + case ACPI_EC_EVENT_OBF: + do { + acpi_ec_status = inb(ec->status_port); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + case ACPI_EC_EVENT_IBE: + do { + acpi_ec_status = inb(ec->status_port); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + default: + return -EINVAL; + } + + return -ETIME; +} + + +static int +acpi_ec_read ( + struct acpi_ec *ec, + u8 address, + u8 *data) +{ + acpi_status status = AE_OK; + int result = 0; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_READ, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (0 != result) + goto end; + + outb(address, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (0 != result) + goto end; + + *data = inb(ec->data_port); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_write ( + struct acpi_ec *ec, + u8 address, + u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_write"); + + if (!ec) + return_VALUE(-EINVAL); + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_WRITE, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (0 != result) + goto end; + + outb(address, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (0 != result) + goto end; + + outb(data, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (0 != result) + goto end; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", + data, address)); + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_query ( + struct acpi_ec *ec, + u8 *data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_query"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_QUERY, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (0 != result) + goto end; + + *data = inb(ec->data_port); + if (!*data) + result = -ENODATA; + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Event Management + -------------------------------------------------------------------------- */ + +struct acpi_ec_query_data { + acpi_handle handle; + u8 data; +}; + + +static void +acpi_ec_gpe_query ( + void *data) +{ + struct acpi_ec_query_data *query_data = NULL; + static char object_name[5] = {'_','Q','0','0','\0'}; + const char hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); + + if (!data) + return; + + query_data = (struct acpi_ec_query_data *) data; + + object_name[2] = hex[((query_data->data >> 4) & 0x0F)]; + object_name[3] = hex[(query_data->data & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate(query_data->handle, object_name, NULL, NULL); + + kfree(query_data); + + return; +} + + +static void +acpi_ec_gpe_handler ( + void *data) +{ + acpi_status status = AE_OK; + struct acpi_ec *ec = (struct acpi_ec *) data; + u8 value = 0; + unsigned long flags = 0; + struct acpi_ec_query_data *query_data = NULL; + + if (!ec) + return; + + spin_lock_irqsave(&ec->lock, flags); + value = inb(ec->command_port); + spin_unlock_irqrestore(&ec->lock, flags); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ + + if (!(value & ACPI_EC_FLAG_SCI)) + return; + + if (0 != acpi_ec_query(ec, &value)) + return; + + query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC); + if (!query_data) + return; + query_data->handle = ec->handle; + query_data->data = value; + + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, query_data); + if (ACPI_FAILURE(status)) + kfree(query_data); + + return; +} + + +/* -------------------------------------------------------------------------- + Address Space Management + -------------------------------------------------------------------------- */ + +static acpi_status +acpi_ec_space_setup ( + acpi_handle region_handle, + u32 function, + void *handler_context, + void **return_context) +{ + /* + * The EC object is in the handler context and is needed + * when calling the acpi_ec_space_handler. + */ + *return_context = handler_context; + + return AE_OK; +} + + +static acpi_status +acpi_ec_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + acpi_integer *value, + void *handler_context, + void *region_context) +{ + int result = 0; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_space_handler"); + + if ((address > 0xFF) || (bit_width != 8) || !value || !handler_context) + return_VALUE(AE_BAD_PARAMETER); + + ec = (struct acpi_ec *) handler_context; + + switch (function) { + case ACPI_READ: + result = acpi_ec_read(ec, (u8) address, (u8*) value); + break; + case ACPI_WRITE: + result = acpi_ec_write(ec, (u8) address, (u8) *value); + break; + default: + result = -EINVAL; + break; + } + + switch (result) { + case -EINVAL: + return_VALUE(AE_BAD_PARAMETER); + break; + case -ENODEV: + return_VALUE(AE_NOT_FOUND); + break; + case -ETIME: + return_VALUE(AE_TIME); + break; + default: + return_VALUE(AE_OK); + } + +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#include +#include + +struct proc_dir_entry *acpi_ec_dir = NULL; + + +static int +acpi_ec_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_ec *ec = (struct acpi_ec *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read_info"); + + if (!ec || (off != 0)) + goto end; + + p += sprintf(p, "gpe bit: 0x%02x\n", + (u32) ec->gpe_bit); + p += sprintf(p, "ports: 0x%02x, 0x%02x\n", + (u32) ec->status_port, (u32) ec->data_port); + p += sprintf(p, "use global lock: %s\n", + ec->global_lock?"yes":"no"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_ec_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); + + if (!acpi_ec_dir) { + acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); + if (!acpi_ec_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_ec_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + entry = create_proc_read_entry(ACPI_EC_FILE_INFO, S_IRUGO, + acpi_device_dir(device), acpi_ec_read_info, + acpi_driver_data(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Unable to create '%s' fs entry\n", + ACPI_EC_FILE_INFO)); + + return_VALUE(0); +} + + +static int +acpi_ec_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_ec_remove_fs"); + + if (!acpi_ec_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static int +acpi_ec_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_add"); + + if (!device) + return_VALUE(-EINVAL); + + ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + if (!ec) + return_VALUE(-ENOMEM); + memset(ec, 0, sizeof(struct acpi_ec)); + + ec->handle = device->handle; + ec->lock = SPIN_LOCK_UNLOCKED; + sprintf(acpi_device_name(device), "%s", ACPI_EC_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); + + /* Get GPE bit assignment (EC events). */ + status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error obtaining GPE bit assignment\n")); + result = -ENODEV; + goto end; + } + + result = acpi_ec_add_fs(device); + if (0 != result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->gpe_bit); + +end: + if (0 != result) + kfree(ec); + + return_VALUE(result); +} + + +static int +acpi_ec_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_remove"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + acpi_ec_remove_fs(device); + + kfree(ec); + + return_VALUE(0); +} + + +static int +acpi_ec_start ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_resource *resource = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_start"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + if (!ec) + return_VALUE(-EINVAL); + + /* + * Get I/O port addresses + */ + + status = acpi_get_current_resources(ec->handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); + return_VALUE(-ENODEV); + } + + resource = (acpi_resource *) buffer.pointer; + if (!resource || (resource->id != ACPI_RSTYPE_IO)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); + result = -ENODEV; + goto end; + } + ec->data_port = resource->data.io.min_base_address; + + resource = ACPI_NEXT_RESOURCE(resource); + if (!resource || (resource->id != ACPI_RSTYPE_IO)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); + result = -ENODEV; + goto end; + } + ec->command_port = ec->status_port = resource->data.io.min_base_address; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", + (u32) ec->gpe_bit, (u32) ec->command_port, (u32) ec->data_port)); + + /* + * Install GPE handler + */ + + status = acpi_install_gpe_handler(ec->gpe_bit, + ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + status = acpi_install_address_space_handler (ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, + &acpi_ec_space_setup, ec); + if (ACPI_FAILURE(status)) { + acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + return_VALUE(-ENODEV); + } +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_ec_stop ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_stop"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + status = acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + status = acpi_remove_gpe_handler(ec->gpe_bit, &acpi_ec_gpe_handler); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +int __init +acpi_ec_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_init"); + + result = acpi_bus_register_driver(&acpi_ec_driver); + if (0 > result) { + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_ec_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_exit"); + + result = acpi_bus_unregister_driver(&acpi_ec_driver); + if (0 == result) + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + + return_VOID; +} diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/Makefile linux2.4.21_itanium/drivers/acpi/events/Makefile --- linux2.4.21_itanium.org/drivers/acpi/events/Makefile Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/Makefile Wed Jul 23 18:28:09 2003 @@ -1,11 +1,10 @@ # # Makefile for all Linux ACPI interpreter subdirectories -# EXCEPT for the ospm directory # O_TARGET := $(notdir $(CURDIR)).o -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) +obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evevent.c linux2.4.21_itanium/drivers/acpi/events/evevent.c --- linux2.4.21_itanium.org/drivers/acpi/events/evevent.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evevent.c Wed Jul 23 18:28:09 2003 @@ -1,13 +1,12 @@ /****************************************************************************** * - * Module Name: evevent - Fixed and General Purpose Acpi_event - * handling and dispatch - * $Revision: 51 $ + * Module Name: evevent - Fixed and General Purpose Even handling and dispatch + * $Revision: 88 $ * *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,12 +24,11 @@ */ #include "acpi.h" -#include "achware.h" #include "acevents.h" #include "acnamesp.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evevent") + ACPI_MODULE_NAME ("evevent") /******************************************************************************* @@ -41,9 +39,7 @@ * * RETURN: Status * - * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly - * configured, disables SCI event sources, installs the SCI - * handler + * DESCRIPTION: Initialize global data structures for events. * ******************************************************************************/ @@ -54,7 +50,7 @@ acpi_status status; - FUNCTION_TRACE ("Ev_initialize"); + ACPI_FUNCTION_TRACE ("Ev_initialize"); /* Make sure we have ACPI tables */ @@ -64,17 +60,6 @@ return_ACPI_STATUS (AE_NO_ACPI_TABLES); } - - /* Make sure the BIOS supports ACPI mode */ - - if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "ACPI Mode is not supported!\n")); - return_ACPI_STATUS (AE_ERROR); - } - - - acpi_gbl_original_mode = acpi_hw_get_mode(); - /* * Initialize the Fixed and General Purpose Acpi_events prior. This is * done prior to enabling SCIs to prevent interrupts from occuring @@ -82,30 +67,63 @@ */ status = acpi_ev_fixed_event_initialize (); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize fixed events.\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + "Unable to initialize fixed events, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } status = acpi_ev_gpe_initialize (); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize general purpose events.\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + "Unable to initialize general purpose events, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_handler_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install handlers for the SCI, Global Lock, and GPEs. + * + ******************************************************************************/ + +acpi_status +acpi_ev_handler_initialize ( + void) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Ev_initialize"); + + /* Install the SCI handler */ status = acpi_ev_install_sci_handler (); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to install System Control Interrupt Handler\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + "Unable to install System Control Interrupt Handler, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } - /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ status = acpi_ev_init_gpe_control_methods (); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Gpe control methods\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + "Unable to initialize GPE control methods, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } @@ -113,11 +131,12 @@ status = acpi_ev_init_global_lock_handler (); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Global Lock handler\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + "Unable to initialize Global Lock handler, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } - return_ACPI_STATUS (status); } @@ -130,27 +149,36 @@ * * RETURN: Status * - * DESCRIPTION: Initialize the Fixed Acpi_event data structures + * DESCRIPTION: Install the fixed event handlers and enable the fixed events. * ******************************************************************************/ acpi_status -acpi_ev_fixed_event_initialize(void) +acpi_ev_fixed_event_initialize ( + void) { - int i = 0; + NATIVE_UINT i; + acpi_status status; - /* Initialize the structure that keeps track of fixed event handlers */ + /* + * Initialize the structure that keeps track of fixed event handlers + * and enable the fixed events. + */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; - } - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0); - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0); - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0); - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0); - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0); + /* Enable the fixed event */ + + if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { + status = acpi_set_register (acpi_gbl_fixed_event_info[i].enable_register_id, + 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return (status); + } + } + } return (AE_OK); } @@ -169,54 +197,41 @@ ******************************************************************************/ u32 -acpi_ev_fixed_event_detect (void) +acpi_ev_fixed_event_detect ( + void) { - u32 int_status = INTERRUPT_NOT_HANDLED; - u32 status_register; - u32 enable_register; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + u32 gpe_status; + u32 gpe_enable; + NATIVE_UINT_MAX32 i; - PROC_NAME ("Ev_fixed_event_detect"); + ACPI_FUNCTION_NAME ("Ev_fixed_event_detect"); /* * Read the fixed feature status and enable registers, as all the cases - * depend on their values. + * depend on their values. Ignore errors here. */ - status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS); - enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN); + (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &gpe_status); + (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &gpe_enable); ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Fixed Acpi_event Block: Enable %08X Status %08X\n", - enable_register, status_register)); - - - /* power management timer roll over */ - - if ((status_register & ACPI_STATUS_PMTIMER) && - (enable_register & ACPI_ENABLE_PMTIMER)) { - int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER); - } - - /* global event (BIOS wants the global lock) */ + gpe_enable, gpe_status)); - if ((status_register & ACPI_STATUS_GLOBAL) && - (enable_register & ACPI_ENABLE_GLOBAL)) { - int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL); - } - - /* power button event */ - - if ((status_register & ACPI_STATUS_POWER_BUTTON) && - (enable_register & ACPI_ENABLE_POWER_BUTTON)) { - int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON); - } + /* + * Check for all possible Fixed Events and dispatch those that are active + */ + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + /* Both the status and enable bits must be on for this event */ - /* sleep button event */ + if ((gpe_status & acpi_gbl_fixed_event_info[i].status_bit_mask) && + (gpe_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) { + /* Found an active (signalled) event */ - if ((status_register & ACPI_STATUS_SLEEP_BUTTON) && - (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) { - int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON); + int_status |= acpi_ev_fixed_event_dispatch (i); + } } return (int_status); @@ -240,60 +255,32 @@ acpi_ev_fixed_event_dispatch ( u32 event) { - u32 register_id; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* Clear the status bit */ - switch (event) { - case ACPI_EVENT_PMTIMER: - register_id = TMR_STS; - break; - - case ACPI_EVENT_GLOBAL: - register_id = GBL_STS; - break; - - case ACPI_EVENT_POWER_BUTTON: - register_id = PWRBTN_STS; - break; - - case ACPI_EVENT_SLEEP_BUTTON: - register_id = SLPBTN_STS; - break; - - case ACPI_EVENT_RTC: - register_id = RTC_STS; - break; - - default: - return 0; - break; - } - - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1); + (void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id, + 1, ACPI_MTX_DO_NOT_LOCK); /* * Make sure we've got a handler. If not, report an error. * The event is disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { - register_id = (PM1_EN | REGISTER_BIT_ID(register_id)); - - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, - register_id, 0); + (void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 0, ACPI_MTX_DO_NOT_LOCK); - REPORT_ERROR ( + ACPI_REPORT_ERROR ( ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n", event)); - return (INTERRUPT_NOT_HANDLED); + return (ACPI_INTERRUPT_NOT_HANDLED); } - /* Invoke the handler */ + /* Invoke the Fixed Event handler */ return ((acpi_gbl_fixed_event_handlers[event].handler)( acpi_gbl_fixed_event_handlers[event].context)); @@ -315,138 +302,217 @@ acpi_status acpi_ev_gpe_initialize (void) { - u32 i; - u32 j; - u32 register_index; + NATIVE_UINT_MAX32 i; + NATIVE_UINT_MAX32 j; + u32 gpe_block; + u32 gpe_register; + u32 gpe_number_index; u32 gpe_number; - u16 gpe0register_count; - u16 gpe1_register_count; + ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; - FUNCTION_TRACE ("Ev_gpe_initialize"); + ACPI_FUNCTION_TRACE ("Ev_gpe_initialize"); + /* - * Set up various GPE counts + * Initialize the GPE Block globals * - * You may ask,why are the GPE register block lengths divided by 2? - * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event - * Registers, we have, + * Why the GPE register block lengths divided by 2: From the ACPI Spec, + * section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length - * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the - * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN - * The length of the GPE1_STS and GPE1_EN registers is equal to - * half the GPE1_LEN. If a generic register block is not supported - * then its respective block pointer and block length values in the - * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need - * to be the same size." - */ - gpe0register_count = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len); - gpe1_register_count = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len); - acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count; + * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the + * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN + * The length of the GPE1_STS and GPE1_EN registers is equal to + * half the GPE1_LEN. If a generic register block is not supported + * then its respective block pointer and block length values in the + * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need + * to be the same size." + */ + if ((acpi_gbl_FADT->Xgpe0_blk.register_bit_width != 0) || + (acpi_gbl_FADT->Xgpe0_blk.register_bit_offset != 0) || + (acpi_gbl_FADT->Xgpe0_blk.address != 0)) { + acpi_gbl_gpe_block_info[0].address_space_id = acpi_gbl_FADT->Xgpe0_blk.address_space_id; + acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width); + + if (acpi_gbl_gpe_block_info[0].register_count == 0) + acpi_gbl_gpe_block_info[0].register_count = 1; + acpi_gbl_gpe_block_info[0].block_address = &acpi_gbl_FADT->Xgpe0_blk; + acpi_gbl_gpe_block_info[0].block_base_number = 0; + } + + if ((acpi_gbl_FADT->Xgpe1_blk.register_bit_width != 0) || + (acpi_gbl_FADT->Xgpe1_blk.register_bit_offset != 0) || + (acpi_gbl_FADT->Xgpe1_blk.address != 0)) { + acpi_gbl_gpe_block_info[1].address_space_id = acpi_gbl_FADT->Xgpe1_blk.address_space_id; + acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width); + + if (acpi_gbl_gpe_block_info[1].register_count == 0) + acpi_gbl_gpe_block_info[1].register_count = 1; + acpi_gbl_gpe_block_info[1].block_address = &acpi_gbl_FADT->Xgpe1_blk; + acpi_gbl_gpe_block_info[1].block_base_number = acpi_gbl_FADT->gpe1_base; + } + acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count + + acpi_gbl_gpe_block_info[1].register_count; if (!acpi_gbl_gpe_register_count) { - REPORT_WARNING (("Zero GPEs are defined in the FADT\n")); + ACPI_REPORT_WARNING (("Zero GPEs are defined in the FADT\n")); return_ACPI_STATUS (AE_OK); } + /* Determine the maximum GPE number for this machine */ + + acpi_gbl_gpe_number_max = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1; + + if (acpi_gbl_gpe_block_info[1].register_count) { + /* Check for GPE0/GPE1 overlap */ + + if (acpi_gbl_gpe_number_max >= acpi_gbl_FADT->gpe1_base) { + ACPI_REPORT_ERROR (("GPE0 block overlaps the GPE1 block\n")); + return_ACPI_STATUS (AE_BAD_VALUE); + } + + /* GPE0 and GPE1 do not have to be contiguous in the GPE number space */ + + acpi_gbl_gpe_number_max = acpi_gbl_FADT->gpe1_base + (ACPI_MUL_8 (acpi_gbl_gpe_block_info[1].register_count) - 1); + } + + /* Check for Max GPE number out-of-range */ + + if (acpi_gbl_gpe_number_max > ACPI_GPE_MAX) { + ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n", acpi_gbl_gpe_number_max)); + return_ACPI_STATUS (AE_BAD_VALUE); + } + /* - * Allocate the Gpe information block + * Allocate the GPE number-to-index translation table */ - acpi_gbl_gpe_registers = ACPI_MEM_CALLOCATE (acpi_gbl_gpe_register_count * - sizeof (acpi_gpe_registers)); - if (!acpi_gbl_gpe_registers) { + acpi_gbl_gpe_number_to_index = ACPI_MEM_CALLOCATE ( + sizeof (ACPI_GPE_INDEX_INFO) * + ((ACPI_SIZE) acpi_gbl_gpe_number_max + 1)); + if (!acpi_gbl_gpe_number_to_index) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Could not allocate the Gpe_registers block\n")); + "Could not allocate the Gpe_number_to_index table\n")); return_ACPI_STATUS (AE_NO_MEMORY); } + /* Set the Gpe index table to GPE_INVALID */ + + ACPI_MEMSET (acpi_gbl_gpe_number_to_index, (int) ACPI_GPE_INVALID, + sizeof (ACPI_GPE_INDEX_INFO) * ((ACPI_SIZE) acpi_gbl_gpe_number_max + 1)); + /* - * Allocate the Gpe dispatch handler block - * There are eight distinct GP events per register. - * Initialization to zeros is sufficient - */ - acpi_gbl_gpe_info = ACPI_MEM_CALLOCATE (MUL_8 (acpi_gbl_gpe_register_count) * - sizeof (acpi_gpe_level_info)); - if (!acpi_gbl_gpe_info) { - ACPI_MEM_FREE (acpi_gbl_gpe_registers); - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_info block\n")); - return_ACPI_STATUS (AE_NO_MEMORY); + * Allocate the GPE register information block + */ + acpi_gbl_gpe_register_info = ACPI_MEM_CALLOCATE ( + (ACPI_SIZE) acpi_gbl_gpe_register_count * + sizeof (ACPI_GPE_REGISTER_INFO)); + if (!acpi_gbl_gpe_register_info) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Could not allocate the Gpe_register_info table\n")); + goto error_exit1; } - /* Set the Gpe validation table to GPE_INVALID */ - - MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, ACPI_NUM_GPE); + /* + * Allocate the GPE dispatch handler block. There are eight distinct GPEs + * per register. Initialization to zeros is sufficient. + */ + acpi_gbl_gpe_number_info = ACPI_MEM_CALLOCATE ( + (ACPI_SIZE) ACPI_MUL_8 (acpi_gbl_gpe_register_count) * + sizeof (ACPI_GPE_NUMBER_INFO)); + if (!acpi_gbl_gpe_number_info) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_number_info table\n")); + goto error_exit2; + } /* - * Initialize the Gpe information and validation blocks. A goal of these - * blocks is to hide the fact that there are two separate GPE register sets - * In a given block, the status registers occupy the first half, and - * the enable registers occupy the second half. + * Initialize the GPE information and validation tables. A goal of these + * tables is to hide the fact that there are two separate GPE register sets + * in a given gpe hardware block, the status registers occupy the first half, + * and the enable registers occupy the second half. Another goal is to hide + * the fact that there may be multiple GPE hardware blocks. */ + gpe_register = 0; + gpe_number_index = 0; - /* GPE Block 0 */ + for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) { + for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) { + gpe_register_info = &acpi_gbl_gpe_register_info[gpe_register]; - register_index = 0; + /* Init the Register info for this entire GPE register (8 GPEs) */ - for (i = 0; i < gpe0register_count; i++) { - acpi_gbl_gpe_registers[register_index].status_addr = - (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i); + gpe_register_info->base_gpe_number = (u8) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + + (ACPI_MUL_8 (i))); - acpi_gbl_gpe_registers[register_index].enable_addr = - (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i + gpe0register_count); + ACPI_STORE_ADDRESS (gpe_register_info->status_address.address, + (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + + i)); - acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i); + ACPI_STORE_ADDRESS (gpe_register_info->enable_address.address, + (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + + i + + acpi_gbl_gpe_block_info[gpe_block].register_count)); - for (j = 0; j < 8; j++) { - gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; - acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; - } + gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; + gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; + gpe_register_info->status_address.register_bit_width = 8; + gpe_register_info->enable_address.register_bit_width = 8; + gpe_register_info->status_address.register_bit_offset = 8; + gpe_register_info->enable_address.register_bit_offset = 8; - /* - * Clear the status/enable registers. Note that status registers - * are cleared by writing a '1', while enable registers are cleared - * by writing a '0'. - */ - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00, 8); - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF, 8); + /* Init the Index mapping info for each GPE number within this register */ - register_index++; - } + for (j = 0; j < 8; j++) { + gpe_number = gpe_register_info->base_gpe_number + j; + acpi_gbl_gpe_number_to_index[gpe_number].number_index = (u8) gpe_number_index; - /* GPE Block 1 */ + acpi_gbl_gpe_number_info[gpe_number_index].bit_mask = acpi_gbl_decode_to8bit[j]; + gpe_number_index++; + } - for (i = 0; i < gpe1_register_count; i++) { - acpi_gbl_gpe_registers[register_index].status_addr = - (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i); + /* + * Clear the status/enable registers. Note that status registers + * are cleared by writing a '1', while enable registers are cleared + * by writing a '0'. + */ - acpi_gbl_gpe_registers[register_index].enable_addr = - (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count); + status = acpi_hw_low_level_write (8, 0x00, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_gbl_gpe_registers[register_index].gpe_base = - (u8) (acpi_gbl_FADT->gpe1_base + MUL_8 (i)); + status = acpi_hw_low_level_write (8, 0xFF, &gpe_register_info->status_address, 0); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - for (j = 0; j < 8; j++) { - gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; - acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; + gpe_register++; } - /* - * Clear the status/enable registers. Note that status registers - * are cleared by writing a '1', while enable registers are cleared - * by writing a '0'. - */ - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00, 8); - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF, 8); - - register_index++; + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d: %X registers at %8.8X%8.8X\n", + (s32) gpe_block, acpi_gbl_gpe_block_info[0].register_count, + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address)))); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d Range GPE #%2.2X to GPE #%2.2X\n", + (s32) gpe_block, + acpi_gbl_gpe_block_info[gpe_block].block_base_number, + acpi_gbl_gpe_block_info[gpe_block].block_base_number + + ((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1))); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%8.8X%8.8X (Blk0) %X@%8.8X%8.8X (Blk1)\n", - gpe0register_count, HIDWORD(acpi_gbl_FADT->Xgpe0blk.address), LODWORD(acpi_gbl_FADT->Xgpe0blk.address), - gpe1_register_count, HIDWORD(acpi_gbl_FADT->Xgpe1_blk.address), LODWORD(acpi_gbl_FADT->Xgpe1_blk.address))); - return_ACPI_STATUS (AE_OK); + + + /* Error cleanup */ + +error_exit2: + ACPI_MEM_FREE (acpi_gbl_gpe_register_info); + +error_exit1: + ACPI_MEM_FREE (acpi_gbl_gpe_number_to_index); + return_ACPI_STATUS (AE_NO_MEMORY); } @@ -468,7 +534,7 @@ * Where: * L - means that the GPE is level triggered * E - means that the GPE is edge triggered - * nn - is the GPE number + * nn - is the GPE number [in HEX] * ******************************************************************************/ @@ -480,28 +546,34 @@ void **return_value) { u32 gpe_number; + u32 gpe_number_index; NATIVE_CHAR name[ACPI_NAME_SIZE + 1]; u8 type; + acpi_status status; - PROC_NAME ("Ev_save_method_info"); + ACPI_FUNCTION_NAME ("Ev_save_method_info"); /* Extract the name from the object and convert to a string */ - MOVE_UNALIGNED32_TO_32 (name, &((acpi_namespace_node *) obj_handle)->name); + ACPI_MOVE_UNALIGNED32_TO_32 (name, + &((acpi_namespace_node *) obj_handle)->name.integer); name[ACPI_NAME_SIZE] = 0; /* - * Edge/Level determination is based on the 2nd s8 of the method name + * Edge/Level determination is based on the 2nd character of the method name */ - if (name[1] == 'L') { + switch (name[1]) { + case 'L': type = ACPI_EVENT_LEVEL_TRIGGERED; - } - else if (name[1] == 'E') { + break; + + case 'E': type = ACPI_EVENT_EDGE_TRIGGERED; - } - else { + break; + + default: /* Unknown method type, just ignore it! */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -510,9 +582,9 @@ return (AE_OK); } - /* Convert the last two characters of the name to the Gpe Number */ + /* Convert the last two characters of the name to the GPE Number */ - gpe_number = STRTOUL (&name[2], NULL, 16); + gpe_number = ACPI_STRTOUL (&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ @@ -522,9 +594,10 @@ return (AE_OK); } - /* Ensure that we have a valid GPE number */ + /* Get GPE index and ensure that we have a valid GPE number */ - if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + gpe_number_index = acpi_ev_get_gpe_number_index (gpe_number); + if (gpe_number_index == ACPI_GPE_INVALID) { /* Not valid, all we can do here is ignore it */ return (AE_OK); @@ -534,14 +607,16 @@ * Now we can add this information to the Gpe_info block * for use during dispatch of this GPE. */ - acpi_gbl_gpe_info [gpe_number].type = type; - acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle; - + acpi_gbl_gpe_number_info [gpe_number_index].type = type; + acpi_gbl_gpe_number_info [gpe_number_index].method_handle = obj_handle; /* * Enable the GPE (SCIs should be disabled at this point) */ - acpi_hw_enable_gpe (gpe_number); + status = acpi_hw_enable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return (status); + } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n", name, gpe_number)); @@ -555,10 +630,9 @@ * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Obtain the control methods associated with the GPEs. - * * NOTE: Must be called AFTER namespace initialization! * ******************************************************************************/ @@ -569,7 +643,7 @@ acpi_status status; - FUNCTION_TRACE ("Ev_init_gpe_control_methods"); + ACPI_FUNCTION_TRACE ("Ev_init_gpe_control_methods"); /* Get a permanent handle to the _GPE object */ @@ -597,21 +671,25 @@ * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * - * DESCRIPTION: Detect if any GP events have occurred + * DESCRIPTION: Detect if any GP events have occurred. This function is + * executed at interrupt level. * ******************************************************************************/ u32 acpi_ev_gpe_detect (void) { - u32 int_status = INTERRUPT_NOT_HANDLED; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u32 i; u32 j; u8 enabled_status_byte; u8 bit_mask; + ACPI_GPE_REGISTER_INFO *gpe_register_info; + u32 in_value; + acpi_status status; - PROC_NAME ("Ev_gpe_detect"); + ACPI_FUNCTION_NAME ("Ev_gpe_detect"); /* @@ -620,23 +698,31 @@ * Find all currently active GP events. */ for (i = 0; i < acpi_gbl_gpe_register_count; i++) { - acpi_os_read_port (acpi_gbl_gpe_registers[i].status_addr, - &acpi_gbl_gpe_registers[i].status, 8); + gpe_register_info = &acpi_gbl_gpe_register_info[i]; + + status = acpi_hw_low_level_read (8, &in_value, &gpe_register_info->status_address, 0); + gpe_register_info->status = (u8) in_value; + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } - acpi_os_read_port (acpi_gbl_gpe_registers[i].enable_addr, - &acpi_gbl_gpe_registers[i].enable, 8); + status = acpi_hw_low_level_read (8, &in_value, &gpe_register_info->enable_address, 0); + gpe_register_info->enable = (u8) in_value; + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, - "GPE block at %X - Enable %08X Status %08X\n", - acpi_gbl_gpe_registers[i].enable_addr, - acpi_gbl_gpe_registers[i].status, - acpi_gbl_gpe_registers[i].enable)); + "GPE block at %8.8X%8.8X - Values: Enable %02X Status %02X\n", + ACPI_HIDWORD (ACPI_GET_ADDRESS (gpe_register_info->enable_address.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (gpe_register_info->enable_address.address)), + gpe_register_info->enable, + gpe_register_info->status)); /* First check if there is anything active at all in this register */ - enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status & - acpi_gbl_gpe_registers[i].enable); - + enabled_status_byte = (u8) (gpe_register_info->status & + gpe_register_info->enable); if (!enabled_status_byte) { /* No active GPEs in this register, move on */ @@ -654,7 +740,7 @@ * or method. */ int_status |= acpi_ev_gpe_dispatch ( - acpi_gbl_gpe_registers[i].gpe_base + j); + gpe_register_info->base_gpe_number + j); } } } @@ -667,7 +753,7 @@ * * FUNCTION: Acpi_ev_asynch_execute_gpe_method * - * PARAMETERS: Gpe_number - The 0-based Gpe number + * PARAMETERS: Gpe_number - The 0-based GPE number * * RETURN: None * @@ -679,46 +765,66 @@ * ******************************************************************************/ -static void +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method ( void *context) { - unsigned long gpe_number = (unsigned long) context; - acpi_gpe_level_info gpe_info; + u32 gpe_number = (u32) ACPI_TO_INTEGER (context); + u32 gpe_number_index; + ACPI_GPE_NUMBER_INFO gpe_info; + acpi_status status; - FUNCTION_TRACE ("Ev_asynch_execute_gpe_method"); + ACPI_FUNCTION_TRACE ("Ev_asynch_execute_gpe_method"); - /* - * Take a snapshot of the GPE info for this level - */ - acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - gpe_info = acpi_gbl_gpe_info [gpe_number]; - acpi_ut_release_mutex (ACPI_MTX_EVENTS); + + gpe_number_index = acpi_ev_get_gpe_number_index (gpe_number); + if (gpe_number_index == ACPI_GPE_INVALID) { + return_VOID; + } /* - * Method Handler (_Lxx, _Exx): - * ---------------------------- - * Evaluate the _Lxx/_Exx control method that corresponds to this GPE. + * Take a snapshot of the GPE info for this level - we copy the + * info to prevent a race condition with Remove_handler. */ + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_VOID; + } + + gpe_info = acpi_gbl_gpe_number_info [gpe_number_index]; + status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_VOID; + } + if (gpe_info.method_handle) { - acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + /* + * Invoke the GPE Method (_Lxx, _Exx): + * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) + */ + status = acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("%s while evaluated GPE%X method\n", + acpi_format_exception (status), gpe_number)); + } } - /* - * Level-Triggered? - * ---------------- - * If level-triggered we clear the GPE status bit after handling the event. - */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + /* + * GPE is level-triggered, we clear the GPE status bit after handling + * the event. + */ + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return_VOID; + } } /* * Enable the GPE. */ - acpi_hw_enable_gpe (gpe_number); - + (void) acpi_hw_enable_gpe (gpe_number); return_VOID; } @@ -727,18 +833,13 @@ * * FUNCTION: Acpi_ev_gpe_dispatch * - * PARAMETERS: Gpe_number - The 0-based Gpe number + * PARAMETERS: Gpe_number - The 0-based GPE number * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * - * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event. - * Clears the status bit for the requested event. - * - * TBD: [Investigate] is this still valid or necessary: - * The Gpe handler differs from the fixed events in that it clears the enable - * bit rather than the status bit to clear the interrupt. This allows - * software outside of interrupt context to determine what caused the SCI and - * dispatch the correct AML. + * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) + * or method (e.g. _Lxx/_Exx) handler. This function executes + * at interrupt level. * ******************************************************************************/ @@ -746,82 +847,96 @@ acpi_ev_gpe_dispatch ( u32 gpe_number) { - acpi_gpe_level_info gpe_info; + u32 gpe_number_index; + ACPI_GPE_NUMBER_INFO *gpe_info; + acpi_status status; - FUNCTION_TRACE ("Ev_gpe_dispatch"); + ACPI_FUNCTION_TRACE ("Ev_gpe_dispatch"); - /* - * Valid GPE number? - */ - if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", gpe_number)); - return_VALUE (INTERRUPT_NOT_HANDLED); + gpe_number_index = acpi_ev_get_gpe_number_index (gpe_number); + if (gpe_number_index == ACPI_GPE_INVALID) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid event, GPE[%X].\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } /* - * Disable the GPE. + * We don't have to worry about mutex on Gpe_info because we are + * executing at interrupt level. */ - acpi_hw_disable_gpe (gpe_number); - - gpe_info = acpi_gbl_gpe_info [gpe_number]; + gpe_info = &acpi_gbl_gpe_number_info [gpe_number_index]; /* - * Edge-Triggered? - * --------------- * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. */ - if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + if (gpe_info->type & ACPI_EVENT_EDGE_TRIGGERED) { + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } } - /* - * Function Handler (e.g. EC)? - */ - if (gpe_info.handler) { - /* Invoke function handler (at interrupt level). */ - - gpe_info.handler (gpe_info.context); - /* Level-Triggered? */ + /* + * Dispatch the GPE to either an installed handler, or the control + * method associated with this GPE (_Lxx or _Exx). + * If a handler exists, we invoke it and do not attempt to run the method. + * If there is neither a handler nor a method, we disable the level to + * prevent further events from coming in here. + */ + if (gpe_info->handler) { + /* Invoke the installed handler (at interrupt level) */ - if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + gpe_info->handler (gpe_info->context); + } + else if (gpe_info->method_handle) { + /* + * Disable GPE, so it doesn't keep firing before the method has a + * chance to run. + */ + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } - /* Enable GPE */ - - acpi_hw_enable_gpe (gpe_number); + /* + * Execute the method associated with the GPE. + */ + if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, + acpi_ev_asynch_execute_gpe_method, + ACPI_TO_POINTER (gpe_number)))) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%X], event is disabled\n", gpe_number)); + } } + else { + /* No handler or method to run! */ - /* - * Method Handler (e.g. _Exx/_Lxx)? - */ - else if (gpe_info.method_handle) { - if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE, - acpi_ev_asynch_execute_gpe_method, (void*) (u64)gpe_number))) { - /* - * Shoudn't occur, but if it does report an error. Note that - * the GPE will remain disabled until the ACPI Core Subsystem - * is restarted, or the handler is removed/reinstalled. - */ - REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: No handler or method for GPE[%X], disabling event\n", gpe_number)); + + /* + * Disable the GPE. The GPE will remain disabled until the ACPI + * Core Subsystem is restarted, or the handler is reinstalled. + */ + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } /* - * No Handler? Report an error and leave the GPE disabled. + * It is now safe to clear level-triggered evnets. */ - else { - REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number)); - - /* Level-Triggered? */ - - if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + if (gpe_info->type & ACPI_EVENT_LEVEL_TRIGGERED) { + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } - return_VALUE (INTERRUPT_HANDLED); + return_VALUE (ACPI_INTERRUPT_HANDLED); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evmisc.c linux2.4.21_itanium/drivers/acpi/events/evmisc.c --- linux2.4.21_itanium.org/drivers/acpi/events/evmisc.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evmisc.c Wed Jul 23 18:28:09 2003 @@ -1,13 +1,12 @@ /****************************************************************************** * - * Module Name: evmisc - ACPI device notification handler dispatch - * and ACPI Global Lock support - * $Revision: 35 $ + * Module Name: evmisc - Miscellaneous event manager support functions + * $Revision: 53 $ * *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,10 +27,95 @@ #include "acevents.h" #include "acnamesp.h" #include "acinterp.h" -#include "achware.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evmisc") + ACPI_MODULE_NAME ("evmisc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_is_notify_object + * + * PARAMETERS: Node - Node to check + * + * RETURN: TRUE if notifies allowed on this object + * + * DESCRIPTION: Check type of node for a object that supports notifies. + * + * TBD: This could be replaced by a flag bit in the node. + * + ******************************************************************************/ + +u8 +acpi_ev_is_notify_object ( + acpi_namespace_node *node) +{ + switch (node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + case ACPI_TYPE_THERMAL: + /* + * These are the ONLY objects that can receive ACPI notifications + */ + return (TRUE); + + default: + return (FALSE); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_get_gpe_register_index + * + * PARAMETERS: Gpe_number - Raw GPE number + * + * RETURN: None. + * + * DESCRIPTION: Returns the register index (index into the GPE register info + * table) associated with this GPE. + * + ******************************************************************************/ + +u32 +acpi_ev_get_gpe_register_index ( + u32 gpe_number) +{ + + if (gpe_number > acpi_gbl_gpe_number_max) { + return (ACPI_GPE_INVALID); + } + + return (ACPI_DIV_8 (acpi_gbl_gpe_number_to_index[gpe_number].number_index)); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_get_gpe_number_index + * + * PARAMETERS: Gpe_number - Raw GPE number + * + * RETURN: None. + * + * DESCRIPTION: Returns the number index (index into the GPE number info table) + * associated with this GPE. + * + ******************************************************************************/ + +u32 +acpi_ev_get_gpe_number_index ( + u32 gpe_number) +{ + + if (gpe_number > acpi_gbl_gpe_number_max) { + return (ACPI_GPE_INVALID); + } + + return (acpi_gbl_gpe_number_to_index[gpe_number].number_index); +} /******************************************************************************* @@ -58,7 +142,7 @@ acpi_status status = AE_OK; - PROC_NAME ("Ev_queue_notify_request"); + ACPI_FUNCTION_NAME ("Ev_queue_notify_request"); /* @@ -92,43 +176,38 @@ break; } - /* - * Get the notify object attached to the device Node + * Get the notify object attached to the NS Node */ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - /* We have the notify object, Get the right handler */ switch (node->type) { case ACPI_TYPE_DEVICE: - if (notify_value <= MAX_SYS_NOTIFY) { - handler_obj = obj_desc->device.sys_handler; - } - else { - handler_obj = obj_desc->device.drv_handler; - } - break; - case ACPI_TYPE_THERMAL: - if (notify_value <= MAX_SYS_NOTIFY) { - handler_obj = obj_desc->thermal_zone.sys_handler; + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + handler_obj = obj_desc->common_notify.sys_handler; } else { - handler_obj = obj_desc->thermal_zone.drv_handler; + handler_obj = obj_desc->common_notify.drv_handler; } break; + + default: + /* All other types are not supported */ + return (AE_TYPE); } } - /* If there is any handler to run, schedule the dispatcher */ - if ((acpi_gbl_sys_notify.handler && (notify_value <= MAX_SYS_NOTIFY)) || - (acpi_gbl_drv_notify.handler && (notify_value > MAX_SYS_NOTIFY)) || + if ((acpi_gbl_sys_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || + (acpi_gbl_drv_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { - notify_info = acpi_ut_create_generic_state (); if (!notify_info) { return (AE_NO_MEMORY); @@ -169,7 +248,7 @@ * ******************************************************************************/ -void +void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch ( void *context) { @@ -179,14 +258,14 @@ acpi_operand_object *handler_obj; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* * We will invoke a global notify handler if installed. * This is done _before_ we invoke the per-device handler attached to the device. */ - if (notify_info->notify.value <= MAX_SYS_NOTIFY) { + if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { /* Global system notification handler */ if (acpi_gbl_sys_notify.handler) { @@ -194,7 +273,6 @@ global_context = acpi_gbl_sys_notify.context; } } - else { /* Global driver notification handler */ @@ -204,7 +282,6 @@ } } - /* Invoke the system handler first, if present */ if (global_handler) { @@ -237,18 +314,23 @@ * ******************************************************************************/ -static void +static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread ( void *context) { + acpi_status status; + /* Signal threads that are waiting for the lock */ if (acpi_gbl_global_lock_thread_count) { /* Send sufficient units to the semaphore */ - acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, + status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, acpi_gbl_global_lock_thread_count); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n")); + } } } @@ -270,7 +352,7 @@ void *context) { u8 acquired = FALSE; - void *global_lock; + acpi_status status; /* @@ -278,8 +360,7 @@ * If we don't get it now, it will be marked pending and we will * take another interrupt when it becomes free. */ - global_lock = acpi_gbl_FACS->global_lock; - ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { /* Got the lock, now wake all threads waiting for it */ @@ -287,11 +368,17 @@ /* Run the Global Lock thread which will signal all waiting threads */ - acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_global_lock_thread, - context); + status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, + acpi_ev_global_lock_thread, context); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n", + acpi_format_exception (status))); + + return (ACPI_INTERRUPT_NOT_HANDLED); + } } - return (INTERRUPT_HANDLED); + return (ACPI_INTERRUPT_HANDLED); } @@ -311,7 +398,7 @@ acpi_status status; - FUNCTION_TRACE ("Ev_init_global_lock_handler"); + ACPI_FUNCTION_TRACE ("Ev_init_global_lock_handler"); acpi_gbl_global_lock_present = TRUE; @@ -320,7 +407,7 @@ /* * If the global lock does not exist on this platform, the attempt - * to enable GBL_STS will fail (the GBL_EN bit will not stick) + * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick) * Map to AE_OK, but mark global lock as not present. * Any attempt to actually use the global lock will be flagged * with an error. @@ -345,14 +432,15 @@ *****************************************************************************/ acpi_status -acpi_ev_acquire_global_lock(void) +acpi_ev_acquire_global_lock ( + u32 timeout) { acpi_status status = AE_OK; u8 acquired = FALSE; - void *global_lock; - FUNCTION_TRACE ("Ev_acquire_global_lock"); + ACPI_FUNCTION_TRACE ("Ev_acquire_global_lock"); + /* Make sure that we actually have a global lock */ @@ -364,46 +452,36 @@ acpi_gbl_global_lock_thread_count++; - - /* If we (OS side) have the hardware lock already, we are done */ + /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */ if (acpi_gbl_global_lock_acquired) { return_ACPI_STATUS (AE_OK); } - /* Only if the FACS is valid */ - - if (!acpi_gbl_FACS) { - return_ACPI_STATUS (AE_OK); - } - - /* We must acquire the actual hardware lock */ - global_lock = acpi_gbl_FACS->global_lock; - ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { /* We got the lock */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired the Global Lock\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired the HW Global Lock\n")); acpi_gbl_global_lock_acquired = TRUE; return_ACPI_STATUS (AE_OK); } - /* * Did not get the lock. The pending bit was set above, and we must now * wait until we get the global lock released interrupt. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for the HW Global Lock\n")); - /* - * Acquire the global lock semaphore first. - * Since this wait will block, we must release the interpreter - */ + /* + * Acquire the global lock semaphore first. + * Since this wait will block, we must release the interpreter + */ status = acpi_ex_system_wait_semaphore (acpi_gbl_global_lock_semaphore, - ACPI_UINT32_MAX); + timeout); return_ACPI_STATUS (status); } @@ -416,45 +494,86 @@ * ******************************************************************************/ -void +acpi_status acpi_ev_release_global_lock (void) { u8 pending = FALSE; - void *global_lock; + acpi_status status = AE_OK; - FUNCTION_TRACE ("Ev_release_global_lock"); + ACPI_FUNCTION_TRACE ("Ev_release_global_lock"); if (!acpi_gbl_global_lock_thread_count) { - REPORT_WARNING(("Global Lock has not be acquired, cannot release\n")); - return_VOID; + ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n")); + return_ACPI_STATUS (AE_NOT_ACQUIRED); } - /* One fewer thread has the global lock */ + /* One fewer thread has the global lock */ acpi_gbl_global_lock_thread_count--; + if (acpi_gbl_global_lock_thread_count) { + /* There are still some threads holding the lock, cannot release */ - /* Have all threads released the lock? */ + return_ACPI_STATUS (AE_OK); + } - if (!acpi_gbl_global_lock_thread_count) { - /* - * No more threads holding lock, we can do the actual hardware - * release - */ - global_lock = acpi_gbl_FACS->global_lock; - ACPI_RELEASE_GLOBAL_LOCK (global_lock, pending); - acpi_gbl_global_lock_acquired = FALSE; + /* + * No more threads holding lock, we can do the actual hardware + * release + */ + ACPI_RELEASE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, pending); + acpi_gbl_global_lock_acquired = FALSE; - /* - * If the pending bit was set, we must write GBL_RLS to the control - * register - */ - if (pending) { - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, - GBL_RLS, 1); - } + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (pending) { + status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK); + } + + return_ACPI_STATUS (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ev_terminate (void) +{ + + ACPI_FUNCTION_TRACE ("Ev_terminate"); + + + /* + * Free global tables, etc. + */ + if (acpi_gbl_gpe_register_info) { + ACPI_MEM_FREE (acpi_gbl_gpe_register_info); + acpi_gbl_gpe_register_info = NULL; + } + + if (acpi_gbl_gpe_number_info) { + ACPI_MEM_FREE (acpi_gbl_gpe_number_info); + acpi_gbl_gpe_number_info = NULL; + } + + if (acpi_gbl_gpe_number_to_index) { + ACPI_MEM_FREE (acpi_gbl_gpe_number_to_index); + acpi_gbl_gpe_number_to_index = NULL; } return_VOID; } + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evregion.c linux2.4.21_itanium/drivers/acpi/events/evregion.c --- linux2.4.21_itanium.org/drivers/acpi/events/evregion.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evregion.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,15 +28,14 @@ #include "acevents.h" #include "acnamesp.h" #include "acinterp.h" -#include "amlcode.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evregion") + ACPI_MODULE_NAME ("evregion") /******************************************************************************* * - * FUNCTION: Acpi_ev_install_default_address_space_handlers + * FUNCTION: Acpi_ev_init_address_spaces * * PARAMETERS: * @@ -47,13 +46,13 @@ ******************************************************************************/ acpi_status -acpi_ev_install_default_address_space_handlers ( +acpi_ev_init_address_spaces ( void) { acpi_status status; - FUNCTION_TRACE ("Ev_install_default_address_space_handlers"); + ACPI_FUNCTION_TRACE ("Ev_init_address_spaces"); /* @@ -68,40 +67,46 @@ * space must be always available -- even though we are nowhere * near ready to find the PCI root buses at this point. * - * NOTE: We ignore AE_EXIST because this means that a handler has - * already been installed (via Acpi_install_address_space_handler) + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via Acpi_install_address_space_handler) */ - status = acpi_install_address_space_handler (acpi_gbl_root_node, + + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) { + (status != AE_ALREADY_EXISTS)) { return_ACPI_STATUS (status); } - status = acpi_install_address_space_handler (acpi_gbl_root_node, + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) { + (status != AE_ALREADY_EXISTS)) { return_ACPI_STATUS (status); } - status = acpi_install_address_space_handler (acpi_gbl_root_node, + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) { + (status != AE_ALREADY_EXISTS)) { return_ACPI_STATUS (status); } + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, + ACPI_ADR_SPACE_DATA_TABLE, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_ALREADY_EXISTS)) { + return_ACPI_STATUS (status); + } return_ACPI_STATUS (AE_OK); } -/* TBD: [Restructure] Move elsewhere */ - /******************************************************************************* * * FUNCTION: Acpi_ev_execute_reg_method @@ -121,13 +126,19 @@ u32 function) { acpi_operand_object *params[3]; + acpi_operand_object *region_obj2; acpi_status status; - FUNCTION_TRACE ("Ev_execute_reg_method"); + ACPI_FUNCTION_TRACE ("Ev_execute_reg_method"); - if (region_obj->region.extra->extra.method_REG == NULL) { + region_obj2 = acpi_ns_get_secondary_object (region_obj); + if (!region_obj2) { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + if (region_obj2->extra.method_REG == NULL) { return_ACPI_STATUS (AE_OK); } @@ -154,15 +165,15 @@ /* * Set up the parameter objects */ - params[0]->integer.value = region_obj->region.space_id; + params[0]->integer.value = region_obj->region.space_id; params[1]->integer.value = function; params[2] = NULL; /* * Execute the method, no return value */ - DEBUG_EXEC(acpi_ut_display_init_pathname (region_obj->region.extra->extra.method_REG, " [Method]")); - status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL); + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (region_obj2->extra.method_REG, " [Method]")); + status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL); acpi_ut_remove_reference (params[1]); @@ -181,7 +192,7 @@ * Space_id - ID of the address space (0-255) * Function - Read or Write operation * Address - Where in the space to read or write - * Bit_width - Field width in bits (8, 16, or 32) + * Bit_width - Field width in bits (8, 16, 32, or 64) * Value - Pointer to in or out value * * RETURN: Status @@ -197,18 +208,25 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value) + void *value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; acpi_operand_object *handler_desc; + acpi_operand_object *region_obj2; void *region_context = NULL; - FUNCTION_TRACE ("Ev_address_space_dispatch"); + ACPI_FUNCTION_TRACE ("Ev_address_space_dispatch"); + region_obj2 = acpi_ns_get_secondary_object (region_obj); + if (!region_obj2) { + return_ACPI_STATUS (AE_NOT_EXIST); + } + /* * Ensure that there is a handler associated with this region */ @@ -217,14 +235,14 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - return_ACPI_STATUS(AE_NOT_EXIST); + return_ACPI_STATUS (AE_NOT_EXIST); } /* * It may be the case that the region has never been initialized * Some types of regions require special init code */ - if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) { + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { /* * This region has not been initialized yet, do it */ @@ -249,7 +267,10 @@ /* Re-enter the interpreter */ - acpi_ex_enter_interpreter (); + status2 = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } /* * Init routine may fail @@ -258,16 +279,16 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n", acpi_format_exception (status), acpi_ut_get_region_name (region_obj->region.space_id))); - return_ACPI_STATUS(status); + return_ACPI_STATUS (status); } - region_obj->region.flags |= AOPOBJ_INITIALIZED; + region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; /* * Save the returned context for use in all accesses to * this particular region. */ - region_obj->region.extra->extra.region_context = region_context; + region_obj2->extra.region_context = region_context; } /* @@ -277,10 +298,10 @@ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Addrhandler %p (%p), Address %8.8X%8.8X\n", - ®ion_obj->region.addr_handler->addr_handler, handler, HIDWORD(address), - LODWORD(address))); + ®ion_obj->region.addr_handler->addr_handler, handler, + ACPI_HIDWORD (address), ACPI_LODWORD (address))); - if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't @@ -294,20 +315,23 @@ */ status = handler (function, address, bit_width, value, handler_desc->addr_handler.context, - region_obj->region.extra->extra.region_context); + region_obj2->extra.region_context); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region handler: %s [%s]\n", - acpi_format_exception (status), - acpi_ut_get_region_name (region_obj->region.space_id))); + ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n", + acpi_ut_get_region_name (region_obj->region.space_id), + acpi_format_exception (status))); } - if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_enter_interpreter (); + status2 = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } return_ACPI_STATUS (status); @@ -315,7 +339,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_disassociate_region_from_handler + * FUNCTION: Acpi_ev_detach_region * * PARAMETERS: Region_obj - Region Object * Acpi_ns_is_locked - Namespace Region Already Locked? @@ -328,7 +352,7 @@ ******************************************************************************/ void -acpi_ev_disassociate_region_from_handler( +acpi_ev_detach_region( acpi_operand_object *region_obj, u8 acpi_ns_is_locked) { @@ -337,13 +361,18 @@ acpi_operand_object **last_obj_ptr; acpi_adr_space_setup region_setup; void *region_context; + acpi_operand_object *region_obj2; acpi_status status; - FUNCTION_TRACE ("Ev_disassociate_region_from_handler"); + ACPI_FUNCTION_TRACE ("Ev_detach_region"); - region_context = region_obj->region.extra->extra.region_context; + region_obj2 = acpi_ns_get_secondary_object (region_obj); + if (!region_obj2) { + return_VOID; + } + region_context = region_obj2->extra.region_context; /* * Get the address handler from the region object @@ -378,16 +407,27 @@ obj_desc->region.next = NULL; /* Must clear field */ if (acpi_ns_is_locked) { - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_VOID; + } } /* * Now stop region accesses by executing the _REG method */ - acpi_ev_execute_reg_method (region_obj, 0); + status = acpi_ev_execute_reg_method (region_obj, 0); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n", + acpi_format_exception (status), + acpi_ut_get_region_name (region_obj->region.space_id))); + } if (acpi_ns_is_locked) { - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_VOID; + } } /* @@ -406,7 +446,7 @@ acpi_ut_get_region_name (region_obj->region.space_id))); } - region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); + region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); /* * Remove handler reference in the region @@ -444,7 +484,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_associate_region_and_handler + * FUNCTION: Acpi_ev_attach_region * * PARAMETERS: Handler_obj - Handler Object * Region_obj - Region Object @@ -458,15 +498,16 @@ ******************************************************************************/ acpi_status -acpi_ev_associate_region_and_handler ( +acpi_ev_attach_region ( acpi_operand_object *handler_obj, acpi_operand_object *region_obj, u8 acpi_ns_is_locked) { - acpi_status status; + acpi_status status; + acpi_status status2; - FUNCTION_TRACE ("Ev_associate_region_and_handler"); + ACPI_FUNCTION_TRACE ("Ev_attach_region"); ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -475,27 +516,34 @@ /* - * Link this region to the front of the handler's list + * Link this region to the front of the handler's list */ region_obj->region.next = handler_obj->addr_handler.region_list; handler_obj->addr_handler.region_list = region_obj; /* - * set the region's handler + * Set the region's handler */ region_obj->region.addr_handler = handler_obj; /* - * Last thing, tell all users that this region is usable + * Tell all users that this region is usable by running the _REG + * method */ if (acpi_ns_is_locked) { - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status2 = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } status = acpi_ev_execute_reg_method (region_obj, 1); if (acpi_ns_is_locked) { - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } return_ACPI_STATUS (status); @@ -510,8 +558,8 @@ * Level - Nesting level of the handle * Context - Passed into Acpi_ns_walk_namespace * - * DESCRIPTION: This routine checks to see if the object is a Region if it - * is then the address handler is installed in it. + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region. * * If the Object is a Device, and the device has a handler of * the same type then the search is terminated in that branch. @@ -535,7 +583,7 @@ acpi_status status; - PROC_NAME ("Ev_addr_handler_helper"); + ACPI_FUNCTION_NAME ("Ev_addr_handler_helper"); handler_obj = (acpi_operand_object *) context; @@ -576,7 +624,7 @@ /* * Devices are handled different than regions */ - if (IS_THIS_OBJECT_TYPE (obj_desc, ACPI_TYPE_DEVICE)) { + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { /* * See if this guy has any handlers */ @@ -635,12 +683,12 @@ * * First disconnect region for any previous handler (if any) */ - acpi_ev_disassociate_region_from_handler (obj_desc, FALSE); + acpi_ev_detach_region (obj_desc, FALSE); /* * Then connect the region to the new handler */ - status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc, FALSE); + status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); return (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evrgnini.c linux2.4.21_itanium/drivers/acpi/events/evrgnini.c --- linux2.4.21_itanium.org/drivers/acpi/events/evrgnini.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evrgnini.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,11 +27,9 @@ #include "acpi.h" #include "acevents.h" #include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evrgnini") + ACPI_MODULE_NAME ("evrgnini") /******************************************************************************* @@ -56,7 +54,10 @@ void *handler_context, void **region_context) { - FUNCTION_TRACE ("Ev_system_memory_region_setup"); + acpi_operand_object *region_desc = (acpi_operand_object *) handle; + acpi_mem_space_context *local_region_context; + + ACPI_FUNCTION_TRACE ("Ev_system_memory_region_setup"); if (function == ACPI_REGION_DEACTIVATE) { @@ -70,11 +71,17 @@ /* Activate. Create a new context */ - *region_context = ACPI_MEM_CALLOCATE (sizeof (acpi_mem_space_context)); - if (!(*region_context)) { + local_region_context = ACPI_MEM_CALLOCATE (sizeof (acpi_mem_space_context)); + if (!(local_region_context)) { return_ACPI_STATUS (AE_NO_MEMORY); } + /* Save the region length and address for use in the handler */ + + local_region_context->length = region_desc->region.length; + local_region_context->address = region_desc->region.address; + + *region_context = local_region_context; return_ACPI_STATUS (AE_OK); } @@ -101,7 +108,7 @@ void *handler_context, void **region_context) { - FUNCTION_TRACE ("Ev_io_space_region_setup"); + ACPI_FUNCTION_TRACE ("Ev_io_space_region_setup"); if (function == ACPI_REGION_DEACTIVATE) { @@ -148,7 +155,7 @@ acpi_device_id object_hID; - FUNCTION_TRACE ("Ev_pci_config_region_setup"); + ACPI_FUNCTION_TRACE ("Ev_pci_config_region_setup"); handler_obj = region_obj->region.addr_handler; @@ -188,7 +195,7 @@ * First get device and function numbers from the _ADR object * in the parent's scope. */ - node = acpi_ns_get_parent_object (region_obj->region.node); + node = acpi_ns_get_parent_node (region_obj->region.node); /* Acpi_evaluate the _ADR object */ @@ -196,12 +203,12 @@ status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); /* - * The default is zero, since the allocation above zeroed the data, just - * do nothing on failures. + * The default is zero, and since the allocation above zeroed + * the data, just do nothing on failure. */ if (ACPI_SUCCESS (status)) { - pci_id->device = HIWORD (temp); - pci_id->function = LOWORD (temp); + pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); + pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); } /* @@ -224,16 +231,20 @@ while (node != acpi_gbl_root_node) { status = acpi_ut_execute_HID (node, &object_hID); if (ACPI_SUCCESS (status)) { - if (!(STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, + if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { - acpi_install_address_space_handler (node, + status = acpi_install_address_space_handler ((acpi_handle) node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not install handler for %4.4s, %s\n", + node->name.ascii, acpi_format_exception (status))); + } break; } } - node = acpi_ns_get_parent_object (node); + node = acpi_ns_get_parent_node (node); } } else { @@ -245,7 +256,7 @@ */ status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); if (ACPI_SUCCESS (status)) { - pci_id->segment = LOWORD (temp); + pci_id->segment = ACPI_LOWORD (temp); } /* @@ -253,7 +264,7 @@ */ status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); if (ACPI_SUCCESS (status)) { - pci_id->bus = LOWORD (temp); + pci_id->bus = ACPI_LOWORD (temp); } *region_context = pci_id; @@ -286,7 +297,7 @@ void **region_context) { - FUNCTION_TRACE ("Ev_pci_bar_region_setup"); + ACPI_FUNCTION_TRACE ("Ev_pci_bar_region_setup"); return_ACPI_STATUS (AE_OK); @@ -318,7 +329,7 @@ void **region_context) { - FUNCTION_TRACE ("Ev_cmos_region_setup"); + ACPI_FUNCTION_TRACE ("Ev_cmos_region_setup"); return_ACPI_STATUS (AE_OK); @@ -347,7 +358,7 @@ void *handler_context, void **region_context) { - FUNCTION_TRACE ("Ev_default_region_setup"); + ACPI_FUNCTION_TRACE ("Ev_default_region_setup"); if (function == ACPI_REGION_DEACTIVATE) { @@ -394,21 +405,33 @@ acpi_status status; acpi_namespace_node *method_node; acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; + acpi_operand_object *region_obj2; - FUNCTION_TRACE_U32 ("Ev_initialize_region", acpi_ns_locked); + ACPI_FUNCTION_TRACE_U32 ("Ev_initialize_region", acpi_ns_locked); if (!region_obj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - node = acpi_ns_get_parent_object (region_obj->region.node); + if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { + return_ACPI_STATUS (AE_OK); + } + + region_obj2 = acpi_ns_get_secondary_object (region_obj); + if (!region_obj2) { + return_ACPI_STATUS (AE_NOT_EXIST); + } + node = acpi_ns_get_parent_node (region_obj->region.node); + + space_id = region_obj->region.space_id; region_obj->region.addr_handler = NULL; - region_obj->region.extra->extra.method_REG = NULL; - region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); + region_obj2->extra.method_REG = NULL; + region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); + region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; /* * Find any "_REG" associated with this region definition @@ -421,7 +444,7 @@ * definition. This will be executed when the handler is attached * or removed */ - region_obj->region.extra->extra.method_REG = method_node; + region_obj2->extra.method_REG = method_node; } /* @@ -436,7 +459,7 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* - * can only be a handler if the object exists + * Can only be a handler if the object exists */ switch (node->type) { case ACPI_TYPE_DEVICE: @@ -453,6 +476,10 @@ handler_obj = obj_desc->thermal_zone.addr_handler; break; + + default: + /* Ignore other objects */ + break; } while (handler_obj) { @@ -468,8 +495,9 @@ /* * Found it! Now update the region and the handler */ - acpi_ev_associate_region_and_handler (handler_obj, region_obj, - acpi_ns_locked); + status = acpi_ev_attach_region (handler_obj, region_obj, + acpi_ns_locked); + return_ACPI_STATUS (AE_OK); } @@ -482,7 +510,7 @@ * This one does not have the handler we need * Pop up one level */ - node = acpi_ns_get_parent_object (node); + node = acpi_ns_get_parent_node (node); } /* while Node != ROOT */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evsci.c linux2.4.21_itanium/drivers/acpi/events/evsci.c --- linux2.4.21_itanium.org/drivers/acpi/events/evsci.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evsci.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,23 +25,11 @@ */ #include "acpi.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evsci") - - -/* - * Elements correspond to counts for TMR, NOT_USED, GBL, PWR_BTN, SLP_BTN, RTC, - * and GENERAL respectively. These counts are modified by the ACPI interrupt - * handler. - * - * TBD: [Investigate] Note that GENERAL should probably be split out into - * one element for each bit in the GPE registers - */ + ACPI_MODULE_NAME ("evsci") /******************************************************************************* @@ -58,23 +46,31 @@ * ******************************************************************************/ -static u32 -acpi_ev_sci_handler (void *context) +static u32 ACPI_SYSTEM_XFACE +acpi_ev_sci_handler ( + void *context) { - u32 interrupt_handled = INTERRUPT_NOT_HANDLED; + u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; + u32 value; + acpi_status status; - FUNCTION_TRACE("Ev_sci_handler"); + ACPI_FUNCTION_TRACE("Ev_sci_handler"); /* * Make sure that ACPI is enabled by checking SCI_EN. Note that we are * required to treat the SCI interrupt as sharable, level, active low. */ - if (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_DO_NOT_LOCK, SCI_EN)) { + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } + + if (!value) { /* ACPI is not enabled; this interrupt cannot be for us */ - return_VALUE (INTERRUPT_NOT_HANDLED); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } /* @@ -113,7 +109,7 @@ u32 status = AE_OK; - FUNCTION_TRACE ("Ev_install_sci_handler"); + ACPI_FUNCTION_TRACE ("Ev_install_sci_handler"); status = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, @@ -123,7 +119,6 @@ /****************************************************************************** - * * FUNCTION: Acpi_ev_remove_sci_handler * @@ -132,151 +127,31 @@ * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not * installed to begin with * - * DESCRIPTION: Restores original status of all fixed event enable bits and - * removes SCI handler. + * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be + * taken. + * + * Note: It doesn't seem important to disable all events or set the event + * enable registers to their original values. The OS should disable + * the SCI interrupt level when the handler is removed, so no more + * events will come in. * ******************************************************************************/ acpi_status acpi_ev_remove_sci_handler (void) { - FUNCTION_TRACE ("Ev_remove_sci_handler"); + acpi_status status; -#if 0 - /* TBD:[Investigate] Figure this out!! Disable all events first ??? */ - - if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (TMR_FIXED_EVENT)) { - acpi_event_disable_event (TMR_FIXED_EVENT); - } - - if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (GBL_FIXED_EVENT)) { - acpi_event_disable_event (GBL_FIXED_EVENT); - } - - if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (PWR_BTN_FIXED_EVENT)) { - acpi_event_disable_event (PWR_BTN_FIXED_EVENT); - } - - if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (SLP_BTN_FIXED_EVENT)) { - acpi_event_disable_event (SLP_BTN_FIXED_EVENT); - } - - if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (RTC_FIXED_EVENT)) { - acpi_event_disable_event (RTC_FIXED_EVENT); - } + ACPI_FUNCTION_TRACE ("Ev_remove_sci_handler"); - original_fixed_enable_bit_status = 0; -#endif + /* Just let the OS remove the handler and disable the level */ - acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, + status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, acpi_ev_sci_handler); - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ev_restore_acpi_state - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: Restore the original ACPI state of the machine - * - ******************************************************************************/ - -void -acpi_ev_restore_acpi_state (void) -{ - u32 index; - - - FUNCTION_TRACE ("Ev_restore_acpi_state"); - - - /* Restore the state of the chipset enable bits. */ - - if (acpi_gbl_restore_acpi_chipset == TRUE) { - /* Restore the fixed events */ - - if (acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN) != - acpi_gbl_pm1_enable_register_save) { - acpi_hw_register_write (ACPI_MTX_LOCK, PM1_EN, - acpi_gbl_pm1_enable_register_save); - } - - - /* Ensure that all status bits are clear */ - - acpi_hw_clear_acpi_status (); - - - /* Now restore the GPEs */ - - for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { - if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index) != - acpi_gbl_gpe0enable_register_save[index]) { - acpi_hw_register_write (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index, - acpi_gbl_gpe0enable_register_save[index]); - } - } - - /* GPE 1 present? */ - - if (acpi_gbl_FADT->gpe1_blk_len) { - for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { - if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index) != - acpi_gbl_gpe1_enable_register_save[index]) { - acpi_hw_register_write (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index, - acpi_gbl_gpe1_enable_register_save[index]); - } - } - } - - if (acpi_hw_get_mode() != acpi_gbl_original_mode) { - acpi_hw_set_mode (acpi_gbl_original_mode); - } - } - - return_VOID; -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_terminate - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: free memory allocated for table storage. - * - ******************************************************************************/ - -void -acpi_ev_terminate (void) -{ - - FUNCTION_TRACE ("Ev_terminate"); - - - /* - * Free global tables, etc. - */ - if (acpi_gbl_gpe_registers) { - ACPI_MEM_FREE (acpi_gbl_gpe_registers); - } - - if (acpi_gbl_gpe_info) { - ACPI_MEM_FREE (acpi_gbl_gpe_info); - } - - return_VOID; + return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evxface.c linux2.4.21_itanium/drivers/acpi/events/evxface.c --- linux2.4.21_itanium.org/drivers/acpi/events/evxface.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evxface.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,14 +25,12 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" #include "acinterp.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evxface") + ACPI_MODULE_NAME ("evxface") /******************************************************************************* @@ -60,7 +58,7 @@ acpi_status status; - FUNCTION_TRACE ("Acpi_install_fixed_event_handler"); + ACPI_FUNCTION_TRACE ("Acpi_install_fixed_event_handler"); /* Parameter validation */ @@ -69,12 +67,15 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Don't allow two handlers. */ if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { - status = AE_EXIST; + status = AE_ALREADY_EXISTS; goto cleanup; } @@ -85,7 +86,7 @@ acpi_gbl_fixed_event_handlers[event].context = context; status = acpi_enable_event (event, ACPI_EVENT_FIXED, 0); - if (!ACPI_SUCCESS (status)) { + if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n")); /* Remove the handler */ @@ -93,7 +94,6 @@ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; } - else { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Enabled fixed event %X, Handler=%p\n", event, handler)); @@ -101,7 +101,7 @@ cleanup: - acpi_ut_release_mutex (ACPI_MTX_EVENTS); + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } @@ -127,7 +127,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE ("Acpi_remove_fixed_event_handler"); + ACPI_FUNCTION_TRACE ("Acpi_remove_fixed_event_handler"); /* Parameter validation */ @@ -136,7 +136,10 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Disable the event before removing the handler */ @@ -147,7 +150,7 @@ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; - if (!ACPI_SUCCESS (status)) { + if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not write to fixed event enable register.\n")); } @@ -155,7 +158,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event)); } - acpi_ut_release_mutex (ACPI_MTX_EVENTS); + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } @@ -186,26 +189,30 @@ { acpi_operand_object *obj_desc; acpi_operand_object *notify_obj; - acpi_namespace_node *device_node; - acpi_status status = AE_OK; + acpi_namespace_node *node; + acpi_status status; - FUNCTION_TRACE ("Acpi_install_notify_handler"); + ACPI_FUNCTION_TRACE ("Acpi_install_notify_handler"); /* Parameter validation */ - if ((!handler) || + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Convert and validate the device handle */ - device_node = acpi_ns_map_handle_to_node (device); - if (!device_node) { + node = acpi_ns_map_handle_to_node (device); + if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -223,17 +230,17 @@ acpi_gbl_sys_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && acpi_gbl_drv_notify.handler)) { - status = AE_EXIST; + status = AE_ALREADY_EXISTS; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_sys_notify.node = device_node; + acpi_gbl_sys_notify.node = node; acpi_gbl_sys_notify.handler = handler; acpi_gbl_sys_notify.context = context; } else /* ACPI_DEVICE_NOTIFY */ { - acpi_gbl_drv_notify.node = device_node; + acpi_gbl_drv_notify.node = node; acpi_gbl_drv_notify.handler = handler; acpi_gbl_drv_notify.context = context; } @@ -247,37 +254,32 @@ * Note that only certain object types can receive notifications. */ else { - /* - * These are the ONLY objects that can receive ACPI notifications - */ - if ((device_node->type != ACPI_TYPE_DEVICE) && - (device_node->type != ACPI_TYPE_PROCESSOR) && - (device_node->type != ACPI_TYPE_POWER) && - (device_node->type != ACPI_TYPE_THERMAL)) { - status = AE_BAD_PARAMETER; + /* Notifies allowed on this object? */ + + if (!acpi_ev_is_notify_object (node)) { + status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object (device_node); + obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* Object exists - make sure there's no handler */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && - obj_desc->device.sys_handler) || + obj_desc->common_notify.sys_handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - obj_desc->device.drv_handler)) { - status = AE_EXIST; + obj_desc->common_notify.drv_handler)) { + status = AE_ALREADY_EXISTS; goto unlock_and_exit; } } - else { /* Create a new object */ - obj_desc = acpi_ut_create_internal_object (device_node->type); + obj_desc = acpi_ut_create_internal_object (node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -285,7 +287,7 @@ /* Attach new object to the Node */ - status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type); + status = acpi_ns_attach_object (device, obj_desc, node->type); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -299,23 +301,21 @@ goto unlock_and_exit; } - notify_obj->notify_handler.node = device_node; + notify_obj->notify_handler.node = node; notify_obj->notify_handler.handler = handler; notify_obj->notify_handler.context = context; - if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->device.sys_handler = notify_obj; + obj_desc->common_notify.sys_handler = notify_obj; } - else /* ACPI_DEVICE_NOTIFY */ { - obj_desc->device.drv_handler = notify_obj; + obj_desc->common_notify.drv_handler = notify_obj; } } unlock_and_exit: - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } @@ -343,26 +343,30 @@ { acpi_operand_object *notify_obj; acpi_operand_object *obj_desc; - acpi_namespace_node *device_node; - acpi_status status = AE_OK; + acpi_namespace_node *node; + acpi_status status; - FUNCTION_TRACE ("Acpi_remove_notify_handler"); + ACPI_FUNCTION_TRACE ("Acpi_remove_notify_handler"); /* Parameter validation */ - if ((!handler) || + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Convert and validate the device handle */ - device_node = acpi_ns_map_handle_to_node (device); - if (!device_node) { + node = acpi_ns_map_handle_to_node (device); + if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -397,20 +401,16 @@ * All Other Objects */ else { - /* - * These are the ONLY objects that can receive ACPI notifications - */ - if ((device_node->type != ACPI_TYPE_DEVICE) && - (device_node->type != ACPI_TYPE_PROCESSOR) && - (device_node->type != ACPI_TYPE_POWER) && - (device_node->type != ACPI_TYPE_THERMAL)) { - status = AE_BAD_PARAMETER; + /* Notifies allowed on this object? */ + + if (!acpi_ev_is_notify_object (node)) { + status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object (device_node); + obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { status = AE_NOT_EXIST; goto unlock_and_exit; @@ -419,10 +419,10 @@ /* Object exists - make sure there's an existing handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - notify_obj = obj_desc->device.sys_handler; + notify_obj = obj_desc->common_notify.sys_handler; } else { - notify_obj = obj_desc->device.drv_handler; + notify_obj = obj_desc->common_notify.drv_handler; } if ((!notify_obj) || @@ -434,10 +434,10 @@ /* Remove the handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->device.sys_handler = NULL; + obj_desc->common_notify.sys_handler = NULL; } else { - obj_desc->device.drv_handler = NULL; + obj_desc->common_notify.drv_handler = NULL; } acpi_ut_remove_reference (notify_obj); @@ -445,7 +445,7 @@ unlock_and_exit: - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } @@ -474,47 +474,56 @@ acpi_gpe_handler handler, void *context) { - acpi_status status = AE_OK; + acpi_status status; + u32 gpe_number_index; - FUNCTION_TRACE ("Acpi_install_gpe_handler"); + ACPI_FUNCTION_TRACE ("Acpi_install_gpe_handler"); /* Parameter validation */ - if (!handler || (gpe_number > ACPI_GPE_MAX)) { + if (!handler) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Ensure that we have a valid GPE number */ - if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + gpe_number_index = acpi_ev_get_gpe_number_index (gpe_number); + if (gpe_number_index == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Make sure that there isn't a handler there already */ - if (acpi_gbl_gpe_info[gpe_number].handler) { - status = AE_EXIST; + if (acpi_gbl_gpe_number_info[gpe_number_index].handler) { + status = AE_ALREADY_EXISTS; goto cleanup; } /* Install the handler */ - acpi_gbl_gpe_info[gpe_number].handler = handler; - acpi_gbl_gpe_info[gpe_number].context = context; - acpi_gbl_gpe_info[gpe_number].type = (u8) type; + acpi_gbl_gpe_number_info[gpe_number_index].handler = handler; + acpi_gbl_gpe_number_info[gpe_number_index].context = context; + acpi_gbl_gpe_number_info[gpe_number_index].type = (u8) type; /* Clear the GPE (of stale events), the enable it */ - acpi_hw_clear_gpe (gpe_number); - acpi_hw_enable_gpe (gpe_number); + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_hw_enable_gpe (gpe_number); cleanup: - acpi_ut_release_mutex (ACPI_MTX_EVENTS); + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } @@ -537,46 +546,54 @@ u32 gpe_number, acpi_gpe_handler handler) { - acpi_status status = AE_OK; + acpi_status status; + u32 gpe_number_index; - FUNCTION_TRACE ("Acpi_remove_gpe_handler"); + ACPI_FUNCTION_TRACE ("Acpi_remove_gpe_handler"); /* Parameter validation */ - if (!handler || (gpe_number > ACPI_GPE_MAX)) { + if (!handler) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Ensure that we have a valid GPE number */ - if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + gpe_number_index = acpi_ev_get_gpe_number_index (gpe_number); + if (gpe_number_index == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Disable the GPE before removing the handler */ - acpi_hw_disable_gpe (gpe_number); + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Make sure that the installed handler is the same */ - if (acpi_gbl_gpe_info[gpe_number].handler != handler) { - acpi_hw_enable_gpe (gpe_number); + if (acpi_gbl_gpe_number_info[gpe_number_index].handler != handler) { + (void) acpi_hw_enable_gpe (gpe_number); status = AE_BAD_PARAMETER; goto cleanup; } /* Remove the handler */ - acpi_gbl_gpe_info[gpe_number].handler = NULL; - acpi_gbl_gpe_info[gpe_number].context = NULL; + acpi_gbl_gpe_number_info[gpe_number_index].handler = NULL; + acpi_gbl_gpe_number_info[gpe_number_index].context = NULL; cleanup: - acpi_ut_release_mutex (ACPI_MTX_EVENTS); + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } @@ -596,23 +613,29 @@ acpi_status acpi_acquire_global_lock ( - void) + u32 timeout, + u32 *handle) { acpi_status status; + if (!handle) { + return (AE_BAD_PARAMETER); + } + status = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status)) { return (status); } - /* - * TBD: [Restructure] add timeout param to internal interface, and - * perhaps INTERPRETER_LOCKED - */ - status = acpi_ev_acquire_global_lock (); + status = acpi_ev_acquire_global_lock (timeout); acpi_ex_exit_interpreter (); + if (ACPI_SUCCESS (status)) { + acpi_gbl_global_lock_handle++; + *handle = acpi_gbl_global_lock_handle; + } + return (status); } @@ -631,11 +654,17 @@ acpi_status acpi_release_global_lock ( - void) + u32 handle) { + acpi_status status; + - acpi_ev_release_global_lock (); - return (AE_OK); + if (handle != acpi_gbl_global_lock_handle) { + return (AE_NOT_ACQUIRED); + } + + status = acpi_ev_release_global_lock (); + return (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evxfevnt.c linux2.4.21_itanium/drivers/acpi/events/evxfevnt.c --- linux2.4.21_itanium.org/drivers/acpi/events/evxfevnt.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evxfevnt.c Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,14 +25,10 @@ #include "acpi.h" -#include "achware.h" -#include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" -#include "acinterp.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evxfevnt") + ACPI_MODULE_NAME ("evxfevnt") /******************************************************************************* @@ -50,36 +46,36 @@ acpi_status acpi_enable (void) { - acpi_status status; + acpi_status status = AE_OK; - FUNCTION_TRACE ("Acpi_enable"); + ACPI_FUNCTION_TRACE ("Acpi_enable"); - /* Make sure we've got ACPI tables */ + /* Make sure we have ACPI tables */ if (!acpi_gbl_DSDT) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } - /* Make sure the BIOS supports ACPI mode */ + acpi_gbl_original_mode = acpi_hw_get_mode (); - if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Only legacy mode supported!\n")); - return_ACPI_STATUS (AE_ERROR); + if (acpi_gbl_original_mode == ACPI_SYS_MODE_ACPI) { + ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Already in ACPI mode.\n")); } + else { + /* Transition to ACPI mode */ - /* Transition to ACPI mode */ + status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Could not transition to ACPI mode.\n")); + return_ACPI_STATUS (status); + } - status = acpi_hw_set_mode (SYS_MODE_ACPI); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Could not transition to ACPI mode.\n")); - return_ACPI_STATUS (status); + ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Transition to ACPI mode successful\n")); } - ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Transition to ACPI mode successful\n")); - return_ACPI_STATUS (status); } @@ -100,25 +96,25 @@ acpi_status acpi_disable (void) { - acpi_status status; + acpi_status status = AE_OK; - FUNCTION_TRACE ("Acpi_disable"); + ACPI_FUNCTION_TRACE ("Acpi_disable"); - /* Restore original mode */ + if (acpi_hw_get_mode () != acpi_gbl_original_mode) { + /* Restore original mode */ - status = acpi_hw_set_mode (acpi_gbl_original_mode); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to transition to original mode")); - return_ACPI_STATUS (status); + status = acpi_hw_set_mode (acpi_gbl_original_mode); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to transition to original mode")); + return_ACPI_STATUS (status); + } } /* Unload the SCI interrupt handler */ - acpi_ev_remove_sci_handler (); - acpi_ev_restore_acpi_state (); - + status = acpi_ev_remove_sci_handler (); return_ACPI_STATUS (status); } @@ -144,58 +140,46 @@ u32 flags) { acpi_status status = AE_OK; - u32 register_id; + u32 value; - FUNCTION_TRACE ("Acpi_enable_event"); + ACPI_FUNCTION_TRACE ("Acpi_enable_event"); - /* The Type must be either Fixed Acpi_event or GPE */ + /* The Type must be either Fixed Event or GPE */ switch (type) { - case ACPI_EVENT_FIXED: - /* Decode the Fixed Acpi_event */ + /* Decode the Fixed Event */ - switch (event) { - case ACPI_EVENT_PMTIMER: - register_id = TMR_EN; - break; - - case ACPI_EVENT_GLOBAL: - register_id = GBL_EN; - break; - - case ACPI_EVENT_POWER_BUTTON: - register_id = PWRBTN_EN; - break; - - case ACPI_EVENT_SLEEP_BUTTON: - register_id = SLPBTN_EN; - break; - - case ACPI_EVENT_RTC: - register_id = RTC_EN; - break; - - default: + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); - break; } /* * Enable the requested fixed event (by writing a one to the * enable register bit) */ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 1); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (1 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { + /* Make sure that the hardware responded */ + + status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, + &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + if (value != 1) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Fixed event bit clear when it should be set\n")); + "Could not enable %s event\n", acpi_ut_get_event_name (event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } - break; @@ -203,21 +187,20 @@ /* Ensure that we have a valid GPE number */ - if ((event > ACPI_GPE_MAX) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + if (acpi_ev_get_gpe_number_index (event) == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Enable the requested GPE number */ - if (flags & ACPI_EVENT_ENABLE) { - acpi_hw_enable_gpe (event); + status = acpi_hw_enable_gpe (event); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } + if (flags & ACPI_EVENT_WAKE_ENABLE) { acpi_hw_enable_gpe_for_wakeup (event); } - break; @@ -226,7 +209,6 @@ status = AE_BAD_PARAMETER; } - return_ACPI_STATUS (status); } @@ -252,58 +234,44 @@ u32 flags) { acpi_status status = AE_OK; - u32 register_id; + u32 value; - FUNCTION_TRACE ("Acpi_disable_event"); + ACPI_FUNCTION_TRACE ("Acpi_disable_event"); - /* The Type must be either Fixed Acpi_event or GPE */ + /* The Type must be either Fixed Event or GPE */ switch (type) { - case ACPI_EVENT_FIXED: - /* Decode the Fixed Acpi_event */ - - switch (event) { - case ACPI_EVENT_PMTIMER: - register_id = TMR_EN; - break; - - case ACPI_EVENT_GLOBAL: - register_id = GBL_EN; - break; - - case ACPI_EVENT_POWER_BUTTON: - register_id = PWRBTN_EN; - break; - - case ACPI_EVENT_SLEEP_BUTTON: - register_id = SLPBTN_EN; - break; - - case ACPI_EVENT_RTC: - register_id = RTC_EN; - break; + /* Decode the Fixed Event */ - default: + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); - break; } /* * Disable the requested fixed event (by writing a zero to the * enable register bit) */ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 0); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, + &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (0 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { + if (value != 0) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Fixed event bit set when it should be clear,\n")); + "Could not disable %s events\n", acpi_ut_get_event_name (event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } - break; @@ -311,20 +279,21 @@ /* Ensure that we have a valid GPE number */ - if ((event > ACPI_GPE_MAX) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + if (acpi_ev_get_gpe_number_index (event) == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Disable the requested GPE number */ + /* + * Only disable the requested GPE number for wake if specified. + * Otherwise, turn it totally off + */ - if (flags & ACPI_EVENT_DISABLE) { - acpi_hw_disable_gpe (event); - } if (flags & ACPI_EVENT_WAKE_DISABLE) { acpi_hw_disable_gpe_for_wakeup (event); } - + else { + status = acpi_hw_disable_gpe (event); + } break; @@ -355,51 +324,28 @@ u32 type) { acpi_status status = AE_OK; - u32 register_id; - FUNCTION_TRACE ("Acpi_clear_event"); + ACPI_FUNCTION_TRACE ("Acpi_clear_event"); - /* The Type must be either Fixed Acpi_event or GPE */ + /* The Type must be either Fixed Event or GPE */ switch (type) { - case ACPI_EVENT_FIXED: - /* Decode the Fixed Acpi_event */ - - switch (event) { - case ACPI_EVENT_PMTIMER: - register_id = TMR_STS; - break; - - case ACPI_EVENT_GLOBAL: - register_id = GBL_STS; - break; - - case ACPI_EVENT_POWER_BUTTON: - register_id = PWRBTN_STS; - break; - - case ACPI_EVENT_SLEEP_BUTTON: - register_id = SLPBTN_STS; - break; - - case ACPI_EVENT_RTC: - register_id = RTC_STS; - break; + /* Decode the Fixed Event */ - default: + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); - break; } /* * Clear the requested fixed event (By writing a one to the * status register bit) */ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 1); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id, + 1, ACPI_MTX_LOCK); break; @@ -407,13 +353,11 @@ /* Ensure that we have a valid GPE number */ - if ((event > ACPI_GPE_MAX) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + if (acpi_ev_get_gpe_number_index (event) == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - - acpi_hw_clear_gpe (event); + status = acpi_hw_clear_gpe (event); break; @@ -449,10 +393,9 @@ acpi_event_status *event_status) { acpi_status status = AE_OK; - u32 register_id; - FUNCTION_TRACE ("Acpi_get_event_status"); + ACPI_FUNCTION_TRACE ("Acpi_get_event_status"); if (!event_status) { @@ -460,43 +403,21 @@ } - /* The Type must be either Fixed Acpi_event or GPE */ + /* The Type must be either Fixed Event or GPE */ switch (type) { - case ACPI_EVENT_FIXED: - /* Decode the Fixed Acpi_event */ + /* Decode the Fixed Event */ - switch (event) { - case ACPI_EVENT_PMTIMER: - register_id = TMR_STS; - break; - - case ACPI_EVENT_GLOBAL: - register_id = GBL_STS; - break; - - case ACPI_EVENT_POWER_BUTTON: - register_id = PWRBTN_STS; - break; - - case ACPI_EVENT_SLEEP_BUTTON: - register_id = SLPBTN_STS; - break; - - case ACPI_EVENT_RTC: - register_id = RTC_STS; - break; - - default: + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); - break; } /* Get the status of the requested fixed event */ - *event_status = acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, register_id); + status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id, + event_status, ACPI_MTX_LOCK); break; @@ -504,15 +425,13 @@ /* Ensure that we have a valid GPE number */ - if ((event > ACPI_GPE_MAX) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + if (acpi_ev_get_gpe_number_index (event) == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Obtain status on the requested GPE number */ - acpi_hw_get_gpe_status (event, event_status); + status = acpi_hw_get_gpe_status (event, event_status); break; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/events/evxfregn.c linux2.4.21_itanium/drivers/acpi/events/evxfregn.c --- linux2.4.21_itanium.org/drivers/acpi/events/evxfregn.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/events/evxfregn.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,14 +26,12 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" #include "acinterp.h" #define _COMPONENT ACPI_EVENTS - MODULE_NAME ("evxfregn") + ACPI_MODULE_NAME ("evxfregn") /******************************************************************************* @@ -63,23 +61,24 @@ acpi_operand_object *obj_desc; acpi_operand_object *handler_obj; acpi_namespace_node *node; - acpi_status status = AE_OK; - acpi_object_type8 type; + acpi_status status; + acpi_object_type type; u16 flags = 0; - FUNCTION_TRACE ("Acpi_install_address_space_handler"); + ACPI_FUNCTION_TRACE ("Acpi_install_address_space_handler"); /* Parameter validation */ - if ((!device) || - ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || - (space_id > ACPI_MAX_ADDRESS_SPACE)) { + if (!device) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Convert and validate the device handle */ @@ -103,7 +102,7 @@ } if (handler == ACPI_DEFAULT_HANDLER) { - flags = ADDR_HANDLER_DEFAULT_INSTALLED; + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: @@ -131,10 +130,14 @@ setup = acpi_ev_pci_bar_region_setup; break; + case ACPI_ADR_SPACE_DATA_TABLE: + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + default: status = AE_NOT_EXIST; goto unlock_and_exit; - break; } } @@ -164,7 +167,7 @@ * address space. */ if(handler_obj->addr_handler.space_id == space_id) { - status = AE_EXIST; + status = AE_ALREADY_EXISTS; goto unlock_and_exit; } @@ -174,7 +177,6 @@ handler_obj = handler_obj->addr_handler.next; } } - else { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Creating object on Device %p while installing handler\n", node)); @@ -200,7 +202,7 @@ /* Attach the new object to the Node */ - status = acpi_ns_attach_object (node, obj_desc, (u8) type); + status = acpi_ns_attach_object (node, obj_desc, type); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; @@ -246,7 +248,7 @@ * of the branch */ status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, - ACPI_UINT32_MAX, NS_WALK_UNLOCK, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_addr_handler_helper, handler_obj, NULL); @@ -260,7 +262,7 @@ unlock_and_exit: - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } @@ -289,21 +291,22 @@ acpi_operand_object *region_obj; acpi_operand_object **last_obj_ptr; acpi_namespace_node *node; - acpi_status status = AE_OK; + acpi_status status; - FUNCTION_TRACE ("Acpi_remove_address_space_handler"); + ACPI_FUNCTION_TRACE ("Acpi_remove_address_space_handler"); /* Parameter validation */ - if ((!device) || - ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || - (space_id > ACPI_MAX_ADDRESS_SPACE)) { + if (!device) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Convert and validate the device handle */ @@ -313,7 +316,6 @@ goto unlock_and_exit; } - /* Make sure the internal object exists */ obj_desc = acpi_ns_get_attached_object (node); @@ -352,7 +354,7 @@ * The region is just inaccessible as indicated to * the _REG method */ - acpi_ev_disassociate_region_from_handler(region_obj, TRUE); + acpi_ev_detach_region (region_obj, TRUE); /* * Walk the list, since we took the first region and it @@ -396,7 +398,7 @@ unlock_and_exit: - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/Makefile linux2.4.21_itanium/drivers/acpi/executer/Makefile --- linux2.4.21_itanium.org/drivers/acpi/executer/Makefile Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/Makefile Wed Jul 23 18:28:13 2003 @@ -1,11 +1,10 @@ # # Makefile for all Linux ACPI interpreter subdirectories -# EXCEPT for the ospm directory # O_TARGET := $(notdir $(CURDIR)).o -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) +obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exconfig.c linux2.4.21_itanium/drivers/acpi/executer/exconfig.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exconfig.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exconfig.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,161 +25,365 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" #include "acevents.h" #include "actables.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exconfig") + ACPI_MODULE_NAME ("exconfig") -/***************************************************************************** +/******************************************************************************* + * + * FUNCTION: Acpi_ex_add_table + * + * PARAMETERS: Table - Pointer to raw table + * Parent_node - Where to load the table (scope) + * Ddb_handle - Where to return the table handle. + * + * RETURN: Status + * + * DESCRIPTION: Common function to Install and Load an ACPI table with a + * returned table handle. + * + ******************************************************************************/ + +acpi_status +acpi_ex_add_table ( + acpi_table_header *table, + acpi_namespace_node *parent_node, + acpi_operand_object **ddb_handle) +{ + acpi_status status; + acpi_table_desc table_info; + acpi_operand_object *obj_desc; + + + ACPI_FUNCTION_TRACE ("Ex_add_table"); + + + /* Create an object to be the table handle */ + + obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!obj_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Install the new table into the local data structures */ + + table_info.pointer = table; + table_info.length = (ACPI_SIZE) table->length; + table_info.allocation = ACPI_MEM_ALLOCATED; + table_info.base_pointer = table; + + status = acpi_tb_install_table (&table_info); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Add the table to the namespace */ + + status = acpi_ns_load_table (table_info.installed_desc, parent_node); + if (ACPI_FAILURE (status)) { + /* Uninstall table on error */ + + (void) acpi_tb_uninstall_table (table_info.installed_desc); + goto cleanup; + } + + /* Init the table handle */ + + obj_desc->reference.opcode = AML_LOAD_OP; + obj_desc->reference.object = table_info.installed_desc; + *ddb_handle = obj_desc; + return_ACPI_STATUS (AE_OK); + + +cleanup: + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* * * FUNCTION: Acpi_ex_load_table_op * - * PARAMETERS: Rgn_desc - Op region where the table will be obtained - * Ddb_handle - Where a handle to the table will be returned + * PARAMETERS: Walk_state - Current state with operands + * Return_desc - Where to store the return object * * RETURN: Status * * DESCRIPTION: Load an ACPI table * - ****************************************************************************/ + ******************************************************************************/ acpi_status -acpi_ex_load_op ( - acpi_operand_object *rgn_desc, - acpi_operand_object *ddb_handle) +acpi_ex_load_table_op ( + acpi_walk_state *walk_state, + acpi_operand_object **return_desc) { acpi_status status; - acpi_operand_object *table_desc = NULL; - u8 *table_ptr; - u8 *table_data_ptr; - acpi_table_header table_header; - acpi_table_desc table_info; - u32 i; + acpi_operand_object **operand = &walk_state->operands[0]; + acpi_table_header *table; + acpi_namespace_node *parent_node; + acpi_namespace_node *start_node; + acpi_namespace_node *parameter_node = NULL; + acpi_operand_object *ddb_handle; + + + ACPI_FUNCTION_TRACE ("Ex_load_table_op"); + + + /* + * Make sure that the signature does not match one of the tables that + * is already loaded. + */ + status = acpi_tb_match_signature (operand[0]->string.pointer, NULL); + if (status == AE_OK) { + /* Signature matched -- don't allow override */ + + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + /* Find the ACPI table */ + + status = acpi_tb_find_table (operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer, &table); + if (ACPI_FAILURE (status)) { + if (status != AE_NOT_FOUND) { + return_ACPI_STATUS (status); + } + /* Not found, return an Integer=0 and AE_OK */ - FUNCTION_TRACE ("Ex_load_op"); + ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ddb_handle) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + ddb_handle->integer.value = 0; + *return_desc = ddb_handle; - /* TBD: [Unhandled] Object can be either a field or an opregion */ + return_ACPI_STATUS (AE_OK); + } + /* Default nodes */ - /* Get the table header */ + start_node = walk_state->scope_info->scope.node; + parent_node = acpi_gbl_root_node; - table_header.length = 0; - for (i = 0; i < sizeof (acpi_table_header); i++) { - status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, - (ACPI_PHYSICAL_ADDRESS) i, 8, - (u32 *) ((u8 *) &table_header + i)); + /* Root_path (optional parameter) */ + + if (operand[3]->string.length > 0) { + /* + * Find the node referenced by the Root_path_string. This is the + * location within the namespace where the table will be loaded. + */ + status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node, + ACPI_NS_SEARCH_PARENT, &parent_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } - /* Allocate a buffer for the entire table */ + /* Parameter_path (optional parameter) */ - table_ptr = ACPI_MEM_ALLOCATE (table_header.length); - if (!table_ptr) { - return_ACPI_STATUS (AE_NO_MEMORY); + if (operand[4]->string.length > 0) { + if ((operand[4]->string.pointer[0] != '\\') && + (operand[4]->string.pointer[0] != '^')) { + /* + * Path is not absolute, so it will be relative to the node + * referenced by the Root_path_string (or the NS root if omitted) + */ + start_node = parent_node; + } + + /* + * Find the node referenced by the Parameter_path_string + */ + status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node, + ACPI_NS_SEARCH_PARENT, ¶meter_node); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - /* Copy the header to the buffer */ + /* Load the table into the namespace */ - MEMCPY (table_ptr, &table_header, sizeof (acpi_table_header)); - table_data_ptr = table_ptr + sizeof (acpi_table_header); + status = acpi_ex_add_table (table, parent_node, &ddb_handle); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* Parameter Data (optional) */ - /* Get the table from the op region */ + if (parameter_node) { + /* Store the parameter data into the optional parameter object */ - for (i = 0; i < table_header.length; i++) { - status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, - (ACPI_PHYSICAL_ADDRESS) i, 8, - (u32 *) (table_data_ptr + i)); + status = acpi_ex_store (operand[5], ACPI_CAST_PTR (acpi_operand_object, parameter_node), + walk_state); if (ACPI_FAILURE (status)) { - goto cleanup; + (void) acpi_ex_unload_table (ddb_handle); } } + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_load_op + * + * PARAMETERS: Obj_desc - Region or Field where the table will be + * obtained + * Target - Where a handle to the table will be stored + * Walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a field or operation region + * + ******************************************************************************/ + +acpi_status +acpi_ex_load_op ( + acpi_operand_object *obj_desc, + acpi_operand_object *target, + acpi_walk_state *walk_state) +{ + acpi_status status; + acpi_operand_object *ddb_handle; + acpi_operand_object *buffer_desc = NULL; + acpi_table_header *table_ptr = NULL; + u8 *table_data_ptr; + acpi_table_header table_header; + u32 i; + + ACPI_FUNCTION_TRACE ("Ex_load_op"); + + + /* Object can be either an Op_region or a Field */ + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n", + obj_desc, acpi_ut_get_type_name (obj_desc->common.type))); - /* Table must be either an SSDT or a PSDT */ + /* Get the table header */ - if ((!STRNCMP (table_header.signature, + table_header.length = 0; + for (i = 0; i < sizeof (acpi_table_header); i++) { + status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, + (ACPI_PHYSICAL_ADDRESS) i, 8, + ((u8 *) &table_header) + i); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* Allocate a buffer for the entire table */ + + table_ptr = ACPI_MEM_ALLOCATE (table_header.length); + if (!table_ptr) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the header to the buffer */ + + ACPI_MEMCPY (table_ptr, &table_header, sizeof (acpi_table_header)); + table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (acpi_table_header)); + + /* Get the table from the op region */ + + for (i = 0; i < table_header.length; i++) { + status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, + (ACPI_PHYSICAL_ADDRESS) i, 8, + ((u8 *) table_data_ptr + i)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n", + obj_desc, acpi_ut_get_type_name (obj_desc->common.type))); + + /* + * The length of the field must be at least as large as the table. + * Read the entire field and thus the entire table. Buffer is + * allocated during the read. + */ + status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + table_ptr = ACPI_CAST_PTR (acpi_table_header, buffer_desc->buffer.pointer); + break; + + + default: + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* The table must be either an SSDT or a PSDT */ + + if ((!ACPI_STRNCMP (table_ptr->signature, acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && - (!STRNCMP (table_header.signature, + (!ACPI_STRNCMP (table_ptr->signature, acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", - (char*)table_header.signature)); + table_ptr->signature)); status = AE_BAD_SIGNATURE; goto cleanup; } - /* Create an object to be the table handle */ - - table_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); - if (!table_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Install the new table into the local data structures */ - table_info.pointer = (acpi_table_header *) table_ptr; - table_info.length = table_header.length; - table_info.allocation = ACPI_MEM_ALLOCATED; - table_info.base_pointer = table_ptr; - - status = acpi_tb_install_table (NULL, &table_info); + status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE (status)) { goto cleanup; } - /* Add the table to the namespace */ + /* Store the Ddb_handle into the Target operand */ - /* TBD: [Restructure] - change to whatever new interface is appropriate */ -/* - Status = Acpi_load_namespace (); - if (ACPI_FAILURE (Status)) - { -*/ - /* TBD: [Errors] Unload the table on failure ? */ -/* - goto Cleanup; + status = acpi_ex_store (ddb_handle, target, walk_state); + if (ACPI_FAILURE (status)) { + (void) acpi_ex_unload_table (ddb_handle); } -*/ - - - /* TBD: [Investigate] we need a pointer to the table desc */ - - /* Init the table handle */ - - table_desc->reference.opcode = AML_LOAD_OP; - table_desc->reference.object = table_info.installed_desc; - - /* TBD: store the tabledesc into the Ddb_handle target */ - /* Ddb_handle = Table_desc; */ return_ACPI_STATUS (status); cleanup: - ACPI_MEM_FREE (table_desc); - ACPI_MEM_FREE (table_ptr); + if (buffer_desc) { + acpi_ut_remove_reference (buffer_desc); + } + else { + ACPI_MEM_FREE (table_ptr); + } return_ACPI_STATUS (status); } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ex_unload_table * @@ -189,7 +393,7 @@ * * DESCRIPTION: Unload an ACPI table * - ****************************************************************************/ + ******************************************************************************/ acpi_status acpi_ex_unload_table ( @@ -200,7 +404,7 @@ acpi_table_desc *table_info; - FUNCTION_TRACE ("Ex_unload_table"); + ACPI_FUNCTION_TRACE ("Ex_unload_table"); /* @@ -210,7 +414,7 @@ * validated here. */ if ((!ddb_handle) || - (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) || + (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (((acpi_operand_object *)ddb_handle)->common.type != INTERNAL_TYPE_REFERENCE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -224,19 +428,15 @@ * Delete the entire namespace under this table Node * (Offset contains the Table_id) */ - status = acpi_ns_delete_namespace_by_owner (table_info->table_id); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + acpi_ns_delete_namespace_by_owner (table_info->table_id); /* Delete the table itself */ - acpi_tb_uninstall_table (table_info->installed_desc); + (void) acpi_tb_uninstall_table (table_info->installed_desc); /* Delete the table descriptor (Ddb_handle) */ acpi_ut_remove_reference (table_desc); - return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exconvrt.c linux2.4.21_itanium/drivers/acpi/executer/exconvrt.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exconvrt.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exconvrt.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,16 +25,12 @@ #include "acpi.h" -#include "acparser.h" -#include "acnamesp.h" #include "acinterp.h" -#include "acevents.h" #include "amlcode.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exconvrt") + ACPI_MODULE_NAME ("exconvrt") /******************************************************************************* @@ -60,53 +56,33 @@ u32 i; acpi_operand_object *ret_desc; u32 count; - char *pointer; + u8 *pointer; acpi_integer result; - u32 integer_size = sizeof (acpi_integer); + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE_PTR ("Ex_convert_to_integer", obj_desc); switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: *result_desc = obj_desc; - return (AE_OK); + return_ACPI_STATUS (AE_OK); case ACPI_TYPE_STRING: - pointer = obj_desc->string.pointer; + pointer = (u8 *) obj_desc->string.pointer; count = obj_desc->string.length; break; case ACPI_TYPE_BUFFER: - pointer = (char *) obj_desc->buffer.pointer; + pointer = obj_desc->buffer.pointer; count = obj_desc->buffer.length; break; default: - return (AE_TYPE); - } - - /* - * Create a new integer - */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - return (AE_NO_MEMORY); - } - - - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper 32-bit field - */ - integer_size = sizeof (u32); + return_ACPI_STATUS (AE_TYPE); } - /* * Convert the buffer/string to an integer. Note that both buffers and * strings are treated as raw data - we don't convert ascii to hex for @@ -120,8 +96,8 @@ /* Transfer no more than an integer's worth of data */ - if (count > integer_size) { - count = integer_size; + if (count > acpi_gbl_integer_byte_width) { + count = acpi_gbl_integer_byte_width; } /* @@ -130,13 +106,14 @@ switch (obj_desc->common.type) { case ACPI_TYPE_STRING: - /* TBD: Need to use 64-bit STRTOUL */ - /* * Convert string to an integer * String must be hexadecimal as per the ACPI specification */ - result = STRTOUL (pointer, NULL, 16); + status = acpi_ut_strtoul64 ((char *) pointer, 16, &result); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } break; @@ -154,10 +131,22 @@ */ result |= (((acpi_integer) pointer[i]) << (i * 8)); } + break; + + default: + /* No other types can get here */ break; } + /* + * Create a new integer + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + /* Save the Result, delete original descriptor, store new descriptor */ ret_desc->integer.value = result; @@ -169,7 +158,7 @@ } *result_desc = ret_desc; - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -195,61 +184,47 @@ { acpi_operand_object *ret_desc; u32 i; - u32 integer_size = sizeof (acpi_integer); u8 *new_buf; - FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE_PTR ("Ex_convert_to_buffer", obj_desc); switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* - * Create a new Buffer + * Create a new Buffer object */ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!ret_desc) { - return (AE_NO_MEMORY); - } - - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper - * 32-bit field - */ - integer_size = sizeof (u32); + return_ACPI_STATUS (AE_NO_MEMORY); } - /* Need enough space for one integers */ + /* Need enough space for one integer */ - ret_desc->buffer.length = integer_size; - new_buf = ACPI_MEM_CALLOCATE (integer_size); + new_buf = ACPI_MEM_CALLOCATE (acpi_gbl_integer_byte_width); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_convert_to_buffer: Buffer allocation failure\n")); acpi_ut_remove_reference (ret_desc); - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the integer to the buffer */ - for (i = 0; i < integer_size; i++) { + for (i = 0; i < acpi_gbl_integer_byte_width; i++) { new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8)); } + + /* Complete buffer object initialization */ + + ret_desc->buffer.flags |= AOPOBJ_DATA_VALID; ret_desc->buffer.pointer = new_buf; + ret_desc->buffer.length = acpi_gbl_integer_byte_width; /* Return the new buffer descriptor */ - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - *result_desc = ret_desc; break; @@ -265,11 +240,13 @@ default: - return (AE_TYPE); - break; - } + return_ACPI_STATUS (AE_TYPE); + } + + /* Mark buffer initialized */ - return (AE_OK); + (*result_desc)->common.flags |= AOPOBJ_DATA_VALID; + return_ACPI_STATUS (AE_OK); } @@ -294,14 +271,14 @@ u32 i; u32 j; u32 k = 0; - u8 hex_digit; + char hex_digit; acpi_integer digit; u32 remainder; u32 length = sizeof (acpi_integer); u8 leading_zero = TRUE; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); switch (base) { @@ -313,7 +290,7 @@ digit = integer; for (j = 1; j < i; j++) { - acpi_ut_short_divide (&digit, 10, &digit, &remainder); + (void) acpi_ut_short_divide (&digit, 10, &digit, &remainder); } /* Create the decimal digit */ @@ -323,7 +300,7 @@ } if (!leading_zero) { - string[k] = (u8) (ASCII_ZERO + remainder); + string[k] = (u8) (ACPI_ASCII_ZERO + remainder); k++; } } @@ -336,12 +313,12 @@ for (i = 0, j = ((length * 2) -1); i < (length * 2); i++, j--) { hex_digit = acpi_ut_hex_to_ascii_char (integer, (j * 4)); - if (hex_digit != ASCII_ZERO) { + if (hex_digit != ACPI_ASCII_ZERO) { leading_zero = FALSE; } if (!leading_zero) { - string[k] = hex_digit; + string[k] = (u8) hex_digit; k++; } } @@ -358,7 +335,7 @@ * Finally, null terminate the string and return the length */ if (!k) { - string [0] = ASCII_ZERO; + string [0] = ACPI_ASCII_ZERO; k = 1; } string [k] = 0; @@ -393,29 +370,17 @@ u32 i; u32 index; u32 string_length; - u32 integer_size = sizeof (acpi_integer); u8 *new_buf; u8 *pointer; - FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE_PTR ("Ex_convert_to_string", obj_desc); switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper - * 32-bit field - */ - integer_size = sizeof (u32); - } - - string_length = integer_size * 2; + string_length = acpi_gbl_integer_byte_width * 2; if (base == 10) { string_length = ACPI_MAX_DECIMAL_DIGITS; } @@ -425,20 +390,19 @@ */ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); if (!ret_desc) { - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* Need enough space for one ASCII integer plus null terminator */ - new_buf = ACPI_MEM_CALLOCATE (string_length + 1); + new_buf = ACPI_MEM_CALLOCATE ((ACPI_SIZE) string_length + 1); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_convert_to_string: Buffer allocation failure\n")); acpi_ut_remove_reference (ret_desc); - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } - /* Convert */ i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf); @@ -477,7 +441,7 @@ if (max_length > ACPI_MAX_STRING_CONVERSION) { if (string_length > ACPI_MAX_STRING_CONVERSION) { - return (AE_AML_STRING_LIMIT); + return_ACPI_STATUS (AE_AML_STRING_LIMIT); } } @@ -486,7 +450,7 @@ */ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); if (!ret_desc) { - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* String length is the lesser of the Max or the actual length */ @@ -495,12 +459,12 @@ string_length = max_length; } - new_buf = ACPI_MEM_CALLOCATE (string_length + 1); + new_buf = ACPI_MEM_CALLOCATE ((ACPI_SIZE) string_length + 1); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_convert_to_string: Buffer allocation failure\n")); acpi_ut_remove_reference (ret_desc); - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* @@ -509,7 +473,7 @@ pointer = obj_desc->buffer.pointer; index = 0; for (i = 0, index = 0; i < obj_desc->buffer.length; i++) { - index = acpi_ex_convert_to_ascii (pointer[i], base, &new_buf[index]); + index = acpi_ex_convert_to_ascii ((acpi_integer) pointer[i], base, &new_buf[index]); new_buf[index] = ' '; index++; @@ -519,8 +483,7 @@ new_buf [index-1] = 0; ret_desc->buffer.pointer = new_buf; - ret_desc->string.length = STRLEN ((char *) new_buf); - + ret_desc->string.length = ACPI_STRLEN ((char *) new_buf); /* Return the new buffer descriptor */ @@ -543,17 +506,16 @@ else { /* Must copy the string first and then truncate it */ - return (AE_NOT_IMPLEMENTED); + return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } break; default: - return (AE_TYPE); - break; - } + return_ACPI_STATUS (AE_TYPE); + } - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -561,26 +523,32 @@ * * FUNCTION: Acpi_ex_convert_to_target_type * - * PARAMETERS: *Obj_desc - Object to be converted. - * Walk_state - Current method state + * PARAMETERS: Destination_type - Current type of the destination + * Source_desc - Source object to be converted. + * Walk_state - Current method state * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Implements "implicit conversion" rules for storing an object. * ******************************************************************************/ acpi_status acpi_ex_convert_to_target_type ( - acpi_object_type8 destination_type, - acpi_operand_object **obj_desc, + acpi_object_type destination_type, + acpi_operand_object *source_desc, + acpi_operand_object **result_desc, acpi_walk_state *walk_state) { acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_convert_to_target_type"); + ACPI_FUNCTION_TRACE ("Ex_convert_to_target_type"); + + /* Default behavior */ + + *result_desc = source_desc; /* * If required by the target, @@ -601,10 +569,10 @@ default: /* No conversion allowed for these types */ - if (destination_type != (*obj_desc)->common.type) { + if (destination_type != source_desc->common.type) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Target does not allow conversion of type %s to %s\n", - acpi_ut_get_type_name ((*obj_desc)->common.type), + acpi_ut_get_type_name ((source_desc)->common.type), acpi_ut_get_type_name (destination_type))); status = AE_TYPE; } @@ -623,7 +591,7 @@ * These types require an Integer operand. We can convert * a Buffer or a String to an Integer if necessary. */ - status = acpi_ex_convert_to_integer (*obj_desc, obj_desc, walk_state); + status = acpi_ex_convert_to_integer (source_desc, result_desc, walk_state); break; @@ -633,17 +601,22 @@ * The operand must be a String. We can convert an * Integer or Buffer if necessary */ - status = acpi_ex_convert_to_string (*obj_desc, obj_desc, 16, ACPI_UINT32_MAX, walk_state); + status = acpi_ex_convert_to_string (source_desc, result_desc, 16, ACPI_UINT32_MAX, walk_state); break; case ACPI_TYPE_BUFFER: /* - * The operand must be a String. We can convert an - * Integer or Buffer if necessary + * The operand must be a Buffer. We can convert an + * Integer or String if necessary */ - status = acpi_ex_convert_to_buffer (*obj_desc, obj_desc, walk_state); + status = acpi_ex_convert_to_buffer (source_desc, result_desc, walk_state); + break; + + + default: + status = AE_AML_INTERNAL; break; } break; @@ -665,7 +638,6 @@ status = AE_AML_INTERNAL; } - /* * Source-to-Target conversion semantics: * diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/excreate.c linux2.4.21_itanium/drivers/acpi/executer/excreate.c --- linux2.4.21_itanium.org/drivers/acpi/executer/excreate.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/excreate.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,16 +25,15 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" #include "acevents.h" -#include "acdispat.h" +#include "actables.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("excreate") + ACPI_MODULE_NAME ("excreate") /***************************************************************************** @@ -58,7 +57,7 @@ acpi_status status; - FUNCTION_TRACE ("Ex_create_alias"); + ACPI_FUNCTION_TRACE ("Ex_create_alias"); /* Get the source/alias operands (both namespace nodes) */ @@ -69,7 +68,7 @@ /* Attach the original source object to the new Alias Node */ status = acpi_ns_attach_object ((acpi_namespace_node *) walk_state->operands[0], - source_node->object, + acpi_ns_get_attached_object (source_node), source_node->type); /* @@ -105,7 +104,7 @@ acpi_operand_object *obj_desc; - FUNCTION_TRACE ("Ex_create_event"); + ACPI_FUNCTION_TRACE ("Ex_create_event"); obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT); @@ -114,11 +113,11 @@ goto cleanup; } - /* Create the actual OS semaphore */ - - /* TBD: [Investigate] should be created with 0 or 1 units? */ - - status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, + /* + * Create the actual OS semaphore, with zero initial units -- meaning + * that the event is created in an unsignalled state + */ + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &obj_desc->event.semaphore); if (ACPI_FAILURE (status)) { goto cleanup; @@ -127,7 +126,7 @@ /* Attach object to the Node */ status = acpi_ns_attach_object ((acpi_namespace_node *) walk_state->operands[0], - obj_desc, (u8) ACPI_TYPE_EVENT); + obj_desc, ACPI_TYPE_EVENT); cleanup: /* @@ -161,7 +160,7 @@ acpi_operand_object *obj_desc; - FUNCTION_TRACE_PTR ("Ex_create_mutex", WALK_OPERANDS); + ACPI_FUNCTION_TRACE_PTR ("Ex_create_mutex", ACPI_WALK_OPERANDS); /* Create the new mutex object */ @@ -172,8 +171,11 @@ goto cleanup; } - /* Create the actual OS semaphore */ - + /* + * Create the actual OS semaphore. + * One unit max to make it a mutex, with one initial unit to allow + * the mutex to be acquired. + */ status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); if (ACPI_FAILURE (status)) { goto cleanup; @@ -184,7 +186,7 @@ obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value; status = acpi_ns_attach_object ((acpi_namespace_node *) walk_state->operands[0], - obj_desc, (u8) ACPI_TYPE_MUTEX); + obj_desc, ACPI_TYPE_MUTEX); cleanup: @@ -222,20 +224,21 @@ acpi_status status; acpi_operand_object *obj_desc; acpi_namespace_node *node; + acpi_operand_object *region_obj2; - FUNCTION_TRACE ("Ex_create_region"); + ACPI_FUNCTION_TRACE ("Ex_create_region"); /* Get the Node from the object stack */ - node = (acpi_namespace_node *) walk_state->operands[0]; + node = walk_state->op->common.node; /* * If the region object is already attached to this node, * just return */ - if (node->object) { + if (acpi_ns_get_attached_object (node)) { return_ACPI_STATUS (AE_OK); } @@ -243,9 +246,9 @@ * Space ID must be one of the predefined IDs, or in the user-defined * range */ - if ((region_space >= NUM_REGION_TYPES) && - (region_space < USER_REGION_BEGIN)) { - REPORT_ERROR (("Invalid Address_space type %X\n", region_space)); + if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && + (region_space < ACPI_USER_REGION_BEGIN)) { + ACPI_REPORT_ERROR (("Invalid Address_space type %X\n", region_space)); return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); } @@ -261,21 +264,13 @@ goto cleanup; } - /* Allocate a method object for this region */ - - obj_desc->region.extra = acpi_ut_create_internal_object ( - INTERNAL_TYPE_EXTRA); - if (!obj_desc->region.extra) { - status = AE_NO_MEMORY; - goto cleanup; - } - /* * Remember location in AML stream of address & length * operands since they need to be evaluated at run time. */ - obj_desc->region.extra->extra.aml_start = aml_start; - obj_desc->region.extra->extra.aml_length = aml_length; + region_obj2 = obj_desc->common.next_object; + region_obj2->extra.aml_start = aml_start; + region_obj2->extra.aml_length = aml_length; /* Init the region from the operands */ @@ -286,34 +281,14 @@ /* Install the new region object in the parent Node */ - status = acpi_ns_attach_object (node, obj_desc, - (u8) ACPI_TYPE_REGION); - if (ACPI_FAILURE (status)) { - goto cleanup; - } + status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); - /* - * If we have a valid region, initialize it - * Namespace is NOT locked at this point. - */ - status = acpi_ev_initialize_region (obj_desc, FALSE); - if (ACPI_FAILURE (status)) { - /* - * If AE_NOT_EXIST is returned, it is not fatal - * because many regions get created before a handler - * is installed for said region. - */ - if (AE_NOT_EXIST == status) { - status = AE_OK; - } - } cleanup: /* Remove local reference to the object */ acpi_ut_remove_reference (obj_desc); - return_ACPI_STATUS (status); } @@ -334,24 +309,81 @@ acpi_ex_create_table_region ( acpi_walk_state *walk_state) { - acpi_status status = AE_OK; + acpi_status status; + acpi_operand_object **operand = &walk_state->operands[0]; + acpi_operand_object *obj_desc; + acpi_namespace_node *node; + acpi_table_header *table; + acpi_operand_object *region_obj2; - FUNCTION_TRACE ("Ex_create_table_region"); + ACPI_FUNCTION_TRACE ("Ex_create_table_region"); -/* - acpi_operand_object *Obj_desc; - Obj_desc = Acpi_ut_create_internal_object (ACPI_TYPE_REGION); - if (!Obj_desc) - { - Status = AE_NO_MEMORY; - goto Cleanup; + /* Get the Node from the object stack */ + + node = walk_state->op->common.node; + + /* + * If the region object is already attached to this node, + * just return + */ + if (acpi_ns_get_attached_object (node)) { + return_ACPI_STATUS (AE_OK); + } + + /* Find the ACPI table */ + + status = acpi_tb_find_table (operand[1]->string.pointer, + operand[2]->string.pointer, + operand[3]->string.pointer, &table); + + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } + /* Create the region descriptor */ -Cleanup: -*/ + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); + if (!obj_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + region_obj2 = obj_desc->common.next_object; + region_obj2->extra.region_context = NULL; + + /* Init the region from the operands */ + + obj_desc->region.space_id = REGION_DATA_TABLE; + obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) ACPI_TO_INTEGER (table); + obj_desc->region.length = table->length; + obj_desc->region.node = node; + obj_desc->region.flags = AOPOBJ_DATA_VALID; + + /* Install the new region object in the parent Node */ + status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_ev_initialize_region (obj_desc, FALSE); + if (ACPI_FAILURE (status)) { + if (status == AE_NOT_EXIST) { + status = AE_OK; + } + else { + goto cleanup; + } + } + + obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; + + +cleanup: + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); } @@ -381,7 +413,7 @@ acpi_status status; - FUNCTION_TRACE_PTR ("Ex_create_processor", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ex_create_processor", walk_state); /* Create the processor object */ @@ -401,7 +433,7 @@ /* Install the processor object in the parent Node */ status = acpi_ns_attach_object ((acpi_namespace_node *) operand[0], - obj_desc, (u8) ACPI_TYPE_PROCESSOR); + obj_desc, ACPI_TYPE_PROCESSOR); /* Remove local reference to the object */ @@ -436,7 +468,7 @@ acpi_operand_object *obj_desc; - FUNCTION_TRACE_PTR ("Ex_create_power_resource", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ex_create_power_resource", walk_state); /* Create the power resource object */ @@ -454,7 +486,7 @@ /* Install the power resource object in the parent Node */ status = acpi_ns_attach_object ((acpi_namespace_node *) operand[0], - obj_desc, (u8) ACPI_TYPE_POWER); + obj_desc, ACPI_TYPE_POWER); /* Remove local reference to the object */ @@ -491,7 +523,7 @@ u8 method_flags; - FUNCTION_TRACE_PTR ("Ex_create_method", walk_state); + ACPI_FUNCTION_TRACE_PTR ("Ex_create_method", walk_state); /* Create a new method object */ @@ -533,7 +565,7 @@ /* Attach the new object to the method Node */ status = acpi_ns_attach_object ((acpi_namespace_node *) operand[0], - obj_desc, (u8) ACPI_TYPE_METHOD); + obj_desc, ACPI_TYPE_METHOD); /* Remove local reference to the object */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exdump.c linux2.4.21_itanium/drivers/acpi/executer/exdump.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exdump.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exdump.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,11 +28,10 @@ #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "actables.h" #include "acparser.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exdump") + ACPI_MODULE_NAME ("exdump") /* @@ -43,229 +42,155 @@ /***************************************************************************** * - * FUNCTION: Acpi_ex_show_hex_value - * - * PARAMETERS: Byte_count - Number of bytes to print (1, 2, or 4) - * *Aml_start - Address in AML stream of bytes to print - * Interpreter_mode - Current running mode (load1/Load2/Exec) - * Lead_space - # of spaces to print ahead of value - * 0 => none ahead but one behind - * - * DESCRIPTION: Print Byte_count byte(s) starting at Aml_start as a single - * value, in hex. If Byte_count > 1 or the value printed is > 9, also - * print in decimal. - * - ****************************************************************************/ - -void -acpi_ex_show_hex_value ( - u32 byte_count, - u8 *aml_start, - u32 lead_space) -{ - u32 value; /* Value retrieved from AML stream */ - u32 show_decimal_value; - u32 length; /* Length of printed field */ - u8 *current_aml_ptr = NULL; /* Pointer to current byte of AML value */ - - - FUNCTION_TRACE ("Ex_show_hex_value"); - - - if (!aml_start) { - REPORT_ERROR (("Ex_show_hex_value: null pointer\n")); - } - - /* - * AML numbers are always stored little-endian, - * even if the processor is big-endian. - */ - for (current_aml_ptr = aml_start + byte_count, - value = 0; - current_aml_ptr > aml_start; ) { - value = (value << 8) + (u32)* --current_aml_ptr; - } - - length = lead_space * byte_count + 2; - if (byte_count > 1) { - length += (byte_count - 1); - } - - show_decimal_value = (byte_count > 1 || value > 9); - if (show_decimal_value) { - length += 3 + acpi_ex_digits_needed (value, 10); - } - - for (length = lead_space; length; --length ) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, " ")); - } - - while (byte_count--) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, "%02x", *aml_start++)); - - if (byte_count) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, " ")); - } - } - - if (show_decimal_value) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, " [%d]", value)); - } - - if (0 == lead_space) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, " ")); - } - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_LOAD, "\n")); - return_VOID; -} - - -/***************************************************************************** - * * FUNCTION: Acpi_ex_dump_operand * - * PARAMETERS: *Entry_desc - Pointer to entry to be dumped + * PARAMETERS: *Obj_desc - Pointer to entry to be dumped * * RETURN: Status * - * DESCRIPTION: Dump a stack entry + * DESCRIPTION: Dump an operand object * ****************************************************************************/ -acpi_status +void acpi_ex_dump_operand ( - acpi_operand_object *entry_desc) + acpi_operand_object *obj_desc) { u8 *buf = NULL; u32 length; u32 i; + acpi_operand_object **element; + u16 element_index; + + ACPI_FUNCTION_NAME ("Ex_dump_operand") - PROC_NAME ("Ex_dump_operand") + if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { + return; + } - if (!entry_desc) { + if (!obj_desc) { /* * This usually indicates that something serious is wrong -- * since most (if not all) * code that dumps the stack expects something to be there! */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null stack entry ptr\n")); - return (AE_OK); + acpi_os_printf ("Null stack entry ptr\n"); + return; } - if (VALID_DESCRIPTOR_TYPE (entry_desc, ACPI_DESC_TYPE_NAMED)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p NS Node: ", entry_desc)); - DUMP_ENTRY (entry_desc, ACPI_LV_INFO); - return (AE_OK); + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p NS Node: ", obj_desc)); + ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC); + return; } - if (!VALID_DESCRIPTOR_TYPE (entry_desc, ACPI_DESC_TYPE_INTERNAL)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p Is not a local object \n", entry_desc)); - DUMP_BUFFER (entry_desc, sizeof (acpi_operand_object)); - return (AE_OK); + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is not a local object\n", obj_desc)); + ACPI_DUMP_BUFFER (obj_desc, sizeof (acpi_operand_object)); + return; } - /* Entry_desc is a valid object */ + /* Obj_desc is a valid object */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p ", entry_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc)); - switch (entry_desc->common.type) { + switch (obj_desc->common.type) { case INTERNAL_TYPE_REFERENCE: - switch (entry_desc->reference.opcode) { + switch (obj_desc->reference.opcode) { case AML_ZERO_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Zero\n")); + acpi_os_printf ("Reference: Zero\n"); break; case AML_ONE_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: One\n")); + acpi_os_printf ("Reference: One\n"); break; case AML_ONES_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Ones\n")); + acpi_os_printf ("Reference: Ones\n"); break; case AML_REVISION_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Revision\n")); + acpi_os_printf ("Reference: Revision\n"); break; case AML_DEBUG_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Debug\n")); + acpi_os_printf ("Reference: Debug\n"); break; case AML_NAME_OP: - DUMP_PATHNAME (entry_desc->reference.object, "Reference: Name: ", + ACPI_DUMP_PATHNAME (obj_desc->reference.object, "Reference: Name: ", ACPI_LV_INFO, _COMPONENT); - DUMP_ENTRY (entry_desc->reference.object, ACPI_LV_INFO); + ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO); break; case AML_INDEX_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Index %p\n", - entry_desc->reference.object)); + acpi_os_printf ("Reference: Index %p\n", + obj_desc->reference.object); break; case AML_ARG_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Arg%d", - entry_desc->reference.offset)); + acpi_os_printf ("Reference: Arg%d", + obj_desc->reference.offset); - if (ACPI_TYPE_INTEGER == entry_desc->common.type) { + if (ACPI_TYPE_INTEGER == obj_desc->common.type) { /* Value is a Number */ - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, " value is [%8.8X%8.8x]", - HIDWORD(entry_desc->integer.value), - LODWORD(entry_desc->integer.value))); + acpi_os_printf (" value is [%8.8X%8.8x]", + ACPI_HIDWORD(obj_desc->integer.value), + ACPI_LODWORD(obj_desc->integer.value)); } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n")); + acpi_os_printf ("\n"); break; case AML_LOCAL_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference: Local%d", - entry_desc->reference.offset)); + acpi_os_printf ("Reference: Local%d", + obj_desc->reference.offset); - if (ACPI_TYPE_INTEGER == entry_desc->common.type) { + if (ACPI_TYPE_INTEGER == obj_desc->common.type) { /* Value is a Number */ - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, " value is [%8.8X%8.8x]", - HIDWORD(entry_desc->integer.value), - LODWORD(entry_desc->integer.value))); + acpi_os_printf (" value is [%8.8X%8.8x]", + ACPI_HIDWORD(obj_desc->integer.value), + ACPI_LODWORD(obj_desc->integer.value)); } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n")); + acpi_os_printf ("\n"); break; case AML_INT_NAMEPATH_OP: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Reference.Node->Name %X\n", - entry_desc->reference.node->name)); + acpi_os_printf ("Reference.Node->Name %X\n", + obj_desc->reference.node->name.integer); break; default: /* unknown opcode */ - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Unknown opcode=%X\n", - entry_desc->reference.opcode)); + acpi_os_printf ("Unknown opcode=%X\n", + obj_desc->reference.opcode); break; } @@ -275,11 +200,11 @@ case ACPI_TYPE_BUFFER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Buffer len %X @ %p \n", - entry_desc->buffer.length, - entry_desc->buffer.pointer)); + acpi_os_printf ("Buffer len %X @ %p \n", + obj_desc->buffer.length, + obj_desc->buffer.pointer); - length = entry_desc->buffer.length; + length = obj_desc->buffer.length; if (length > 64) { length = 64; @@ -287,13 +212,13 @@ /* Debug only -- dump the buffer contents */ - if (entry_desc->buffer.pointer) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Buffer Contents: ")); + if (obj_desc->buffer.pointer) { + acpi_os_printf ("Buffer Contents: "); - for (buf = entry_desc->buffer.pointer; length--; ++buf) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, " %02x", *buf)); + for (buf = obj_desc->buffer.pointer; length--; ++buf) { + acpi_os_printf (" %02x", *buf); } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,"\n")); + acpi_os_printf ("\n"); } break; @@ -301,135 +226,128 @@ case ACPI_TYPE_INTEGER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Integer %8.8X%8.8X\n", - HIDWORD (entry_desc->integer.value), - LODWORD (entry_desc->integer.value))); + acpi_os_printf ("Integer %8.8X%8.8X\n", + ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; case INTERNAL_TYPE_IF: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "If [Integer] %8.8X%8.8X\n", - HIDWORD (entry_desc->integer.value), - LODWORD (entry_desc->integer.value))); + acpi_os_printf ("If [Integer] %8.8X%8.8X\n", + ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; case INTERNAL_TYPE_WHILE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "While [Integer] %8.8X%8.8X\n", - HIDWORD (entry_desc->integer.value), - LODWORD (entry_desc->integer.value))); + acpi_os_printf ("While [Integer] %8.8X%8.8X\n", + ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; case ACPI_TYPE_PACKAGE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Package count %X @ %p\n", - entry_desc->package.count, entry_desc->package.elements)); + acpi_os_printf ("Package count %X @ %p\n", + obj_desc->package.count, obj_desc->package.elements); /* * If elements exist, package vector pointer is valid, * and debug_level exceeds 1, dump package's elements. */ - if (entry_desc->package.count && - entry_desc->package.elements && + if (obj_desc->package.count && + obj_desc->package.elements && acpi_dbg_level > 1) { - acpi_operand_object**element; - u16 element_index; - - for (element_index = 0, element = entry_desc->package.elements; - element_index < entry_desc->package.count; + for (element_index = 0, element = obj_desc->package.elements; + element_index < obj_desc->package.count; ++element_index, ++element) { acpi_ex_dump_operand (*element); } } - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n")); - + acpi_os_printf ("\n"); break; case ACPI_TYPE_REGION: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Region %s (%X)", - acpi_ut_get_region_name (entry_desc->region.space_id), - entry_desc->region.space_id)); + acpi_os_printf ("Region %s (%X)", + acpi_ut_get_region_name (obj_desc->region.space_id), + obj_desc->region.space_id); /* * If the address and length have not been evaluated, * don't print them. */ - if (!(entry_desc->region.flags & AOPOBJ_DATA_VALID)) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n")); + if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) { + acpi_os_printf ("\n"); } else { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, " base %8.8X%8.8X Length %X\n", - HIDWORD(entry_desc->region.address), - LODWORD(entry_desc->region.address), - entry_desc->region.length)); + acpi_os_printf (" base %8.8X%8.8X Length %X\n", + ACPI_HIDWORD (obj_desc->region.address), + ACPI_LODWORD (obj_desc->region.address), + obj_desc->region.length); } break; case ACPI_TYPE_STRING: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "String length %X @ %p \"", - entry_desc->string.length, entry_desc->string.pointer)); + acpi_os_printf ("String length %X @ %p \"", + obj_desc->string.length, obj_desc->string.pointer); - for (i = 0; i < entry_desc->string.length; i++) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "%c", - entry_desc->string.pointer[i])); + for (i = 0; i < obj_desc->string.length; i++) { + acpi_os_printf ("%c", + obj_desc->string.pointer[i]); } - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\"\n")); + acpi_os_printf ("\"\n"); break; case INTERNAL_TYPE_BANK_FIELD: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Bank_field\n")); + acpi_os_printf ("Bank_field\n"); break; case INTERNAL_TYPE_REGION_FIELD: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, - "Region_field: bits=%X bitaccwidth=%X lock=%X update=%X at byte=%X bit=%X of below:\n", - entry_desc->field.bit_length, entry_desc->field.access_bit_width, - entry_desc->field.lock_rule, entry_desc->field.update_rule, - entry_desc->field.base_byte_offset, entry_desc->field.start_field_bit_offset)); - DUMP_STACK_ENTRY (entry_desc->field.region_obj); + acpi_os_printf ( + "Region_field: Bits=%X Acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", + obj_desc->field.bit_length, obj_desc->field.access_byte_width, + obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, + obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, + obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset); + ACPI_DUMP_STACK_ENTRY (obj_desc->field.region_obj); break; case INTERNAL_TYPE_INDEX_FIELD: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Index_field\n")); + acpi_os_printf ("Index_field\n"); break; case ACPI_TYPE_BUFFER_FIELD: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + acpi_os_printf ( "Buffer_field: %X bits at byte %X bit %X of \n", - entry_desc->buffer_field.bit_length, entry_desc->buffer_field.base_byte_offset, - entry_desc->buffer_field.start_field_bit_offset)); + obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, + obj_desc->buffer_field.start_field_bit_offset); - if (!entry_desc->buffer_field.buffer_obj) + if (!obj_desc->buffer_field.buffer_obj) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*NULL* \n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n")); } - else if (ACPI_TYPE_BUFFER != - entry_desc->buffer_field.buffer_obj->common.type) + obj_desc->buffer_field.buffer_obj->common.type) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "*not a Buffer* \n")); + acpi_os_printf ("*not a Buffer* \n"); } - else { - DUMP_STACK_ENTRY (entry_desc->buffer_field.buffer_obj); + ACPI_DUMP_STACK_ENTRY (obj_desc->buffer_field.buffer_obj); } break; @@ -437,71 +355,57 @@ case ACPI_TYPE_EVENT: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Event\n")); + acpi_os_printf ("Event\n"); break; case ACPI_TYPE_METHOD: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + acpi_os_printf ( "Method(%X) @ %p:%X\n", - entry_desc->method.param_count, - entry_desc->method.aml_start, entry_desc->method.aml_length)); + obj_desc->method.param_count, + obj_desc->method.aml_start, obj_desc->method.aml_length); break; case ACPI_TYPE_MUTEX: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Mutex\n")); + acpi_os_printf ("Mutex\n"); break; case ACPI_TYPE_DEVICE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Device\n")); + acpi_os_printf ("Device\n"); break; case ACPI_TYPE_POWER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Power\n")); + acpi_os_printf ("Power\n"); break; case ACPI_TYPE_PROCESSOR: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Processor\n")); + acpi_os_printf ("Processor\n"); break; case ACPI_TYPE_THERMAL: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Thermal\n")); + acpi_os_printf ("Thermal\n"); break; default: - /* unknown Entry_desc->Common.Type value */ - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "Unknown Type %X\n", - entry_desc->common.type)); - - /* Back up to previous entry */ - - entry_desc--; + /* Unknown Obj_desc->Common.Type value */ - - /* TBD: [Restructure] Change to use dump object routine !! */ - /* What is all of this?? */ - - DUMP_BUFFER (entry_desc, sizeof (acpi_operand_object)); - DUMP_BUFFER (++entry_desc, sizeof (acpi_operand_object)); - DUMP_BUFFER (++entry_desc, sizeof (acpi_operand_object)); + acpi_os_printf ("Unknown Type %X\n", obj_desc->common.type); break; - } - return (AE_OK); + return; } @@ -521,7 +425,7 @@ void acpi_ex_dump_operands ( acpi_operand_object **operands, - operating_mode interpreter_mode, + acpi_interpreter_mode interpreter_mode, NATIVE_CHAR *ident, u32 num_levels, NATIVE_CHAR *note, @@ -529,10 +433,10 @@ u32 line_number) { NATIVE_UINT i; - acpi_operand_object **entry_desc; + acpi_operand_object **obj_desc; - PROC_NAME ("Ex_dump_operands"); + ACPI_FUNCTION_NAME ("Ex_dump_operands"); if (!ident) @@ -545,8 +449,7 @@ note = "?"; } - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "************* Operand Stack Contents (Opcode [%s], %d Operands)\n", ident, num_levels)); @@ -555,19 +458,15 @@ num_levels = 1; } - /* Dump the stack starting at the top, working down */ + /* Dump the operand stack starting at the top */ for (i = 0; num_levels > 0; i--, num_levels--) { - entry_desc = &operands[i]; - - if (ACPI_FAILURE (acpi_ex_dump_operand (*entry_desc))) - { - break; - } + obj_desc = &operands[i]; + acpi_ex_dump_operand (*obj_desc); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "************* Stack dump from %s(%d), %s\n", module_name, line_number, note)); return; @@ -576,6 +475,58 @@ /***************************************************************************** * + * FUNCTION: Acpi_ex_out* + * + * PARAMETERS: Title - Descriptive text + * Value - Value to be displayed + * + * DESCRIPTION: Object dump output formatting functions. These functions + * reduce the number of format strings required and keeps them + * all in one place for easy modification. + * + ****************************************************************************/ + +void +acpi_ex_out_string ( + char *title, + char *value) +{ + acpi_os_printf ("%20s : %s\n", title, value); +} + +void +acpi_ex_out_pointer ( + char *title, + void *value) +{ + acpi_os_printf ("%20s : %p\n", title, value); +} + +void +acpi_ex_out_integer ( + char *title, + u32 value) +{ + acpi_os_printf ("%20s : %X\n", title, value); +} + +void +acpi_ex_out_address ( + char *title, + ACPI_PHYSICAL_ADDRESS value) +{ + +#if ACPI_MACHINE_WIDTH == 16 + acpi_os_printf ("%20s : %p\n", title, value); +#else + acpi_os_printf ("%20s : %8.8X%8.8X\n", title, + ACPI_HIDWORD (value), ACPI_LODWORD (value)); +#endif +} + + +/***************************************************************************** + * * FUNCTION: Acpi_ex_dump_node * * PARAMETERS: *Node - Descriptor to dump @@ -591,7 +542,7 @@ u32 flags) { - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); if (!flags) @@ -602,16 +553,15 @@ } } - - acpi_os_printf ("%20s : %4.4s\n", "Name", (char*)&node->name); - acpi_os_printf ("%20s : %s\n", "Type", acpi_ut_get_type_name (node->type)); - acpi_os_printf ("%20s : %X\n", "Flags", node->flags); - acpi_os_printf ("%20s : %X\n", "Owner Id", node->owner_id); - acpi_os_printf ("%20s : %X\n", "Reference Count", node->reference_count); - acpi_os_printf ("%20s : %p\n", "Attached Object", node->object); - acpi_os_printf ("%20s : %p\n", "Child_list", node->child); - acpi_os_printf ("%20s : %p\n", "Next_peer", node->peer); - acpi_os_printf ("%20s : %p\n", "Parent", acpi_ns_get_parent_object (node)); + acpi_os_printf ("%20s : %4.4s\n", "Name", node->name.ascii); + acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type)); + acpi_ex_out_integer ("Flags", node->flags); + acpi_ex_out_integer ("Owner Id", node->owner_id); + acpi_ex_out_integer ("Reference Count", node->reference_count); + acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node)); + acpi_ex_out_pointer ("Child_list", node->child); + acpi_ex_out_pointer ("Next_peer", node->peer); + acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node)); } @@ -631,10 +581,10 @@ acpi_operand_object *obj_desc, u32 flags) { - const acpi_opcode_info *op_info; + u32 i; - FUNCTION_TRACE ("Ex_dump_object_descriptor"); + ACPI_FUNCTION_TRACE ("Ex_dump_object_descriptor"); if (!flags) @@ -645,16 +595,17 @@ } } - if (!(VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL))) + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf ("%p is not a valid ACPI object\n", obj_desc); + acpi_os_printf ("Ex_dump_object_descriptor: %p is not a valid ACPI object\n", obj_desc); return; } /* Common Fields */ - acpi_os_printf ("%20s : %X\n", "Reference Count", obj_desc->common.reference_count); - acpi_os_printf ("%20s : %X\n", "Flags", obj_desc->common.flags); + acpi_ex_out_string ("Type", acpi_ut_get_type_name (obj_desc->common.type)); + acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count); + acpi_ex_out_integer ("Flags", obj_desc->common.flags); /* Object-specific Fields */ @@ -662,198 +613,192 @@ { case ACPI_TYPE_INTEGER: - acpi_os_printf ("%20s : %s\n", "Type", "Integer"); - acpi_os_printf ("%20s : %X%8.8X\n", "Value", HIDWORD (obj_desc->integer.value), - LODWORD (obj_desc->integer.value)); + acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value", + ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; case ACPI_TYPE_STRING: - acpi_os_printf ("%20s : %s\n", "Type", "String"); - acpi_os_printf ("%20s : %X\n", "Length", obj_desc->string.length); - acpi_os_printf ("%20s : %p\n", "Pointer", obj_desc->string.pointer); + acpi_ex_out_integer ("Length", obj_desc->string.length); + acpi_ex_out_pointer ("Pointer", obj_desc->string.pointer); break; case ACPI_TYPE_BUFFER: - acpi_os_printf ("%20s : %s\n", "Type", "Buffer"); - acpi_os_printf ("%20s : %X\n", "Length", obj_desc->buffer.length); - acpi_os_printf ("%20s : %p\n", "Pointer", obj_desc->buffer.pointer); + acpi_ex_out_integer ("Length", obj_desc->buffer.length); + acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); break; case ACPI_TYPE_PACKAGE: - acpi_os_printf ("%20s : %s\n", "Type", "Package"); - acpi_os_printf ("%20s : %X\n", "Flags", obj_desc->package.flags); - acpi_os_printf ("%20s : %X\n", "Count", obj_desc->package.count); - acpi_os_printf ("%20s : %p\n", "Elements", obj_desc->package.elements); - acpi_os_printf ("%20s : %p\n", "Next_element", obj_desc->package.next_element); - break; + acpi_ex_out_integer ("Flags", obj_desc->package.flags); + acpi_ex_out_integer ("Count", obj_desc->package.count); + acpi_ex_out_pointer ("Elements", obj_desc->package.elements); + /* Dump the package contents */ - case ACPI_TYPE_BUFFER_FIELD: - - acpi_os_printf ("%20s : %s\n", "Type", "Buffer_field"); - acpi_os_printf ("%20s : %X\n", "Bit_length", obj_desc->buffer_field.bit_length); - acpi_os_printf ("%20s : %X\n", "Bit_offset", obj_desc->buffer_field.start_field_bit_offset); - acpi_os_printf ("%20s : %X\n", "Base_byte_offset",obj_desc->buffer_field.base_byte_offset); - acpi_os_printf ("%20s : %p\n", "Buffer_obj", obj_desc->buffer_field.buffer_obj); + if (obj_desc->package.count > 0) + { + acpi_os_printf ("\n_package Contents:\n"); + for (i = 0; i < obj_desc->package.count; i++) + { + acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); + if (obj_desc->package.elements[i]) + { + acpi_os_printf (" %s", acpi_ut_get_type_name ((obj_desc->package.elements[i])->common.type)); + } + acpi_os_printf ("\n"); + } + } break; case ACPI_TYPE_DEVICE: - acpi_os_printf ("%20s : %s\n", "Type", "Device"); - acpi_os_printf ("%20s : %p\n", "Addr_handler", obj_desc->device.addr_handler); - acpi_os_printf ("%20s : %p\n", "Sys_handler", obj_desc->device.sys_handler); - acpi_os_printf ("%20s : %p\n", "Drv_handler", obj_desc->device.drv_handler); + acpi_ex_out_pointer ("Addr_handler", obj_desc->device.addr_handler); + acpi_ex_out_pointer ("Sys_handler", obj_desc->device.sys_handler); + acpi_ex_out_pointer ("Drv_handler", obj_desc->device.drv_handler); break; + case ACPI_TYPE_EVENT: - acpi_os_printf ("%20s : %s\n", "Type", "Event"); - acpi_os_printf ("%20s : %X\n", "Semaphore", obj_desc->event.semaphore); + acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore); break; case ACPI_TYPE_METHOD: - acpi_os_printf ("%20s : %s\n", "Type", "Method"); - acpi_os_printf ("%20s : %X\n", "Param_count", obj_desc->method.param_count); - acpi_os_printf ("%20s : %X\n", "Concurrency", obj_desc->method.concurrency); - acpi_os_printf ("%20s : %p\n", "Semaphore", obj_desc->method.semaphore); - acpi_os_printf ("%20s : %X\n", "Aml_length", obj_desc->method.aml_length); - acpi_os_printf ("%20s : %X\n", "Aml_start", obj_desc->method.aml_start); + acpi_ex_out_integer ("Param_count", obj_desc->method.param_count); + acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); + acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); + acpi_ex_out_integer ("Owning_id", obj_desc->method.owning_id); + acpi_ex_out_integer ("Aml_length", obj_desc->method.aml_length); + acpi_ex_out_pointer ("Aml_start", obj_desc->method.aml_start); break; case ACPI_TYPE_MUTEX: - acpi_os_printf ("%20s : %s\n", "Type", "Mutex"); - acpi_os_printf ("%20s : %X\n", "Sync_level", obj_desc->mutex.sync_level); - acpi_os_printf ("%20s : %p\n", "Owner", obj_desc->mutex.owner); - acpi_os_printf ("%20s : %X\n", "Acquisition_depth", obj_desc->mutex.acquisition_depth); - acpi_os_printf ("%20s : %p\n", "Semaphore", obj_desc->mutex.semaphore); + acpi_ex_out_integer ("Sync_level", obj_desc->mutex.sync_level); + acpi_ex_out_pointer ("Owner_thread", obj_desc->mutex.owner_thread); + acpi_ex_out_integer ("Acquisition_depth",obj_desc->mutex.acquisition_depth); + acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore); break; case ACPI_TYPE_REGION: - acpi_os_printf ("%20s : %s\n", "Type", "Region"); - acpi_os_printf ("%20s : %X\n", "Space_id", obj_desc->region.space_id); - acpi_os_printf ("%20s : %X\n", "Flags", obj_desc->region.flags); - acpi_os_printf ("%20s : %X\n", "Address", obj_desc->region.address); - acpi_os_printf ("%20s : %X\n", "Length", obj_desc->region.length); - acpi_os_printf ("%20s : %p\n", "Addr_handler", obj_desc->region.addr_handler); - acpi_os_printf ("%20s : %p\n", "Next", obj_desc->region.next); + acpi_ex_out_integer ("Space_id", obj_desc->region.space_id); + acpi_ex_out_integer ("Flags", obj_desc->region.flags); + acpi_ex_out_address ("Address", obj_desc->region.address); + acpi_ex_out_integer ("Length", obj_desc->region.length); + acpi_ex_out_pointer ("Addr_handler", obj_desc->region.addr_handler); + acpi_ex_out_pointer ("Next", obj_desc->region.next); break; case ACPI_TYPE_POWER: - acpi_os_printf ("%20s : %s\n", "Type", "Power_resource"); - acpi_os_printf ("%20s : %X\n", "System_level", obj_desc->power_resource.system_level); - acpi_os_printf ("%20s : %X\n", "Resource_order", obj_desc->power_resource.resource_order); - acpi_os_printf ("%20s : %p\n", "Sys_handler", obj_desc->power_resource.sys_handler); - acpi_os_printf ("%20s : %p\n", "Drv_handler", obj_desc->power_resource.drv_handler); + acpi_ex_out_integer ("System_level", obj_desc->power_resource.system_level); + acpi_ex_out_integer ("Resource_order", obj_desc->power_resource.resource_order); + acpi_ex_out_pointer ("Sys_handler", obj_desc->power_resource.sys_handler); + acpi_ex_out_pointer ("Drv_handler", obj_desc->power_resource.drv_handler); break; case ACPI_TYPE_PROCESSOR: - acpi_os_printf ("%20s : %s\n", "Type", "Processor"); - acpi_os_printf ("%20s : %X\n", "Processor ID", obj_desc->processor.proc_id); - acpi_os_printf ("%20s : %X\n", "Length", obj_desc->processor.length); - acpi_os_printf ("%20s : %X\n", "Address", obj_desc->processor.address); - acpi_os_printf ("%20s : %p\n", "Sys_handler", obj_desc->processor.sys_handler); - acpi_os_printf ("%20s : %p\n", "Drv_handler", obj_desc->processor.drv_handler); - acpi_os_printf ("%20s : %p\n", "Addr_handler", obj_desc->processor.addr_handler); + acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); + acpi_ex_out_integer ("Length", obj_desc->processor.length); + acpi_ex_out_address ("Address", (ACPI_PHYSICAL_ADDRESS) obj_desc->processor.address); + acpi_ex_out_pointer ("Sys_handler", obj_desc->processor.sys_handler); + acpi_ex_out_pointer ("Drv_handler", obj_desc->processor.drv_handler); + acpi_ex_out_pointer ("Addr_handler", obj_desc->processor.addr_handler); break; case ACPI_TYPE_THERMAL: - acpi_os_printf ("%20s : %s\n", "Type", "Thermal_zone"); - acpi_os_printf ("%20s : %p\n", "Sys_handler", obj_desc->thermal_zone.sys_handler); - acpi_os_printf ("%20s : %p\n", "Drv_handler", obj_desc->thermal_zone.drv_handler); - acpi_os_printf ("%20s : %p\n", "Addr_handler", obj_desc->thermal_zone.addr_handler); + acpi_ex_out_pointer ("Sys_handler", obj_desc->thermal_zone.sys_handler); + acpi_ex_out_pointer ("Drv_handler", obj_desc->thermal_zone.drv_handler); + acpi_ex_out_pointer ("Addr_handler", obj_desc->thermal_zone.addr_handler); break; + case ACPI_TYPE_BUFFER_FIELD: case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: - acpi_os_printf ("%20s : %p\n", "Access_bit_width", obj_desc->field.access_bit_width); - acpi_os_printf ("%20s : %p\n", "Bit_length", obj_desc->field.bit_length); - acpi_os_printf ("%20s : %p\n", "Base_byte_offset",obj_desc->field.base_byte_offset); - acpi_os_printf ("%20s : %p\n", "Bit_offset", obj_desc->field.start_field_bit_offset); - acpi_os_printf ("%20s : %p\n", "Region_obj", obj_desc->field.region_obj); - break; - + acpi_ex_out_integer ("Field_flags", obj_desc->common_field.field_flags); + acpi_ex_out_integer ("Access_byte_width", obj_desc->common_field.access_byte_width); + acpi_ex_out_integer ("Bit_length", obj_desc->common_field.bit_length); + acpi_ex_out_integer ("Fld_bit_offset", obj_desc->common_field.start_field_bit_offset); + acpi_ex_out_integer ("Base_byte_offset", obj_desc->common_field.base_byte_offset); + acpi_ex_out_integer ("Datum_valid_bits", obj_desc->common_field.datum_valid_bits); + acpi_ex_out_integer ("End_fld_valid_bits", obj_desc->common_field.end_field_valid_bits); + acpi_ex_out_integer ("End_buf_valid_bits", obj_desc->common_field.end_buffer_valid_bits); + acpi_ex_out_pointer ("Parent_node", obj_desc->common_field.node); - case INTERNAL_TYPE_BANK_FIELD: + switch (obj_desc->common.type) + { + case ACPI_TYPE_BUFFER_FIELD: + acpi_ex_out_pointer ("Buffer_obj", obj_desc->buffer_field.buffer_obj); + break; - acpi_os_printf ("%20s : %s\n", "Type", "Bank_field"); - acpi_os_printf ("%20s : %X\n", "Access_bit_width", obj_desc->bank_field.access_bit_width); - acpi_os_printf ("%20s : %X\n", "Lock_rule", obj_desc->bank_field.lock_rule); - acpi_os_printf ("%20s : %X\n", "Update_rule", obj_desc->bank_field.update_rule); - acpi_os_printf ("%20s : %X\n", "Bit_length", obj_desc->bank_field.bit_length); - acpi_os_printf ("%20s : %X\n", "Bit_offset", obj_desc->bank_field.start_field_bit_offset); - acpi_os_printf ("%20s : %X\n", "Base_byte_offset", obj_desc->bank_field.base_byte_offset); - acpi_os_printf ("%20s : %X\n", "Value", obj_desc->bank_field.value); - acpi_os_printf ("%20s : %p\n", "Region_obj", obj_desc->bank_field.region_obj); - acpi_os_printf ("%20s : %X\n", "Bank_register_obj", obj_desc->bank_field.bank_register_obj); - break; + case INTERNAL_TYPE_REGION_FIELD: + acpi_ex_out_pointer ("Region_obj", obj_desc->field.region_obj); + break; + case INTERNAL_TYPE_BANK_FIELD: + acpi_ex_out_integer ("Value", obj_desc->bank_field.value); + acpi_ex_out_pointer ("Region_obj", obj_desc->bank_field.region_obj); + acpi_ex_out_pointer ("Bank_obj", obj_desc->bank_field.bank_obj); + break; - case INTERNAL_TYPE_INDEX_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + acpi_ex_out_integer ("Value", obj_desc->index_field.value); + acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); + acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); + break; - acpi_os_printf ("%20s : %s\n", "Type", "Index_field"); - acpi_os_printf ("%20s : %X\n", "Access_bit_width", obj_desc->index_field.access_bit_width); - acpi_os_printf ("%20s : %X\n", "Lock_rule", obj_desc->index_field.lock_rule); - acpi_os_printf ("%20s : %X\n", "Update_rule", obj_desc->index_field.update_rule); - acpi_os_printf ("%20s : %X\n", "Bit_length", obj_desc->index_field.bit_length); - acpi_os_printf ("%20s : %X\n", "Bit_offset", obj_desc->index_field.start_field_bit_offset); - acpi_os_printf ("%20s : %X\n", "Value", obj_desc->index_field.value); - acpi_os_printf ("%20s : %X\n", "Index", obj_desc->index_field.index_obj); - acpi_os_printf ("%20s : %X\n", "Data", obj_desc->index_field.data_obj); + default: + /* All object types covered above */ + break; + } break; case INTERNAL_TYPE_REFERENCE: - op_info = acpi_ps_get_opcode_info (obj_desc->reference.opcode); - - acpi_os_printf ("%20s : %s\n", "Type", "Reference"); - acpi_os_printf ("%20s : %X\n", "Target_type", obj_desc->reference.target_type); - acpi_os_printf ("%20s : %s\n", "Opcode", op_info->name); - acpi_os_printf ("%20s : %X\n", "Offset", obj_desc->reference.offset); - acpi_os_printf ("%20s : %p\n", "Obj_desc", obj_desc->reference.object); - acpi_os_printf ("%20s : %p\n", "Node", obj_desc->reference.node); - acpi_os_printf ("%20s : %p\n", "Where", obj_desc->reference.where); + acpi_ex_out_integer ("Target_type", obj_desc->reference.target_type); + acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name); + acpi_ex_out_integer ("Offset", obj_desc->reference.offset); + acpi_ex_out_pointer ("Obj_desc", obj_desc->reference.object); + acpi_ex_out_pointer ("Node", obj_desc->reference.node); + acpi_ex_out_pointer ("Where", obj_desc->reference.where); break; case INTERNAL_TYPE_ADDRESS_HANDLER: - acpi_os_printf ("%20s : %s\n", "Type", "Address Handler"); - acpi_os_printf ("%20s : %X\n", "Space_id", obj_desc->addr_handler.space_id); - acpi_os_printf ("%20s : %p\n", "Next", obj_desc->addr_handler.next); - acpi_os_printf ("%20s : %p\n", "Region_list", obj_desc->addr_handler.region_list); - acpi_os_printf ("%20s : %p\n", "Node", obj_desc->addr_handler.node); - acpi_os_printf ("%20s : %p\n", "Handler", obj_desc->addr_handler.handler); - acpi_os_printf ("%20s : %p\n", "Context", obj_desc->addr_handler.context); + acpi_ex_out_integer ("Space_id", obj_desc->addr_handler.space_id); + acpi_ex_out_pointer ("Next", obj_desc->addr_handler.next); + acpi_ex_out_pointer ("Region_list", obj_desc->addr_handler.region_list); + acpi_ex_out_pointer ("Node", obj_desc->addr_handler.node); + acpi_ex_out_pointer ("Context", obj_desc->addr_handler.context); break; case INTERNAL_TYPE_NOTIFY: - acpi_os_printf ("%20s : %s\n", "Type", "Notify Handler"); - acpi_os_printf ("%20s : %p\n", "Node", obj_desc->notify_handler.node); - acpi_os_printf ("%20s : %p\n", "Handler", obj_desc->notify_handler.handler); - acpi_os_printf ("%20s : %p\n", "Context", obj_desc->notify_handler.context); + acpi_ex_out_pointer ("Node", obj_desc->notify_handler.node); + acpi_ex_out_pointer ("Context", obj_desc->notify_handler.context); break; @@ -866,15 +811,17 @@ case INTERNAL_TYPE_WHILE: case INTERNAL_TYPE_SCOPE: case INTERNAL_TYPE_DEF_ANY: + case INTERNAL_TYPE_EXTRA: + case INTERNAL_TYPE_DATA: - acpi_os_printf ("*** Structure display not implemented for type %X! ***\n", + acpi_os_printf ("Ex_dump_object_descriptor: Display not implemented for object type %X\n", obj_desc->common.type); break; default: - acpi_os_printf ("*** Cannot display unknown type %X! ***\n", obj_desc->common.type); + acpi_os_printf ("Ex_dump_object_descriptor: Unknown object type %X\n", obj_desc->common.type); break; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exfield.c linux2.4.21_itanium/drivers/acpi/executer/exfield.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exfield.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exfield.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,33 +27,30 @@ #include "acpi.h" #include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exfield") + ACPI_MODULE_NAME ("exfield") /******************************************************************************* * * FUNCTION: Acpi_ex_read_data_from_field * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer + * PARAMETERS: Walk_state - Current execution state + * Obj_desc - The named field + * Ret_buffer_desc - Where the return data object is stored * - * RETURN: Status3 + * RETURN: Status * - * DESCRIPTION: Read or write a named field + * DESCRIPTION: Read from a named field. Returns either an Integer or a + * Buffer, depending on the size of the field. * ******************************************************************************/ acpi_status acpi_ex_read_data_from_field ( + acpi_walk_state *walk_state, acpi_operand_object *obj_desc, acpi_operand_object **ret_buffer_desc) { @@ -61,9 +58,10 @@ acpi_operand_object *buffer_desc; u32 length; void *buffer; + u8 locked; - FUNCTION_TRACE_PTR ("Ex_read_data_from_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_read_data_from_field", obj_desc); /* Parameter validation */ @@ -72,6 +70,19 @@ return_ACPI_STATUS (AE_AML_NO_OPERAND); } + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { + /* + * If the Buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + } + /* * Allocate a buffer for the contents of the field. * @@ -82,9 +93,8 @@ * * Note: Field.length is in bits. */ - length = ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); - - if (length > sizeof (acpi_integer)) { + length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); + if (length > acpi_gbl_integer_byte_width) { /* Field is too large for an Integer, create a Buffer instead */ buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); @@ -100,10 +110,10 @@ return_ACPI_STATUS (AE_NO_MEMORY); } + buffer_desc->common.flags = AOPOBJ_DATA_VALID; buffer_desc->buffer.length = length; buffer = buffer_desc->buffer.pointer; } - else { /* Field will fit within an Integer (normal case) */ @@ -112,39 +122,34 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - length = sizeof (buffer_desc->integer.value); + length = acpi_gbl_integer_byte_width; + buffer_desc->integer.value = 0; buffer = &buffer_desc->integer.value; } + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Obj=%p Type=%X Buf=%p Len=%X\n", + obj_desc, obj_desc->common.type, buffer, length)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field_write: Bit_len=%X Bit_off=%X Byte_off=%X\n", + obj_desc->common_field.bit_length, + obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.base_byte_offset)); - /* Read from the appropriate field */ - - switch (obj_desc->common.type) { - case ACPI_TYPE_BUFFER_FIELD: - status = acpi_ex_access_buffer_field (ACPI_READ, obj_desc, buffer, length); - break; - - case INTERNAL_TYPE_REGION_FIELD: - status = acpi_ex_access_region_field (ACPI_READ, obj_desc, buffer, length); - break; - - case INTERNAL_TYPE_BANK_FIELD: - status = acpi_ex_access_bank_field (ACPI_READ, obj_desc, buffer, length); - break; + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); - case INTERNAL_TYPE_INDEX_FIELD: - status = acpi_ex_access_index_field (ACPI_READ, obj_desc, buffer, length); - break; + /* Read from the field */ - default: - status = AE_AML_INTERNAL; - } + status = acpi_ex_extract_from_field (obj_desc, buffer, length); + /* + * Release global lock if we acquired it earlier + */ + acpi_ex_release_global_lock (locked); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (buffer_desc); } - else if (ret_buffer_desc) { *ret_buffer_desc = buffer_desc; } @@ -157,18 +162,15 @@ * * FUNCTION: Acpi_ex_write_data_to_field * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer + * PARAMETERS: Source_desc - Contains data to write + * Obj_desc - The named field * * RETURN: Status * - * DESCRIPTION: Read or write a named field + * DESCRIPTION: Write to a named field * ******************************************************************************/ - acpi_status acpi_ex_write_data_to_field ( acpi_operand_object *source_desc, @@ -176,10 +178,13 @@ { acpi_status status; u32 length; + u32 required_length; void *buffer; + void *new_buffer; + u8 locked; - FUNCTION_TRACE_PTR ("Ex_write_data_to_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_write_data_to_field", obj_desc); /* Parameter validation */ @@ -188,6 +193,18 @@ return_ACPI_STATUS (AE_AML_NO_OPERAND); } + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { + /* + * If the Buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + } /* * Get a pointer to the data to be written @@ -212,315 +229,61 @@ return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } - /* - * Decode the type of field to be written + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. */ - switch (obj_desc->common.type) { - case ACPI_TYPE_BUFFER_FIELD: - status = acpi_ex_access_buffer_field (ACPI_WRITE, obj_desc, buffer, length); - break; - - case INTERNAL_TYPE_REGION_FIELD: - status = acpi_ex_access_region_field (ACPI_WRITE, obj_desc, buffer, length); - break; - - case INTERNAL_TYPE_BANK_FIELD: - status = acpi_ex_access_bank_field (ACPI_WRITE, obj_desc, buffer, length); - break; - - case INTERNAL_TYPE_INDEX_FIELD: - status = acpi_ex_access_index_field (ACPI_WRITE, obj_desc, buffer, length); - break; - - default: - return_ACPI_STATUS (AE_AML_INTERNAL); - } - - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_access_buffer_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer - * - * RETURN: Status - * - * DESCRIPTION: Read or write a named field - * - ******************************************************************************/ - -acpi_status -acpi_ex_access_buffer_field ( - u32 mode, - acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length) -{ - acpi_status status; - + new_buffer = NULL; + required_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); - FUNCTION_TRACE_PTR ("Ex_access_buffer_field", obj_desc); + if (length < required_length) { + /* We need to create a new buffer */ - - /* - * If the Buffer_field arguments have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_buffer_field_arguments (obj_desc); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + new_buffer = ACPI_MEM_CALLOCATE (required_length); + if (!new_buffer) { + return_ACPI_STATUS (AE_NO_MEMORY); } - } - - status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_access_region_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer - * - * RETURN: Status - * - * DESCRIPTION: Read or write a named field - * - ******************************************************************************/ - -acpi_status -acpi_ex_access_region_field ( - u32 mode, - acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length) -{ - acpi_status status; - u8 locked; - - - FUNCTION_TRACE_PTR ("Ex_access_region_field", obj_desc); - - - /* - * Get the global lock if needed - */ - locked = acpi_ex_acquire_global_lock (obj_desc->field.lock_rule); - - status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); - - - /* - * Release global lock if we acquired it earlier - */ - acpi_ex_release_global_lock (locked); - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_access_bank_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer - * - * RETURN: Status - * - * DESCRIPTION: Read or write a Bank Field - * - ******************************************************************************/ - -acpi_status -acpi_ex_access_bank_field ( - u32 mode, - acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length) -{ - acpi_status status; - u8 locked; - - - FUNCTION_TRACE_PTR ("Ex_access_bank_field", obj_desc); - - - /* - * Get the global lock if needed - */ - locked = acpi_ex_acquire_global_lock (obj_desc->bank_field.lock_rule); + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length); + buffer = new_buffer; + length = required_length; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Obj=%p Type=%X Buf=%p Len=%X\n", + obj_desc, obj_desc->common.type, buffer, length)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field_read: Bit_len=%X Bit_off=%X Byte_off=%X\n", + obj_desc->common_field.bit_length, + obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.base_byte_offset)); + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); /* - * Write the Bank_value to the Bank_register to select the bank. - * The Bank_value for this Bank_field is specified in the - * Bank_field ASL declaration. The Bank_register is always a Field in - * an operation region. + * Write to the field */ - status = acpi_ex_common_access_field (ACPI_WRITE, - obj_desc->bank_field.bank_register_obj, - &obj_desc->bank_field.value, - sizeof (obj_desc->bank_field.value)); - if (ACPI_FAILURE (status)) { - goto cleanup; - } + status = acpi_ex_insert_into_field (obj_desc, buffer, length); /* - * The bank was successfully selected, now read or write the actual - * data. - */ - status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); - - -cleanup: - /* * Release global lock if we acquired it earlier */ acpi_ex_release_global_lock (locked); - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_access_index_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer - * - * RETURN: Status - * - * DESCRIPTION: Read or write a Index Field - * - ******************************************************************************/ - -acpi_status -acpi_ex_access_index_field ( - u32 mode, - acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length) -{ - acpi_status status; - u8 locked; - - - FUNCTION_TRACE_PTR ("Ex_access_index_field", obj_desc); - - - /* - * Get the global lock if needed - */ - locked = acpi_ex_acquire_global_lock (obj_desc->index_field.lock_rule); + /* Free temporary buffer if we used one */ - - /* - * Set Index value to select proper Data register - */ - status = acpi_ex_common_access_field (ACPI_WRITE, - obj_desc->index_field.index_obj, - &obj_desc->index_field.value, - sizeof (obj_desc->index_field.value)); - if (ACPI_FAILURE (status)) { - goto cleanup; + if (new_buffer) { + ACPI_MEM_FREE (new_buffer); } - /* Now read/write the data register */ - - status = acpi_ex_common_access_field (mode, obj_desc->index_field.data_obj, - buffer, buffer_length); - -cleanup: - /* - * Release global lock if we acquired it earlier - */ - acpi_ex_release_global_lock (locked); - return_ACPI_STATUS (status); } -/******************************************************************************* - * - * FUNCTION: Acpi_ex_common_access_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * *Field_node - Parent node for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Size of buffer, in bytes. Must be large - * enough for all bits of the field. - * - * RETURN: Status - * - * DESCRIPTION: Read or write a named field - * - ******************************************************************************/ - -acpi_status -acpi_ex_common_access_field ( - u32 mode, - acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length) -{ - acpi_status status; - - - FUNCTION_TRACE_PTR ("Ex_common_access_field", obj_desc); - - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj=%p Type=%X Buf=%p Len=%X\n", - obj_desc, obj_desc->common.type, buffer, buffer_length)); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode=%d Bit_len=%X Bit_off=%X Byte_off=%X\n", - mode, obj_desc->common_field.bit_length, - obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.base_byte_offset)); - - - /* Perform the actual read or write of the field */ - - switch (mode) { - case ACPI_READ: - - status = acpi_ex_extract_from_field (obj_desc, buffer, buffer_length); - break; - - - case ACPI_WRITE: - - status = acpi_ex_insert_into_field (obj_desc, buffer, buffer_length); - break; - - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown I/O Mode: %X\n", mode)); - status = AE_BAD_PARAMETER; - break; - } - - - return_ACPI_STATUS (status); -} - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exfldio.c linux2.4.21_itanium/drivers/acpi/executer/exfldio.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exfldio.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exfldio.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,32 +27,31 @@ #include "acpi.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" #include "acdispat.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exfldio") + ACPI_MODULE_NAME ("exfldio") /******************************************************************************* * - * FUNCTION: Acpi_ex_setup_field + * FUNCTION: Acpi_ex_setup_region * - * PARAMETERS: *Obj_desc - Field to be read or written - * Field_datum_byte_offset - Current offset into the field + * PARAMETERS: *Obj_desc - Field to be read or written + * Field_datum_byte_offset - Byte offset of this datum within the + * parent field * * RETURN: Status * * DESCRIPTION: Common processing for Acpi_ex_extract_from_field and - * Acpi_ex_insert_into_field + * Acpi_ex_insert_into_field. Initialize the * ******************************************************************************/ acpi_status -acpi_ex_setup_field ( +acpi_ex_setup_region ( acpi_operand_object *obj_desc, u32 field_datum_byte_offset) { @@ -60,13 +59,13 @@ acpi_operand_object *rgn_desc; - FUNCTION_TRACE_U32 ("Ex_setup_field", field_datum_byte_offset); + ACPI_FUNCTION_TRACE_U32 ("Ex_setup_region", field_datum_byte_offset); rgn_desc = obj_desc->common_field.region_obj; if (ACPI_TYPE_REGION != rgn_desc->common.type) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %x %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n", rgn_desc->common.type, acpi_ut_get_type_name (rgn_desc->common.type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } @@ -76,7 +75,6 @@ * evaluate them now and save the results. */ if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_region_arguments (rgn_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -88,9 +86,9 @@ * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ - if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + - field_datum_byte_offset + - obj_desc->common_field.access_byte_width)) { + if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + + field_datum_byte_offset + + obj_desc->common_field.access_byte_width)) { if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { /* * This is the case where the Access_type (Acc_word, etc.) is wider @@ -98,8 +96,9 @@ * byte, and a field with Dword access specified. */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field access width (%d bytes) too large for region size (%X)\n", - obj_desc->common_field.access_byte_width, rgn_desc->region.length)); + "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", + obj_desc->common_field.node->name.ascii, obj_desc->common_field.access_byte_width, + rgn_desc->region.node->name.ascii, rgn_desc->region.length)); } /* @@ -107,10 +106,10 @@ * exceeds region length, indicate an error */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field base+offset+width %X+%X+%X exceeds region size (%X bytes) field=%p region=%p\n", - obj_desc->common_field.base_byte_offset, field_datum_byte_offset, - obj_desc->common_field.access_byte_width, - rgn_desc->region.length, obj_desc, rgn_desc)); + "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", + obj_desc->common_field.node->name.ascii, obj_desc->common_field.base_byte_offset, + field_datum_byte_offset, obj_desc->common_field.access_byte_width, + rgn_desc->region.node->name.ascii, rgn_desc->region.length)); return_ACPI_STATUS (AE_AML_REGION_LIMIT); } @@ -121,116 +120,410 @@ /******************************************************************************* * - * FUNCTION: Acpi_ex_read_field_datum + * FUNCTION: Acpi_ex_access_region * - * PARAMETERS: *Obj_desc - Field to be read - * *Value - Where to store value (must be 32 bits) + * PARAMETERS: *Obj_desc - Field to be read + * Field_datum_byte_offset - Byte offset of this datum within the + * parent field + * *Value - Where to store value (must be 32 bits) + * Read_write - Read or Write flag * * RETURN: Status * - * DESCRIPTION: Retrieve the value of the given field + * DESCRIPTION: Read or Write a single field datum to an Operation Region. * ******************************************************************************/ acpi_status -acpi_ex_read_field_datum ( +acpi_ex_access_region ( acpi_operand_object *obj_desc, u32 field_datum_byte_offset, - u32 *value) + acpi_integer *value, + u32 read_write) { acpi_status status; acpi_operand_object *rgn_desc; ACPI_PHYSICAL_ADDRESS address; - u32 local_value; - FUNCTION_TRACE_U32 ("Ex_read_field_datum", field_datum_byte_offset); + ACPI_FUNCTION_TRACE ("Ex_access_region"); + + + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + rgn_desc = obj_desc->common_field.region_obj; + address = rgn_desc->region.address + + obj_desc->common_field.base_byte_offset + + field_datum_byte_offset; + + if (read_write == ACPI_READ) { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD, + " Region[%s-%X] Access %X Base:Off %X:%X at %8.8X%8.8X\n", + acpi_ut_get_region_name (rgn_desc->region.space_id), + rgn_desc->region.space_id, + obj_desc->common_field.access_byte_width, + obj_desc->common_field.base_byte_offset, + field_datum_byte_offset, + ACPI_HIDWORD (address), ACPI_LODWORD (address))); + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, read_write, + address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value); + + if (ACPI_FAILURE (status)) { + if (status == AE_NOT_IMPLEMENTED) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Region %s(%X) not implemented\n", + acpi_ut_get_region_name (rgn_desc->region.space_id), + rgn_desc->region.space_id)); + } + + else if (status == AE_NOT_EXIST) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Region %s(%X) has no handler\n", + acpi_ut_get_region_name (rgn_desc->region.space_id), + rgn_desc->region.space_id)); + } + } + + return_ACPI_STATUS (status); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_register_overflow + * + * PARAMETERS: *Obj_desc - Register(Field) to be written + * Value - Value to be stored + * + * RETURN: TRUE if value overflows the field, FALSE otherwise + * + * DESCRIPTION: Check if a value is out of range of the field being written. + * Used to check if the values written to Index and Bank registers + * are out of range. Normally, the value is simply truncated + * to fit the field, but this case is most likely a serious + * coding error in the ASL. + * + ******************************************************************************/ + +u8 +acpi_ex_register_overflow ( + acpi_operand_object *obj_desc, + acpi_integer value) +{ - if (!value) { - local_value = 0; - value = &local_value; /* support reads without saving value */ + if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { + /* + * The field is large enough to hold the maximum integer, so we can + * never overflow it. + */ + return (FALSE); } - /* Clear the entire return buffer first, [Very Important!] */ + if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { + /* + * The Value is larger than the maximum value that can fit into + * the register. + */ + return (TRUE); + } + + /* The Value will fit into the field with no truncation */ + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_field_datum_io + * + * PARAMETERS: *Obj_desc - Field to be read + * Field_datum_byte_offset - Byte offset of this datum within the + * parent field + * *Value - Where to store value (must be 64 bits) + * Read_write - Read or Write flag + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single datum of a field. The Field_type is + * demultiplexed here to handle the different types of fields + * (Buffer_field, Region_field, Index_field, Bank_field) + * + ******************************************************************************/ + +acpi_status +acpi_ex_field_datum_io ( + acpi_operand_object *obj_desc, + u32 field_datum_byte_offset, + acpi_integer *value, + u32 read_write) +{ + acpi_status status; + acpi_integer local_value; + + + ACPI_FUNCTION_TRACE_U32 ("Ex_field_datum_io", field_datum_byte_offset); + + + if (read_write == ACPI_READ) { + if (!value) { + local_value = 0; + value = &local_value; /* To support reads without saving return value */ + } + + /* Clear the entire return buffer first, [Very Important!] */ - *value = 0; + *value = 0; + } /* - * Buffer_fields - Read from a Buffer - * Other Fields - Read from a Operation Region. + * The four types of fields are: + * + * Buffer_fields - Read/write from/to a Buffer + * Region_fields - Read/write from/to a Operation Region. + * Bank_fields - Write to a Bank Register, then read/write from/to an Op_region + * Index_fields - Write to an Index Register, then read/write from/to a Data Register */ switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER_FIELD: - /* - * For Buffer_fields, we only need to copy the data from the - * source buffer. Length is the field width in bytes. + * If the Buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. */ - MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer - + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, - obj_desc->common_field.access_byte_width); + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + if (read_write == ACPI_READ) { + /* + * Copy the data from the source buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, + obj_desc->common_field.access_byte_width); + } + else { + /* + * Copy the data to the target buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, + value, obj_desc->common_field.access_byte_width); + } + status = AE_OK; break; - case INTERNAL_TYPE_REGION_FIELD: case INTERNAL_TYPE_BANK_FIELD: + /* Ensure that the Bank_value is not beyond the capacity of the register */ + + if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, + (acpi_integer) obj_desc->bank_field.value)) { + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + /* - * For other fields, we need to go through an Operation Region - * (Only types that will get here are Region_fields and Bank_fields) + * For Bank_fields, we must write the Bank_value to the Bank_register + * (itself a Region_field) before we can access the data. */ - status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset); + status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj, + &obj_desc->bank_field.value, + sizeof (obj_desc->bank_field.value)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* - * The physical address of this field datum is: - * - * 1) The base of the region, plus - * 2) The base offset of the field, plus - * 3) The current offset into the field - */ - rgn_desc = obj_desc->common_field.region_obj; - address = rgn_desc->region.address + obj_desc->common_field.base_byte_offset + - field_datum_byte_offset; - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Region %s(%X) width %X base:off %X:%X at %8.8X%8.8X\n", - acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id, obj_desc->common_field.access_bit_width, - obj_desc->common_field.base_byte_offset, field_datum_byte_offset, - HIDWORD(address), LODWORD(address))); + * Now that the Bank has been selected, fall through to the + * Region_field case and write the datum to the Operation Region + */ - /* Invoke the appropriate Address_space/Op_region handler */ + /*lint -fallthrough */ - status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, - address, obj_desc->common_field.access_bit_width, value); - if (status == AE_NOT_IMPLEMENTED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) not implemented\n", - acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id)); + + case INTERNAL_TYPE_REGION_FIELD: + /* + * For simple Region_fields, we just directly access the owning + * Operation Region. + */ + status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - else if (status == AE_NOT_EXIST) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) has no handler\n", - acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id)); + status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value, + read_write); + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + + /* Ensure that the Index_value is not beyond the capacity of the register */ + + if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, + (acpi_integer) obj_desc->index_field.value)) { + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + + /* Write the index value to the Index_register (itself a Region_field) */ + + status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj, + &obj_desc->index_field.value, + sizeof (obj_desc->index_field.value)); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + if (read_write == ACPI_READ) { + /* Read the datum from the Data_register */ + + status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj, + value, obj_desc->common_field.access_byte_width); + } + else { + /* Write the datum to the Data register */ + + status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj, + value, obj_desc->common_field.access_byte_width); } break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n", obj_desc, acpi_ut_get_type_name (obj_desc->common.type))); status = AE_AML_INTERNAL; break; } + if (ACPI_SUCCESS (status)) { + if (read_write == ACPI_READ) { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read=%8.8X%8.8X\n", + ACPI_HIDWORD (*value), ACPI_LODWORD (*value))); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written=%8.8X%8.8X\n", + ACPI_HIDWORD (*value), ACPI_LODWORD (*value))); + } + } + + return_ACPI_STATUS (status); +} - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Returned value=%08X \n", *value)); + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_write_with_update_rule + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ******************************************************************************/ + +acpi_status +acpi_ex_write_with_update_rule ( + acpi_operand_object *obj_desc, + acpi_integer mask, + acpi_integer field_value, + u32 field_datum_byte_offset) +{ + acpi_status status = AE_OK; + acpi_integer merged_value; + acpi_integer current_value; + + + ACPI_FUNCTION_TRACE_U32 ("Ex_write_with_update_rule", mask); + + + /* Start with the new bits */ + + merged_value = field_value; + + /* If the mask is all ones, we don't need to worry about the update rule */ + + if (mask != ACPI_INTEGER_MAX) { + /* Decode the update rule */ + + switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) { + case AML_FIELD_UPDATE_PRESERVE: + /* + * Check if update rule needs to be applied (not if mask is all + * ones) The left shift drops the bits we want to ignore. + */ + if ((~mask << (ACPI_MUL_8 (sizeof (mask)) - + ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + ¤t_value, ACPI_READ); + merged_value |= (current_value & ~mask); + } + break; + + case AML_FIELD_UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + merged_value |= ~mask; + break; + + case AML_FIELD_UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + merged_value &= mask; + break; + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Write_with_update_rule: Unknown Update_rule setting: %X\n", + (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK))); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + } + + /* Write the merged value */ + + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &merged_value, ACPI_WRITE); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Mask %8.8X%8.8X Datum_offset %X Value %8.8X%8.8X, Merged_value %8.8X%8.8X\n", + ACPI_HIDWORD (mask), ACPI_LODWORD (mask), + field_datum_byte_offset, + ACPI_HIDWORD (field_value), ACPI_LODWORD (field_value), + ACPI_HIDWORD (merged_value),ACPI_LODWORD (merged_value))); return_ACPI_STATUS (status); } @@ -240,41 +533,53 @@ * * FUNCTION: Acpi_ex_get_buffer_datum * - * PARAMETERS: Merged_datum - Value to store - * Buffer - Receiving buffer - * Byte_granularity - 1/2/4 Granularity of the field + * PARAMETERS: Datum - Where the Datum is returned + * Buffer - Raw field buffer + * Byte_granularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * Offset - Datum offset into the buffer * * RETURN: none * - * DESCRIPTION: Store the merged datum to the buffer according to the + * DESCRIPTION: Get a datum from the buffer according to the buffer field * byte granularity * ******************************************************************************/ -static void +void acpi_ex_get_buffer_datum( - u32 *datum, + acpi_integer *datum, void *buffer, u32 byte_granularity, u32 offset) { - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); switch (byte_granularity) { case ACPI_FIELD_BYTE_GRANULARITY: + *datum = ((u8 *) buffer) [offset]; break; case ACPI_FIELD_WORD_GRANULARITY: - MOVE_UNALIGNED16_TO_32 (datum, &(((u16 *) buffer) [offset])); + + ACPI_MOVE_UNALIGNED16_TO_32 (datum, &(((u16 *) buffer) [offset])); break; case ACPI_FIELD_DWORD_GRANULARITY: - MOVE_UNALIGNED32_TO_32 (datum, &(((u32 *) buffer) [offset])); + + ACPI_MOVE_UNALIGNED32_TO_32 (datum, &(((u32 *) buffer) [offset])); + break; + + case ACPI_FIELD_QWORD_GRANULARITY: + + ACPI_MOVE_UNALIGNED64_TO_64 (datum, &(((u64 *) buffer) [offset])); + break; + + default: + /* Should not get here */ break; } } @@ -286,7 +591,7 @@ * * PARAMETERS: Merged_datum - Value to store * Buffer - Receiving buffer - * Byte_granularity - 1/2/4 Granularity of the field + * Byte_granularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * Offset - Datum offset into the buffer * @@ -297,28 +602,40 @@ * ******************************************************************************/ -static void +void acpi_ex_set_buffer_datum ( - u32 merged_datum, + acpi_integer merged_datum, void *buffer, u32 byte_granularity, u32 offset) { - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); switch (byte_granularity) { case ACPI_FIELD_BYTE_GRANULARITY: + ((u8 *) buffer) [offset] = (u8) merged_datum; break; case ACPI_FIELD_WORD_GRANULARITY: - MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[offset]), &merged_datum); + + ACPI_MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[offset]), &merged_datum); break; case ACPI_FIELD_DWORD_GRANULARITY: - MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[offset]), &merged_datum); + + ACPI_MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[offset]), &merged_datum); + break; + + case ACPI_FIELD_QWORD_GRANULARITY: + + ACPI_MOVE_UNALIGNED64_TO_64 (&(((u64 *) buffer)[offset]), &merged_datum); + break; + + default: + /* Should not get here */ break; } } @@ -346,22 +663,23 @@ acpi_status status; u32 field_datum_byte_offset; u32 datum_offset; - u32 previous_raw_datum; - u32 this_raw_datum = 0; - u32 merged_datum = 0; + acpi_integer previous_raw_datum; + acpi_integer this_raw_datum = 0; + acpi_integer merged_datum = 0; u32 byte_field_length; u32 datum_count; - FUNCTION_TRACE ("Ex_extract_from_field"); + ACPI_FUNCTION_TRACE ("Ex_extract_from_field"); /* * The field must fit within the caller's buffer */ - byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); + byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); if (byte_field_length > buffer_length) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Field size %X (bytes) too large for buffer (%X)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field size %X (bytes) too large for buffer (%X)\n", byte_field_length, buffer_length)); return_ACPI_STATUS (AE_BUFFER_OVERFLOW); @@ -369,26 +687,27 @@ /* Convert field byte count to datum count, round up if necessary */ - datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + datum_count = ACPI_ROUND_UP_TO (byte_field_length, + obj_desc->common_field.access_byte_width); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Byte_len=%x, Datum_len=%x, Bit_gran=%x, Byte_gran=%x\n", - byte_field_length, datum_count, obj_desc->common_field.access_bit_width, - obj_desc->common_field.access_byte_width)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Byte_len=%X, Datum_len=%X, Byte_gran=%X\n", + byte_field_length, datum_count,obj_desc->common_field.access_byte_width)); /* * Clear the caller's buffer (the whole buffer length as given) * This is very important, especially in the cases where a byte is read, * but the buffer is really a u32 (4 bytes). */ - MEMSET (buffer, 0, buffer_length); + ACPI_MEMSET (buffer, 0, buffer_length); /* Read the first raw datum to prime the loop */ field_datum_byte_offset = 0; datum_offset= 0; - status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &previous_raw_datum); + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &previous_raw_datum, ACPI_READ); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -397,7 +716,7 @@ /* We might actually be done if the request fits in one datum */ if ((datum_count == 1) && - (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) { + (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) { /* 1) Shift the valid data bits down to start at bit 0 */ merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); @@ -405,7 +724,7 @@ /* 2) Mask off any upper unused bits (bits not part of the field) */ if (obj_desc->common_field.end_buffer_valid_bits) { - merged_datum &= MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); + merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); } /* Store the datum to the caller buffer */ @@ -427,17 +746,18 @@ * to perform a final read, since this would potentially read * past the end of the region. * - * TBD: [Investigate] It may make more sense to just split the aligned - * and non-aligned cases since the aligned case is so very simple, + * We could just split the aligned and non-aligned cases since the + * aligned case is so very simple, but this would require more code. */ - if ((obj_desc->common_field.start_field_bit_offset != 0) || + if ((obj_desc->common_field.start_field_bit_offset != 0) || ((obj_desc->common_field.start_field_bit_offset == 0) && (datum_offset < (datum_count -1)))) { /* * Get the next raw datum, it contains some or all bits * of the current field datum */ - status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &this_raw_datum); + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &this_raw_datum, ACPI_READ); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -451,7 +771,6 @@ merged_datum = previous_raw_datum; } - else { /* * Put together the appropriate bits of the two raw data to make a @@ -474,7 +793,7 @@ */ if (obj_desc->common_field.end_buffer_valid_bits) { merged_datum &= - MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); + ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); } } } @@ -483,8 +802,8 @@ * Store the merged field datum in the caller's buffer, according to * the granularity of the field (size of each datum). */ - acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width, - datum_offset); + acpi_ex_set_buffer_datum (merged_datum, buffer, + obj_desc->common_field.access_byte_width, datum_offset); /* * Save the raw datum that was just acquired since it may contain bits @@ -500,211 +819,6 @@ /******************************************************************************* * - * FUNCTION: Acpi_ex_write_field_datum - * - * PARAMETERS: *Obj_desc - Field to be set - * Value - Value to store - * - * RETURN: Status - * - * DESCRIPTION: Store the value into the given field - * - ******************************************************************************/ - -static acpi_status -acpi_ex_write_field_datum ( - acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - u32 value) -{ - acpi_status status = AE_OK; - acpi_operand_object *rgn_desc = NULL; - ACPI_PHYSICAL_ADDRESS address; - - - FUNCTION_TRACE_U32 ("Ex_write_field_datum", field_datum_byte_offset); - - - /* - * Buffer_fields - Read from a Buffer - * Other Fields - Read from a Operation Region. - */ - switch (obj_desc->common.type) { - case ACPI_TYPE_BUFFER_FIELD: - - /* - * For Buffer_fields, we only need to copy the data to the - * target buffer. Length is the field width in bytes. - */ - MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer - + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, - &value, obj_desc->common_field.access_byte_width); - status = AE_OK; - break; - - - case INTERNAL_TYPE_REGION_FIELD: - case INTERNAL_TYPE_BANK_FIELD: - - /* - * For other fields, we need to go through an Operation Region - * (Only types that will get here are Region_fields and Bank_fields) - */ - status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - /* - * The physical address of this field datum is: - * - * 1) The base of the region, plus - * 2) The base offset of the field, plus - * 3) The current offset into the field - */ - rgn_desc = obj_desc->common_field.region_obj; - address = rgn_desc->region.address + - obj_desc->common_field.base_byte_offset + - field_datum_byte_offset; - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Store %X in Region %s(%X) at %8.8X%8.8X width %X\n", - value, acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id, HIDWORD(address), LODWORD(address), - obj_desc->common_field.access_bit_width)); - - /* Invoke the appropriate Address_space/Op_region handler */ - - status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_WRITE_ADR_SPACE, - address, obj_desc->common_field.access_bit_width, &value); - - if (status == AE_NOT_IMPLEMENTED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Region type %s(%X) not implemented\n", - acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id)); - } - - else if (status == AE_NOT_EXIST) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Region type %s(%X) does not have a handler\n", - acpi_ut_get_region_name (rgn_desc->region.space_id), - rgn_desc->region.space_id)); - } - - break; - - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n", - obj_desc, acpi_ut_get_type_name (obj_desc->common.type))); - status = AE_AML_INTERNAL; - break; - } - - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value written=%08X \n", value)); - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_write_field_datum_with_update_rule - * - * PARAMETERS: *Obj_desc - Field to be set - * Value - Value to store - * - * RETURN: Status - * - * DESCRIPTION: Apply the field update rule to a field write - * - ******************************************************************************/ - -static acpi_status -acpi_ex_write_field_datum_with_update_rule ( - acpi_operand_object *obj_desc, - u32 mask, - u32 field_value, - u32 field_datum_byte_offset) -{ - acpi_status status = AE_OK; - u32 merged_value; - u32 current_value; - - - FUNCTION_TRACE ("Ex_write_field_datum_with_update_rule"); - - - /* Start with the new bits */ - - merged_value = field_value; - - /* If the mask is all ones, we don't need to worry about the update rule */ - - if (mask != ACPI_UINT32_MAX) { - /* Decode the update rule */ - - switch (obj_desc->common_field.update_rule) { - case UPDATE_PRESERVE: - /* - * Check if update rule needs to be applied (not if mask is all - * ones) The left shift drops the bits we want to ignore. - */ - if ((~mask << (sizeof (mask) * 8 - - obj_desc->common_field.access_bit_width)) != 0) { - /* - * Read the current contents of the byte/word/dword containing - * the field, and merge with the new field value. - */ - status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, - ¤t_value); - merged_value |= (current_value & ~mask); - } - break; - - - case UPDATE_WRITE_AS_ONES: - - /* Set positions outside the field to all ones */ - - merged_value |= ~mask; - break; - - - case UPDATE_WRITE_AS_ZEROS: - - /* Set positions outside the field to all zeros */ - - merged_value &= mask; - break; - - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Write_with_update_rule: Unknown Update_rule setting: %x\n", - obj_desc->common_field.update_rule)); - return_ACPI_STATUS (AE_AML_OPERAND_VALUE); - break; - } - } - - - /* Write the merged value */ - - status = acpi_ex_write_field_datum (obj_desc, field_datum_byte_offset, - merged_value); - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %X Datum_offset %X Value %X, Merged_value %X\n", - mask, field_datum_byte_offset, field_value, merged_value)); - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * * FUNCTION: Acpi_ex_insert_into_field * * PARAMETERS: *Obj_desc - Field to be set @@ -725,15 +839,15 @@ acpi_status status; u32 field_datum_byte_offset; u32 datum_offset; - u32 mask; - u32 merged_datum; - u32 previous_raw_datum; - u32 this_raw_datum; + acpi_integer mask; + acpi_integer merged_datum; + acpi_integer previous_raw_datum; + acpi_integer this_raw_datum; u32 byte_field_length; u32 datum_count; - FUNCTION_TRACE ("Ex_insert_into_field"); + ACPI_FUNCTION_TRACE ("Ex_insert_into_field"); /* @@ -742,24 +856,21 @@ * larger than the field, this typically happens when an integer is * written to a field that is actually smaller than an integer. */ - byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); + byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); if (buffer_length < byte_field_length) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer length %X too small for field %X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Buffer length %X too small for field %X\n", buffer_length, byte_field_length)); - /* TBD: Need a better error code */ - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); } /* Convert byte count to datum count, round up if necessary */ - datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + datum_count = ACPI_ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Byte_len=%x, Datum_len=%x, Bit_gran=%x, Byte_gran=%x\n", - byte_field_length, datum_count, obj_desc->common_field.access_bit_width, - obj_desc->common_field.access_byte_width)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Byte_len=%X, Datum_len=%X, Byte_gran=%X\n", + byte_field_length, datum_count, obj_desc->common_field.access_byte_width)); /* * Break the request into up to three parts (similar to an I/O request): @@ -785,15 +896,15 @@ * * Mask off bits that are "below" the field (if any) */ - mask = MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset); + mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset); /* If the field fits in one datum, may need to mask upper bits */ - if ((obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM) && + if ((obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM) && obj_desc->common_field.end_field_valid_bits) { /* There are bits above the field, mask them off also */ - mask &= MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); + mask &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); } /* Shift and mask the value into the field position */ @@ -803,7 +914,7 @@ /* Apply the update rule (if necessary) and write the datum to the field */ - status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, merged_datum, + status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_datum_byte_offset); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -812,7 +923,7 @@ /* If the entire field fits within one datum, we are done. */ if ((datum_count == 1) && - (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) { + (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) { return_ACPI_STATUS (AE_OK); } @@ -849,7 +960,6 @@ (previous_raw_datum >> obj_desc->common_field.datum_valid_bits) | (this_raw_datum << obj_desc->common_field.start_field_bit_offset); } - else { /* Field began aligned on datum boundary */ @@ -874,24 +984,23 @@ * * Mask off the unused bits above (after) the end-of-field */ - mask = MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); + mask = ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); merged_datum &= mask; /* Write the last datum with the update rule */ - status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, - merged_datum, field_datum_byte_offset); + status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, + field_datum_byte_offset); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } } - else { /* Normal case -- write the completed datum */ - status = acpi_ex_write_field_datum (obj_desc, - field_datum_byte_offset, merged_datum); + status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, + &merged_datum, ACPI_WRITE); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exmisc.c linux2.4.21_itanium/drivers/acpi/executer/exmisc.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exmisc.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exmisc.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,14 +26,13 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acdispat.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exmisc") + ACPI_MODULE_NAME ("exmisc") /******************************************************************************* @@ -59,10 +58,12 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc); - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { + case ACPI_DESC_TYPE_OPERAND: + if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { *return_desc = NULL; status = AE_TYPE; @@ -77,8 +78,9 @@ case AML_LOCAL_OP: case AML_ARG_OP: - *return_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode, - obj_desc->reference.offset, walk_state); + status = acpi_ds_method_data_get_node (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state, + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, return_desc)); break; default: @@ -89,18 +91,22 @@ status = AE_AML_INTERNAL; goto cleanup; } + break; - } - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + case ACPI_DESC_TYPE_NAMED: + /* Must be a named object; Just return the Node */ *return_desc = obj_desc; - } + break; + + + default: - else { *return_desc = NULL; status = AE_TYPE; + break; } @@ -113,7 +119,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ex_do_concatenate + * FUNCTION: Acpi_ex_concat_template * * PARAMETERS: *Obj_desc - Object to be converted. Must be an * Integer, Buffer, or String @@ -121,13 +127,106 @@ * * RETURN: Status * + * DESCRIPTION: Concatenate two resource templates + * + ******************************************************************************/ + +acpi_status +acpi_ex_concat_template ( + acpi_operand_object *obj_desc1, + acpi_operand_object *obj_desc2, + acpi_operand_object **actual_return_desc, + acpi_walk_state *walk_state) +{ + acpi_status status; + acpi_operand_object *return_desc; + NATIVE_CHAR *new_buf; + u8 *end_tag1; + u8 *end_tag2; + ACPI_SIZE length1; + ACPI_SIZE length2; + + + ACPI_FUNCTION_TRACE ("Ex_concat_template"); + + + /* Find the End_tags in each resource template */ + + end_tag1 = acpi_ut_get_resource_end_tag (obj_desc1); + end_tag2 = acpi_ut_get_resource_end_tag (obj_desc2); + if (!end_tag1 || !end_tag2) { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Create a new buffer object for the result */ + + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!return_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Allocate a new buffer for the result */ + + length1 = ACPI_PTR_DIFF (end_tag1, obj_desc1->buffer.pointer); + length2 = ACPI_PTR_DIFF (end_tag2, obj_desc2->buffer.pointer) + + 2; /* Size of END_TAG */ + + new_buf = ACPI_MEM_ALLOCATE (length1 + length2); + if (!new_buf) { + ACPI_REPORT_ERROR + (("Ex_concat_template: Buffer allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Copy the templates to the new descriptor */ + + ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, length1); + ACPI_MEMCPY (new_buf + length1, obj_desc2->buffer.pointer, length2); + + /* Complete the buffer object initialization */ + + return_desc->common.flags = AOPOBJ_DATA_VALID; + return_desc->buffer.pointer = (u8 *) new_buf; + return_desc->buffer.length = (u32) (length1 + length2); + + /* Compute the new checksum */ + + new_buf[return_desc->buffer.length - 1] = (NATIVE_CHAR) + acpi_ut_generate_checksum (return_desc->buffer.pointer, + (return_desc->buffer.length - 1)); + + /* Return the completed template descriptor */ + + *actual_return_desc = return_desc; + return_ACPI_STATUS (AE_OK); + + +cleanup: + + acpi_ut_remove_reference (return_desc); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_do_concatenate + * + * PARAMETERS: Obj_desc1 - First source object + * Obj_desc2 - Second source object + * Actual_return_desc - Where to place the return object + * Walk_state - Current walk state + * + * RETURN: Status + * * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. * ******************************************************************************/ acpi_status acpi_ex_do_concatenate ( - acpi_operand_object *obj_desc, + acpi_operand_object *obj_desc1, acpi_operand_object *obj_desc2, acpi_operand_object **actual_return_desc, acpi_walk_state *walk_state) @@ -137,73 +236,66 @@ acpi_integer this_integer; acpi_operand_object *return_desc; NATIVE_CHAR *new_buf; - u32 integer_size = sizeof (acpi_integer); - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* * There are three cases to handle: - * 1) Two Integers concatenated to produce a buffer - * 2) Two Strings concatenated to produce a string - * 3) Two Buffers concatenated to produce a buffer + * + * 1) Two Integers concatenated to produce a new Buffer + * 2) Two Strings concatenated to produce a new String + * 3) Two Buffers concatenated to produce a new Buffer */ - switch (obj_desc->common.type) { + switch (obj_desc1->common.type) { case ACPI_TYPE_INTEGER: - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper - * 32-bit field - */ - integer_size = sizeof (u32); - } - - /* Result of two integers is a buffer */ + /* Result of two Integers is a Buffer */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!return_desc) { return (AE_NO_MEMORY); } - /* Need enough space for two integers */ + /* Need enough buffer space for two integers */ - return_desc->buffer.length = integer_size * 2; + return_desc->buffer.length = acpi_gbl_integer_byte_width * 2; new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_do_concatenate: Buffer allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } - return_desc->buffer.pointer = (u8 *) new_buf; - /* Convert the first integer */ - this_integer = obj_desc->integer.value; - for (i = 0; i < integer_size; i++) { - new_buf[i] = (u8) this_integer; + this_integer = obj_desc1->integer.value; + for (i = 0; i < acpi_gbl_integer_byte_width; i++) { + new_buf[i] = (NATIVE_CHAR) this_integer; this_integer >>= 8; } /* Convert the second integer */ this_integer = obj_desc2->integer.value; - for (; i < (integer_size * 2); i++) { - new_buf[i] = (u8) this_integer; + for (; i < (ACPI_MUL_2 (acpi_gbl_integer_byte_width)); i++) { + new_buf[i] = (NATIVE_CHAR) this_integer; this_integer >>= 8; } + /* Complete the buffer object initialization */ + + return_desc->common.flags = AOPOBJ_DATA_VALID; + return_desc->buffer.pointer = (u8 *) new_buf; break; case ACPI_TYPE_STRING: + /* Result of two Strings is a String */ + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); if (!return_desc) { return (AE_NO_MEMORY); @@ -211,66 +303,71 @@ /* Operand0 is string */ - new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length + - obj_desc2->string.length + 1); + new_buf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) obj_desc1->string.length + + (ACPI_SIZE) obj_desc2->string.length + 1); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_do_concatenate: String allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } - STRCPY (new_buf, obj_desc->string.pointer); - STRCPY (new_buf + obj_desc->string.length, + /* Concatenate the strings */ + + ACPI_STRCPY (new_buf, obj_desc1->string.pointer); + ACPI_STRCPY (new_buf + obj_desc1->string.length, obj_desc2->string.pointer); - /* Point the return object to the new string */ + /* Complete the String object initialization */ return_desc->string.pointer = new_buf; - return_desc->string.length = obj_desc->string.length += - obj_desc2->string.length; + return_desc->string.length = obj_desc1->string.length + + obj_desc2->string.length; break; case ACPI_TYPE_BUFFER: - /* Operand0 is a buffer */ + /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!return_desc) { return (AE_NO_MEMORY); } - new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length + - obj_desc2->buffer.length); + new_buf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) obj_desc1->buffer.length + + (ACPI_SIZE) obj_desc2->buffer.length); if (!new_buf) { - REPORT_ERROR + ACPI_REPORT_ERROR (("Ex_do_concatenate: Buffer allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } - MEMCPY (new_buf, obj_desc->buffer.pointer, - obj_desc->buffer.length); - MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, + /* Concatenate the buffers */ + + ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, + obj_desc1->buffer.length); + ACPI_MEMCPY (new_buf + obj_desc1->buffer.length, obj_desc2->buffer.pointer, obj_desc2->buffer.length); - /* - * Point the return object to the new buffer - */ + /* Complete the buffer object initialization */ - return_desc->buffer.pointer = (u8 *) new_buf; - return_desc->buffer.length = obj_desc->buffer.length + - obj_desc2->buffer.length; + return_desc->common.flags = AOPOBJ_DATA_VALID; + return_desc->buffer.pointer = (u8 *) new_buf; + return_desc->buffer.length = obj_desc1->buffer.length + + obj_desc2->buffer.length; break; default: + + /* Invalid object type, should not happen here */ + status = AE_AML_INTERNAL; return_desc = NULL; } - *actual_return_desc = return_desc; return (AE_OK); @@ -288,7 +385,7 @@ * * PARAMETERS: Opcode - AML opcode * Operand0 - Integer operand #0 - * Operand0 - Integer operand #1 + * Operand1 - Integer operand #1 * * RETURN: Integer result of the operation * @@ -369,7 +466,7 @@ * * PARAMETERS: Opcode - AML opcode * Operand0 - Integer operand #0 - * Operand0 - Integer operand #1 + * Operand1 - Integer operand #1 * * RETURN: TRUE/FALSE result of the operation * @@ -432,6 +529,9 @@ return (TRUE); } break; + + default: + break; } return (FALSE); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exmutex.c linux2.4.21_itanium/drivers/acpi/executer/exmutex.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exmutex.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exmutex.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,12 +27,9 @@ #include "acpi.h" #include "acinterp.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exmutex") + ACPI_MODULE_NAME ("exmutex") /******************************************************************************* @@ -51,13 +48,23 @@ acpi_ex_unlink_mutex ( acpi_operand_object *obj_desc) { + ACPI_THREAD_STATE *thread = obj_desc->mutex.owner_thread; + + + if (!thread) { + return; + } if (obj_desc->mutex.next) { (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; } + if (obj_desc->mutex.prev) { (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; } + else { + thread->acquired_mutex_list = obj_desc->mutex.next; + } } @@ -77,23 +84,27 @@ void acpi_ex_link_mutex ( acpi_operand_object *obj_desc, - acpi_operand_object *list_head) + ACPI_THREAD_STATE *thread) { + acpi_operand_object *list_head; + + + list_head = thread->acquired_mutex_list; /* This object will be the first object in the list */ - obj_desc->mutex.prev = list_head; - obj_desc->mutex.next = list_head->mutex.next; + obj_desc->mutex.prev = NULL; + obj_desc->mutex.next = list_head; /* Update old first object to point back to this object */ - if (list_head->mutex.next) { - (list_head->mutex.next)->mutex.prev = obj_desc; + if (list_head) { + list_head->mutex.prev = obj_desc; } /* Update list head */ - list_head->mutex.next = obj_desc; + thread->acquired_mutex_list = obj_desc; } @@ -119,7 +130,7 @@ acpi_status status; - FUNCTION_TRACE_PTR ("Ex_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_acquire_mutex", obj_desc); if (!obj_desc) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -129,15 +140,18 @@ * Current Sync must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ - if (walk_state->current_sync_level > obj_desc->mutex.sync_level) { + if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } /* - * If the mutex is already owned by this thread, - * just increment the acquisition depth + * Support for multiple acquires by the owning thread */ - if (obj_desc->mutex.owner == walk_state) { + if (obj_desc->mutex.owner_thread == walk_state->thread) { + /* + * The mutex is already owned by this thread, + * just increment the acquisition depth + */ obj_desc->mutex.acquisition_depth++; return_ACPI_STATUS (AE_OK); } @@ -153,14 +167,14 @@ /* Have the mutex, update mutex and walk info */ - obj_desc->mutex.owner = walk_state; + obj_desc->mutex.owner_thread = walk_state->thread; obj_desc->mutex.acquisition_depth = 1; - walk_state->current_sync_level = obj_desc->mutex.sync_level; - /* Link the mutex to the walk state for force-unlock at method exit */ + walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + + /* Link the mutex to the current thread for force-unlock at method exit */ - acpi_ex_link_mutex (obj_desc, (acpi_operand_object *) - &(walk_state->walk_list->acquired_mutex_list)); + acpi_ex_link_mutex (obj_desc, walk_state->thread); return_ACPI_STATUS (AE_OK); } @@ -186,7 +200,7 @@ acpi_status status; - FUNCTION_TRACE ("Ex_release_mutex"); + ACPI_FUNCTION_TRACE ("Ex_release_mutex"); if (!obj_desc) { @@ -195,13 +209,13 @@ /* The mutex must have been previously acquired in order to release it */ - if (!obj_desc->mutex.owner) { + if (!obj_desc->mutex.owner_thread) { return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); } /* The Mutex is owned, but this thread must be the owner */ - if (obj_desc->mutex.owner != walk_state) { + if (obj_desc->mutex.owner_thread != walk_state->thread) { return_ACPI_STATUS (AE_AML_NOT_OWNER); } @@ -209,7 +223,7 @@ * The sync level of the mutex must be less than or * equal to the current sync level */ - if (obj_desc->mutex.sync_level > walk_state->current_sync_level) { + if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } @@ -223,6 +237,9 @@ return_ACPI_STATUS (AE_OK); } + /* Unlink the mutex from the owner's list */ + + acpi_ex_unlink_mutex (obj_desc); /* Release the mutex */ @@ -230,12 +247,8 @@ /* Update the mutex and walk state */ - obj_desc->mutex.owner = NULL; - walk_state->current_sync_level = obj_desc->mutex.sync_level; - - /* Unlink the mutex from the owner's list */ - - acpi_ex_unlink_mutex (obj_desc); + obj_desc->mutex.owner_thread = NULL; + walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; return_ACPI_STATUS (status); } @@ -253,15 +266,16 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_release_all_mutexes ( - acpi_operand_object *list_head) + ACPI_THREAD_STATE *thread) { - acpi_operand_object *next = list_head->mutex.next; + acpi_operand_object *next = thread->acquired_mutex_list; acpi_operand_object *this; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* @@ -271,19 +285,21 @@ this = next; next = this->mutex.next; - /* Mark mutex un-owned */ - - this->mutex.owner = NULL; - this->mutex.prev = NULL; - this->mutex.next = NULL; - this->mutex.acquisition_depth = 0; + this->mutex.acquisition_depth = 1; + this->mutex.prev = NULL; + this->mutex.next = NULL; /* Release the mutex */ - acpi_ex_system_release_mutex (this); - } + status = acpi_ex_system_release_mutex (this); + if (ACPI_FAILURE (status)) { + continue; + } - return (AE_OK); + /* Mark mutex unowned */ + + this->mutex.owner_thread = NULL; + } } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exnames.c linux2.4.21_itanium/drivers/acpi/executer/exnames.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exnames.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exnames.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,10 +28,9 @@ #include "acpi.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exnames") + ACPI_MODULE_NAME ("exnames") /* AML Package Length encodings */ @@ -67,7 +66,7 @@ NATIVE_CHAR *name_string; u32 size_needed; - FUNCTION_TRACE ("Ex_allocate_name_string"); + ACPI_FUNCTION_TRACE ("Ex_allocate_name_string"); /* @@ -75,7 +74,7 @@ * Also, one byte for the null terminator. * This may actually be somewhat longer than needed. */ - if (prefix_count == (u32) -1) { + if (prefix_count == ACPI_UINT32_MAX) { /* Special case for root */ size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; @@ -90,7 +89,7 @@ */ name_string = ACPI_MEM_ALLOCATE (size_needed); if (!name_string) { - REPORT_ERROR (("Ex_allocate_name_string: Could not allocate size %d\n", size_needed)); + ACPI_REPORT_ERROR (("Ex_allocate_name_string: Could not allocate size %d\n", size_needed)); return_PTR (NULL); } @@ -98,10 +97,9 @@ /* Set up Root or Parent prefixes if needed */ - if (prefix_count == (u32) -1) { + if (prefix_count == ACPI_UINT32_MAX) { *temp_ptr++ = AML_ROOT_PREFIX; } - else { while (prefix_count--) { *temp_ptr++ = AML_PARENT_PREFIX; @@ -117,7 +115,6 @@ *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; *temp_ptr++ = (char) num_name_segs; } - else if (2 == num_name_segs) { /* Set up dual prefixes */ @@ -150,13 +147,13 @@ u8 **in_aml_address, NATIVE_CHAR *name_string) { - u8 *aml_address = *in_aml_address; + char *aml_address = (void *) *in_aml_address; acpi_status status = AE_OK; u32 index; - NATIVE_CHAR char_buf[5]; + char char_buf[5]; - FUNCTION_TRACE ("Ex_name_segment"); + ACPI_FUNCTION_TRACE ("Ex_name_segment"); /* @@ -172,34 +169,32 @@ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 4; - (index > 0) && (acpi_ut_valid_acpi_character (*aml_address)); - --index) { - char_buf[4 - index] = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[4 - index])); + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address)); + index++) { + char_buf[index] = *aml_address++; + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index])); } /* Valid name segment */ - if (0 == index) { + if (index == 4) { /* Found 4 valid characters */ char_buf[4] = '\0'; if (name_string) { - STRCAT (name_string, char_buf); + ACPI_STRCAT (name_string, char_buf); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Appended to - %s \n", name_string)); } - else { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "No Name string - %s \n", char_buf)); } } - - else if (4 == index) { + else if (index == 0) { /* * First character was not a valid name character, * so we are looking at something other than a name. @@ -209,7 +204,6 @@ char_buf[0])); status = AE_CTRL_PENDING; } - else { /* Segment started with one or more valid characters, but fewer than 4 */ @@ -218,7 +212,7 @@ *aml_address, aml_address)); } - *in_aml_address = aml_address; + *in_aml_address = (u8 *) aml_address; return_ACPI_STATUS (status); } @@ -235,10 +229,9 @@ * ******************************************************************************/ - acpi_status acpi_ex_get_name_string ( - acpi_object_type8 data_type, + acpi_object_type data_type, u8 *in_aml_address, NATIVE_CHAR **out_name_string, u32 *out_name_length) @@ -248,11 +241,10 @@ NATIVE_CHAR *name_string = NULL; u32 num_segments; u32 prefix_count = 0; - u8 prefix = 0; u8 has_prefix = FALSE; - FUNCTION_TRACE_PTR ("Ex_get_name_string", aml_address); + ACPI_FUNCTION_TRACE_PTR ("Ex_get_name_string", aml_address); if (INTERNAL_TYPE_REGION_FIELD == data_type || @@ -268,24 +260,22 @@ status = acpi_ex_name_segment (&aml_address, name_string); } } - else { /* * Data_type is not a field name. * Examine first character of name for root or parent prefix operators */ switch (*aml_address) { - case AML_ROOT_PREFIX: - prefix = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Root_prefix: %x\n", prefix)); + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Root_prefix(\\) at %p\n", aml_address)); /* * Remember that we have a Root_prefix -- * see comment in Acpi_ex_allocate_name_string() */ - prefix_count = (u32) -1; + aml_address++; + prefix_count = ACPI_UINT32_MAX; has_prefix = TRUE; break; @@ -295,18 +285,21 @@ /* Increment past possibly multiple parent prefixes */ do { - prefix = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Parent_prefix: %x\n", prefix)); + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Parent_prefix (^) at %p\n", aml_address)); - ++prefix_count; + aml_address++; + prefix_count++; } while (*aml_address == AML_PARENT_PREFIX); + has_prefix = TRUE; break; default: + /* Not a prefix character */ + break; } @@ -314,12 +307,11 @@ /* Examine first character of name for name segment prefix operator */ switch (*aml_address) { - case AML_DUAL_NAME_PREFIX: - prefix = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Dual_name_prefix: %x\n", prefix)); + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Dual_name_prefix at %p\n", aml_address)); + aml_address++; name_string = acpi_ex_allocate_name_string (prefix_count, 2); if (!name_string) { status = AE_NO_MEMORY; @@ -339,12 +331,12 @@ case AML_MULTI_NAME_PREFIX_OP: - prefix = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Multi_name_prefix: %x\n", prefix)); + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Multi_name_prefix at %p\n", aml_address)); /* Fetch count of segments remaining in name path */ - num_segments = *aml_address++; + aml_address++; + num_segments = *aml_address; name_string = acpi_ex_allocate_name_string (prefix_count, num_segments); if (!name_string) { @@ -354,11 +346,12 @@ /* Indicate that we processed a prefix */ + aml_address++; has_prefix = TRUE; while (num_segments && (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) { - --num_segments; + num_segments--; } break; @@ -368,7 +361,7 @@ /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */ - if (-1 == prefix_count) { + if (prefix_count == ACPI_UINT32_MAX) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Name_seg is \"\\\" followed by NULL\n")); } @@ -396,20 +389,17 @@ status = acpi_ex_name_segment (&aml_address, name_string); break; - - } /* Switch (Peek_op ()) */ + } } - if (AE_CTRL_PENDING == status && has_prefix) { /* Ran out of segments after processing a prefix */ - REPORT_ERROR ( + ACPI_REPORT_ERROR ( ("Ex_do_name: Malformed Name at %p\n", name_string)); status = AE_AML_BAD_NAME; } - *out_name_string = name_string; *out_name_length = (u32) (aml_address - in_aml_address); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exoparg1.c linux2.4.21_itanium/drivers/acpi/executer/exoparg1.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exoparg1.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exoparg1.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -34,7 +34,7 @@ #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exoparg1") + ACPI_MODULE_NAME ("exoparg1") /*! @@ -81,10 +81,10 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_STR ("Ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); - /* Examine the opcode */ + /* Examine the AML opcode */ switch (walk_state->opcode) { case AML_RELEASE_OP: /* Release (Mutex_object) */ @@ -107,13 +107,13 @@ case AML_SLEEP_OP: /* Sleep (Msec_time) */ - acpi_ex_system_do_suspend ((u32) operand[0]->integer.value); + status = acpi_ex_system_do_suspend ((u32) operand[0]->integer.value); break; case AML_STALL_OP: /* Stall (Usec_time) */ - acpi_ex_system_do_stall ((u32) operand[0]->integer.value); + status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value); break; @@ -125,7 +125,7 @@ default: /* Unknown opcode */ - REPORT_ERROR (("Acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; break; @@ -156,19 +156,20 @@ acpi_operand_object **operand = &walk_state->operands[0]; - FUNCTION_TRACE_STR ("Ex_opcode_1A_1T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_1A_1T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); - switch (walk_state->opcode) { + /* Examine the AML opcode */ + switch (walk_state->opcode) { case AML_LOAD_OP: - status = acpi_ex_load_op (operand[0], operand[1]); + status = acpi_ex_load_op (operand[0], operand[1], walk_state); break; default: /* Unknown opcode */ - REPORT_ERROR (("Acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; @@ -208,10 +209,10 @@ acpi_integer digit; - FUNCTION_TRACE_STR ("Ex_opcode_1A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_1A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); - /* Create a return object of type Integer for most opcodes */ + /* Examine the AML opcode */ switch (walk_state->opcode) { case AML_BIT_NOT_OP: @@ -221,156 +222,158 @@ case AML_TO_BCD_OP: case AML_COND_REF_OF_OP: + /* Create a return object of type Integer for these opcodes */ + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } - break; - } + switch (walk_state->opcode) { + case AML_BIT_NOT_OP: /* Not (Operand, Result) */ + return_desc->integer.value = ~operand[0]->integer.value; + break; - switch (walk_state->opcode) { - case AML_BIT_NOT_OP: /* Not (Operand, Result) */ + case AML_FIND_SET_LEFT_BIT_OP: /* Find_set_left_bit (Operand, Result) */ - return_desc->integer.value = ~operand[0]->integer.value; - break; + return_desc->integer.value = operand[0]->integer.value; + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value >>= 1; + } - case AML_FIND_SET_LEFT_BIT_OP: /* Find_set_left_bit (Operand, Result) */ + return_desc->integer.value = temp32; + break; - return_desc->integer.value = operand[0]->integer.value; + case AML_FIND_SET_RIGHT_BIT_OP: /* Find_set_right_bit (Operand, Result) */ - /* - * Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value >>= 1; - } + return_desc->integer.value = operand[0]->integer.value; - return_desc->integer.value = temp32; - break; + /* + * The Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value <<= 1; + } + /* Since the bit position is one-based, subtract from 33 (65) */ - case AML_FIND_SET_RIGHT_BIT_OP: /* Find_set_right_bit (Operand, Result) */ + return_desc->integer.value = temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + break; - return_desc->integer.value = operand[0]->integer.value; + case AML_FROM_BCD_OP: /* From_bcd (BCDValue, Result) */ - /* - * The Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value <<= 1; - } + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD integers + */ + return_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Get one BCD digit */ - /* Since the bit position is one-based, subtract from 33 (65) */ + digit = (acpi_integer) ((operand[0]->integer.value >> (i * 4)) & 0xF); - return_desc->integer.value = temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; - break; + /* Check the range of the digit */ + + if (digit > 9) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", + (u32) digit)); + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + if (digit > 0) { + /* Sum into the result with the appropriate power of 10 */ - case AML_FROM_BCD_OP: /* From_bcd (BCDValue, Result) */ + for (j = 0; j < i; j++) { + digit *= 10; + } - /* - * The 64-bit ACPI integer can hold 16 4-bit BCD integers - */ - return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Get one BCD digit */ + return_desc->integer.value += digit; + } + } + break; - digit = (acpi_integer) ((operand[0]->integer.value >> (i * 4)) & 0xF); - /* Check the range of the digit */ + case AML_TO_BCD_OP: /* To_bcd (Operand, Result) */ - if (digit > 9) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", - (u32) digit)); + if (operand[0]->integer.value > ACPI_MAX_BCD_VALUE) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", + ACPI_HIDWORD(operand[0]->integer.value), + ACPI_LODWORD(operand[0]->integer.value))); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } - if (digit > 0) { - /* Sum into the result with the appropriate power of 10 */ + return_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Divide by nth factor of 10 */ + temp32 = 0; + digit = operand[0]->integer.value; for (j = 0; j < i; j++) { - digit *= 10; + (void) acpi_ut_short_divide (&digit, 10, &digit, &temp32); } - return_desc->integer.value += digit; - } - } - break; + /* Create the BCD digit from the remainder above */ + if (digit > 0) { + return_desc->integer.value += ((acpi_integer) temp32 << (i * 4)); + } + } + break; - case AML_TO_BCD_OP: /* To_bcd (Operand, Result) */ - if (operand[0]->integer.value > ACPI_MAX_BCD_VALUE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", - HIDWORD(operand[0]->integer.value), LODWORD(operand[0]->integer.value))); - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } + case AML_COND_REF_OF_OP: /* Cond_ref_of (Source_object, Result) */ - return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Divide by nth factor of 10 */ + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + if ((acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + return_desc->integer.value = 0; - temp32 = 0; - digit = operand[0]->integer.value; - for (j = 0; j < i; j++) { - acpi_ut_short_divide (&digit, 10, &digit, &temp32); + /* + * Must delete the result descriptor since there is no reference + * being returned + */ + acpi_ut_remove_reference (operand[1]); + goto cleanup; } - /* Create the BCD digit from the remainder above */ + /* Get the object reference and store it */ - if (digit > 0) { - return_desc->integer.value += (temp32 << (i * 4)); + status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; } - } - break; - - case AML_COND_REF_OF_OP: /* Cond_ref_of (Source_object, Result) */ + status = acpi_ex_store (return_desc2, operand[1], walk_state); - /* - * This op is a little strange because the internal return value is - * different than the return value stored in the result descriptor - * (There are really two return values) - */ - if ((acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { - /* - * This means that the object does not exist in the namespace, - * return FALSE - */ - return_desc->integer.value = 0; + /* The object exists in the namespace, return TRUE */ - /* - * Must delete the result descriptor since there is no reference - * being returned - */ - acpi_ut_remove_reference (operand[1]); + return_desc->integer.value = ACPI_INTEGER_MAX; goto cleanup; - } - /* Get the object reference and store it */ - status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; + default: + /* No other opcodes get here */ + break; } - - status = acpi_ex_store (return_desc2, operand[1], walk_state); - - /* The object exists in the namespace, return TRUE */ - - return_desc->integer.value = ACPI_INTEGER_MAX; - goto cleanup; break; @@ -395,7 +398,6 @@ walk_state->result_obj = operand[0]; walk_state->operands[0] = NULL; /* Prevent deletion */ return_ACPI_STATUS (status); - break; /* @@ -403,8 +405,7 @@ */ case AML_COPY_OP: /* Copy (Source, Target) */ - status = AE_NOT_IMPLEMENTED; - goto cleanup; + status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc, walk_state); break; @@ -432,29 +433,26 @@ break; - /* - * These are two obsolete opcodes - */ case AML_SHIFT_LEFT_BIT_OP: /* Shift_left_bit (Source, Bit_num) */ case AML_SHIFT_RIGHT_BIT_OP: /* Shift_right_bit (Source, Bit_num) */ - + /* + * These are two obsolete opcodes + */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s is obsolete and not implemented\n", acpi_ps_get_opcode_name (walk_state->opcode))); status = AE_SUPPORT; goto cleanup; - break; default: /* Unknown opcode */ - REPORT_ERROR (("Acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } - /* * Store the return value computed above into the target object */ @@ -499,13 +497,12 @@ acpi_integer value; - FUNCTION_TRACE_STR ("Ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_1A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); - /* Get the operand and decode the opcode */ + /* Examine the AML opcode */ switch (walk_state->opcode) { - case AML_LNOT_OP: /* LNot (Operand) */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); @@ -523,10 +520,10 @@ /* * Since we are expecting a Reference operand, it - * can be either a Node or an internal object. + * can be either a NS Node or an internal object. */ return_desc = operand[0]; - if (VALID_DESCRIPTOR_TYPE (operand[0], ACPI_DESC_TYPE_INTERNAL)) { + if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_OPERAND) { /* Internal reference object - prevent deletion */ acpi_ut_add_reference (return_desc); @@ -582,7 +579,7 @@ case AML_DEBUG_OP: - /* Per 1.0b spec, Debug object is of type "Debug_object" */ + /* The Debug Object is of type "Debug_object" */ type = ACPI_TYPE_DEBUG_OBJECT; break; @@ -601,7 +598,6 @@ */ type = (*(operand[0]->reference.where))->common.type; } - break; @@ -615,13 +611,12 @@ default: - REPORT_ERROR (("Acpi_ex_opcode_1A_0T_1R/Type_op: Internal error - Unknown Reference subtype %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_1A_0T_1R/Type_op: Internal error - Unknown Reference subtype %X\n", operand[0]->reference.opcode)); status = AE_AML_INTERNAL; goto cleanup; } } - else { /* * It's not a Reference, so it must be a direct name pointer. @@ -636,6 +631,11 @@ case INTERNAL_TYPE_INDEX_FIELD: type = ACPI_TYPE_FIELD_UNIT; + break; + + default: + /* No change to Type required */ + break; } } @@ -655,15 +655,19 @@ case AML_SIZE_OF_OP: /* Size_of (Source_object) */ temp_desc = operand[0]; - if (VALID_DESCRIPTOR_TYPE (operand[0], ACPI_DESC_TYPE_NAMED)) { + if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) { temp_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) operand[0]); } if (!temp_desc) { value = 0; } - else { + /* + * Type is guaranteed to be a buffer, string, or package at this + * point (even if the original operand was an object reference, it + * will be resolved and typechecked during operand resolution.) + */ switch (temp_desc->common.type) { case ACPI_TYPE_BUFFER: value = temp_desc->buffer.length; @@ -677,16 +681,9 @@ value = temp_desc->package.count; break; - case INTERNAL_TYPE_REFERENCE: - - /* TBD: this must be a reference to a buf/str/pkg?? */ - - value = 4; - break; - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Not Buf/Str/Pkg - found type %X\n", - temp_desc->common.type)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Size_of, Not Buf/Str/Pkg - found type %s\n", + acpi_ut_get_type_name (temp_desc->common.type))); status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -715,79 +712,113 @@ break; - case AML_DEREF_OF_OP: /* Deref_of (Obj_reference) */ + case AML_DEREF_OF_OP: /* Deref_of (Obj_reference | String) */ - /* Check for a method local or argument */ + /* Check for a method local or argument, or standalone String */ - if (!VALID_DESCRIPTOR_TYPE (operand[0], ACPI_DESC_TYPE_NAMED)) { - /* - * Must resolve/dereference the local/arg reference first - */ - switch (operand[0]->reference.opcode) { - /* Set Operand[0] to the value of the local/arg */ + if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) { + switch (ACPI_GET_OBJECT_TYPE (operand[0])) { + case INTERNAL_TYPE_REFERENCE: + /* + * This is a Deref_of (Local_x | Arg_x) + * + * Must resolve/dereference the local/arg reference first + */ + switch (operand[0]->reference.opcode) { + case AML_LOCAL_OP: + case AML_ARG_OP: + + /* Set Operand[0] to the value of the local/arg */ + + status = acpi_ds_method_data_get_value (operand[0]->reference.opcode, + operand[0]->reference.offset, walk_state, &temp_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } - case AML_LOCAL_OP: - case AML_ARG_OP: + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_ut_remove_reference (operand[0]); + operand[0] = temp_desc; + break; - acpi_ds_method_data_get_value (operand[0]->reference.opcode, - operand[0]->reference.offset, walk_state, &temp_desc); + default: + + /* Must be an Index op - handled below */ + break; + } + break; + + + case ACPI_TYPE_STRING: /* - * Delete our reference to the input object and - * point to the object just retrieved + * This is a Deref_of (String). The string is a reference to a named ACPI object. + * + * 1) Find the owning Node + * 2) Dereference the node to an actual object. Could be a Field, so we nee + * to resolve the node to a value. */ - acpi_ut_remove_reference (operand[0]); - operand[0] = temp_desc; - break; + status = acpi_ns_get_node_by_path (operand[0]->string.pointer, + walk_state->scope_info->scope.node, ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &return_desc)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_ex_resolve_node_to_value ( + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &return_desc), walk_state); + goto cleanup; + default: - /* Index op - handled below */ - break; + status = AE_AML_OPERAND_TYPE; + goto cleanup; } } - /* Operand[0] may have changed from the code above */ - if (VALID_DESCRIPTOR_TYPE (operand[0], ACPI_DESC_TYPE_NAMED)) { - /* Get the actual object from the Node (This is the dereference) */ - - return_desc = ((acpi_namespace_node *) operand[0])->object; - - /* Returning a pointer to the object, add another reference! */ - - acpi_ut_add_reference (return_desc); + if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) { + /* + * This is a Deref_of (Object_reference) + * Get the actual object from the Node (This is the dereference). + * -- This case may only happen when a Local_x or Arg_x is dereferenced above. + */ + return_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) operand[0]); } - else { /* - * This must be a reference object produced by the Index - * ASL operation -- check internal opcode + * This must be a reference object produced by either the Index() or + * Ref_of() operator */ - if ((operand[0]->reference.opcode != AML_INDEX_OP) && - (operand[0]->reference.opcode != AML_REF_OF_OP)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode in ref(%p) - %X\n", - operand[0], operand[0]->reference.opcode)); - - status = AE_TYPE; - goto cleanup; - } - - switch (operand[0]->reference.opcode) { case AML_INDEX_OP: /* - * Supported target types for the Index operator are - * 1) A Buffer - * 2) A Package + * The target type for the Index operator must be + * either a Buffer or a Package */ - if (operand[0]->reference.target_type == ACPI_TYPE_BUFFER_FIELD) { + 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 + /* - * The target is a buffer, we must create a new object that - * contains one element of the buffer, the element pointed - * to by the index. + * Create a new object that contains one element of the + * buffer -- the element pointed to by the index. * * NOTE: index into a buffer is NOT a pointer to a * sub-buffer of the main buffer, it is only a pointer to a @@ -799,20 +830,29 @@ goto cleanup; } - temp_desc = operand[0]->reference.object; + /* + * Since we are returning the value of the buffer at the + * indexed location, we don't need to add an additional + * reference to the buffer itself. + */ return_desc->integer.value = temp_desc->buffer.pointer[operand[0]->reference.offset]; + break; - /* TBD: [Investigate] (see below) Don't add an additional - * ref! - */ - } - else if (operand[0]->reference.target_type == ACPI_TYPE_PACKAGE) { + 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 /* - * The target is a package, we want to return the referenced - * element of the package. We must add another reference to - * this object, however. + * Return the referenced element of the package. We must add + * another reference to the referenced object, however. */ return_desc = *(operand[0]->reference.where); if (!return_desc) { @@ -821,7 +861,6 @@ * an uninitialized package element and is thus a * severe error. */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "NULL package element obj %p\n", operand[0])); status = AE_AML_UNINITIALIZED_ELEMENT; @@ -829,15 +868,16 @@ } acpi_ut_add_reference (return_desc); - } + break; + + + default: - else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Target_type %X in obj %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Index Target_type %X in obj %p\n", operand[0]->reference.target_type, operand[0])); status = AE_AML_OPERAND_TYPE; goto cleanup; } - break; @@ -849,15 +889,22 @@ acpi_ut_add_reference (return_desc); break; + + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode in ref(%p) - %X\n", + operand[0], operand[0]->reference.opcode)); + + status = AE_TYPE; + goto cleanup; } } - break; default: - REPORT_ERROR (("Acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exoparg2.c linux2.4.21_itanium/drivers/acpi/executer/exoparg2.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exoparg2.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exoparg2.c Wed Jul 23 18:28:13 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,15 +26,13 @@ #include "acpi.h" #include "acparser.h" -#include "acnamesp.h" #include "acinterp.h" #include "acevents.h" #include "amlcode.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exoparg2") + ACPI_MODULE_NAME ("exoparg2") /*! @@ -84,50 +82,45 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R", + acpi_ps_get_opcode_name (walk_state->opcode)); /* Examine the opcode */ switch (walk_state->opcode) { - case AML_NOTIFY_OP: /* Notify (Notify_object, Notify_value) */ /* The first operand is a namespace node */ node = (acpi_namespace_node *) operand[0]; - /* The node must refer to a device or thermal zone */ - - if (node && operand[1]) /* TBD: is this check necessary? */ { - switch (node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: + /* Notifies allowed on this object? */ - /* - * Dispatch the notify to the appropriate handler - * NOTE: the request is queued for execution after this method - * completes. The notify handlers are NOT invoked synchronously - * from this thread -- because handlers may in turn run other - * control methods. - */ - status = acpi_ev_queue_notify_request (node, - (u32) operand[1]->integer.value); - break; - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type %X\n", - node->type)); + if (!acpi_ev_is_notify_object (node)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n", + acpi_ut_get_type_name (node->type))); - status = AE_AML_OPERAND_TYPE; - break; - } + status = AE_AML_OPERAND_TYPE; + break; } + + /* + * Dispatch the notify to the appropriate handler + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + status = acpi_ev_queue_notify_request (node, + (u32) operand[1]->integer.value); break; + default: - REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; } @@ -158,7 +151,7 @@ acpi_status status; - FUNCTION_TRACE_STR ("Ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); /* @@ -191,11 +184,10 @@ default: - REPORT_ERROR (("Acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; - break; } @@ -257,7 +249,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_STR ("Ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); /* @@ -344,7 +336,7 @@ case AML_CONCAT_RES_OP: /* Concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ - status = AE_NOT_IMPLEMENTED; + status = acpi_ex_concat_template (operand[0], operand[1], &return_desc, walk_state); break; @@ -424,12 +416,11 @@ walk_state->result_obj = return_desc; goto cleanup; - break; default: - REPORT_ERROR (("Acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; break; @@ -486,7 +477,7 @@ u8 logical_result = FALSE; - FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); /* Create the internal return object */ @@ -531,10 +522,9 @@ default: - REPORT_ERROR (("Acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; - break; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exoparg3.c linux2.4.21_itanium/drivers/acpi/executer/exoparg3.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exoparg3.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exoparg3.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -32,7 +32,7 @@ #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exoparg3") + ACPI_MODULE_NAME ("exoparg3") /*! @@ -79,7 +79,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_STR ("Ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode)); switch (walk_state->opcode) { @@ -87,7 +87,7 @@ case AML_FATAL_OP: /* Fatal (Fatal_type Fatal_code Fatal_arg) */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Fatal_op: Type %x Code %x Arg %x <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + "Fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); @@ -102,7 +102,7 @@ /* * Always signal the OS! */ - acpi_os_signal (ACPI_SIGNAL_FATAL, fatal); + status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal); /* Might return while OS is shutting down, just continue */ @@ -112,11 +112,10 @@ default: - REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; - break; } @@ -146,11 +145,11 @@ acpi_operand_object *return_desc = NULL; char *buffer; acpi_status status = AE_OK; - u32 index; - u32 length; + NATIVE_UINT index; + ACPI_SIZE length; - FUNCTION_TRACE_STR ("Ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); switch (walk_state->opcode) { @@ -168,8 +167,8 @@ /* Get the Integer values from the objects */ - index = (u32) operand[1]->integer.value; - length = (u32) operand[2]->integer.value; + index = (NATIVE_UINT) operand[1]->integer.value; + length = (ACPI_SIZE) operand[2]->integer.value; /* * If the index is beyond the length of the String/Buffer, or if the @@ -181,37 +180,36 @@ if ((index + length) > operand[0]->string.length) { - length = operand[0]->string.length - index; + length = (ACPI_SIZE) operand[0]->string.length - index; } /* Allocate a new buffer for the String/Buffer */ - buffer = ACPI_MEM_CALLOCATE (length + 1); + buffer = ACPI_MEM_CALLOCATE ((ACPI_SIZE) length + 1); if (!buffer) { - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } /* Copy the portion requested */ - MEMCPY (buffer, operand[0]->string.pointer + index, - length); + ACPI_MEMCPY (buffer, operand[0]->string.pointer + index, + length); /* Set the length of the new String/Buffer */ return_desc->string.pointer = buffer; - return_desc->string.length = length; + return_desc->string.length = (u32) length; } - break; default: - REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; - break; } /* Store the result in the target */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exoparg6.c linux2.4.21_itanium/drivers/acpi/executer/exoparg6.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exoparg6.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exoparg6.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -32,7 +32,7 @@ #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exoparg6") + ACPI_MODULE_NAME ("exoparg6") /*! @@ -158,7 +158,7 @@ acpi_operand_object *this_element; - FUNCTION_TRACE_STR ("Ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("Ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); switch (walk_state->opcode) { @@ -199,6 +199,7 @@ * Examine each element until a match is found. Within the loop, * "continue" signifies that the current element does not match * and the next should be examined. + * * Upon finding a match, the loop will terminate via "break" at * the bottom. If it terminates "normally", Match_value will be -1 * (its initial value) indicating that no match was found. When @@ -209,27 +210,21 @@ /* * Treat any NULL or non-numeric elements as non-matching. - * TBD [Unhandled] - if an element is a Name, - * should we examine its value? */ if (!this_element || this_element->common.type != ACPI_TYPE_INTEGER) { continue; } - /* - * Within these switch statements: - * "break" (exit from the switch) signifies a match; - * "continue" (proceed to next iteration of enclosing - * "for" loop) signifies a non-match. + * "continue" (proceed to next iteration of enclosing + * "for" loop) signifies a non-match. */ if (!acpi_ex_do_match ((u32) operand[1]->integer.value, this_element->integer.value, operand[2]->integer.value)) { continue; } - if (!acpi_ex_do_match ((u32) operand[3]->integer.value, this_element->integer.value, operand[4]->integer.value)) { continue; @@ -246,18 +241,16 @@ case AML_LOAD_TABLE_OP: - status = AE_NOT_IMPLEMENTED; - goto cleanup; + status = acpi_ex_load_table_op (walk_state, &return_desc); break; default: - REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", + ACPI_REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; - break; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exprep.c linux2.4.21_itanium/drivers/acpi/executer/exprep.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exprep.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exprep.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -29,88 +29,128 @@ #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exprep") + ACPI_MODULE_NAME ("exprep") /******************************************************************************* * - * FUNCTION: Acpi_ex_decode_field_access_type + * FUNCTION: Acpi_ex_decode_field_access * * PARAMETERS: Access - Encoded field access bits * Length - Field length. * - * RETURN: Field granularity (8, 16, 32 or 64) + * RETURN: Field granularity (8, 16, 32 or 64) and + * Byte_alignment (1, 2, 3, or 4) * * DESCRIPTION: Decode the Access_type bits of a field definition. * ******************************************************************************/ static u32 -acpi_ex_decode_field_access_type ( - u32 access, - u16 length, - u32 *alignment) +acpi_ex_decode_field_access ( + acpi_operand_object *obj_desc, + u8 field_flags, + u32 *return_byte_alignment) { - PROC_NAME ("Ex_decode_field_access_type"); + u32 access; + u8 byte_alignment; + u8 bit_length; +/* u32 Length; */ + + + ACPI_FUNCTION_NAME ("Ex_decode_field_access"); + + access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); switch (access) { - case ACCESS_ANY_ACC: + case AML_FIELD_ACCESS_ANY: - *alignment = 8; + byte_alignment = 1; + bit_length = 8; + +#if 0 + /* + * TBD: optimize + * + * Any attempt to optimize the access size to the size of the field + * must take into consideration the length of the region and take + * care that an access to the field will not attempt to access + * beyond the end of the region. + */ /* Use the length to set the access type */ + length = obj_desc->common_field.bit_length; + if (length <= 8) { - return (8); + bit_length = 8; } else if (length <= 16) { - return (16); + bit_length = 16; } else if (length <= 32) { - return (32); + bit_length = 32; } else if (length <= 64) { - return (64); + bit_length = 64; } + else { + /* Larger than Qword - just use byte-size chunks */ - /* Default is 8 (byte) */ + bit_length = 8; + } +#endif + break; - return (8); + case AML_FIELD_ACCESS_BYTE: + byte_alignment = 1; + bit_length = 8; break; - case ACCESS_BYTE_ACC: - *alignment = 8; - return (8); + case AML_FIELD_ACCESS_WORD: + byte_alignment = 2; + bit_length = 16; break; - case ACCESS_WORD_ACC: - *alignment = 16; - return (16); + case AML_FIELD_ACCESS_DWORD: + byte_alignment = 4; + bit_length = 32; break; - case ACCESS_DWORD_ACC: - *alignment = 32; - return (32); + case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + byte_alignment = 8; + bit_length = 64; break; - case ACCESS_QWORD_ACC: /* ACPI 2.0 */ - *alignment = 64; - return (64); + case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 */ + byte_alignment = 8; + bit_length = 8; break; default: /* Invalid field access type */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown field access type %x\n", + "Unknown field access type %X\n", access)); return (0); } + + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { + /* + * Buffer_field access can be on any byte boundary, so the + * Byte_alignment is always 1 byte -- regardless of any Byte_alignment + * implied by the field access type. + */ + byte_alignment = 1; + } + + *return_byte_alignment = byte_alignment; + return (bit_length); } @@ -128,7 +168,9 @@ * RETURN: Status * * DESCRIPTION: Initialize the areas of the field object that are common - * to the various types of fields. + * to the various types of fields. Note: This is very "sensitive" + * code because we are solving the general case for field + * alignment. * ******************************************************************************/ @@ -136,107 +178,106 @@ acpi_ex_prep_common_field_object ( acpi_operand_object *obj_desc, u8 field_flags, + u8 field_attribute, u32 field_bit_position, u32 field_bit_length) { u32 access_bit_width; - u32 alignment; + u32 byte_alignment; u32 nearest_byte_address; - FUNCTION_TRACE ("Ex_prep_common_field_object"); + ACPI_FUNCTION_TRACE ("Ex_prep_common_field_object"); /* * Note: the structure being initialized is the - * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common area - * are initialized by this procedure. + * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common + * area are initialized by this procedure. */ - - /* Demultiplex the Field_flags byte */ - - obj_desc->common_field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK) - >> LOCK_RULE_SHIFT); - obj_desc->common_field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK) - >> UPDATE_RULE_SHIFT); - /* Other misc fields */ - - obj_desc->common_field.bit_length = (u16) field_bit_length; + obj_desc->common_field.field_flags = field_flags; + obj_desc->common_field.attribute = field_attribute; + obj_desc->common_field.bit_length = field_bit_length; /* * Decode the access type so we can compute offsets. The access type gives * two pieces of information - the width of each field access and the - * necessary alignment of the access. For Any_acc, the width used is the - * largest necessary/possible in an attempt to access the whole field in one - * I/O operation. However, for Any_acc, the alignment is 8. For all other - * access types (Byte, Word, Dword, Qword), the width is the same as the - * alignment. + * necessary Byte_alignment (address granularity) of the access. + * + * For Any_acc, the Access_bit_width is the largest width that is both + * necessary and possible in an attempt to access the whole field in one + * I/O operation. However, for Any_acc, the Byte_alignment is always one + * byte. + * + * For all Buffer Fields, the Byte_alignment is always one byte. + * + * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is + * the same (equivalent) as the Byte_alignment. */ - access_bit_width = acpi_ex_decode_field_access_type ( - ((field_flags & ACCESS_TYPE_MASK) >> ACCESS_TYPE_SHIFT), - obj_desc->field.bit_length, &alignment); + access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags, + &byte_alignment); if (!access_bit_width) { return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } /* Setup width (access granularity) fields */ - obj_desc->common_field.access_bit_width = (u8) access_bit_width; /* 8, 16, 32, 64 */ - obj_desc->common_field.access_byte_width = (u8) DIV_8 (access_bit_width); /* 1, 2, 4, 8 */ - - if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { - /* - * Buffer_field access can be on any byte boundary, so the - * alignment is always 8 (regardless of any alignment implied by the - * field access type.) - */ - alignment = 8; - } - + obj_desc->common_field.access_byte_width = (u8) + ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */ /* - * Base_byte_offset is the address of the start of the field within the region. It is - * the byte address of the first *datum* (field-width data unit) of the field. - * (i.e., the first datum that contains at least the first *bit* of the field.) + * Base_byte_offset is the address of the start of the field within the + * region. It is the byte address of the first *datum* (field-width data + * unit) of the field. (i.e., the first datum that contains at least the + * first *bit* of the field.) + * + * Note: Byte_alignment is always either equal to the Access_bit_width or 8 + * (Byte access), and it defines the addressing granularity of the parent + * region or buffer. */ - nearest_byte_address = ROUND_BITS_DOWN_TO_BYTES (field_bit_position); - obj_desc->common_field.base_byte_offset = ROUND_DOWN (nearest_byte_address, - DIV_8 (alignment)); + nearest_byte_address = + ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position); + obj_desc->common_field.base_byte_offset = + ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment); /* - * Start_field_bit_offset is the offset of the first bit of the field within a field datum. - * This is calculated as the number of bits from the Base_byte_offset. In other words, - * the start of the field is relative to a byte address, regardless of the access type - * of the field. + * Start_field_bit_offset is the offset of the first bit of the field within + * a field datum. */ - obj_desc->common_field.start_field_bit_offset = (u8) (MOD_8 (field_bit_position)); + obj_desc->common_field.start_field_bit_offset = (u8) + (field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset)); /* - * Datum_valid_bits is the number of valid field bits in the first field datum. + * Valid bits -- the number of bits that compose a partial datum, + * 1) At the end of the field within the region (arbitrary starting bit + * offset) + * 2) At the end of a buffer used to contain the field (starting offset + * always zero) */ - obj_desc->common_field.datum_valid_bits = (u8) (access_bit_width - - obj_desc->common_field.start_field_bit_offset); + obj_desc->common_field.end_field_valid_bits = (u8) + ((obj_desc->common_field.start_field_bit_offset + field_bit_length) % + access_bit_width); + /* Start_buffer_bit_offset always = 0 */ + + obj_desc->common_field.end_buffer_valid_bits = (u8) + (field_bit_length % access_bit_width); /* - * Valid bits -- the number of bits that compose a partial datum, - * 1) At the end of the field within the region (arbitrary starting bit offset) - * 2) At the end of a buffer used to contain the field (starting offset always zero) + * Datum_valid_bits is the number of valid field bits in the first + * field datum. */ - obj_desc->common_field.end_field_valid_bits = (u8) ((obj_desc->common_field.start_field_bit_offset + - field_bit_length) % access_bit_width); - obj_desc->common_field.end_buffer_valid_bits = (u8) (field_bit_length % access_bit_width); /* Start_buffer_bit_offset always = 0 */ - + obj_desc->common_field.datum_valid_bits = (u8) + (access_bit_width - obj_desc->common_field.start_field_bit_offset); /* - * Does the entire field fit within a single field access element - * (datum)? (without crossing a datum boundary) + * Does the entire field fit within a single field access element? (datum) + * (i.e., without crossing a datum boundary) */ - if ((obj_desc->common_field.start_field_bit_offset + obj_desc->common_field.bit_length) <= - (u16) obj_desc->common_field.access_bit_width) { - obj_desc->common_field.access_flags |= AFIELD_SINGLE_DATUM; + if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <= + (u16) access_bit_width) { + obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM; } - return_ACPI_STATUS (AE_OK); } @@ -267,7 +308,7 @@ acpi_status status; - FUNCTION_TRACE ("Ex_prep_field_value"); + ACPI_FUNCTION_TRACE ("Ex_prep_field_value"); /* Parameter validation */ @@ -280,14 +321,15 @@ type = acpi_ns_get_type (info->region_node); if (type != ACPI_TYPE_REGION) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Needed Region, found type %X %s\n", type, acpi_ut_get_type_name (type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } - /* Allocate a new region object */ + /* Allocate a new field object */ obj_desc = acpi_ut_create_internal_object (info->field_type); if (!obj_desc) { @@ -296,8 +338,9 @@ /* Initialize areas of the object that are common to all fields */ + obj_desc->common_field.node = info->field_node; status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags, - info->field_bit_position, info->field_bit_length); + info->attribute, info->field_bit_position, info->field_bit_length); if (ACPI_FAILURE (status)) { acpi_ut_delete_object_desc (obj_desc); return_ACPI_STATUS (status); @@ -308,33 +351,37 @@ switch (info->field_type) { case INTERNAL_TYPE_REGION_FIELD: - obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node); + obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node); /* An additional reference for the container */ acpi_ut_add_reference (obj_desc->field.region_obj); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Region_field: Bitoff=%X Off=%X Gran=%X Region %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Region_field: Bitoff=%X Off=%X Gran=%X Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, - obj_desc->field.access_bit_width, obj_desc->field.region_obj)); + obj_desc->field.access_byte_width, obj_desc->field.region_obj)); break; case INTERNAL_TYPE_BANK_FIELD: - obj_desc->bank_field.value = info->bank_value; - obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node); - obj_desc->bank_field.bank_register_obj = acpi_ns_get_attached_object (info->register_node); + obj_desc->bank_field.value = info->bank_value; + obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node); + obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node); /* An additional reference for the attached objects */ acpi_ut_add_reference (obj_desc->bank_field.region_obj); - acpi_ut_add_reference (obj_desc->bank_field.bank_register_obj); + acpi_ut_add_reference (obj_desc->bank_field.bank_obj); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Bank Field: Bit_off=%X Off=%X Gran=%X Region %p Bank_reg %p\n", - obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, - obj_desc->field.access_bit_width, obj_desc->bank_field.region_obj, - obj_desc->bank_field.bank_register_obj)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Bank Field: Bit_off=%X Off=%X Gran=%X Region %p Bank_reg %p\n", + obj_desc->bank_field.start_field_bit_offset, + obj_desc->bank_field.base_byte_offset, + obj_desc->field.access_byte_width, + obj_desc->bank_field.region_obj, + obj_desc->bank_field.bank_obj)); break; @@ -342,8 +389,8 @@ obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node); obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node); - obj_desc->index_field.value = (u32) (info->field_bit_position / - obj_desc->field.access_bit_width); + obj_desc->index_field.value = (u32) + (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width)); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n")); @@ -355,11 +402,18 @@ acpi_ut_add_reference (obj_desc->index_field.data_obj); acpi_ut_add_reference (obj_desc->index_field.index_obj); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n", - obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, - obj_desc->field.access_bit_width, obj_desc->index_field.index_obj, + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n", + obj_desc->index_field.start_field_bit_offset, + obj_desc->index_field.base_byte_offset, + obj_desc->field.access_byte_width, + obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); break; + + default: + /* No other types should get here */ + break; } /* @@ -367,10 +421,10 @@ * preserving the current type of that Named_obj. */ status = acpi_ns_attach_object (info->field_node, obj_desc, - (u8) acpi_ns_get_type (info->field_node)); + acpi_ns_get_type (info->field_node)); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "set Named_obj %p (%4.4s) val = %p\n", - info->field_node, (char*)&(info->field_node->name), obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set Named_obj %p (%4.4s) val = %p\n", + info->field_node, info->field_node->name.ascii, obj_desc)); /* Remove local reference to the object */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exregion.c linux2.4.21_itanium/drivers/acpi/executer/exregion.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exregion.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exregion.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,14 +27,10 @@ #include "acpi.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exregion") + ACPI_MODULE_NAME ("exregion") /******************************************************************************* @@ -60,7 +56,7 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value, + acpi_integer *value, void *handler_context, void *region_context) { @@ -68,9 +64,12 @@ void *logical_addr_ptr = NULL; acpi_mem_space_context *mem_info = region_context; u32 length; + ACPI_SIZE window_size; +#ifndef _HW_ALIGNMENT_SUPPORT + u32 remainder; +#endif - - FUNCTION_TRACE ("Ex_system_memory_space_handler"); + ACPI_FUNCTION_TRACE ("Ex_system_memory_space_handler"); /* Validate and translate the bit width */ @@ -88,14 +87,28 @@ length = 4; break; + case 64: + length = 8; + break; + default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid System_memory width %d\n", bit_width)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); - break; } +#ifndef _HW_ALIGNMENT_SUPPORT + /* + * Hardware does not support non-aligned data transfers, we must verify + * the request. + */ + (void) acpi_ut_short_divide ((acpi_integer *) &address, length, NULL, &remainder); + if (remainder != 0) { + return_ACPI_STATUS (AE_AML_ALIGNMENT); + } +#endif + /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR @@ -115,61 +128,80 @@ mem_info->mapped_length); } - mem_info->mapped_length = 0; /* In case of failure below */ + /* + * Don't attempt to map memory beyond the end of the region, and + * constrain the maximum mapping size to something reasonable. + */ + window_size = (ACPI_SIZE) ((mem_info->address + mem_info->length) - address); + if (window_size > SYSMEM_REGION_WINDOW_SIZE) { + window_size = SYSMEM_REGION_WINDOW_SIZE; + } /* Create a new mapping starting at the address given */ - status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE, + status = acpi_os_map_memory (address, window_size, (void **) &mem_info->mapped_logical_address); if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n", + ACPI_HIDWORD (address), ACPI_LODWORD (address), (u32) window_size)); + mem_info->mapped_length = 0; return_ACPI_STATUS (status); } /* Save the physical address and mapping size */ mem_info->mapped_physical_address = address; - mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; + mem_info->mapped_length = window_size; } - /* * Generate a logical pointer corresponding to the address we want to * access */ - - /* TBD: should these pointers go to 64-bit in all cases ? */ - logical_addr_ptr = mem_info->mapped_logical_address + ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, - HIDWORD (address), LODWORD (address))); - - /* Perform the memory read or write */ + ACPI_HIDWORD (address), ACPI_LODWORD (address))); + /* + * Perform the memory read or write + * + * Note: For machines that do not support non-aligned transfers, the target + * address was checked for alignment above. We do not attempt to break the + * transfer up into smaller (byte-size) chunks because the AML specifically + * asked for a transfer width that the hardware may require. + */ switch (function) { + case ACPI_READ: - case ACPI_READ_ADR_SPACE: - + *value = 0; switch (bit_width) { case 8: - *value = (u32)* (u8 *) logical_addr_ptr; + *value = (acpi_integer) *((u8 *) logical_addr_ptr); break; case 16: - MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr); + *value = (acpi_integer) *((u16 *) logical_addr_ptr); break; case 32: - MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); + *value = (acpi_integer) *((u32 *) logical_addr_ptr); break; - } +#if ACPI_MACHINE_WIDTH != 16 + case 64: + *value = (acpi_integer) *((u64 *) logical_addr_ptr); + break; +#endif + default: + /* Bit_width was already validated */ + break; + } break; - - case ACPI_WRITE_ADR_SPACE: + case ACPI_WRITE: switch (bit_width) { case 8: @@ -177,16 +209,24 @@ break; case 16: - MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); + *(u16 *) logical_addr_ptr = (u16) *value; break; case 32: - MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); + *(u32 *) logical_addr_ptr = (u32) *value; break; - } - break; +#if ACPI_MACHINE_WIDTH != 16 + case 64: + *(u64 *) logical_addr_ptr = (u64) *value; + break; +#endif + default: + /* Bit_width was already validated */ + break; + } + break; default: status = AE_BAD_PARAMETER; @@ -220,37 +260,34 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value, + acpi_integer *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_system_io_space_handler"); + ACPI_FUNCTION_TRACE ("Ex_system_io_space_handler"); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, - HIDWORD (address), LODWORD (address))); + ACPI_HIDWORD (address), ACPI_LODWORD (address))); /* Decode the function parameter */ switch (function) { - - case ACPI_READ_ADR_SPACE: + case ACPI_READ: *value = 0; status = acpi_os_read_port ((ACPI_IO_ADDRESS) address, value, bit_width); break; - - case ACPI_WRITE_ADR_SPACE: + case ACPI_WRITE: status = acpi_os_write_port ((ACPI_IO_ADDRESS) address, *value, bit_width); break; - default: status = AE_BAD_PARAMETER; break; @@ -283,7 +320,7 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value, + acpi_integer *value, void *handler_context, void *region_context) { @@ -292,11 +329,11 @@ u16 pci_register; - FUNCTION_TRACE ("Ex_pci_config_space_handler"); + ACPI_FUNCTION_TRACE ("Ex_pci_config_space_handler"); /* - * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: + * The arguments to Acpi_os(Read|Write)Pci_configuration are: * * Pci_segment is the PCI bus segment range 0-31 * Pci_bus is the PCI bus number range 0-255 @@ -308,7 +345,7 @@ * */ pci_id = (acpi_pci_id *) region_context; - pci_register = (u16) address; + pci_register = (u16) (u32) address; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", @@ -316,20 +353,17 @@ pci_id->function, pci_register)); switch (function) { - - case ACPI_READ_ADR_SPACE: + case ACPI_READ: *value = 0; status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width); break; - - case ACPI_WRITE_ADR_SPACE: + case ACPI_WRITE: status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width); break; - default: status = AE_BAD_PARAMETER; @@ -363,14 +397,14 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value, + acpi_integer *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_cmos_space_handler"); + ACPI_FUNCTION_TRACE ("Ex_cmos_space_handler"); return_ACPI_STATUS (status); @@ -400,16 +434,76 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value, + acpi_integer *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_pci_bar_space_handler"); + ACPI_FUNCTION_TRACE ("Ex_pci_bar_space_handler"); return_ACPI_STATUS (status); } + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_data_table_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the Data Table address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_data_table_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + acpi_integer *value, + void *handler_context, + void *region_context) +{ + acpi_status status = AE_OK; + u32 byte_width = ACPI_DIV_8 (bit_width); + u32 i; + char *logical_addr_ptr; + + + ACPI_FUNCTION_TRACE ("Ex_data_table_space_handler"); + + + logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address); + + + /* Perform the memory read or write */ + + switch (function) { + case ACPI_READ: + + for (i = 0; i < byte_width; i++) { + ((char *) value) [i] = logical_addr_ptr[i]; + } + break; + + case ACPI_WRITE: + default: + + return_ACPI_STATUS (AE_SUPPORT); + } + + return_ACPI_STATUS (status); +} + + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exresnte.c linux2.4.21_itanium/drivers/acpi/executer/exresnte.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exresnte.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exresnte.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,16 +27,13 @@ #include "acpi.h" #include "amlcode.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exresnte") + ACPI_MODULE_NAME ("exresnte") /******************************************************************************* @@ -75,25 +72,24 @@ acpi_operand_object *source_desc; acpi_operand_object *obj_desc = NULL; acpi_namespace_node *node; - acpi_object_type8 entry_type; + acpi_object_type entry_type; acpi_integer temp_val; - FUNCTION_TRACE ("Ex_resolve_node_to_value"); + ACPI_FUNCTION_TRACE ("Ex_resolve_node_to_value"); /* * The stack pointer points to a acpi_namespace_node (Node). Get the * object that is attached to the Node. */ - node = *object_ptr; - source_desc = acpi_ns_get_attached_object (node); + node = *object_ptr; + source_desc = acpi_ns_get_attached_object (node); entry_type = acpi_ns_get_type ((acpi_handle) node); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p Source_desc=%p Type=%X\n", node, source_desc, entry_type)); - /* * Several object types require no further processing: * 1) Devices rarely have an attached object, return the Node @@ -115,7 +111,6 @@ * of the attached object or pointer */ switch (entry_type) { - case ACPI_TYPE_PACKAGE: if (ACPI_TYPE_PACKAGE != source_desc->common.type) { @@ -124,10 +119,13 @@ return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } - /* Return an additional reference to the object */ + status = acpi_ds_get_package_arguments (source_desc); + if (ACPI_SUCCESS (status)) { + /* Return an additional reference to the object */ - obj_desc = source_desc; - acpi_ut_add_reference (obj_desc); + obj_desc = source_desc; + acpi_ut_add_reference (obj_desc); + } break; @@ -139,10 +137,13 @@ return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } - /* Return an additional reference to the object */ + status = acpi_ds_get_buffer_arguments (source_desc); + if (ACPI_SUCCESS (status)) { + /* Return an additional reference to the object */ - obj_desc = source_desc; - acpi_ut_add_reference (obj_desc); + obj_desc = source_desc; + acpi_ut_add_reference (obj_desc); + } break; @@ -184,10 +185,9 @@ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Field_read Node=%p Source_desc=%p Type=%X\n", node, source_desc, entry_type)); - status = acpi_ex_read_data_from_field (source_desc, &obj_desc); + status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc); break; - /* * For these objects, just return the object attached to the Node */ @@ -214,7 +214,6 @@ node)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ - break; /* diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exresolv.c linux2.4.21_itanium/drivers/acpi/executer/exresolv.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exresolv.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exresolv.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,121 +27,12 @@ #include "acpi.h" #include "amlcode.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" -#include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exresolv") - - -/******************************************************************************* - * - * FUNCTION: Acpi_ex_get_buffer_field_value - * - * PARAMETERS: *Obj_desc - Pointer to a Buffer_field - * *Result_desc - Pointer to an empty descriptor which will - * become an Integer with the field's value - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value from a Buffer_field - * - ******************************************************************************/ - -acpi_status -acpi_ex_get_buffer_field_value ( - acpi_operand_object *obj_desc, - acpi_operand_object *result_desc) -{ - acpi_status status; - u32 mask; - u8 *location; - - - FUNCTION_TRACE ("Ex_get_buffer_field_value"); - - - /* - * Parameter validation - */ - if (!obj_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null field pointer\n")); - return_ACPI_STATUS (AE_AML_NO_OPERAND); - } - - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_buffer_field_arguments (obj_desc); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - } - - if (!obj_desc->buffer_field.buffer_obj) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null container pointer\n")); - return_ACPI_STATUS (AE_AML_INTERNAL); - } - - if (ACPI_TYPE_BUFFER != obj_desc->buffer_field.buffer_obj->common.type) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - container is not a Buffer\n")); - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - } - - if (!result_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null result pointer\n")); - return_ACPI_STATUS (AE_AML_INTERNAL); - } - - - /* Field location is (base of buffer) + (byte offset) */ - - location = obj_desc->buffer_field.buffer_obj->buffer.pointer - + obj_desc->buffer_field.base_byte_offset; - - /* - * Construct Mask with as many 1 bits as the field width - * - * NOTE: Only the bottom 5 bits are valid for a shift operation, so - * special care must be taken for any shift greater than 31 bits. - * - * TBD: [Unhandled] Fields greater than 32 bits will not work. - */ - if (obj_desc->buffer_field.bit_length < 32) { - mask = ((u32) 1 << obj_desc->buffer_field.bit_length) - (u32) 1; - } - else { - mask = ACPI_UINT32_MAX; - } - - result_desc->integer.type = (u8) ACPI_TYPE_INTEGER; - - /* Get the 32 bit value at the location */ - - MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location); - - /* - * Shift the 32-bit word containing the field, and mask off the - * resulting value - */ - result_desc->integer.value = - (result_desc->integer.value >> obj_desc->buffer_field.start_field_bit_offset) & mask; - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "** Read from buffer %p byte %d bit %d width %d addr %p mask %08X val %8.8X%8.8X\n", - obj_desc->buffer_field.buffer_obj->buffer.pointer, - obj_desc->buffer_field.base_byte_offset, - obj_desc->buffer_field.start_field_bit_offset, - obj_desc->buffer_field.bit_length, - location, mask, - HIDWORD(result_desc->integer.value), - LODWORD(result_desc->integer.value))); - - return_ACPI_STATUS (AE_OK); -} + ACPI_MODULE_NAME ("exresolv") /******************************************************************************* @@ -167,7 +58,7 @@ acpi_status status; - FUNCTION_TRACE_PTR ("Ex_resolve_to_value", stack_ptr); + ACPI_FUNCTION_TRACE_PTR ("Ex_resolve_to_value", stack_ptr); if (!stack_ptr || !*stack_ptr) { @@ -175,13 +66,12 @@ return_ACPI_STATUS (AE_AML_NO_OPERAND); } - /* * The entity pointed to by the Stack_ptr can be either * 1) A valid acpi_operand_object, or * 2) A acpi_namespace_node (Named_obj) */ - if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { + if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -192,16 +82,16 @@ * Object on the stack may have changed if Acpi_ex_resolve_object_to_value() * was called (i.e., we can't use an _else_ here.) */ - if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { - status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) stack_ptr, + if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) { + status = acpi_ex_resolve_node_to_value ( + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, stack_ptr), walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Resolved object %p\n", *stack_ptr)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr)); return_ACPI_STATUS (AE_OK); } @@ -233,7 +123,7 @@ u16 opcode; - FUNCTION_TRACE ("Ex_resolve_object_to_value"); + ACPI_FUNCTION_TRACE ("Ex_resolve_object_to_value"); stack_desc = *stack_ptr; @@ -241,13 +131,11 @@ /* This is an acpi_operand_object */ switch (stack_desc->common.type) { - case INTERNAL_TYPE_REFERENCE: opcode = stack_desc->reference.opcode; switch (opcode) { - case AML_NAME_OP: /* @@ -286,11 +174,10 @@ acpi_ut_remove_reference (stack_desc); *stack_ptr = obj_desc; - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] Value_obj is %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] Value_obj is %p\n", stack_desc->reference.offset, obj_desc)); break; - /* * For constants, we must change the reference/constant object * to a real integer object @@ -327,6 +214,10 @@ case AML_REVISION_OP: obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL; break; + + default: + /* No other opcodes can get here */ + break; } /* @@ -359,7 +250,6 @@ acpi_ut_add_reference (obj_desc); *stack_ptr = obj_desc; } - else { /* * A NULL object descriptor means an unitialized element of @@ -381,7 +271,6 @@ status = AE_AML_INTERNAL; break; } - break; @@ -403,50 +292,36 @@ break; /* case INTERNAL_TYPE_REFERENCE */ - case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_BUFFER: - obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); - if (!obj_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } + status = acpi_ds_get_buffer_arguments (stack_desc); + break; - status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); - if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (obj_desc); - obj_desc = NULL; - } - *stack_ptr = (void *) obj_desc; + case ACPI_TYPE_PACKAGE: + + status = acpi_ds_get_package_arguments (stack_desc); break; + /* + * These cases may never happen here, but just in case.. + */ + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_REGION_FIELD: case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: - obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); - if (!obj_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* TBD: WRONG! */ - - status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); - if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (obj_desc); - obj_desc = NULL; - } + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Field_read Source_desc=%p Type=%X\n", + stack_desc, stack_desc->common.type)); + status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc); *stack_ptr = (void *) obj_desc; break; - - /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ - default: - break; - - } /* switch (Stack_desc->Common.Type) */ - + } return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exresop.c linux2.4.21_itanium/drivers/acpi/executer/exresop.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exresop.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exresop.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -28,15 +28,12 @@ #include "acpi.h" #include "amlcode.h" #include "acparser.h" -#include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exresop") + ACPI_MODULE_NAME ("exresop") /******************************************************************************* @@ -59,7 +56,7 @@ acpi_object_type this_type, void *object) { - PROC_NAME ("Ex_check_object_type"); + ACPI_FUNCTION_NAME ("Ex_check_object_type"); if (type_needed == ACPI_TYPE_ANY) { @@ -69,7 +66,7 @@ } if (type_needed != this_type) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [%s], found [%s] %p\n", acpi_ut_get_type_name (type_needed), acpi_ut_get_type_name (this_type), object)); @@ -85,18 +82,21 @@ * * FUNCTION: Acpi_ex_resolve_operands * - * PARAMETERS: Opcode Opcode being interpreted - * Stack_ptr Top of operand stack + * PARAMETERS: Opcode - Opcode being interpreted + * Stack_ptr - Pointer to the operand stack to be + * resolved + * Walk_state - Current stateu * * RETURN: Status * - * DESCRIPTION: Convert stack entries to required types + * DESCRIPTION: Convert multiple input operands to the types required by the + * target operator. * - * Each nibble in Arg_types represents one required operand - * and indicates the required Type: + * Each nibble (actually 5 bits) in Arg_types represents one required + * operand and indicates the required Type: * - * The corresponding stack entry will be converted to the - * required type if possible, else return an exception + * The corresponding operand will be converted to the required type if + * possible, otherwise we abort with an exception. * ******************************************************************************/ @@ -116,7 +116,7 @@ acpi_object_type type_needed; - FUNCTION_TRACE_U32 ("Ex_resolve_operands", opcode); + ACPI_FUNCTION_TRACE_U32 ("Ex_resolve_operands", opcode); op_info = acpi_ps_get_opcode_info (opcode); @@ -124,7 +124,6 @@ return_ACPI_STATUS (AE_AML_BAD_OPCODE); } - arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n", @@ -133,9 +132,8 @@ return_ACPI_STATUS (AE_AML_INTERNAL); } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X Operand_types=%X \n", - opcode, arg_types)); - + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] Operand_types=%X \n", + opcode, op_info->name, arg_types)); /* * Normal exit is with (Arg_types == 0) at end of argument list. @@ -158,13 +156,17 @@ /* Decode the descriptor type */ - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { + case ACPI_DESC_TYPE_NAMED: + /* Node */ object_type = ((acpi_namespace_node *) obj_desc)->type; - } + break; + + + case ACPI_DESC_TYPE_OPERAND: - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { /* ACPI internal object */ object_type = obj_desc->common.type; @@ -187,7 +189,6 @@ return_ACPI_STATUS (AE_AML_BAD_OPCODE); } - switch (obj_desc->reference.opcode) { case AML_ZERO_OP: case AML_ONE_OP: @@ -199,27 +200,28 @@ case AML_LOCAL_OP: case AML_REVISION_OP: - DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Reference Opcode: %s\n", op_info->name))); break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Reference Opcode: Unknown [%02x]\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - break; } } - } + break; + + + default: - else { /* Invalid descriptor */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad descriptor type %X in Obj %p\n", - obj_desc->common.data_type, obj_desc)); + ACPI_GET_DESCRIPTOR_TYPE (obj_desc), obj_desc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } @@ -231,24 +233,36 @@ this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); INCREMENT_ARG_LIST (arg_types); - /* * Handle cases where the object does not need to be * resolved to a value */ switch (this_arg_type) { + case ARGI_REF_OR_STRING: /* Can be a String or Reference */ - case ARGI_REFERENCE: /* References */ + if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) && + (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) { + /* + * String found - the string references a named object and must be + * resolved to a node + */ + goto next_operand; + } + + /* Else not a string - fall through to the normal Reference case below */ + /*lint -fallthrough */ + + case ARGI_REFERENCE: /* References: */ case ARGI_INTEGER_REF: case ARGI_OBJECT_REF: case ARGI_DEVICE_REF: - case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */ + case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ - case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ + case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ /* Need an operand of type INTERNAL_TYPE_REFERENCE */ - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) /* Node (name) ptr OK as-is */ { goto next_operand; } @@ -258,7 +272,6 @@ return_ACPI_STATUS (status); } - if (AML_NAME_OP == obj_desc->reference.opcode) { /* * Convert an indirect name ptr to direct name ptr and put @@ -268,9 +281,7 @@ acpi_ut_remove_reference (obj_desc); (*stack_ptr) = temp_node; } - goto next_operand; - break; case ARGI_ANYTYPE: @@ -287,6 +298,10 @@ goto next_operand; } break; + + default: + /* All cases covered above */ + break; } @@ -298,7 +313,6 @@ return_ACPI_STATUS (status); } - /* * Check the resulting object (value) type */ @@ -362,7 +376,7 @@ status = acpi_ex_convert_to_integer (*stack_ptr, stack_ptr, walk_state); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [Integer/String/Buffer], found [%s] %p\n", acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); @@ -371,9 +385,7 @@ return_ACPI_STATUS (status); } - goto next_operand; - break; case ARGI_BUFFER: @@ -385,7 +397,7 @@ status = acpi_ex_convert_to_buffer (*stack_ptr, stack_ptr, walk_state); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [Integer/String/Buffer], found [%s] %p\n", acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); @@ -394,9 +406,7 @@ return_ACPI_STATUS (status); } - goto next_operand; - break; case ARGI_STRING: @@ -408,7 +418,7 @@ status = acpi_ex_convert_to_string (*stack_ptr, stack_ptr, 16, ACPI_UINT32_MAX, walk_state); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [Integer/String/Buffer], found [%s] %p\n", acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); @@ -417,82 +427,109 @@ return_ACPI_STATUS (status); } - goto next_operand; - break; case ARGI_COMPUTEDATA: /* Need an operand of type INTEGER, STRING or BUFFER */ - if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) && - (ACPI_TYPE_STRING != (*stack_ptr)->common.type) && - (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + switch ((*stack_ptr)->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [Integer/String/Buffer], found [%s] %p\n", acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto next_operand; - break; case ARGI_DATAOBJECT: /* * ARGI_DATAOBJECT is only used by the Size_of operator. + * Need a buffer, string, package, or Node reference. * - * The ACPI specification allows Size_of to return the size of - * a Buffer, String or Package. However, the MS ACPI.SYS AML - * Interpreter also allows an Node reference to return without - * error with a size of 4. - */ - - /* Need a buffer, string, package or Node reference */ - - if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && - ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && - ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && - ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Needed [Buf/Str/Pkg/Ref], found [%s] %p\n", - acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); - - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - } - - /* - * If this is a reference, only allow a reference to an Node. + * The only reference allowed here is a direct reference to + * a namespace node. */ if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { if (!(*stack_ptr)->reference.node) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed [Node Reference], found [%p]\n", *stack_ptr)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } + + /* Get the object attached to the node */ + + temp_node = acpi_ns_get_attached_object ((*stack_ptr)->reference.node); + if (!temp_node) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Node [%p] has no attached object\n", + (*stack_ptr)->reference.node)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* + * Swap the reference object with the node's object. Must add + * a reference to the node object, and remove a reference from + * the original reference object. + */ + acpi_ut_add_reference (temp_node); + acpi_ut_remove_reference (*stack_ptr); + (*stack_ptr) = temp_node; + } + + /* Need a buffer, string, package */ + + switch ((*stack_ptr)->common.type) { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Needed [Buf/Str/Pkg], found [%s] %p\n", + acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto next_operand; - break; case ARGI_COMPLEXOBJ: /* Need a buffer or package or (ACPI 2.0) String */ - if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && - ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && - ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Needed [Buf/Pkg], found [%s] %p\n", + switch ((*stack_ptr)->common.type) { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Needed [Buf/Str/Pkg], found [%s] %p\n", acpi_ut_get_type_name ((*stack_ptr)->common.type), *stack_ptr)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto next_operand; - break; default: @@ -506,7 +543,6 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* * Make sure that the original object was resolved to the * required object type (Simple cases only). @@ -517,7 +553,6 @@ return_ACPI_STATUS (status); } - next_operand: /* * If more operands needed, decrement Stack_ptr to point @@ -529,7 +564,6 @@ } /* while (*Types) */ - return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exstore.c linux2.4.21_itanium/drivers/acpi/executer/exstore.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exstore.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exstore.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,16 +26,14 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exstore") + ACPI_MODULE_NAME ("exstore") /******************************************************************************* @@ -46,13 +44,15 @@ * *Dest_desc - Where to store it. Must be an NS node * or an acpi_operand_object of type * Reference; + * Walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Store the value described by Source_desc into the location * described by Dest_desc. Called by various interpreter * functions to store the result of an operation into - * the destination operand. + * the destination operand -- not just simply the actual "Store" + * ASL operator. * ******************************************************************************/ @@ -66,19 +66,19 @@ acpi_operand_object *ref_desc = dest_desc; - FUNCTION_TRACE_PTR ("Ex_store", dest_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_store", dest_desc); /* Validate parameters */ if (!source_desc || !dest_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n")); return_ACPI_STATUS (AE_AML_NO_OPERAND); } /* Dest_desc can be either a namespace node or an ACPI object */ - if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { + if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) { /* * Dest is a namespace node, * Storing an object into a Name "container" @@ -86,12 +86,9 @@ status = acpi_ex_store_object_to_node (source_desc, (acpi_namespace_node *) dest_desc, walk_state); - /* All done, that's it */ - return_ACPI_STATUS (status); } - /* Destination object must be an object of type Reference */ if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { @@ -100,15 +97,14 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Destination is not a Reference_obj [%p]\n", dest_desc)); - DUMP_STACK_ENTRY (source_desc); - DUMP_STACK_ENTRY (dest_desc); - DUMP_OPERANDS (&dest_desc, IMODE_EXECUTE, "Ex_store", + ACPI_DUMP_STACK_ENTRY (source_desc); + ACPI_DUMP_STACK_ENTRY (dest_desc); + ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "Ex_store", 2, "Target is not a Reference_obj"); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } - /* * Examine the Reference opcode. These cases are handled: * @@ -119,7 +115,6 @@ * 5) Store to a constant -- a noop */ switch (ref_desc->reference.opcode) { - case AML_NAME_OP: /* Storing an object into a Name "container" */ @@ -153,7 +148,7 @@ * Storing to the Debug object causes the value stored to be * displayed and otherwise has no effect -- see ACPI Specification */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Write to Debug Object: ****:\n\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Write to Debug Object: ****:\n\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ", acpi_ut_get_type_name (source_desc->common.type))); @@ -161,15 +156,16 @@ switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%X (%d)\n", - (u32) source_desc->integer.value, (u32) source_desc->integer.value)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n", + ACPI_HIWORD (source_desc->integer.value), + ACPI_LOWORD (source_desc->integer.value))); break; case ACPI_TYPE_BUFFER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%X\n", - (u32) source_desc->buffer.length)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length %.2X\n", + (u32) source_desc->buffer.length)); break; @@ -181,18 +177,19 @@ case ACPI_TYPE_PACKAGE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements - %p\n", - source_desc->package.elements)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements Ptr - %p\n", + source_desc->package.elements)); break; default: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "@0x%p\n", source_desc)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Type %s %p\n", + acpi_ut_get_type_name (source_desc->common.type), source_desc)); break; } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n")); break; @@ -202,27 +199,23 @@ case AML_REVISION_OP: /* - * Storing to a constant is a no-op -- see ACPI Specification - * Delete the reference descriptor, however + * Storing to a constant is a no-op according to the ACPI + * Specification. (Delete the reference descriptor, however.) */ break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - Unknown Reference subtype %02x\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %02x\n", ref_desc->reference.opcode)); - - /* TBD: [Restructure] use object dump routine !! */ - - DUMP_BUFFER (ref_desc, sizeof (acpi_operand_object)); + ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR); status = AE_AML_INTERNAL; break; } /* switch (Ref_desc->Reference.Opcode) */ - return_ACPI_STATUS (status); } @@ -231,36 +224,36 @@ * * FUNCTION: Acpi_ex_store_object_to_index * - * PARAMETERS: *Source_desc - Value to be stored - * *Node - Named object to receive the value + * PARAMETERS: *Source_desc - Value to be stored + * *Dest_desc - Named object to receive the value + * Walk_state - Current walk state * * RETURN: Status * - * DESCRIPTION: Store the object to the named object. + * DESCRIPTION: Store the object to indexed Buffer or Package element * ******************************************************************************/ acpi_status acpi_ex_store_object_to_index ( acpi_operand_object *source_desc, - acpi_operand_object *dest_desc, + acpi_operand_object *index_desc, acpi_walk_state *walk_state) { acpi_status status = AE_OK; acpi_operand_object *obj_desc; - u32 length; - u32 i; + acpi_operand_object *new_desc; u8 value = 0; - FUNCTION_TRACE ("Ex_store_object_to_index"); + ACPI_FUNCTION_TRACE ("Ex_store_object_to_index"); /* * Destination must be a reference pointer, and * must point to either a buffer or a package */ - switch (dest_desc->reference.target_type) { + switch (index_desc->reference.target_type) { case ACPI_TYPE_PACKAGE: /* * Storing to a package element is not simple. The source must be @@ -268,95 +261,48 @@ * source is copied into the destination - we can't just point to the * source object. */ - if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) { - /* - * The object at *(Dest_desc->Reference.Where) is the - * element within the package that is to be modified. - */ - obj_desc = *(dest_desc->reference.where); - if (obj_desc) { - /* - * If the Destination element is a package, we will delete - * that object and construct a new one. - * - * TBD: [Investigate] Should both the src and dest be required - * to be packages? - * && (Source_desc->Common.Type == ACPI_TYPE_PACKAGE) - */ - if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { - /* Take away the reference for being part of a package */ - - acpi_ut_remove_reference (obj_desc); - obj_desc = NULL; - } - } - - if (!obj_desc) { - /* - * If the Obj_desc is NULL, it means that an uninitialized package - * element has been used as a destination (this is OK), therefore, - * we must create the destination element to match the type of the - * source element NOTE: Source_desccan be of any type. - */ - obj_desc = acpi_ut_create_internal_object (source_desc->common.type); - if (!obj_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* - * If the source is a package, copy the source to the new dest - */ - if (ACPI_TYPE_PACKAGE == obj_desc->common.type) { - status = acpi_ut_copy_ipackage_to_ipackage (source_desc, obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (obj_desc); - return_ACPI_STATUS (status); - } - } - - /* Install the new descriptor into the package */ - - *(dest_desc->reference.where) = obj_desc; - } - - if (ACPI_TYPE_PACKAGE != obj_desc->common.type) { - /* - * The destination element is not a package, so we need to - * convert the contents of the source (Source_desc) and copy into - * the destination (Obj_desc) - */ - status = acpi_ex_store_object_to_object (source_desc, obj_desc, - walk_state); - if (ACPI_FAILURE (status)) { - /* - * An error occurrered when copying the internal object - * so delete the reference. - */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unable to copy the internal object\n")); - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); - } - } + /* + * The object at *(Index_desc->Reference.Where) is the + * element within the package that is to be modified. + */ + obj_desc = *(index_desc->reference.where); + + /* Do the conversion/store */ + + status = acpi_ex_store_object_to_object (source_desc, obj_desc, &new_desc, + walk_state); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Could not store object to indexed package element\n")); + return_ACPI_STATUS (status); + } + + /* + * If a new object was created, we must install it as the new + * package element + */ + if (new_desc != obj_desc) { + acpi_ut_remove_reference (obj_desc); + *(index_desc->reference.where) = new_desc; } break; case ACPI_TYPE_BUFFER_FIELD: - - /* TBD: can probably call the generic Buffer/Field routines */ - /* - * Storing into a buffer at a location defined by an Index. + * Store into a Buffer (not actually a real Buffer_field) at a + * location defined by an Index. * - * Each 8-bit element of the source object is written to the - * 8-bit Buffer Field of the Index destination object. + * The first 8-bit element of the source object is written to the + * 8-bit Buffer location defined by the Index destination object, + * according to the ACPI 2.0 specification. */ /* - * Set the Obj_desc to the destination object and type check. + * Make sure the target is a Buffer */ - obj_desc = dest_desc->reference.object; + obj_desc = index_desc->reference.object; if (obj_desc->common.type != ACPI_TYPE_BUFFER) { return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } @@ -367,65 +313,45 @@ */ switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: - /* - * Type is Integer, assign bytewise - * This loop to assign each of the elements is somewhat - * backward because of the Big Endian-ness of IA-64 - */ - length = sizeof (acpi_integer); - for (i = length; i != 0; i--) { - value = (u8)(source_desc->integer.value >> (MUL_8 (i - 1))); - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } - break; + /* Use the least-significant byte of the integer */ - case ACPI_TYPE_BUFFER: - /* - * Type is Buffer, the Length is in the structure. - * Just loop through the elements and assign each one in turn. - */ - length = source_desc->buffer.length; - for (i = 0; i < length; i++) { - value = source_desc->buffer.pointer[i]; - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } + value = (u8) (source_desc->integer.value); break; + case ACPI_TYPE_BUFFER: - case ACPI_TYPE_STRING: - /* - * Type is String, the Length is in the structure. - * Just loop through the elements and assign each one in turn. - */ - length = source_desc->string.length; - for (i = 0; i < length; i++) { - value = source_desc->string.pointer[i]; - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } + value = source_desc->buffer.pointer[0]; break; + case ACPI_TYPE_STRING: + + value = (u8) source_desc->string.pointer[0]; + break; default: - /* Other types are invalid */ + /* All other types are invalid */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Source must be Number/Buffer/String type, not %X\n", - source_desc->common.type)); - status = AE_AML_OPERAND_TYPE; - break; + "Source must be Integer/Buffer/String type, not %s\n", + acpi_ut_get_type_name (source_desc->common.type))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } + + /* Store the source value into the target buffer byte */ + + obj_desc->buffer.pointer[index_desc->reference.offset] = value; break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Target is not a Package or Buffer_field\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Target is not a Package or Buffer_field\n")); status = AE_AML_OPERAND_TYPE; break; } - return_ACPI_STATUS (status); } @@ -434,15 +360,16 @@ * * FUNCTION: Acpi_ex_store_object_to_node * - * PARAMETERS: *Source_desc - Value to be stored - * *Node - Named object to receive the value + * PARAMETERS: Source_desc - Value to be stored + * Node - Named object to receive the value + * Walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Store the object to the named object. * * The Assignment of an object to a named object is handled here - * The val passed in will replace the current value (if any) + * The value passed in will replace the current value (if any) * with the input value. * * When storing into an object the data is converted to the @@ -450,10 +377,7 @@ * that the target object type (for an initialized target) will * not be changed by a store operation. * - * NOTE: the global lock is acquired early. This will result - * in the global lock being held a bit longer. Also, if the - * function fails during set up we may get the lock when we - * don't really need it. I don't think we care. + * Assumes parameters are already validated. * ******************************************************************************/ @@ -465,15 +389,12 @@ { acpi_status status = AE_OK; acpi_operand_object *target_desc; - acpi_object_type8 target_type = ACPI_TYPE_ANY; - + acpi_operand_object *new_desc; + acpi_object_type target_type; - FUNCTION_TRACE ("Ex_store_object_to_node"); + ACPI_FUNCTION_TRACE_PTR ("Ex_store_object_to_node", source_desc); - /* - * Assuming the parameters were already validated - */ /* * Get current type of the node, and object attached to Node @@ -481,10 +402,9 @@ target_type = acpi_ns_get_type (node); target_desc = acpi_ns_get_attached_object (node); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Storing %p(%s) into node %p(%s)\n", - node, acpi_ut_get_type_name (source_desc->common.type), - source_desc, acpi_ut_get_type_name (target_type))); - + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + source_desc, acpi_ut_get_type_name (source_desc->common.type), + node, acpi_ut_get_type_name (target_type))); /* * Resolve the source object to an actual value @@ -495,7 +415,6 @@ return_ACPI_STATUS (status); } - /* * Do the actual store operation */ @@ -522,28 +441,30 @@ * * Copy and/or convert the source object to a new target object */ - status = acpi_ex_store_object (source_desc, target_type, &target_desc, walk_state); + status = acpi_ex_store_object_to_object (source_desc, target_desc, &new_desc, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* - * Store the new Target_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * Source_desc reference count is incremented by Attach_object. - */ - status = acpi_ns_attach_object (node, target_desc, target_type); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Store %s into %s via Convert/Attach\n", - acpi_ut_get_type_name (target_desc->common.type), - acpi_ut_get_type_name (target_type))); + if (new_desc != target_desc) { + /* + * Store the new New_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Source_desc reference count is incremented by Attach_object. + */ + status = acpi_ns_attach_object (node, new_desc, target_type); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Store %s into %s via Convert/Attach\n", + acpi_ut_get_type_name (source_desc->common.type), + acpi_ut_get_type_name (new_desc->common.type))); + } break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %s (%p) directly into node (%p), no implicit conversion\n", acpi_ut_get_type_name (source_desc->common.type), source_desc, node)); @@ -553,91 +474,7 @@ break; } - return_ACPI_STATUS (status); } -/******************************************************************************* - * - * FUNCTION: Acpi_ex_store_object_to_object - * - * PARAMETERS: *Source_desc - Value to be stored - * *Dest_desc - Object to receive the value - * - * RETURN: Status - * - * DESCRIPTION: Store an object to another object. - * - * The Assignment of an object to another (not named) object - * is handled here. - * The val passed in will replace the current value (if any) - * with the input value. - * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * This module allows destination types of Number, String, - * and Buffer. - * - ******************************************************************************/ - -acpi_status -acpi_ex_store_object_to_object ( - acpi_operand_object *source_desc, - acpi_operand_object *dest_desc, - acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - acpi_object_type8 destination_type = dest_desc->common.type; - - - FUNCTION_TRACE ("Ex_store_object_to_object"); - - - /* - * Assuming the parameters are valid! - */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Storing %p(%s) to %p(%s)\n", - source_desc, acpi_ut_get_type_name (source_desc->common.type), - dest_desc, acpi_ut_get_type_name (dest_desc->common.type))); - - - /* - * From this interface, we only support Integers/Strings/Buffers - */ - switch (destination_type) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - break; - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into %s not implemented\n", - acpi_ut_get_type_name (dest_desc->common.type))); - - return_ACPI_STATUS (AE_NOT_IMPLEMENTED); - } - - - /* - * Resolve the source object to an actual value - * (If it is a reference object) - */ - status = acpi_ex_resolve_object (&source_desc, destination_type, walk_state); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - - /* - * Copy and/or convert the source object to the destination object - */ - status = acpi_ex_store_object (source_desc, destination_type, &dest_desc, walk_state); - - - return_ACPI_STATUS (status); -} - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exstoren.c linux2.4.21_itanium/drivers/acpi/executer/exstoren.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exstoren.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exstoren.c Wed Jul 23 18:28:13 2003 @@ -8,7 +8,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,16 +27,11 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exstoren") + ACPI_MODULE_NAME ("exstoren") /******************************************************************************* @@ -57,66 +52,61 @@ acpi_status acpi_ex_resolve_object ( acpi_operand_object **source_desc_ptr, - acpi_object_type8 target_type, + acpi_object_type target_type, acpi_walk_state *walk_state) { acpi_operand_object *source_desc = *source_desc_ptr; acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_resolve_object"); + ACPI_FUNCTION_TRACE ("Ex_resolve_object"); /* - * Ensure we have a Source that can be stored in the target + * Ensure we have a Target that can be stored to */ switch (target_type) { - - /* This case handles the "interchangeable" types Integer, String, and Buffer. */ - - /* - * These cases all require only Integers or values that - * can be converted to Integers (Strings or Buffers) - */ case ACPI_TYPE_BUFFER_FIELD: case INTERNAL_TYPE_REGION_FIELD: case INTERNAL_TYPE_BANK_FIELD: case INTERNAL_TYPE_INDEX_FIELD: + /* + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) + */ - /* - * Stores into a Field/Region or into a Buffer/String - * are all essentially the same. - */ case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: + /* + * Stores into a Field/Region or into a Integer/Buffer/String + * are all essentially the same. This case handles the + * "interchangeable" types Integer, String, and Buffer. + */ + if (source_desc->common.type == INTERNAL_TYPE_REFERENCE) { + /* Resolve a reference object first */ - /* TBD: FIX - check for source==REF, resolve, then check type */ + status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state); + if (ACPI_FAILURE (status)) { + break; + } + } /* - * If Source_desc is not a valid type, try to resolve it to one. + * Must have a Integer, Buffer, or String */ if ((source_desc->common.type != ACPI_TYPE_INTEGER) && (source_desc->common.type != ACPI_TYPE_BUFFER) && (source_desc->common.type != ACPI_TYPE_STRING)) { /* - * Initially not a valid type, convert + * Conversion successful but still not a valid type */ - status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state); - if (ACPI_SUCCESS (status) && - (source_desc->common.type != ACPI_TYPE_INTEGER) && - (source_desc->common.type != ACPI_TYPE_BUFFER) && - (source_desc->common.type != ACPI_TYPE_STRING)) { - /* - * Conversion successful but still not a valid type - */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Cannot assign type %s to %s (must be type Int/Str/Buf)\n", - acpi_ut_get_type_name ((*source_desc_ptr)->common.type), - acpi_ut_get_type_name (target_type))); - status = AE_AML_OPERAND_TYPE; - } + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Cannot assign type %s to %s (must be type Int/Str/Buf)\n", + acpi_ut_get_type_name (source_desc->common.type), + acpi_ut_get_type_name (target_type))); + status = AE_AML_OPERAND_TYPE; } break; @@ -147,11 +137,11 @@ /******************************************************************************* * - * FUNCTION: Acpi_ex_store_object + * FUNCTION: Acpi_ex_store_object_to_object * * PARAMETERS: Source_desc - Object to store - * Target_type - Current type of the target - * Target_desc_ptr - Pointer to the target + * Dest_desc - Object to receive a copy of the source + * New_desc - New object if Dest_desc is obsoleted * Walk_state - Current walk state * * RETURN: Status @@ -161,93 +151,114 @@ * conversion), and a copy of the value of the source to * the target. * + * The Assignment of an object to another (not named) object + * is handled here. + * The Source passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * Buffer, and Package. + * + * Assumes parameters are already validated. NOTE: Source_desc + * resolution (from a reference object) must be performed by + * the caller if necessary. + * ******************************************************************************/ acpi_status -acpi_ex_store_object ( +acpi_ex_store_object_to_object ( acpi_operand_object *source_desc, - acpi_object_type8 target_type, - acpi_operand_object **target_desc_ptr, + acpi_operand_object *dest_desc, + acpi_operand_object **new_desc, acpi_walk_state *walk_state) { - acpi_operand_object *target_desc = *target_desc_ptr; + acpi_operand_object *actual_src_desc; acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_store_object"); + ACPI_FUNCTION_TRACE_PTR ("Acpi_ex_store_object_to_object", source_desc); - /* - * Perform the "implicit conversion" of the source to the current type - * of the target - As per the ACPI specification. - * - * If no conversion performed, Source_desc is left alone, otherwise it - * is updated with a new object. - */ - status = acpi_ex_convert_to_target_type (target_type, &source_desc, walk_state); - if (ACPI_FAILURE (status)) { + actual_src_desc = source_desc; + if (!dest_desc) { + /* + * There is no destination object (An uninitialized node or + * package element), so we can simply copy the source object + * creating a new destination object + */ + status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state); return_ACPI_STATUS (status); } + if (source_desc->common.type != dest_desc->common.type) { + /* + * The source type does not match the type of the destination. + * Perform the "implicit conversion" of the source to the current type + * of the target as per the ACPI specification. + * + * If no conversion performed, Actual_src_desc = Source_desc. + * Otherwise, Actual_src_desc is a temporary object to hold the + * converted object. + */ + status = acpi_ex_convert_to_target_type (dest_desc->common.type, source_desc, + &actual_src_desc, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + /* * We now have two objects of identical types, and we can perform a * copy of the *value* of the source object. */ - switch (target_type) { - case ACPI_TYPE_ANY: - case INTERNAL_TYPE_DEF_ANY: - - /* - * The target namespace node is uninitialized (has no target object), - * and will take on the type of the source object - */ - *target_desc_ptr = source_desc; - break; - - + switch (dest_desc->common.type) { case ACPI_TYPE_INTEGER: - target_desc->integer.value = source_desc->integer.value; + dest_desc->integer.value = actual_src_desc->integer.value; /* Truncate value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table (target_desc, walk_state); + acpi_ex_truncate_for32bit_table (dest_desc, walk_state); break; case ACPI_TYPE_STRING: - status = acpi_ex_copy_string_to_string (source_desc, target_desc); + status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc); break; - case ACPI_TYPE_BUFFER: - status = acpi_ex_copy_buffer_to_buffer (source_desc, target_desc); + status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc); break; - case ACPI_TYPE_PACKAGE: - /* - * TBD: [Unhandled] Not real sure what to do here - */ - status = AE_NOT_IMPLEMENTED; + status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc, walk_state); break; - default: - /* * All other types come here. */ ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n", - acpi_ut_get_type_name (target_type))); + acpi_ut_get_type_name (dest_desc->common.type))); status = AE_NOT_IMPLEMENTED; break; } + if (actual_src_desc != source_desc) { + /* Delete the intermediate (temporary) source object */ + + acpi_ut_remove_reference (actual_src_desc); + } + *new_desc = dest_desc; return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exstorob.c linux2.4.21_itanium/drivers/acpi/executer/exstorob.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exstorob.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exstorob.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,21 +26,16 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exstorob") + ACPI_MODULE_NAME ("exstorob") /******************************************************************************* * - * FUNCTION: Acpi_ex_copy_buffer_to_buffer + * FUNCTION: Acpi_ex_store_buffer_to_buffer * * PARAMETERS: Source_desc - Source object to copy * Target_desc - Destination object of the copy @@ -52,7 +47,7 @@ ******************************************************************************/ acpi_status -acpi_ex_copy_buffer_to_buffer ( +acpi_ex_store_buffer_to_buffer ( acpi_operand_object *source_desc, acpi_operand_object *target_desc) { @@ -60,7 +55,7 @@ u8 *buffer; - PROC_NAME ("Ex_copy_buffer_to_buffer"); + ACPI_FUNCTION_NAME ("Ex_store_buffer_to_buffer"); /* @@ -89,28 +84,32 @@ if (length <= target_desc->buffer.length) { /* Clear existing buffer and copy in the new one */ - MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); - MEMCPY (target_desc->buffer.pointer, buffer, length); + ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); + ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length); } else { /* * Truncate the source, copy only what will fit */ - MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length); + ACPI_MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Truncating src buffer from %X to %X\n", length, target_desc->buffer.length)); } + /* Copy flags */ + + target_desc->buffer.flags = source_desc->buffer.flags; + return (AE_OK); } /******************************************************************************* * - * FUNCTION: Acpi_ex_copy_string_to_string + * FUNCTION: Acpi_ex_store_string_to_string * * PARAMETERS: Source_desc - Source object to copy * Target_desc - Destination object of the copy @@ -122,7 +121,7 @@ ******************************************************************************/ acpi_status -acpi_ex_copy_string_to_string ( +acpi_ex_store_string_to_string ( acpi_operand_object *source_desc, acpi_operand_object *target_desc) { @@ -130,7 +129,7 @@ u8 *buffer; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* @@ -145,8 +144,8 @@ if (length < target_desc->string.length) { /* Clear old string and copy in the new one */ - MEMSET (target_desc->string.pointer, 0, target_desc->string.length); - MEMCPY (target_desc->string.pointer, buffer, length); + ACPI_MEMSET (target_desc->string.pointer, 0, target_desc->string.length); + ACPI_MEMCPY (target_desc->string.pointer, buffer, length); } else { @@ -162,13 +161,13 @@ ACPI_MEM_FREE (target_desc->string.pointer); } - target_desc->string.pointer = ACPI_MEM_ALLOCATE (length + 1); + target_desc->string.pointer = ACPI_MEM_ALLOCATE ((ACPI_SIZE) length + 1); if (!target_desc->string.pointer) { return (AE_NO_MEMORY); } target_desc->string.length = length; - MEMCPY (target_desc->string.pointer, buffer, length); + ACPI_MEMCPY (target_desc->string.pointer, buffer, length); } return (AE_OK); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exsystem.c linux2.4.21_itanium/drivers/acpi/executer/exsystem.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exsystem.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exsystem.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,12 +27,10 @@ #include "acpi.h" #include "acinterp.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exsystem") + ACPI_MODULE_NAME ("exsystem") /******************************************************************************* @@ -56,9 +54,10 @@ u32 timeout) { acpi_status status; + acpi_status status2; - FUNCTION_TRACE ("Ex_system_wait_semaphore"); + ACPI_FUNCTION_TRACE ("Ex_system_wait_semaphore"); status = acpi_os_wait_semaphore (semaphore, 1, 0); @@ -78,11 +77,11 @@ /* Reacquire the interpreter */ - status = acpi_ex_enter_interpreter (); - if (ACPI_SUCCESS (status)) { - /* Restore the timeout exception */ + status2 = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status2)) { + /* Report fatal error, could not acquire interpreter */ - status = AE_TIME; + return_ACPI_STATUS (status2); } } @@ -96,17 +95,20 @@ * * PARAMETERS: How_long - The amount of time to stall * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Suspend running thread for specified amount of time. * ******************************************************************************/ -void +acpi_status acpi_ex_system_do_stall ( u32 how_long) { - FUNCTION_ENTRY (); + acpi_status status = AE_OK; + + + ACPI_FUNCTION_ENTRY (); if (how_long > 1000) /* 1 millisecond */ { @@ -118,12 +120,14 @@ /* And now we must get the interpreter again */ - acpi_ex_enter_interpreter (); + status = acpi_ex_enter_interpreter (); } else { acpi_os_sleep (0, (how_long / 1000) + 1); } + + return (status); } @@ -139,12 +143,14 @@ * ******************************************************************************/ -void +acpi_status acpi_ex_system_do_suspend ( u32 how_long) { + acpi_status status; - FUNCTION_ENTRY (); + + ACPI_FUNCTION_ENTRY (); /* Since this thread will sleep, we must release the interpreter */ @@ -156,7 +162,8 @@ /* And now we must get the interpreter again */ - acpi_ex_enter_interpreter (); + status = acpi_ex_enter_interpreter (); + return (status); } @@ -183,7 +190,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE_PTR ("Ex_system_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR ("Ex_system_acquire_mutex", obj_desc); if (!obj_desc) { @@ -194,7 +201,7 @@ * Support for the _GL_ Mutex object -- go get the global lock */ if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { - status = acpi_ev_acquire_global_lock (); + status = acpi_ev_acquire_global_lock ((u32) time_desc->integer.value); return_ACPI_STATUS (status); } @@ -226,7 +233,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_system_release_mutex"); + ACPI_FUNCTION_TRACE ("Ex_system_release_mutex"); if (!obj_desc) { @@ -237,8 +244,8 @@ * Support for the _GL_ Mutex object -- release the global lock */ if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { - acpi_ev_release_global_lock (); - return_ACPI_STATUS (AE_OK); + status = acpi_ev_release_global_lock (); + return_ACPI_STATUS (status); } status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); @@ -266,7 +273,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_system_signal_event"); + ACPI_FUNCTION_TRACE ("Ex_system_signal_event"); if (obj_desc) { @@ -300,7 +307,7 @@ acpi_status status = AE_OK; - FUNCTION_TRACE ("Ex_system_wait_event"); + ACPI_FUNCTION_TRACE ("Ex_system_wait_event"); if (obj_desc) { @@ -308,7 +315,6 @@ (u32) time_desc->integer.value); } - return_ACPI_STATUS (status); } @@ -333,7 +339,7 @@ void *temp_semaphore; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* @@ -342,7 +348,7 @@ */ status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); if (ACPI_SUCCESS (status)) { - acpi_os_delete_semaphore (obj_desc->event.semaphore); + (void) acpi_os_delete_semaphore (obj_desc->event.semaphore); obj_desc->event.semaphore = temp_semaphore; } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/executer/exutils.c linux2.4.21_itanium/drivers/acpi/executer/exutils.c --- linux2.4.21_itanium.org/drivers/acpi/executer/exutils.c Wed Jul 23 18:20:45 2003 +++ linux2.4.21_itanium/drivers/acpi/executer/exutils.c Wed Jul 23 18:28:13 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -42,15 +42,12 @@ #define DEFINE_AML_GLOBALS #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" #include "acevents.h" -#include "acparser.h" #define _COMPONENT ACPI_EXECUTER - MODULE_NAME ("exutils") + ACPI_MODULE_NAME ("exutils") /******************************************************************************* @@ -59,8 +56,8 @@ * * PARAMETERS: None * - * DESCRIPTION: Enter the interpreter execution region - * TBD: should be a macro + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ @@ -69,10 +66,14 @@ { acpi_status status; - FUNCTION_TRACE ("Ex_enter_interpreter"); + ACPI_FUNCTION_TRACE ("Ex_enter_interpreter"); status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n")); + } + return_ACPI_STATUS (status); } @@ -95,17 +96,21 @@ * already executing * 7) About to invoke a user-installed opregion handler * - * TBD: should be a macro - * ******************************************************************************/ void acpi_ex_exit_interpreter (void) { - FUNCTION_TRACE ("Ex_exit_interpreter"); + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Ex_exit_interpreter"); - acpi_ut_release_mutex (ACPI_MTX_EXECUTE); + status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not release interpreter mutex\n")); + } return_VOID; } @@ -126,7 +131,7 @@ acpi_object_type type) { - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || @@ -159,7 +164,7 @@ acpi_walk_state *walk_state) { - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); /* @@ -172,7 +177,7 @@ return; } - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + if (acpi_gbl_integer_byte_width == 4) { /* * We are running a method that exists in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper 32-bit field @@ -186,7 +191,8 @@ * * FUNCTION: Acpi_ex_acquire_global_lock * - * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock + * PARAMETERS: Field_flags - Flags with Lock rule: + * Always_lock or Never_lock * * RETURN: TRUE/FALSE indicating whether the lock was actually acquired * @@ -198,25 +204,24 @@ u8 acpi_ex_acquire_global_lock ( - u32 rule) + u32 field_flags) { u8 locked = FALSE; acpi_status status; - FUNCTION_TRACE ("Ex_acquire_global_lock"); + ACPI_FUNCTION_TRACE ("Ex_acquire_global_lock"); - /* Only attempt lock if the Rule says so */ + /* Only attempt lock if the Always_lock bit is set */ - if (rule == (u32) GLOCK_ALWAYS_LOCK) { - /* We should attempt to get the lock */ + if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* We should attempt to get the lock, wait forever */ - status = acpi_ev_acquire_global_lock (); + status = acpi_ev_acquire_global_lock (ACPI_UINT32_MAX); if (ACPI_SUCCESS (status)) { locked = TRUE; } - else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n", acpi_format_exception (status))); @@ -240,12 +245,14 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_release_global_lock ( u8 locked_by_me) { + acpi_status status; + - FUNCTION_TRACE ("Ex_release_global_lock"); + ACPI_FUNCTION_TRACE ("Ex_release_global_lock"); /* Only attempt unlock if the caller locked it */ @@ -253,11 +260,13 @@ if (locked_by_me) { /* OK, now release the lock */ - acpi_ev_release_global_lock (); - } - + status = acpi_ev_release_global_lock (); + if (ACPI_FAILURE (status)) { + /* Report the error, but there isn't much else we can do */ - return_ACPI_STATUS (AE_OK); + ACPI_REPORT_ERROR (("Could not release ACPI Global Lock\n")); + } + } } @@ -277,23 +286,24 @@ acpi_integer value, u32 base) { - u32 num_digits = 0; + u32 num_digits; + acpi_integer current_value; + acpi_integer quotient; - FUNCTION_TRACE ("Ex_digits_needed"); + ACPI_FUNCTION_TRACE ("Ex_digits_needed"); - if (base < 1) { - REPORT_ERROR (("Ex_digits_needed: Internal error - Invalid base\n")); - } + /* + * acpi_integer is unsigned, so we don't worry about a '-' + */ + current_value = value; + num_digits = 0; - else { - /* - * acpi_integer is unsigned, which is why we don't worry about a '-' - */ - for (num_digits = 1; - (acpi_ut_short_divide (&value, base, &value, NULL)); - ++num_digits) { ; } + while (current_value) { + (void) acpi_ut_short_divide (¤t_value, base, "ient, NULL); + num_digits++; + current_value = quotient; } return_VALUE (num_digits); @@ -302,45 +312,6 @@ /******************************************************************************* * - * FUNCTION: ntohl - * - * PARAMETERS: Value - Value to be converted - * - * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) - * - ******************************************************************************/ - -static u32 -_ntohl ( - u32 value) -{ - union { - u32 value; - u8 bytes[4]; - } out; - - union { - u32 value; - u8 bytes[4]; - } in; - - - FUNCTION_ENTRY (); - - - in.value = value; - - out.bytes[0] = in.bytes[3]; - out.bytes[1] = in.bytes[2]; - out.bytes[2] = in.bytes[1]; - out.bytes[3] = in.bytes[0]; - - return (out.value); -} - - -/******************************************************************************* - * * FUNCTION: Acpi_ex_eisa_id_to_string * * PARAMETERS: Numeric_id - EISA ID to be converted @@ -350,31 +321,29 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_eisa_id_to_string ( u32 numeric_id, NATIVE_CHAR *out_string) { - u32 id; + u32 eisa_id; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* swap to big-endian to get contiguous bits */ + /* Swap ID to big-endian to get contiguous bits */ - id = _ntohl (numeric_id); + eisa_id = acpi_ut_dword_byte_swap (numeric_id); - out_string[0] = (char) ('@' + ((id >> 26) & 0x1f)); - out_string[1] = (char) ('@' + ((id >> 21) & 0x1f)); - out_string[2] = (char) ('@' + ((id >> 16) & 0x1f)); - out_string[3] = acpi_ut_hex_to_ascii_char (id, 12); - out_string[4] = acpi_ut_hex_to_ascii_char (id, 8); - out_string[5] = acpi_ut_hex_to_ascii_char (id, 4); - out_string[6] = acpi_ut_hex_to_ascii_char (id, 0); + out_string[0] = (char) ('@' + ((eisa_id >> 26) & 0x1f)); + out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f)); + out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f)); + out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12); + out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8); + out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4); + out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0); out_string[7] = 0; - - return (AE_OK); } @@ -389,7 +358,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_unsigned_integer_to_string ( acpi_integer value, NATIVE_CHAR *out_string) @@ -397,20 +366,20 @@ u32 count; u32 digits_needed; u32 remainder; + acpi_integer quotient; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); digits_needed = acpi_ex_digits_needed (value, 10); out_string[digits_needed] = 0; for (count = digits_needed; count > 0; count--) { - acpi_ut_short_divide (&value, 10, &value, &remainder); - out_string[count-1] = (NATIVE_CHAR) ('0' + remainder); + (void) acpi_ut_short_divide (&value, 10, "ient, &remainder); + out_string[count-1] = (NATIVE_CHAR) ('0' + remainder);\ + value = quotient; } - - return (AE_OK); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/fan.c linux2.4.21_itanium/drivers/acpi/fan.c --- linux2.4.21_itanium.org/drivers/acpi/fan.c Thu Jan 1 09:00:00 1970 +++ linux2.4.21_itanium/drivers/acpi/fan.c Wed Jul 23 18:28:09 2003 @@ -0,0 +1,300 @@ +/* + * acpi_fan.c - ACPI Fan Driver ($Revision: 1.1.1.1 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or 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 +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_FAN_COMPONENT +ACPI_MODULE_NAME ("acpi_fan") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +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, + }, +}; + +struct acpi_fan { + acpi_handle handle; +}; + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#include +#include + +struct proc_dir_entry *acpi_fan_dir = NULL; + + +static int +acpi_fan_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_fan *fan = (struct acpi_fan *) data; + char *p = page; + int len = 0; + int state = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_read_state"); + + if (!fan || (off != 0)) + goto end; + + if (0 != acpi_bus_get_power(fan->handle, &state)) + goto end; + + p += sprintf(p, "status: %s\n", + !state?"on":"off"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_fan_write_state ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_fan *fan = (struct acpi_fan *) data; + char state_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_fan_write_state"); + + if (!fan || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + result = acpi_bus_set_power(fan->handle, + simple_strtoul(state_string, NULL, 0)); + if (0 != result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_fan_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_fan_add_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (!acpi_fan_dir) { + acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); + if (!acpi_fan_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_fan_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'status' [R/W] */ + entry = create_proc_entry(ACPI_FAN_FILE_STATE, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_FAN_FILE_STATE)); + else { + entry->read_proc = acpi_fan_read_state; + entry->write_proc = acpi_fan_write_state; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_fan_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_fan_remove_fs"); + + if (!acpi_fan_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +int +acpi_fan_add ( + struct acpi_device *device) +{ + int result = 0; + struct acpi_fan *fan = NULL; + int state = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_add"); + + if (!device) + return_VALUE(-EINVAL); + + fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL); + if (!fan) + return_VALUE(-ENOMEM); + memset(fan, 0, sizeof(struct acpi_fan)); + + fan->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_FAN_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_FAN_CLASS); + acpi_driver_data(device) = fan; + + result = acpi_bus_get_power(fan->handle, &state); + if (0 != result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading power state\n")); + goto end; + } + + result = acpi_fan_add_fs(device); + if (0 != result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), + !device->power.state?"on":"off"); + +end: + if (0 != result) + kfree(fan); + + return_VALUE(result); +} + + +int +acpi_fan_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_fan *fan = NULL; + + ACPI_FUNCTION_TRACE("acpi_fan_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + fan = (struct acpi_fan *) acpi_driver_data(device); + + acpi_fan_remove_fs(device); + + kfree(fan); + + return_VALUE(0); +} + + +int __init +acpi_fan_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_init"); + + result = acpi_bus_register_driver(&acpi_fan_driver); + if (0 > result) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +void __exit +acpi_fan_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_exit"); + + result = acpi_bus_unregister_driver(&acpi_fan_driver); + if (0 == result) + remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_fan_init); +module_exit(acpi_fan_exit); + diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/Makefile linux2.4.21_itanium/drivers/acpi/hardware/Makefile --- linux2.4.21_itanium.org/drivers/acpi/hardware/Makefile Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/Makefile Wed Jul 23 18:28:09 2003 @@ -1,11 +1,10 @@ # # Makefile for all Linux ACPI interpreter subdirectories -# EXCEPT for the ospm directory # O_TARGET := $(notdir $(CURDIR)).o -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) +obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/hwacpi.c linux2.4.21_itanium/drivers/acpi/hardware/hwacpi.c --- linux2.4.21_itanium.org/drivers/acpi/hardware/hwacpi.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/hwacpi.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -26,11 +26,10 @@ #include "acpi.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE - MODULE_NAME ("hwacpi") + ACPI_MODULE_NAME ("hwacpi") /****************************************************************************** @@ -49,131 +48,28 @@ acpi_hw_initialize ( void) { - acpi_status status = AE_OK; - u32 index; + acpi_status status; - FUNCTION_TRACE ("Hw_initialize"); + ACPI_FUNCTION_TRACE ("Hw_initialize"); /* We must have the ACPI tables by the time we get here */ if (!acpi_gbl_FADT) { - acpi_gbl_restore_acpi_chipset = FALSE; - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "A FADT is not loaded\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } - /* Identify current ACPI/legacy mode */ - - switch (acpi_gbl_system_flags & SYS_MODES_MASK) { - case (SYS_MODE_ACPI): - - acpi_gbl_original_mode = SYS_MODE_ACPI; - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n")); - break; - - - case (SYS_MODE_LEGACY): - - acpi_gbl_original_mode = SYS_MODE_LEGACY; - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n")); - break; - - - case (SYS_MODE_ACPI | SYS_MODE_LEGACY): - - if (acpi_hw_get_mode () == SYS_MODE_ACPI) { - acpi_gbl_original_mode = SYS_MODE_ACPI; - } - else { - acpi_gbl_original_mode = SYS_MODE_LEGACY; - } - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "System supports both ACPI and LEGACY modes.\n")); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "System is currently in %s mode.\n", - (acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY")); - break; - } - - - if (acpi_gbl_system_flags & SYS_MODE_ACPI) { - /* Target system supports ACPI mode */ - - /* - * The purpose of this code is to save the initial state - * of the ACPI event enable registers. An exit function will be - * registered which will restore this state when the application - * exits. The exit function will also clear all of the ACPI event - * status bits prior to restoring the original mode. - * - * The location of the PM1a_evt_blk enable registers is defined as the - * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further - * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset - * for the enable registers is always 2 from the base. It is hard - * coded here. If this changes in the spec, this code will need to - * be modified. The PM1b_evt_blk behaves as expected. - */ - acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read ( - ACPI_MTX_LOCK, PM1_EN); - - - /* - * The GPEs behave similarly, except that the length of the register - * block is not fixed, so the buffer must be allocated with malloc - */ - if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && - acpi_gbl_FADT->gpe0blk_len) { - /* GPE0 specified in FADT */ - - acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE ( - DIV_2 (acpi_gbl_FADT->gpe0blk_len)); - if (!acpi_gbl_gpe0enable_register_save) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Save state of GPE0 enable bits */ - - for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { - acpi_gbl_gpe0enable_register_save[index] = - (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index); - } - } - - else { - acpi_gbl_gpe0enable_register_save = NULL; - } + /* Sanity check the FADT for valid values */ - if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && - acpi_gbl_FADT->gpe1_blk_len) { - /* GPE1 defined */ - - acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE ( - DIV_2 (acpi_gbl_FADT->gpe1_blk_len)); - if (!acpi_gbl_gpe1_enable_register_save) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* save state of GPE1 enable bits */ - - for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { - acpi_gbl_gpe1_enable_register_save[index] = - (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index); - } - } - - else { - acpi_gbl_gpe1_enable_register_save = NULL; - } + status = acpi_ut_validate_fadt (); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - return_ACPI_STATUS (status); + return_ACPI_STATUS (AE_OK); } @@ -185,8 +81,7 @@ * * RETURN: Status * - * DESCRIPTION: Transitions the system into the requested mode or does nothing - * if the system is already in that mode. + * DESCRIPTION: Transitions the system into the requested mode. * ******************************************************************************/ @@ -195,36 +90,68 @@ u32 mode) { - acpi_status status = AE_NO_HARDWARE_RESPONSE; + acpi_status status; + u32 retry; - FUNCTION_TRACE ("Hw_set_mode"); + ACPI_FUNCTION_TRACE ("Hw_set_mode"); - if (mode == SYS_MODE_ACPI) { + if (mode == acpi_hw_get_mode()) + return_ACPI_STATUS (AE_OK); + + /* If no SMI_CMD, system does not support SMI */ + if (!acpi_gbl_FADT->smi_cmd) + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); + + switch (mode) { + case ACPI_SYS_MODE_ACPI: + /* BIOS should have disabled ALL fixed and GP events */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, + (acpi_integer) acpi_gbl_FADT->acpi_enable, 8); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); - } + break; - else if (mode == SYS_MODE_LEGACY) { + case ACPI_SYS_MODE_LEGACY: + + /* If both enable/disable are zero, legacy mode is not supported */ + if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); + /* * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, + (acpi_integer) acpi_gbl_FADT->acpi_disable, 8); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); + break; + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Give the platform some time to react */ + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_os_stall (20000); + /* + * Some hardware takes a LONG time to switch modes. Give them 3 sec to + * do so, but allow faster systems to proceed more quickly. + */ + retry = 3000; + while (retry) { + status = AE_NO_HARDWARE_RESPONSE; - if (acpi_hw_get_mode () == mode) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode)); - status = AE_OK; + if (acpi_hw_get_mode() == mode) { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode)); + status = AE_OK; + break; + } + acpi_os_stall(1000); + retry--; } return_ACPI_STATUS (status); @@ -247,74 +174,33 @@ u32 acpi_hw_get_mode (void) { + acpi_status status; + u32 value; - FUNCTION_TRACE ("Hw_get_mode"); + ACPI_FUNCTION_TRACE ("Hw_get_mode"); - if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) { - return_VALUE (SYS_MODE_ACPI); + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_VALUE (ACPI_SYS_MODE_LEGACY); } - else { - return_VALUE (SYS_MODE_LEGACY); - } -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_hw_get_mode_capabilities - * - * PARAMETERS: none - * - * RETURN: logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial - * system state. - * - * DESCRIPTION: Returns capablities of system - * - ******************************************************************************/ - -u32 -acpi_hw_get_mode_capabilities (void) -{ - - FUNCTION_TRACE ("Hw_get_mode_capabilities"); - - if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) { - if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { - /* - * Assume that if this call is being made, Acpi_init has been called - * and ACPI support has been established by the presence of the - * tables. Therefore since we're in SYS_MODE_LEGACY, the system - * must support both modes - */ - acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); + if (value) { + return_VALUE (ACPI_SYS_MODE_ACPI); + } + else { +#ifdef CONFIG_IA64_HP_PROTO + /* + * If enable/disable are zero, the system doesn't support + * legacy mode, so the SCI_EN is wrong. + */ + if (!acpi_gbl_FADT->acpi_enable && + !acpi_gbl_FADT->acpi_disable) { + printk("Warning: Ignoring bogus SCI_EN value\n"); + return_VALUE (ACPI_SYS_MODE_ACPI); } +#endif - else { - /* TBD: [Investigate] !!! this may be unsafe... */ - /* - * system is is ACPI mode, so try to switch back to LEGACY to see if - * it is supported - */ - acpi_hw_set_mode (SYS_MODE_LEGACY); - - if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { - /* Now in SYS_MODE_LEGACY, so both are supported */ - - acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); - acpi_hw_set_mode (SYS_MODE_ACPI); - } - - else { - /* Still in SYS_MODE_ACPI so this must be an ACPI only system */ - - acpi_gbl_system_flags |= SYS_MODE_ACPI; - } - } + return_VALUE (ACPI_SYS_MODE_LEGACY); } - - return_VALUE (acpi_gbl_system_flags & SYS_MODES_MASK); } - - diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/hwgpe.c linux2.4.21_itanium/drivers/acpi/hardware/hwgpe.c --- linux2.4.21_itanium.org/drivers/acpi/hardware/hwgpe.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/hwgpe.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,12 +25,30 @@ */ #include "acpi.h" -#include "achware.h" -#include "acnamesp.h" #include "acevents.h" #define _COMPONENT ACPI_HARDWARE - MODULE_NAME ("hwgpe") + ACPI_MODULE_NAME ("hwgpe") + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_gpe_bit_mask + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: Gpe register bitmask for this gpe level + * + * DESCRIPTION: Get the bitmask for this GPE + * + ******************************************************************************/ + +u8 +acpi_hw_get_gpe_bit_mask ( + u32 gpe_number) +{ + return (acpi_gbl_gpe_number_info [acpi_ev_get_gpe_number_index (gpe_number)].bit_mask); +} /****************************************************************************** @@ -45,38 +63,44 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_enable_gpe ( u32 gpe_number) { u32 in_byte; u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); /* * Read the current value of the register, set the appropriate bit * to enable the GPE, and write out the new register. */ - in_byte = 0; - acpi_os_read_port (acpi_gbl_gpe_registers[register_index].enable_addr, &in_byte, 8); - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, - (in_byte | bit_mask), 8); + status = acpi_hw_low_level_read (8, &in_byte, + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_hw_low_level_write (8, (in_byte | bit_mask), + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + + return (status); } + /****************************************************************************** * * FUNCTION: Acpi_hw_enable_gpe_for_wakeup @@ -95,28 +119,27 @@ u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); /* * Set the bit so we will not disable this when sleeping */ - acpi_gbl_gpe_registers[register_index].wake_enable |= bit_mask; + acpi_gbl_gpe_register_info[register_index].wake_enable |= bit_mask; } + /****************************************************************************** * * FUNCTION: Acpi_hw_disable_gpe @@ -129,40 +152,48 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_disable_gpe ( u32 gpe_number) { u32 in_byte; u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); /* * Read the current value of the register, clear the appropriate bit, * and write out the new register value to disable the GPE. */ - in_byte = 0; - acpi_os_read_port (acpi_gbl_gpe_registers[register_index].enable_addr, &in_byte, 8); - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, - (in_byte & ~bit_mask), 8); + status = acpi_hw_low_level_read (8, &in_byte, + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_hw_low_level_write (8, (in_byte & ~bit_mask), + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } acpi_hw_disable_gpe_for_wakeup(gpe_number); + return (AE_OK); } + /****************************************************************************** * * FUNCTION: Acpi_hw_disable_gpe_for_wakeup @@ -181,28 +212,27 @@ u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); /* * Clear the bit so we will disable this when sleeping */ - acpi_gbl_gpe_registers[register_index].wake_enable &= ~bit_mask; + acpi_gbl_gpe_register_info[register_index].wake_enable &= ~bit_mask; } + /****************************************************************************** * * FUNCTION: Acpi_hw_clear_gpe @@ -215,32 +245,34 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_clear_gpe ( u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); /* * Write a one to the appropriate bit in the status register to * clear this GPE. */ - acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, bit_mask, 8); + status = acpi_hw_low_level_write (8, bit_mask, + &acpi_gbl_gpe_register_info[register_index].status_address, 0); + + return (status); } @@ -256,61 +288,67 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_get_gpe_status ( u32 gpe_number, acpi_event_status *event_status) { u32 in_byte = 0; u32 register_index = 0; - u32 bit_mask = 0; + u8 bit_mask = 0; + ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_ENTRY (); if (!event_status) { - return; + return (AE_BAD_PARAMETER); } (*event_status) = 0; - /* - * Translate GPE number to index into global registers array. - */ - register_index = acpi_gbl_gpe_valid[gpe_number]; + /* Translate GPE number to index into global registers array. */ - /* - * Figure out the bit offset for this GPE within the target register. - */ - bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + register_index = acpi_ev_get_gpe_register_index (gpe_number); + gpe_register_info = &acpi_gbl_gpe_register_info[register_index]; + + /* Get the register bitmask for this GPE */ + + bit_mask = acpi_hw_get_gpe_bit_mask (gpe_number); + + /* GPE Enabled? */ + + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } - /* - * Enabled?: - */ - in_byte = 0; - acpi_os_read_port (acpi_gbl_gpe_registers[register_index].enable_addr, &in_byte, 8); if (bit_mask & in_byte) { (*event_status) |= ACPI_EVENT_FLAG_ENABLED; } - /* - * Enabled for wake?: - */ - if (bit_mask & acpi_gbl_gpe_registers[register_index].wake_enable) { + /* GPE Enabled for wake? */ + + if (bit_mask & gpe_register_info->wake_enable) { (*event_status) |= ACPI_EVENT_FLAG_WAKE_ENABLED; } - /* - * Set? - */ - in_byte = 0; - acpi_os_read_port (acpi_gbl_gpe_registers[register_index].status_addr, &in_byte, 8); + /* GPE active (set)? */ + + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + if (bit_mask & in_byte) { (*event_status) |= ACPI_EVENT_FLAG_SET; } + return (AE_OK); } + /****************************************************************************** * * FUNCTION: Acpi_hw_disable_non_wakeup_gpes @@ -321,36 +359,53 @@ * * DESCRIPTION: Disable all non-wakeup GPEs * Call with interrupts disabled. The interrupt handler also - * modifies Acpi_gbl_Gpe_registers[i].Enable, so it should not be + * modifies Acpi_gbl_Gpe_register_info[i].Enable, so it should not be * given the chance to run until after non-wake GPEs are * re-enabled. * ******************************************************************************/ -void +acpi_status acpi_hw_disable_non_wakeup_gpes ( void) { u32 i; + ACPI_GPE_REGISTER_INFO *gpe_register_info; + u32 in_value; + acpi_status status; + + + ACPI_FUNCTION_ENTRY (); - FUNCTION_ENTRY (); for (i = 0; i < acpi_gbl_gpe_register_count; i++) { + gpe_register_info = &acpi_gbl_gpe_register_info[i]; + /* * Read the enabled status of all GPEs. We * will be using it to restore all the GPEs later. */ - acpi_os_read_port (acpi_gbl_gpe_registers[i].enable_addr, - &acpi_gbl_gpe_registers[i].enable, 8); + status = acpi_hw_low_level_read (8, &in_value, + &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + gpe_register_info->enable = (u8) in_value; /* - * Disable all GPEs but wakeup GPEs. + * Disable all GPEs except wakeup GPEs. */ - acpi_os_write_port(acpi_gbl_gpe_registers[i].enable_addr, - acpi_gbl_gpe_registers[i].wake_enable, 8); + status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, + &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } } + return (AE_OK); } + /****************************************************************************** * * FUNCTION: Acpi_hw_enable_non_wakeup_gpes @@ -363,20 +418,30 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_enable_non_wakeup_gpes ( void) { u32 i; + ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; + + + ACPI_FUNCTION_ENTRY (); - FUNCTION_ENTRY (); for (i = 0; i < acpi_gbl_gpe_register_count; i++) { + gpe_register_info = &acpi_gbl_gpe_register_info[i]; + /* * We previously stored the enabled status of all GPEs. * Blast them back in. */ - acpi_os_write_port(acpi_gbl_gpe_registers[i].enable_addr, - acpi_gbl_gpe_registers[i].enable, 8); + status = acpi_hw_low_level_write (8, gpe_register_info->enable, + &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } } + return (AE_OK); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/hwregs.c linux2.4.21_itanium/drivers/acpi/hardware/hwregs.c --- linux2.4.21_itanium.org/drivers/acpi/hardware/hwregs.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/hwregs.c Wed Jul 23 18:28:09 2003 @@ -8,7 +8,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,40 +27,10 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #define _COMPONENT ACPI_HARDWARE - MODULE_NAME ("hwregs") - - -/******************************************************************************* - * - * FUNCTION: Acpi_hw_get_bit_shift - * - * PARAMETERS: Mask - Input mask to determine bit shift from. - * Must have at least 1 bit set. - * - * RETURN: Bit location of the lsb of the mask - * - * DESCRIPTION: Returns the bit number for the low order bit that's set. - * - ******************************************************************************/ - -u32 -acpi_hw_get_bit_shift ( - u32 mask) -{ - u32 shift; - - - FUNCTION_TRACE ("Hw_get_bit_shift"); - - - for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; } - - return_VALUE (shift); -} + ACPI_MODULE_NAME ("hwregs") /******************************************************************************* @@ -75,92 +45,94 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_clear_acpi_status (void) { - u16 gpe_length; - u16 index; + NATIVE_UINT_MAX32 i; + NATIVE_UINT gpe_block; + acpi_status status; - FUNCTION_TRACE ("Hw_clear_acpi_status"); + ACPI_FUNCTION_TRACE ("Hw_clear_acpi_status"); ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n", - ALL_FIXED_STS_BITS, + ACPI_BITMASK_ALL_FIXED_STATUS, (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address))); - acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); - - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS); - - - if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) { - acpi_os_write_port ((ACPI_IO_ADDRESS) - ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address), - ALL_FIXED_STS_BITS, 16); + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - /* now clear the GPE Bits */ + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, + ACPI_BITMASK_ALL_FIXED_STATUS); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - if (acpi_gbl_FADT->gpe0blk_len) { - gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len); + /* Clear the fixed events */ - for (index = 0; index < gpe_length; index++) { - acpi_os_write_port ((ACPI_IO_ADDRESS) ( - ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index), - 0xFF, 8); + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) { + status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS, + &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; } } - if (acpi_gbl_FADT->gpe1_blk_len) { - gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len); + /* Clear the GPE Bits */ - for (index = 0; index < gpe_length; index++) { - acpi_os_write_port ((ACPI_IO_ADDRESS) ( - ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index), - 0xFF, 8); + for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) { + for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) { + status = acpi_hw_low_level_write (8, 0xFF, + acpi_gbl_gpe_block_info[gpe_block].block_address, i); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } } } - acpi_ut_release_mutex (ACPI_MTX_HARDWARE); - return_VOID; +unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + return_ACPI_STATUS (status); } /******************************************************************************* * - * FUNCTION: Acpi_hw_obtain_sleep_type_register_data + * FUNCTION: Acpi_get_sleep_type_data * - * PARAMETERS: Sleep_state - Numeric state requested - * *Slp_Typ_a - Pointer to byte to receive SLP_TYPa value - * *Slp_Typ_b - Pointer to byte to receive SLP_TYPb value + * PARAMETERS: Sleep_state - Numeric sleep state + * *Sleep_type_a - Where SLP_TYPa is returned + * *Sleep_type_b - Where SLP_TYPb is returned * * RETURN: Status - ACPI status * - * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and - * SLP_TYPb values for the sleep state requested. + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep + * state. * ******************************************************************************/ acpi_status -acpi_hw_obtain_sleep_type_register_data ( +acpi_get_sleep_type_data ( u8 sleep_state, - u8 *slp_typ_a, - u8 *slp_typ_b) + u8 *sleep_type_a, + u8 *sleep_type_b) { acpi_status status = AE_OK; acpi_operand_object *obj_desc; - FUNCTION_TRACE ("Hw_obtain_sleep_type_register_data"); + ACPI_FUNCTION_TRACE ("Acpi_get_sleep_type_data"); /* * Validate parameters */ if ((sleep_state > ACPI_S_STATES_MAX) || - !slp_typ_a || !slp_typ_b) { + !sleep_type_a || !sleep_type_b) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -174,7 +146,7 @@ } if (!obj_desc) { - REPORT_ERROR (("Missing Sleep State object\n")); + ACPI_REPORT_ERROR (("Missing Sleep State object\n")); return_ACPI_STATUS (AE_NOT_EXIST); } @@ -185,387 +157,281 @@ */ /* Even though Acpi_evaluate_object resolves package references, - * Ns_evaluate dpesn't. So, we do it here. + * Ns_evaluate doesn't. So, we do it here. */ status = acpi_ut_resolve_package_references(obj_desc); if (obj_desc->package.count < 2) { /* Must have at least two elements */ - REPORT_ERROR (("Sleep State package does not have at least two elements\n")); - status = AE_ERROR; + ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n")); + status = AE_AML_NO_OPERAND; } - - else if (((obj_desc->package.elements[0])->common.type != - ACPI_TYPE_INTEGER) || - ((obj_desc->package.elements[1])->common.type != - ACPI_TYPE_INTEGER)) { + else if (((obj_desc->package.elements[0])->common.type != ACPI_TYPE_INTEGER) || + ((obj_desc->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) { /* Must have two */ - REPORT_ERROR (("Sleep State package elements are not both of type Number\n")); - status = AE_ERROR; + ACPI_REPORT_ERROR (("Sleep State package elements are not both of type Number\n")); + status = AE_AML_OPERAND_TYPE; } - else { /* * Valid _Sx_ package size, type, and value */ - *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value; - - *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value; + *sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value; + *sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value; } - if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n", obj_desc, obj_desc->common.type)); } acpi_ut_remove_reference (obj_desc); - return_ACPI_STATUS (status); } /******************************************************************************* * - * FUNCTION: Acpi_hw_register_bit_access + * FUNCTION: Acpi_hw_get_register_bit_mask * - * PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE. - * Use_lock - Lock the hardware - * Register_id - index of ACPI Register to access - * Value - (only used on write) value to write to the - * Register. Shifted all the way right. + * PARAMETERS: Register_id - index of ACPI Register to access * - * RETURN: Value written to or read from specified Register. This value - * is shifted all the way right. + * RETURN: The bit mask to be used when accessing the register * - * DESCRIPTION: Generic ACPI Register read/write function. + * DESCRIPTION: Map Register_id into a register bit mask. * ******************************************************************************/ -u32 -acpi_hw_register_bit_access ( - NATIVE_UINT read_write, - u8 use_lock, - u32 register_id, - ...) /* Value (only used on write) */ +ACPI_BIT_REGISTER_INFO * +acpi_hw_get_bit_register_info ( + u32 register_id) { - u32 register_value = 0; - u32 mask = 0; - u32 value = 0; - va_list marker; - + ACPI_FUNCTION_NAME ("Hw_get_bit_register_info"); - FUNCTION_TRACE ("Hw_register_bit_access"); - - - if (read_write == ACPI_WRITE) { - va_start (marker, register_id); - value = va_arg (marker, u32); - va_end (marker); - } - if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (register_id > ACPI_BITREG_MAX) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid Bit_register ID: %X\n", register_id)); + return (NULL); } - /* - * Decode the Register ID - * Register id = Register block id | bit id - * - * Check bit id to fine locate Register offset. - * Check Mask to determine Register offset, and then read-write. - */ - switch (REGISTER_BLOCK_ID (register_id)) { - case PM1_STS: - - switch (register_id) { - case TMR_STS: - mask = TMR_STS_MASK; - break; - - case BM_STS: - mask = BM_STS_MASK; - break; - - case GBL_STS: - mask = GBL_STS_MASK; - break; - - case PWRBTN_STS: - mask = PWRBTN_STS_MASK; - break; - - case SLPBTN_STS: - mask = SLPBTN_STS_MASK; - break; - - case RTC_STS: - mask = RTC_STS_MASK; - break; - - case WAK_STS: - mask = WAK_STS_MASK; - break; - - default: - mask = 0; - break; - } - - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS); - - if (read_write == ACPI_WRITE) { - /* - * Status Registers are different from the rest. Clear by - * writing 1, writing 0 has no effect. So, the only relevent - * information is the single bit we're interested in, all - * others should be written as 0 so they will be left - * unchanged - */ - value <<= acpi_hw_get_bit_shift (mask); - value &= mask; - - if (value) { - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, - (u16) value); - register_value = 0; - } - } - - break; - - - case PM1_EN: + return (&acpi_gbl_bit_register_info[register_id]); +} - switch (register_id) { - case TMR_EN: - mask = TMR_EN_MASK; - break; - case GBL_EN: - mask = GBL_EN_MASK; - break; +/******************************************************************************* + * + * FUNCTION: Acpi_get_register + * + * PARAMETERS: Register_id - index of ACPI Register to access + * Use_lock - Lock the hardware + * + * RETURN: Value is read from specified Register. Value returned is + * normalized to bit0 (is shifted all the way right) + * + * DESCRIPTION: ACPI Bit_register read function. + * + ******************************************************************************/ - case PWRBTN_EN: - mask = PWRBTN_EN_MASK; - break; +acpi_status +acpi_get_register ( + u32 register_id, + u32 *return_value, + u32 flags) +{ + u32 register_value = 0; + ACPI_BIT_REGISTER_INFO *bit_reg_info; + acpi_status status; - case SLPBTN_EN: - mask = SLPBTN_EN_MASK; - break; - case RTC_EN: - mask = RTC_EN_MASK; - break; + ACPI_FUNCTION_TRACE ("Acpi_get_register"); - default: - mask = 0; - break; - } - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN); + /* Get the info structure corresponding to the requested ACPI Register */ - if (read_write == ACPI_WRITE) { - register_value &= ~mask; - value <<= acpi_hw_get_bit_shift (mask); - value &= mask; - register_value |= value; + bit_reg_info = acpi_hw_get_bit_register_info (register_id); + if (!bit_reg_info) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value); + if (flags & ACPI_MTX_LOCK) { + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } + } - break; - - - case PM1_CONTROL: + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + bit_reg_info->parent_register, ®ister_value); - switch (register_id) { - case SCI_EN: - mask = SCI_EN_MASK; - break; + if (flags & ACPI_MTX_LOCK) { + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + } - case BM_RLD: - mask = BM_RLD_MASK; - break; + if (ACPI_SUCCESS (status)) { + /* Normalize the value that was read */ - case GBL_RLS: - mask = GBL_RLS_MASK; - break; + register_value = ((register_value & bit_reg_info->access_bit_mask) + >> bit_reg_info->bit_position); - case SLP_TYPE_A: - case SLP_TYPE_B: - mask = SLP_TYPE_X_MASK; - break; + *return_value = register_value; - case SLP_EN: - mask = SLP_EN_MASK; - break; + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %X\n", register_value)); + } - default: - mask = 0; - break; - } + return_ACPI_STATUS (status); +} - /* - * Read the PM1 Control register. - * Note that at this level, the fact that there are actually TWO - * registers (A and B) and that B may not exist, are abstracted. - */ - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL); +/******************************************************************************* + * + * FUNCTION: Acpi_set_register + * + * PARAMETERS: Register_id - ID of ACPI Bit_register to access + * Value - (only used on write) value to write to the + * Register, NOT pre-normalized to the bit pos. + * Flags - Lock the hardware or not + * + * RETURN: None + * + * DESCRIPTION: ACPI Bit Register write function. + * + ******************************************************************************/ - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value)); +acpi_status +acpi_set_register ( + u32 register_id, + u32 value, + u32 flags) +{ + u32 register_value = 0; + ACPI_BIT_REGISTER_INFO *bit_reg_info; + acpi_status status; - if (read_write == ACPI_WRITE) { - register_value &= ~mask; - value <<= acpi_hw_get_bit_shift (mask); - value &= mask; - register_value |= value; - /* - * SLP_TYPE_x Registers are written differently - * than any other control Registers with - * respect to A and B Registers. The value - * for A may be different than the value for B - * - * Therefore, pass the Register_id, not just generic PM1_CONTROL, - * because we need to do different things. Yuck. - */ - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, - (u16) register_value); - } - break; + ACPI_FUNCTION_TRACE_U32 ("Acpi_set_register", register_id); - case PM2_CONTROL: + /* Get the info structure corresponding to the requested ACPI Register */ - switch (register_id) { - case ARB_DIS: - mask = ARB_DIS_MASK; - break; + bit_reg_info = acpi_hw_get_bit_register_info (register_id); + if (!bit_reg_info) { + ACPI_REPORT_ERROR (("Bad ACPI HW Register_id: %X\n", register_id)); + return_ACPI_STATUS (AE_BAD_PARAMETER); + } - default: - mask = 0; - break; + if (flags & ACPI_MTX_LOCK) { + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } + } - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); - - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", - register_value, HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address), - LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address))); + /* Always do a register read first so we can insert the new bits */ - if (read_write == ACPI_WRITE) { - register_value &= ~mask; - value <<= acpi_hw_get_bit_shift (mask); - value &= mask; - register_value |= value; + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + bit_reg_info->parent_register, ®ister_value); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", - register_value, - HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address), - LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address))); + /* + * Decode the Register ID + * Register id = Register block id | bit id + * + * Check bit id to fine locate Register offset. + * Check Mask to determine Register offset, and then read-write. + */ + switch (bit_reg_info->parent_register) { + case ACPI_REGISTER_PM1_STATUS: - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, - PM2_CONTROL, (u8) (register_value)); + /* + * Status Registers are different from the rest. Clear by + * writing 1, writing 0 has no effect. So, the only relevent + * information is the single bit we're interested in, all others should + * be written as 0 so they will be left unchanged + */ + value = ACPI_REGISTER_PREPARE_BITS (value, + bit_reg_info->bit_position, bit_reg_info->access_bit_mask); + if (value) { + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_STATUS, (u16) value); + register_value = 0; } break; - case PM_TIMER: + case ACPI_REGISTER_PM1_ENABLE: - mask = TMR_VAL_MASK; - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, - PM_TIMER); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %8.8X%8.8X\n", - register_value, - HIDWORD(acpi_gbl_FADT->Xpm_tmr_blk.address), - LODWORD(acpi_gbl_FADT->Xpm_tmr_blk.address))); + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_ENABLE, (u16) register_value); break; - case GPE1_EN_BLOCK: - case GPE1_STS_BLOCK: - case GPE0_EN_BLOCK: - case GPE0_STS_BLOCK: - - /* Determine the bit to be accessed - * - * (u32) Register_id: - * 31 24 16 8 0 - * +--------+--------+--------+--------+ - * | gpe_block_id | gpe_bit_number | - * +--------+--------+--------+--------+ - * - * gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK - * gpe_bit_number is relative from the gpe_block (0x00~0xFF) - */ - mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */ - register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3); - mask = acpi_gbl_decode_to8bit [mask % 8]; + case ACPI_REGISTER_PM1_CONTROL: /* - * The base address of the GPE 0 Register Block - * Plus 1/2 the length of the GPE 0 Register Block - * The enable Register is the Register following the Status Register - * and each Register is defined as 1/2 of the total Register Block + * Read the PM1 Control register. + * Note that at this level, the fact that there are actually TWO + * registers (A and B - and that B may not exist) is abstracted. */ + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value)); - /* - * This sets the bit within Enable_bit that needs to be written to - * the Register indicated in Mask to a 1, all others are 0 - */ + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); - /* Now get the current Enable Bits in the selected Reg */ + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, + (u16) register_value); + break; - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n", - register_value, register_id)); - if (read_write == ACPI_WRITE) { - register_value &= ~mask; - value <<= acpi_hw_get_bit_shift (mask); - value &= mask; - register_value |= value; + case ACPI_REGISTER_PM2_CONTROL: - /* - * This write will put the Action state into the General Purpose - * Enable Register indexed by the value in Mask - */ - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n", - register_value, register_id)); - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, - (u8) register_value); - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, - register_id); + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM2_CONTROL, ®ister_value); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; } - break; + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", + register_value, + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)))); - case SMI_CMD_BLOCK: - case PROCESSOR_BLOCK: + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); - /* Not used by any callers at this time - therefore, not implemented */ + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", + register_value, + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)))); + + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM2_CONTROL, (u8) (register_value)); + break; - default: - mask = 0; + default: break; } - if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + +unlock_and_exit: + + if (flags & ACPI_MTX_LOCK) { + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } + /* Normalize the value that was read */ - register_value &= mask; - register_value >>= acpi_hw_get_bit_shift (mask); + ACPI_DEBUG_EXEC (register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position)); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", register_value)); - return_VALUE (register_value); + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register Write actual %X\n", register_value)); + return_ACPI_STATUS (status); } @@ -583,103 +449,98 @@ * ******************************************************************************/ -u32 +acpi_status acpi_hw_register_read ( u8 use_lock, - u32 register_id) + u32 register_id, + u32 *return_value) { - u32 value = 0; + u32 value1 = 0; + u32 value2 = 0; u32 bank_offset; + acpi_status status; - FUNCTION_TRACE ("Hw_register_read"); + ACPI_FUNCTION_TRACE ("Hw_register_read"); if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } + switch (register_id) { + case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - switch (REGISTER_BLOCK_ID(register_id)) { - case PM1_STS: /* 16-bit access */ + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + value1 |= value2; break; - case PM1_EN: /* 16-bit access*/ - - bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len); - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); - break; - + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ - case PM1_CONTROL: /* 16-bit access */ + bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + value1 |= value2; break; - case PM2_CONTROL: /* 8-bit access */ + case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); - break; - - - case PM_TIMER: /* 32-bit access */ + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + value1 |= value2; break; - /* - * For the GPE? Blocks, the lower word of Register_id contains the - * byte offset for which to read, as each part of each block may be - * several bytes long. - */ - case GPE0_STS_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - bank_offset = REGISTER_BIT_ID(register_id); - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset); + status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); break; - case GPE0_EN_BLOCK: /* 8-bit access */ - - bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id); - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset); - break; - case GPE1_STS_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - bank_offset = REGISTER_BIT_ID(register_id); - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); + status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->Xpm_tmr_blk, 0); break; - case GPE1_EN_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id); - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); - break; - - case SMI_CMD_BLOCK: /* 8bit */ - - acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8); + status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8); break; default: - /* Value will be returned as 0 */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", register_id)); + status = AE_BAD_PARAMETER; break; } - +unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + } + + if (ACPI_SUCCESS (status)) { + *return_value = value1; } - return_VALUE (value); + return_ACPI_STATUS (status); } @@ -697,118 +558,104 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_register_write ( u8 use_lock, u32 register_id, u32 value) { u32 bank_offset; + acpi_status status; - FUNCTION_TRACE ("Hw_register_write"); + ACPI_FUNCTION_TRACE ("Hw_register_write"); if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } + switch (register_id) { + case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - switch (REGISTER_BLOCK_ID (register_id)) { - case PM1_STS: /* 16-bit access */ - - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); - break; - - - case PM1_EN: /* 16-bit access*/ - - bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); - break; - - - case PM1_CONTROL: /* 16-bit access */ + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); break; - case PM1A_CONTROL: /* 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - break; - - - case PM1B_CONTROL: /* 16-bit access */ + bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); break; - case PM2_CONTROL: /* 8-bit access */ - - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); - break; - + case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - case PM_TIMER: /* 32-bit access */ + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } - acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; - case GPE0_STS_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - bank_offset = REGISTER_BIT_ID(register_id); - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); break; - case GPE0_EN_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id); - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; - case GPE1_STS_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - bank_offset = REGISTER_BIT_ID(register_id); - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); + status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); break; - case GPE1_EN_BLOCK: /* 8-bit access */ + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id); - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); + status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0); break; - case SMI_CMD_BLOCK: /* 8bit */ + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - /* For 2.0, SMI_CMD is always in IO space */ - /* TBD: what about 1.0? 0.71? */ + /* SMI_CMD is currently always in IO space */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (acpi_integer) value, 8); break; default: - value = 0; + status = AE_BAD_PARAMETER; break; } - +unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } - return_VOID; + return_ACPI_STATUS (status); } @@ -826,31 +673,33 @@ * ******************************************************************************/ -u32 +acpi_status acpi_hw_low_level_read ( u32 width, + u32 *value, acpi_generic_address *reg, u32 offset) { - u32 value = 0; ACPI_PHYSICAL_ADDRESS mem_address; ACPI_IO_ADDRESS io_address; acpi_pci_id pci_id; u16 pci_register; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_NAME ("Hw_low_level_read"); /* * Must have a valid pointer to a GAS structure, and - * a non-zero address within + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. */ if ((!reg) || (!ACPI_VALID_ADDRESS (reg->address))) { - return 0; + return (AE_OK); } - + *value = 0; /* * Three address spaces supported: @@ -859,17 +708,19 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + mem_address = (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_read_memory (mem_address, &value, width); + status = acpi_os_read_memory (mem_address, value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_read_port (io_address, &value, width); + status = acpi_os_read_port (io_address, value, width); break; @@ -879,13 +730,20 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address)); pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address)); - pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset); + pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + + offset); - acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width); + status = acpi_os_read_pci_configuration (&pci_id, pci_register, value, width); + break; + + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + status = AE_BAD_PARAMETER; break; } - return value; + return (status); } @@ -905,7 +763,7 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_low_level_write ( u32 width, u32 value, @@ -916,21 +774,21 @@ ACPI_IO_ADDRESS io_address; acpi_pci_id pci_id; u16 pci_register; + acpi_status status; - FUNCTION_ENTRY (); + ACPI_FUNCTION_NAME ("Hw_low_level_write"); /* * Must have a valid pointer to a GAS structure, and - * a non-zero address within + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. */ if ((!reg) || (!ACPI_VALID_ADDRESS (reg->address))) { - return; + return (AE_OK); } - - /* * Three address spaces supported: * Memory, Io, or PCI config. @@ -938,17 +796,19 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + mem_address = (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_write_memory (mem_address, value, width); + status = acpi_os_write_memory (mem_address, (acpi_integer) value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_write_port (io_address, value, width); + status = acpi_os_write_port (io_address, (acpi_integer) value, width); break; @@ -958,9 +818,18 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address)); pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address)); - pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset); + pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + + offset); + + status = acpi_os_write_pci_configuration (&pci_id, pci_register, (acpi_integer) value, width); + break; - acpi_os_write_pci_configuration (&pci_id, pci_register, value, width); + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + status = AE_BAD_PARAMETER; break; } + + return (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/hwsleep.c linux2.4.21_itanium/drivers/acpi/hardware/hwsleep.c --- linux2.4.21_itanium.org/drivers/acpi/hardware/hwsleep.c Wed Jul 23 18:20:42 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/hwsleep.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,11 +25,9 @@ */ #include "acpi.h" -#include "acnamesp.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE - MODULE_NAME ("hwsleep") + ACPI_MODULE_NAME ("hwsleep") /****************************************************************************** @@ -39,7 +37,7 @@ * PARAMETERS: Physical_address - Physical address of ACPI real mode * entry point. * - * RETURN: AE_OK or AE_ERROR + * RETURN: Status * * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS * @@ -50,22 +48,18 @@ ACPI_PHYSICAL_ADDRESS physical_address) { - FUNCTION_TRACE ("Acpi_set_firmware_waking_vector"); - + ACPI_FUNCTION_TRACE ("Acpi_set_firmware_waking_vector"); - /* Make sure that we have an FACS */ - - if (!acpi_gbl_FACS) { - return_ACPI_STATUS (AE_NO_ACPI_TABLES); - } /* Set the vector */ - if (acpi_gbl_FACS->vector_width == 32) { - * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address; + if (acpi_gbl_common_fACS.vector_width == 32) { + *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector)) + = (u32) physical_address; } else { - *acpi_gbl_FACS->firmware_waking_vector = physical_address; + *acpi_gbl_common_fACS.firmware_waking_vector + = physical_address; } return_ACPI_STATUS (AE_OK); @@ -82,7 +76,7 @@ * * RETURN: Status * - * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * DESCRIPTION: Access function for Firmware_waking_vector field in FACS * ******************************************************************************/ @@ -91,141 +85,229 @@ ACPI_PHYSICAL_ADDRESS *physical_address) { - FUNCTION_TRACE ("Acpi_get_firmware_waking_vector"); + ACPI_FUNCTION_TRACE ("Acpi_get_firmware_waking_vector"); if (!physical_address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Make sure that we have an FACS */ - - if (!acpi_gbl_FACS) { - return_ACPI_STATUS (AE_NO_ACPI_TABLES); - } - /* Get the vector */ - if (acpi_gbl_FACS->vector_width == 32) { - *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector; + if (acpi_gbl_common_fACS.vector_width == 32) { + *physical_address = (ACPI_PHYSICAL_ADDRESS) + *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector)); } else { - *physical_address = *acpi_gbl_FACS->firmware_waking_vector; + *physical_address = + *acpi_gbl_common_fACS.firmware_waking_vector; } return_ACPI_STATUS (AE_OK); } + /****************************************************************************** * - * FUNCTION: Acpi_enter_sleep_state + * FUNCTION: Acpi_enter_sleep_state_prep * * PARAMETERS: Sleep_state - Which sleep state to enter * * RETURN: Status * - * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. * ******************************************************************************/ acpi_status -acpi_enter_sleep_state ( +acpi_enter_sleep_state_prep ( u8 sleep_state) { acpi_status status; acpi_object_list arg_list; acpi_object arg; - u8 type_a; - u8 type_b; - u16 PM1Acontrol; - u16 PM1Bcontrol; - FUNCTION_TRACE ("Acpi_enter_sleep_state"); + ACPI_FUNCTION_TRACE ("Acpi_enter_sleep_state_prep"); /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ - status = acpi_hw_obtain_sleep_type_register_data (sleep_state, &type_a, &type_b); - if (!ACPI_SUCCESS (status)) { - return status; + status = acpi_get_sleep_type_data (sleep_state, + &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - /* run the _PTS and _GTS methods */ + /* Setup parameter object */ - MEMSET(&arg_list, 0, sizeof(arg_list)); arg_list.count = 1; arg_list.pointer = &arg; - MEMSET(&arg, 0, sizeof(arg)); arg.type = ACPI_TYPE_INTEGER; arg.integer.value = sleep_state; - acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL); - acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL); + /* Run the _PTS and _GTS methods */ + + status = acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS (status); + } + + status = acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS (status); + } + + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_enter_sleep_state + * + * PARAMETERS: Sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +acpi_status +acpi_enter_sleep_state ( + u8 sleep_state) +{ + u32 PM1Acontrol; + u32 PM1Bcontrol; + ACPI_BIT_REGISTER_INFO *sleep_type_reg_info; + ACPI_BIT_REGISTER_INFO *sleep_enable_reg_info; + u32 in_value; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_enter_sleep_state"); + + + if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || + (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { + ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n", + acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + + sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE); + + /* Clear wake status */ - /* clear wake status */ + status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); + /* Disable BM arbitration */ - disable (); + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_disable_non_wakeup_gpes(); + status = acpi_hw_disable_non_wakeup_gpes(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - PM1Acontrol = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, PM1_CONTROL); + /* Get current value of PM1A control */ + status = acpi_hw_register_read (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Entering S%d\n", sleep_state)); - /* mask off SLP_EN and SLP_TYP fields */ + /* Clear SLP_EN and SLP_TYP fields */ - PM1Acontrol &= ~(SLP_TYPE_X_MASK | SLP_EN_MASK); + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask); PM1Bcontrol = PM1Acontrol; - /* mask in SLP_TYP */ + /* Insert SLP_TYP bits */ - PM1Acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); - PM1Bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); + PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); - /* write #1: fill in SLP_TYP data */ + /* Write #1: fill in SLP_TYP data */ + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol); - acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol); + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - /* mask in SLP_EN */ + /* Insert SLP_ENABLE bit */ - PM1Acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); - PM1Bcontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; + PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; - /* flush caches */ + /* Write #2: SLP_TYP + SLP_EN */ - wbinvd(); + ACPI_FLUSH_CPU_CACHE (); - /* write #2: SLP_TYP + SLP_EN */ + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol); - acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol); + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* * Wait a second, then try again. This is to get S4/5 to work on all machines. */ if (sleep_state > ACPI_STATE_S3) { - acpi_os_stall(1000000); - - acpi_hw_register_write (ACPI_MTX_LOCK, PM1_CONTROL, - (1 << acpi_hw_get_bit_shift (SLP_EN_MASK))); + /* + * We wait so long to allow chipsets that poll this reg very slowly to + * still read the right value. Ideally, this entire block would go + * away entirely. + */ + acpi_os_stall (10000000); + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL, + sleep_enable_reg_info->access_bit_mask); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - /* wait until we enter sleep state */ + /* Wait until we enter sleep state */ do { - acpi_os_stall(10000); - } - while (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, WAK_STS)); + status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_enable_non_wakeup_gpes(); + /* Spin until we wake */ - enable (); + } while (!in_value); return_ACPI_STATUS (AE_OK); } @@ -248,25 +330,45 @@ { acpi_object_list arg_list; acpi_object arg; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_leave_sleep_state"); - FUNCTION_TRACE ("Acpi_leave_sleep_state"); + /* Ensure Enter_sleep_state_prep -> Enter_sleep_state ordering */ + acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; + + /* Setup parameter object */ - MEMSET (&arg_list, 0, sizeof(arg_list)); arg_list.count = 1; arg_list.pointer = &arg; - MEMSET (&arg, 0, sizeof(arg)); arg.type = ACPI_TYPE_INTEGER; arg.integer.value = sleep_state; - acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL); - acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL); + /* Ignore any errors from these methods */ + + status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status))); + } + + status = acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status))); + } /* _WAK returns stuff - do we want to look at it? */ - acpi_hw_enable_non_wakeup_gpes(); + status = acpi_hw_enable_non_wakeup_gpes(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Disable BM arbitration */ + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/hardware/hwtimer.c linux2.4.21_itanium/drivers/acpi/hardware/hwtimer.c --- linux2.4.21_itanium.org/drivers/acpi/hardware/hwtimer.c Wed Jul 23 18:20:43 2003 +++ linux2.4.21_itanium/drivers/acpi/hardware/hwtimer.c Wed Jul 23 18:28:09 2003 @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -25,10 +25,9 @@ */ #include "acpi.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE - MODULE_NAME ("hwtimer") + ACPI_MODULE_NAME ("hwtimer") /****************************************************************************** @@ -47,7 +46,7 @@ acpi_get_timer_resolution ( u32 *resolution) { - FUNCTION_TRACE ("Acpi_get_timer_resolution"); + ACPI_FUNCTION_TRACE ("Acpi_get_timer_resolution"); if (!resolution) { @@ -57,7 +56,6 @@ if (0 == acpi_gbl_FADT->tmr_val_ext) { *resolution = 24; } - else { *resolution = 32; } @@ -82,17 +80,19 @@ acpi_get_timer ( u32 *ticks) { - FUNCTION_TRACE ("Acpi_get_timer"); + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_get_timer"); if (!ticks) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_os_read_port ((ACPI_IO_ADDRESS) - ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address), ticks, 32); + status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->Xpm_tmr_blk, 0); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (status); } @@ -129,13 +129,12 @@ u32 *time_elapsed) { u32 delta_ticks = 0; - u32 seconds = 0; - u32 milliseconds = 0; - u32 microseconds = 0; - u32 remainder = 0; + uint64_overlay normalized_ticks; + acpi_status status; + acpi_integer out_quotient; - FUNCTION_TRACE ("Acpi_get_timer_duration"); + ACPI_FUNCTION_TRACE ("Acpi_get_timer_duration"); if (!time_elapsed) { @@ -150,21 +149,18 @@ if (start_ticks < end_ticks) { delta_ticks = end_ticks - start_ticks; } - else if (start_ticks > end_ticks) { - /* 24-bit Timer */ - if (0 == acpi_gbl_FADT->tmr_val_ext) { + /* 24-bit Timer */ + delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF); } - - /* 32-bit Timer */ - else { + /* 32-bit Timer */ + delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; } } - else { *time_elapsed = 0; return_ACPI_STATUS (AE_OK); @@ -173,49 +169,18 @@ /* * Compute Duration: * ----------------- - * Since certain compilers (gcc/Linux, argh!) don't support 64-bit - * divides in kernel-space we have to do some trickery to preserve - * accuracy while using 32-bit math. - * - * TBD: Change to use 64-bit math when supported. * - * The process is as follows: - * 1. Compute the number of seconds by dividing Delta Ticks by - * the timer frequency. - * 2. Compute the number of milliseconds in the remainder from step #1 - * by multiplying by 1000 and then dividing by the timer frequency. - * 3. Compute the number of microseconds in the remainder from step #2 - * by multiplying by 1000 and then dividing by the timer frequency. - * 4. Add the results from steps 1, 2, and 3 to get the total duration. + * Requires a 64-bit divide: * - * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be - * 1199864031 microseconds. This is computed as follows: - * Step #1: Seconds = 1199; Remainder = 3092840 - * Step #2: Milliseconds = 864; Remainder = 113120 - * Step #3: Microseconds = 31; Remainder = + * Time_elapsed = (Delta_ticks * 1000000) / PM_TIMER_FREQUENCY; */ + normalized_ticks.full = ((u64) delta_ticks) * 1000000; - /* Step #1 */ - - seconds = delta_ticks / PM_TIMER_FREQUENCY; - remainder = delta_ticks % PM_TIMER_FREQUENCY; - - /* Step #2 */ - - milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; - remainder = (remainder * 1000) % PM_TIMER_FREQUENCY; + status = acpi_ut_short_divide (&normalized_ticks.full, PM_TIMER_FREQUENCY, + &out_quotient, NULL); - /* Step #3 */ - - microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; - - /* Step #4 */ - - *time_elapsed = seconds * 1000000; - *time_elapsed += milliseconds * 1000; - *time_elapsed += microseconds; - - return_ACPI_STATUS (AE_OK); + *time_elapsed = (u32) out_quotient; + return_ACPI_STATUS (status); } diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acconfig.h linux2.4.21_itanium/drivers/acpi/include/acconfig.h --- linux2.4.21_itanium.org/drivers/acpi/include/acconfig.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acconfig.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -34,12 +34,13 @@ *****************************************************************************/ /* - * ACPI_DEBUG - This switch enables all the debug facilities of the ACPI - * subsystem. This includes the DEBUG_PRINT output statements - * When disabled, all DEBUG_PRINT statements are compiled out. + * ACPI_DEBUG - This switch enables all the debug facilities of the + * ACPI subsystem. This includes the DEBUG_PRINT output + * statements. When disabled, all DEBUG_PRINT + * statements are compiled out. * * ACPI_APPLICATION - Use this switch if the subsystem is going to be run - * at the application level. + * at the application level. * */ @@ -53,43 +54,44 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20011018 +#define ACPI_CA_VERSION 0x20020517 /* Version of ACPI supported */ #define ACPI_CA_SUPPORT_LEVEL 2 - /* Maximum objects in the various object caches */ -#define MAX_STATE_CACHE_DEPTH 64 /* State objects for stacks */ +#define MAX_STATE_CACHE_DEPTH 64 /* State objects for stacks */ #define MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ #define MAX_EXTPARSE_CACHE_DEPTH 64 /* Parse tree objects */ #define MAX_OBJECT_CACHE_DEPTH 64 /* Interpreter operand objects */ -#define MAX_WALK_CACHE_DEPTH 4 /* Objects for parse tree walks (method execution) */ - +#define MAX_WALK_CACHE_DEPTH 4 /* Objects for parse tree walks */ /* String size constants */ #define MAX_STRING_LENGTH 512 -#define PATHNAME_MAX 256 /* A full namespace pathname */ - +#define PATHNAME_MAX 256 /* A full namespace pathname */ /* Maximum count for a semaphore object */ #define MAX_SEMAPHORE_COUNT 256 - /* Max reference count (for debug only) */ #define MAX_REFERENCE_COUNT 0x400 - /* Size of cached memory mapping for system memory operation region */ #define SYSMEM_REGION_WINDOW_SIZE 4096 +/****************************************************************************** + * + * Configuration of subsystem behavior + * + *****************************************************************************/ + /* * Debugger threading model * Use single threaded if the entire subsystem is contained in an application @@ -98,7 +100,6 @@ * By default the model is single threaded if ACPI_APPLICATION is set, * multi-threaded if ACPI_APPLICATION is not set. */ - #define DEBUGGER_SINGLE_THREADED 0 #define DEBUGGER_MULTI_THREADED 1 @@ -109,6 +110,12 @@ #define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED #endif +/* + * Should the subystem abort the loading of an ACPI table if the + * table checksum is incorrect? + */ +#define ACPI_CHECKSUM_ABORT FALSE + /****************************************************************************** * @@ -116,10 +123,13 @@ * *****************************************************************************/ +/* Number of distinct GPE register blocks */ + +#define ACPI_MAX_GPE_BLOCKS 2 + /* * Method info (in WALK_STATE), containing local variables and argumetns */ - #define MTH_NUM_LOCALS 8 #define MTH_MAX_LOCAL 7 @@ -133,17 +143,15 @@ /* * Operand Stack (in WALK_STATE), Must be large enough to contain MTH_MAX_ARG */ - #define OBJ_NUM_OPERANDS 8 #define OBJ_MAX_OPERAND 7 /* Names within the namespace are 4 bytes long */ #define ACPI_NAME_SIZE 4 -#define PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 s8 for separator */ +#define PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ #define PATH_SEPARATOR '.' - /* Constants used in searching for the RSDP in low memory */ #define LO_RSDP_WINDOW_BASE 0 /* Physical Address */ @@ -152,10 +160,32 @@ #define HI_RSDP_WINDOW_SIZE 0x20000 #define RSDP_SCAN_STEP 16 +/* Operation regions */ + +#define ACPI_NUM_PREDEFINED_REGIONS 8 +#define ACPI_USER_REGION_BEGIN 0x80 + /* Maximum Space_ids for Operation Regions */ #define ACPI_MAX_ADDRESS_SPACE 255 -#define ACPI_NUM_ADDRESS_SPACES 256 + +/* RSDP checksums */ + +#define ACPI_RSDP_CHECKSUM_LENGTH 20 +#define ACPI_RSDP_XCHECKSUM_LENGTH 36 + + +/****************************************************************************** + * + * ACPI AML Debugger + * + *****************************************************************************/ + + +#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */ + +#define ACPI_DEBUGGER_COMMAND_PROMPT '-' +#define ACPI_DEBUGGER_EXECUTE_PROMPT '%' #endif /* _ACCONFIG_H */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acdebug.h linux2.4.21_itanium/drivers/acpi/include/acdebug.h --- linux2.4.21_itanium.org/drivers/acpi/include/acdebug.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acdebug.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,61 +27,8 @@ #define __ACDEBUG_H__ -#define DB_MAX_ARGS 8 /* Must be max method args + 1 */ - -#define DB_COMMAND_PROMPT '-' -#define DB_EXECUTE_PROMPT '%' - - -extern int optind; -extern NATIVE_CHAR *optarg; -extern u8 *aml_start; -extern u32 aml_length; - -extern u8 acpi_gbl_db_opt_tables; -extern u8 acpi_gbl_db_opt_disasm; -extern u8 acpi_gbl_db_opt_stats; -extern u8 acpi_gbl_db_opt_parse_jit; -extern u8 acpi_gbl_db_opt_verbose; -extern u8 acpi_gbl_db_opt_ini_methods; - - -extern NATIVE_CHAR *acpi_gbl_db_args[DB_MAX_ARGS]; -extern NATIVE_CHAR acpi_gbl_db_line_buf[80]; -extern NATIVE_CHAR acpi_gbl_db_scope_buf[40]; -extern NATIVE_CHAR acpi_gbl_db_debug_filename[40]; -extern u8 acpi_gbl_db_output_to_file; -extern NATIVE_CHAR *acpi_gbl_db_buffer; -extern NATIVE_CHAR *acpi_gbl_db_filename; -extern NATIVE_CHAR *acpi_gbl_db_disasm_indent; -extern u8 acpi_gbl_db_output_flags; -extern u32 acpi_gbl_db_debug_level; -extern u32 acpi_gbl_db_console_debug_level; -extern acpi_table_header *acpi_gbl_db_table_ptr; - -/* - * Statistic globals - */ -extern u16 acpi_gbl_obj_type_count[INTERNAL_TYPE_NODE_MAX+1]; -extern u16 acpi_gbl_node_type_count[INTERNAL_TYPE_NODE_MAX+1]; -extern u16 acpi_gbl_obj_type_count_misc; -extern u16 acpi_gbl_node_type_count_misc; -extern u32 acpi_gbl_num_nodes; -extern u32 acpi_gbl_num_objects; - - -extern u32 acpi_gbl_size_of_parse_tree; -extern u32 acpi_gbl_size_of_method_trees; -extern u32 acpi_gbl_size_of_node_entries; -extern u32 acpi_gbl_size_of_acpi_objects; - - #define ACPI_DEBUG_BUFFER_SIZE 4196 -#define DB_REDIRECTABLE_OUTPUT 0x01 -#define DB_CONSOLE_OUTPUT 0x02 -#define DB_DUPLICATE_OUTPUT 0x03 - typedef struct command_info { @@ -116,7 +63,7 @@ * dbapi - external debugger interfaces */ -int +acpi_status acpi_db_initialize ( void); @@ -135,7 +82,6 @@ * dbcmds - debug commands and output routines */ - void acpi_db_display_table_info ( NATIVE_CHAR *table_arg); @@ -206,6 +152,38 @@ acpi_db_display_resources ( NATIVE_CHAR *object_arg); +void +acpi_db_check_integrity ( + void); + +acpi_status +acpi_db_integrity_walk ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_and_match_name ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_for_references ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_for_specific_objects ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + /* * dbdisasm - AML disassembler @@ -234,12 +212,20 @@ acpi_db_decode_internal_object ( acpi_operand_object *obj_desc); +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 */ - void acpi_db_display_method_info ( acpi_parse_object *op); @@ -284,6 +270,14 @@ acpi_operand_object *obj_desc, acpi_walk_state *walk_state); +void +acpi_db_dump_parser_descriptor ( + acpi_parse_object *op); + +void * +acpi_db_get_pointer ( + void *target); + /* * dbexec - debugger control method execution @@ -301,16 +295,36 @@ NATIVE_CHAR *num_loops_arg, NATIVE_CHAR *method_name_arg); +acpi_status +acpi_db_execute_method ( + acpi_db_method_info *info, + acpi_buffer *return_obj); + +void +acpi_db_execute_setup ( + acpi_db_method_info *info); + +u32 +acpi_db_get_outstanding_allocations ( + void); + +void ACPI_SYSTEM_XFACE +acpi_db_method_thread ( + void *context); + /* * dbfileio - Debugger file I/O commands */ -acpi_object_type8 +acpi_object_type acpi_db_match_argument ( NATIVE_CHAR *user_argument, ARGUMENT_INFO *arguments); +acpi_status +ae_local_load_table ( + acpi_table_header *table_ptr); void acpi_db_close_debug_file ( @@ -324,6 +338,9 @@ acpi_db_load_acpi_table ( NATIVE_CHAR *filename); +acpi_status +acpi_db_get_acpi_table ( + NATIVE_CHAR *filename); /* * dbhistry - debugger HISTORY command @@ -351,7 +368,7 @@ acpi_walk_state *walk_state, acpi_parse_object *op); -void +void ACPI_SYSTEM_XFACE acpi_db_execute_thread ( void *context); @@ -360,6 +377,27 @@ NATIVE_CHAR prompt, acpi_parse_object *op); +void +acpi_db_display_help ( + NATIVE_CHAR *help_type); + +NATIVE_CHAR * +acpi_db_get_next_token ( + NATIVE_CHAR *string, + NATIVE_CHAR **next); + +u32 +acpi_db_get_line ( + NATIVE_CHAR *input_buffer); + +u32 +acpi_db_match_command ( + NATIVE_CHAR *user_command); + +void +acpi_db_single_thread ( + void); + /* * dbstats - Generation and display of ACPI table statistics @@ -375,6 +413,21 @@ acpi_db_display_statistics ( NATIVE_CHAR *type_arg); +acpi_status +acpi_db_classify_one_object ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +void +acpi_db_count_namespace_objects ( + void); + +void +acpi_db_enumerate_object ( + acpi_operand_object *obj_desc); + /* * dbutils - AML debugger utilities diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acdispat.h linux2.4.21_itanium/drivers/acpi/include/acdispat.h --- linux2.4.21_itanium.org/drivers/acpi/include/acdispat.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acdispat.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -58,6 +58,13 @@ /* dsopcode - support for late evaluation */ acpi_status +acpi_ds_execute_arguments ( + acpi_namespace_node *node, + acpi_namespace_node *scope_node, + u32 aml_length, + u8 *aml_start); + +acpi_status acpi_ds_get_buffer_field_arguments ( acpi_operand_object *obj_desc); @@ -65,6 +72,43 @@ acpi_ds_get_region_arguments ( acpi_operand_object *rgn_desc); +acpi_status +acpi_ds_get_buffer_arguments ( + acpi_operand_object *obj_desc); + +acpi_status +acpi_ds_get_package_arguments ( + acpi_operand_object *obj_desc); + +acpi_status +acpi_ds_init_buffer_field ( + u16 aml_opcode, + acpi_operand_object *obj_desc, + acpi_operand_object *buffer_desc, + acpi_operand_object *offset_desc, + acpi_operand_object *length_desc, + acpi_operand_object *result_desc); + +acpi_status +acpi_ds_eval_buffer_field_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + +acpi_status +acpi_ds_eval_region_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + +acpi_status +acpi_ds_eval_data_object_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op, + acpi_operand_object *obj_desc); + +acpi_status +acpi_ds_initialize_region ( + acpi_handle obj_handle); + /* dsctrl - Parser/Interpreter interface, control stack routines */ @@ -86,7 +130,7 @@ acpi_status acpi_ds_get_predicate_value ( acpi_walk_state *walk_state, - u32 has_result_obj); + acpi_operand_object *result_obj); acpi_status acpi_ds_exec_begin_op ( @@ -101,6 +145,12 @@ /* dsfield - Parser/Interpreter interface for AML fields */ acpi_status +acpi_ds_get_field_names ( + ACPI_CREATE_FIELD_INFO *info, + acpi_walk_state *walk_state, + acpi_parse_object *arg); + +acpi_status acpi_ds_create_field ( acpi_parse_object *op, acpi_namespace_node *region_node, @@ -123,6 +173,11 @@ acpi_parse_object *op, acpi_walk_state *walk_state); +acpi_status +acpi_ds_init_field_objects ( + acpi_parse_object *op, + acpi_walk_state *walk_state); + /* dsload - Parser/Interpreter interface, namespace load callbacks */ @@ -167,7 +222,7 @@ acpi_walk_state *walk_state, acpi_operand_object ***node); -acpi_status +void acpi_ds_method_data_delete_all ( acpi_walk_state *walk_state); @@ -175,7 +230,7 @@ acpi_ds_is_method_value ( acpi_operand_object *obj_desc); -acpi_object_type8 +acpi_object_type acpi_ds_method_data_get_type ( u16 opcode, u32 index, @@ -188,7 +243,7 @@ acpi_walk_state *walk_state, acpi_operand_object **dest_desc); -acpi_status +void acpi_ds_method_data_delete_value ( u16 opcode, u32 index, @@ -200,18 +255,19 @@ u32 max_param_count, acpi_walk_state *walk_state); -acpi_namespace_node * +acpi_status acpi_ds_method_data_get_node ( u16 opcode, u32 index, - acpi_walk_state *walk_state); + acpi_walk_state *walk_state, + acpi_namespace_node **node); -acpi_status +void acpi_ds_method_data_init ( acpi_walk_state *walk_state); acpi_status -acpi_ds_method_data_set_entry ( +acpi_ds_method_data_set_value ( u16 opcode, u32 index, acpi_operand_object *object, @@ -226,7 +282,7 @@ acpi_status acpi_ds_call_control_method ( - acpi_walk_list *walk_list, + ACPI_THREAD_STATE *thread, acpi_walk_state *walk_state, acpi_parse_object *op); @@ -261,9 +317,17 @@ acpi_namespace_node *start_node); acpi_status +acpi_ds_build_internal_buffer_obj ( + acpi_walk_state *walk_state, + acpi_parse_object *op, + u32 buffer_length, + acpi_operand_object **obj_desc_ptr); + +acpi_status acpi_ds_build_internal_package_obj ( acpi_walk_state *walk_state, acpi_parse_object *op, + u32 package_length, acpi_operand_object **obj_desc); acpi_status @@ -286,23 +350,6 @@ acpi_parse_object *op); -/* dsregn - Parser/Interpreter interface - Op Region parsing */ - -acpi_status -acpi_ds_eval_buffer_field_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - -acpi_status -acpi_ds_eval_region_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - -acpi_status -acpi_ds_initialize_region ( - acpi_handle obj_handle); - - /* dsutils - Parser/Interpreter interface utility routines */ u8 @@ -331,15 +378,6 @@ acpi_ds_resolve_operands ( acpi_walk_state *walk_state); -acpi_object_type8 -acpi_ds_map_opcode_to_data_type ( - u16 opcode, - u32 *out_flags); - -acpi_object_type8 -acpi_ds_map_named_opcode_to_data_type ( - u16 opcode); - /* * dswscope - Scope Stack manipulation @@ -348,7 +386,7 @@ acpi_status acpi_ds_scope_stack_push ( acpi_namespace_node *node, - acpi_object_type8 type, + acpi_object_type type, acpi_walk_state *walk_state); @@ -368,7 +406,7 @@ acpi_owner_id owner_id, acpi_parse_object *origin, acpi_operand_object *mth_desc, - acpi_walk_list *walk_list); + ACPI_THREAD_STATE *thread); acpi_status acpi_ds_init_aml_walk ( @@ -396,12 +434,12 @@ acpi_walk_state * acpi_ds_pop_walk_state ( - acpi_walk_list *walk_list); + ACPI_THREAD_STATE *thread); void acpi_ds_push_walk_state ( acpi_walk_state *walk_state, - acpi_walk_list *walk_list); + ACPI_THREAD_STATE *thread); acpi_status acpi_ds_result_stack_pop ( @@ -417,7 +455,7 @@ acpi_walk_state * acpi_ds_get_current_walk_state ( - acpi_walk_list *walk_list); + ACPI_THREAD_STATE *thread); void acpi_ds_delete_walk_state_cache ( diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acevents.h linux2.4.21_itanium/drivers/acpi/include/acevents.h --- linux2.4.21_itanium.org/drivers/acpi/include/acevents.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acevents.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -31,9 +31,13 @@ acpi_ev_initialize ( void); +acpi_status +acpi_ev_handler_initialize ( + void); + /* - * Acpi_evfixed - Fixed event handling + * Evfixed - Fixed event handling */ acpi_status @@ -46,18 +50,22 @@ u32 acpi_ev_fixed_event_dispatch ( - u32 acpi_event); + u32 event); /* - * Acpi_evglock - Global Lock support + * Evmisc */ +u8 +acpi_ev_is_notify_object ( + acpi_namespace_node *node); + acpi_status acpi_ev_acquire_global_lock( - void); + u32 timeout); -void +acpi_status acpi_ev_release_global_lock( void); @@ -65,9 +73,26 @@ acpi_ev_init_global_lock_handler ( void); +u32 +acpi_ev_get_gpe_register_index ( + u32 gpe_number); + +u32 +acpi_ev_get_gpe_number_index ( + u32 gpe_number); + +acpi_status +acpi_ev_queue_notify_request ( + acpi_namespace_node *node, + u32 notify_value); + +void ACPI_SYSTEM_XFACE +acpi_ev_notify_dispatch ( + void *context); + /* - * Acpi_evgpe - GPE handling and dispatch + * Evgpe - GPE handling and dispatch */ acpi_status @@ -86,26 +111,12 @@ acpi_ev_gpe_detect ( void); - /* - * Acpi_evnotify - Device Notify handling and dispatch + * Evregion - Address Space handling */ acpi_status -acpi_ev_queue_notify_request ( - acpi_namespace_node *node, - u32 notify_value); - -void -acpi_ev_notify_dispatch ( - void *context); - -/* - * Acpi_evregion - Address Space handling - */ - -acpi_status -acpi_ev_install_default_address_space_handlers ( +acpi_ev_init_address_spaces ( void); acpi_status @@ -114,8 +125,7 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - u32 *value); - + void *value); acpi_status acpi_ev_addr_handler_helper ( @@ -124,21 +134,20 @@ void *context, void **return_value); -void -acpi_ev_disassociate_region_from_handler( - acpi_operand_object *region_obj, - u8 acpi_ns_is_locked); - - acpi_status -acpi_ev_associate_region_and_handler ( +acpi_ev_attach_region ( acpi_operand_object *handler_obj, acpi_operand_object *region_obj, u8 acpi_ns_is_locked); +void +acpi_ev_detach_region ( + acpi_operand_object *region_obj, + u8 acpi_ns_is_locked); + /* - * Acpi_evregini - Region initialization and setup + * Evregini - Region initialization and setup */ acpi_status @@ -206,10 +215,6 @@ u32 program_sCI); void -acpi_ev_restore_acpi_state ( - void); - -void acpi_ev_terminate ( void); diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acexcep.h linux2.4.21_itanium/drivers/acpi/include/acexcep.h --- linux2.4.21_itanium.org/drivers/acpi/include/acexcep.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acexcep.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -54,7 +54,7 @@ #define AE_NO_MEMORY (acpi_status) (0x0004 | AE_CODE_ENVIRONMENTAL) #define AE_NOT_FOUND (acpi_status) (0x0005 | AE_CODE_ENVIRONMENTAL) #define AE_NOT_EXIST (acpi_status) (0x0006 | AE_CODE_ENVIRONMENTAL) -#define AE_EXIST (acpi_status) (0x0007 | AE_CODE_ENVIRONMENTAL) +#define AE_ALREADY_EXISTS (acpi_status) (0x0007 | AE_CODE_ENVIRONMENTAL) #define AE_TYPE (acpi_status) (0x0008 | AE_CODE_ENVIRONMENTAL) #define AE_NULL_OBJECT (acpi_status) (0x0009 | AE_CODE_ENVIRONMENTAL) #define AE_NULL_ENTRY (acpi_status) (0x000A | AE_CODE_ENVIRONMENTAL) @@ -74,8 +74,9 @@ #define AE_ALREADY_ACQUIRED (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL) #define AE_NO_HARDWARE_RESPONSE (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL) #define AE_NO_GLOBAL_LOCK (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL) +#define AE_LOGICAL_ADDRESS (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL) -#define AE_CODE_ENV_MAX 0x001A +#define AE_CODE_ENV_MAX 0x001B /* * Programmer exceptions @@ -85,8 +86,12 @@ #define AE_BAD_PATHNAME (acpi_status) (0x0003 | AE_CODE_PROGRAMMER) #define AE_BAD_DATA (acpi_status) (0x0004 | AE_CODE_PROGRAMMER) #define AE_BAD_ADDRESS (acpi_status) (0x0005 | AE_CODE_PROGRAMMER) +#define AE_ALIGNMENT (acpi_status) (0x0006 | AE_CODE_PROGRAMMER) +#define AE_BAD_HEX_CONSTANT (acpi_status) (0x0007 | AE_CODE_PROGRAMMER) +#define AE_BAD_OCTAL_CONSTANT (acpi_status) (0x0008 | AE_CODE_PROGRAMMER) +#define AE_BAD_DECIMAL_CONSTANT (acpi_status) (0x0009 | AE_CODE_PROGRAMMER) -#define AE_CODE_PGM_MAX 0x0005 +#define AE_CODE_PGM_MAX 0x0009 /* @@ -96,8 +101,10 @@ #define AE_BAD_HEADER (acpi_status) (0x0002 | AE_CODE_ACPI_TABLES) #define AE_BAD_CHECKSUM (acpi_status) (0x0003 | AE_CODE_ACPI_TABLES) #define AE_BAD_VALUE (acpi_status) (0x0004 | AE_CODE_ACPI_TABLES) +#define AE_TABLE_NOT_SUPPORTED (acpi_status) (0x0005 | AE_CODE_ACPI_TABLES) +#define AE_INVALID_TABLE_LENGTH (acpi_status) (0x0006 | AE_CODE_ACPI_TABLES) -#define AE_CODE_TBL_MAX 0x0003 +#define AE_CODE_TBL_MAX 0x0006 /* @@ -129,8 +136,14 @@ #define AE_AML_MUTEX_ORDER (acpi_status) (0x0017 | AE_CODE_AML) #define AE_AML_MUTEX_NOT_ACQUIRED (acpi_status) (0x0018 | AE_CODE_AML) #define AE_AML_INVALID_RESOURCE_TYPE (acpi_status) (0x0019 | AE_CODE_AML) +#define AE_AML_INVALID_INDEX (acpi_status) (0x001A | AE_CODE_AML) +#define AE_AML_REGISTER_LIMIT (acpi_status) (0x001B | AE_CODE_AML) +#define AE_AML_NO_WHILE (acpi_status) (0x001C | AE_CODE_AML) +#define AE_AML_ALIGNMENT (acpi_status) (0x001D | AE_CODE_AML) +#define AE_AML_NO_RESOURCE_END_TAG (acpi_status) (0x001E | AE_CODE_AML) +#define AE_AML_BAD_RESOURCE_VALUE (acpi_status) (0x001F | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x0019 +#define AE_CODE_AML_MAX 0x001F /* * Internal exceptions used for control @@ -143,8 +156,10 @@ #define AE_CTRL_DEPTH (acpi_status) (0x0006 | AE_CODE_CONTROL) #define AE_CTRL_END (acpi_status) (0x0007 | AE_CODE_CONTROL) #define AE_CTRL_TRANSFER (acpi_status) (0x0008 | AE_CODE_CONTROL) +#define AE_CTRL_BREAK (acpi_status) (0x0009 | AE_CODE_CONTROL) +#define AE_CTRL_CONTINUE (acpi_status) (0x000A | AE_CODE_CONTROL) -#define AE_CODE_CTRL_MAX 0x0008 +#define AE_CODE_CTRL_MAX 0x000A #ifdef DEFINE_ACPI_GLOBALS @@ -162,7 +177,7 @@ "AE_NO_MEMORY", "AE_NOT_FOUND", "AE_NOT_EXIST", - "AE_EXIST", + "AE_ALREADY_EXISTS", "AE_TYPE", "AE_NULL_OBJECT", "AE_NULL_ENTRY", @@ -182,6 +197,7 @@ "AE_ALREADY_ACQUIRED", "AE_NO_HARDWARE_RESPONSE", "AE_NO_GLOBAL_LOCK", + "AE_LOGICAL_ADDRESS" }; NATIVE_CHAR const *acpi_gbl_exception_names_pgm[] = @@ -191,6 +207,10 @@ "AE_BAD_PATHNAME", "AE_BAD_DATA", "AE_BAD_ADDRESS", + "AE_ALIGNMENT", + "AE_BAD_HEX_CONSTANT", + "AE_BAD_OCTAL_CONSTANT", + "AE_BAD_DECIMAL_CONSTANT" }; NATIVE_CHAR const *acpi_gbl_exception_names_tbl[] = @@ -199,6 +219,8 @@ "AE_BAD_HEADER", "AE_BAD_CHECKSUM", "AE_BAD_VALUE", + "AE_TABLE_NOT_SUPPORTED", + "AE_INVALID_TABLE_LENGTH" }; NATIVE_CHAR const *acpi_gbl_exception_names_aml[] = @@ -228,6 +250,12 @@ "AE_AML_MUTEX_ORDER", "AE_AML_MUTEX_NOT_ACQUIRED", "AE_AML_INVALID_RESOURCE_TYPE", + "AE_AML_INVALID_INDEX", + "AE_AML_REGISTER_LIMIT", + "AE_AML_NO_WHILE", + "AE_AML_ALIGNMENT", + "AE_AML_NO_RESOURCE_END_TAG", + "AE_AML_BAD_RESOURCE_VALUE" }; NATIVE_CHAR const *acpi_gbl_exception_names_ctrl[] = @@ -240,6 +268,8 @@ "AE_CTRL_DEPTH", "AE_CTRL_END", "AE_CTRL_TRANSFER", + "AE_CTRL_BREAK", + "AE_CTRL_CONTINUE" }; #endif /* ACPI GLOBALS */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acglobal.h linux2.4.21_itanium/drivers/acpi/include/acglobal.h --- linux2.4.21_itanium.org/drivers/acpi/include/acglobal.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acglobal.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -71,11 +71,21 @@ * of each in the system. Each global points to the actual table. * */ -ACPI_EXTERN RSDP_DESCRIPTOR *acpi_gbl_RSDP; -ACPI_EXTERN xsdt_descriptor *acpi_gbl_XSDT; -ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT; -ACPI_EXTERN acpi_table_header *acpi_gbl_DSDT; -ACPI_EXTERN acpi_common_facs *acpi_gbl_FACS; +ACPI_EXTERN u32 acpi_gbl_table_flags; +ACPI_EXTERN RSDP_DESCRIPTOR *acpi_gbl_RSDP; +ACPI_EXTERN xsdt_descriptor *acpi_gbl_XSDT; +ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT; +ACPI_EXTERN acpi_table_header *acpi_gbl_DSDT; +ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS; +ACPI_EXTERN acpi_common_facs acpi_gbl_common_fACS; + +/* + * Handle both ACPI 1.0 and ACPI 2.0 Integer widths + * If we are running a method that exists in a 32-bit ACPI table. + * Use only 32 bits of the Integer for conversion. + */ +ACPI_EXTERN u8 acpi_gbl_integer_bit_width; +ACPI_EXTERN u8 acpi_gbl_integer_byte_width; /* * Since there may be multiple SSDTs and PSDTS, a single pointer is not @@ -107,22 +117,19 @@ ACPI_EXTERN ACPI_MEMORY_LIST acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS]; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify; -ACPI_EXTERN u8 *acpi_gbl_gpe0enable_register_save; -ACPI_EXTERN u8 *acpi_gbl_gpe1_enable_register_save; +ACPI_EXTERN ACPI_INIT_HANDLER acpi_gbl_init_handler; ACPI_EXTERN acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore; ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count; -ACPI_EXTERN u32 acpi_gbl_restore_acpi_chipset; ACPI_EXTERN u32 acpi_gbl_original_mode; -ACPI_EXTERN u32 acpi_gbl_edge_level_save; -ACPI_EXTERN u32 acpi_gbl_irq_enable_save; ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; ACPI_EXTERN u32 acpi_gbl_ps_find_count; ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; ACPI_EXTERN u16 acpi_gbl_next_table_owner_id; ACPI_EXTERN u16 acpi_gbl_next_method_owner_id; +ACPI_EXTERN u16 acpi_gbl_global_lock_handle; ACPI_EXTERN u8 acpi_gbl_debugger_configuration; ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; ACPI_EXTERN u8 acpi_gbl_step_to_next_call; @@ -130,10 +137,10 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_present; extern u8 acpi_gbl_shutdown; -extern u32 acpi_gbl_system_flags; 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 acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; /***************************************************************************** @@ -150,14 +157,14 @@ ACPI_EXTERN acpi_namespace_node *acpi_gbl_root_node; extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; -extern const predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; +extern const acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; #ifdef ACPI_DEBUG ACPI_EXTERN u32 acpi_gbl_current_node_count; ACPI_EXTERN u32 acpi_gbl_current_node_size; ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; -ACPI_EXTERN unsigned long acpi_gbl_entry_stack_pointer; -ACPI_EXTERN u32 acpi_gbl_lowest_stack_pointer; +ACPI_EXTERN ACPI_SIZE acpi_gbl_entry_stack_pointer; +ACPI_EXTERN ACPI_SIZE acpi_gbl_lowest_stack_pointer; ACPI_EXTERN u32 acpi_gbl_deepest_nesting; #endif @@ -168,11 +175,7 @@ ****************************************************************************/ -ACPI_EXTERN acpi_walk_list *acpi_gbl_current_walk_list; - -/* Address Space handlers */ - -ACPI_EXTERN acpi_adr_space_info acpi_gbl_address_spaces[ACPI_NUM_ADDRESS_SPACES]; +ACPI_EXTERN ACPI_THREAD_STATE *acpi_gbl_current_walk_list; /* Control method single step flag */ @@ -187,34 +190,41 @@ ACPI_EXTERN acpi_parse_object *acpi_gbl_parsed_namespace_root; +/***************************************************************************** + * + * Hardware globals + * + ****************************************************************************/ + +extern ACPI_BIT_REGISTER_INFO acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; +ACPI_EXTERN u8 acpi_gbl_sleep_type_a; +ACPI_EXTERN u8 acpi_gbl_sleep_type_b; + /***************************************************************************** * - * Event globals + * Event and GPE globals * ****************************************************************************/ -ACPI_EXTERN acpi_fixed_event_info acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; +extern acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; +ACPI_EXTERN ACPI_FIXED_EVENT_HANDLER acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; + ACPI_EXTERN acpi_handle acpi_gbl_gpe_obj_handle; ACPI_EXTERN u32 acpi_gbl_gpe_register_count; -ACPI_EXTERN acpi_gpe_registers *acpi_gbl_gpe_registers; -ACPI_EXTERN acpi_gpe_level_info *acpi_gbl_gpe_info; +ACPI_EXTERN u32 acpi_gbl_gpe_number_max; +ACPI_EXTERN ACPI_GPE_REGISTER_INFO *acpi_gbl_gpe_register_info; +ACPI_EXTERN ACPI_GPE_NUMBER_INFO *acpi_gbl_gpe_number_info; +ACPI_EXTERN ACPI_GPE_BLOCK_INFO acpi_gbl_gpe_block_info[ACPI_MAX_GPE_BLOCKS]; /* - * Gpe validation and translation table - * Indexed by the GPE number, returns GPE_INVALID if the GPE is not supported. - * Otherwise, returns a valid index into the global GPE table. + * GPE translation table + * Indexed by the GPE number, returns a valid index into the global GPE tables. * * This table is needed because the GPE numbers supported by block 1 do not * have to be contiguous with the GPE numbers supported by block 0. */ -ACPI_EXTERN u8 acpi_gbl_gpe_valid [ACPI_NUM_GPE]; - -/* Acpi_event counter for debug only */ - -#ifdef ACPI_DEBUG -ACPI_EXTERN u32 acpi_gbl_event_count[ACPI_NUM_FIXED_EVENTS]; -#endif +ACPI_EXTERN ACPI_GPE_INDEX_INFO *acpi_gbl_gpe_number_to_index; /***************************************************************************** @@ -223,10 +233,56 @@ * ****************************************************************************/ + +ACPI_EXTERN u8 acpi_gbl_db_output_flags; + + #ifdef ENABLE_DEBUGGER -ACPI_EXTERN u8 acpi_gbl_method_executing; -ACPI_EXTERN u8 acpi_gbl_db_terminate_threads; -#endif + +extern u8 acpi_gbl_method_executing; +extern u8 acpi_gbl_db_terminate_threads; + +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; + + +ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN NATIVE_CHAR acpi_gbl_db_line_buf[80]; +ACPI_EXTERN NATIVE_CHAR acpi_gbl_db_parsed_buf[80]; +ACPI_EXTERN NATIVE_CHAR acpi_gbl_db_scope_buf[40]; +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; +ACPI_EXTERN acpi_namespace_node *acpi_gbl_db_scope_node; + +/* + * Statistic globals + */ +ACPI_EXTERN u16 acpi_gbl_obj_type_count[INTERNAL_TYPE_NODE_MAX+1]; +ACPI_EXTERN u16 acpi_gbl_node_type_count[INTERNAL_TYPE_NODE_MAX+1]; +ACPI_EXTERN u16 acpi_gbl_obj_type_count_misc; +ACPI_EXTERN u16 acpi_gbl_node_type_count_misc; +ACPI_EXTERN u32 acpi_gbl_num_nodes; +ACPI_EXTERN u32 acpi_gbl_num_objects; + + +ACPI_EXTERN u32 acpi_gbl_size_of_parse_tree; +ACPI_EXTERN u32 acpi_gbl_size_of_method_trees; +ACPI_EXTERN u32 acpi_gbl_size_of_node_entries; +ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects; + +#endif /* ENABLE_DEBUGGER */ #endif /* __ACGLOBAL_H__ */ diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/achware.h linux2.4.21_itanium/drivers/acpi/include/achware.h --- linux2.4.21_itanium.org/drivers/acpi/include/achware.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/achware.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -60,50 +60,48 @@ /* Register I/O Prototypes */ +ACPI_BIT_REGISTER_INFO * +acpi_hw_get_bit_register_info ( + u32 register_id); -u32 -acpi_hw_register_bit_access ( - NATIVE_UINT read_write, - u8 use_lock, - u32 register_id, - ... /* DWORD Write Value */); - -u32 +acpi_status acpi_hw_register_read ( u8 use_lock, - u32 register_id); + u32 register_id, + u32 *return_value); -void +acpi_status acpi_hw_register_write ( u8 use_lock, u32 register_id, u32 value); -u32 +acpi_status acpi_hw_low_level_read ( u32 width, + u32 *value, acpi_generic_address *reg, u32 offset); -void +acpi_status acpi_hw_low_level_write ( u32 width, u32 value, acpi_generic_address *reg, u32 offset); -void +acpi_status acpi_hw_clear_acpi_status ( void); -u32 -acpi_hw_get_bit_shift ( - u32 mask); - /* GPE support */ -void +u8 +acpi_hw_get_gpe_bit_mask ( + u32 gpe_number); + +acpi_status acpi_hw_enable_gpe ( u32 gpe_number); @@ -111,7 +109,7 @@ acpi_hw_enable_gpe_for_wakeup ( u32 gpe_number); -void +acpi_status acpi_hw_disable_gpe ( u32 gpe_number); @@ -119,33 +117,24 @@ acpi_hw_disable_gpe_for_wakeup ( u32 gpe_number); -void +acpi_status acpi_hw_clear_gpe ( u32 gpe_number); -void +acpi_status acpi_hw_get_gpe_status ( u32 gpe_number, acpi_event_status *event_status); -void +acpi_status acpi_hw_disable_non_wakeup_gpes ( void); -void +acpi_status acpi_hw_enable_non_wakeup_gpes ( void); -/* Sleep Prototypes */ - -acpi_status -acpi_hw_obtain_sleep_type_register_data ( - u8 sleep_state, - u8 *slp_typ_a, - u8 *slp_typ_b); - - /* ACPI Timer prototypes */ acpi_status diff -r -u -N -x CVS -I '$ID:' -I '$Id:' -I '$Revision:' linux2.4.21_itanium.org/drivers/acpi/include/acinterp.h linux2.4.21_itanium/drivers/acpi/include/acinterp.h --- linux2.4.21_itanium.org/drivers/acpi/include/acinterp.h Wed Jul 23 18:20:44 2003 +++ linux2.4.21_itanium/drivers/acpi/include/acinterp.h Wed Jul 23 18:28:09 2003 @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000, 2001 R. Byron Moore + * 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 @@ -27,24 +27,7 @@ #define __ACINTERP_H__ -#define WALK_OPERANDS &(walk_state->operands [walk_state->num_operands -1]) - - -/* Interpreter constants */ - -#define AML_END_OF_BLOCK -1 -#define PUSH_PKG_LENGTH 1 -#define DO_NOT_PUSH_PKG_LENGTH 0 - - -#define STACK_TOP 0 -#define STACK_BOTTOM (u32) -1 - -/* Constants for global "When_to_parse_methods" */ - -#define METHOD_PARSE_AT_INIT 0x0 -#define METHOD_PARSE_JUST_IN_TIME 0x1 -#define METHOD_DELETE_AT_COMPLETION 0x2 +#define ACPI_WALK_OPERANDS (&(walk_state->operands [walk_state->num_operands -1])) acpi_status @@ -53,9 +36,14 @@ acpi_operand_object **stack_ptr, acpi_walk_state *walk_state); +acpi_status +acpi_ex_check_object_type ( + acpi_object_type type_needed, + acpi_object_type this_type, + void *object); /* - * amxface - External interpreter interfaces + * exxface - External interpreter interfaces */ acpi_status @@ -70,7 +58,7 @@ /* - * amconvrt - object conversion + * exconvrt - object conversion */ acpi_status @@ -95,13 +83,19 @@ acpi_status acpi_ex_convert_to_target_type ( - acpi_object_type8 destination_type, - acpi_operand_object **obj_desc, + acpi_object_type destination_type, + acpi_operand_object *source_desc, + acpi_operand_object **result_desc, acpi_walk_state *walk_state); +u32 +acpi_ex_convert_to_ascii ( + acpi_integer integer, + u32 base, + u8 *string); /* - * amfield - ACPI AML (p-code) execution - field manipulation + * exfield - ACPI AML (p-code) execution - field manipulation */ acpi_status @@ -117,55 +111,53 @@ u32 buffer_length); acpi_status -acpi_ex_setup_field ( +acpi_ex_setup_region ( acpi_operand_object *obj_desc, - u32 field_byte_offset); + u32 field_datum_byte_offset); acpi_status -acpi_ex_read_field_datum ( +acpi_ex_access_region ( acpi_operand_object *obj_desc, - u32 field_byte_offset, - u32 *value); + u32 field_datum_byte_offset, + acpi_integer *value, + u32 read_write); -acpi_status -acpi_ex_common_access_field ( - u32 mode, +u8 +acpi_ex_register_overflow ( acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length); - + acpi_integer value); acpi_status -acpi_ex_access_index_field ( - u32 mode, +acpi_ex_field_datum_io ( acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length); + u32 field_datum_byte_offset, + acpi_integer *value, + u32 read_write); acpi_status -acpi_ex_access_bank_field ( - u32 mode, +acpi_ex_write_with_update_rule ( acpi_operand_object *obj_desc, - void *buffer, - u32 buffer_length); + acpi_integer mask, + acpi_integer field_value, + u32 field_datum_byte_offset); -acpi_status -acpi_ex_access_region_field ( - u32 mode, - acpi_operand_object *obj_desc, +void +acpi_ex_get_buffer_datum( + acpi_integer *datum, void *buffer, - u32 buffer_length); - + u32 byte_granularity, + u32 offset); -acpi_status -acpi_ex_access_buffer_field ( - u32 mode, - acpi_operand_object *obj_desc, +void +acpi_ex_set_buffer_datum ( + acpi_integer merged_datum, void *buffer, - u32 buffer_length); + u32 byte_granularity, + u32 offset); acpi_status acpi_ex_read_data_from_field ( + acpi_walk_state *walk_state, acpi_operand_object *obj_desc, acpi_operand_object **ret_buffer_desc); @@ -175,7 +167,7 @@ acpi_operand_object *obj_desc); /* - * ammisc - ACPI AML (p-code) execution - specific opcodes + * exmisc - ACPI AML (p-code) execution - specific opcodes */ acpi_status @@ -190,6 +182,12 @@ acpi_ex_opcode_6A_0T_1R ( acpi_walk_state *walk_state); +u8 +acpi_ex_do_match ( + u32 match_op, + acpi_integer package_value, + acpi_integer match_value); + acpi_status acpi_ex_get_object_reference ( acpi_operand_object *obj_desc, @@ -197,6 +195,13 @@ acpi_walk_state *walk_state); acpi_status +acpi_ex_concat_template ( + acpi_operand_object *obj_desc, + acpi_operand_object *obj_desc2, + acpi_operand_object **actual_return_desc, + acpi_walk_state *walk_state); + +acpi_status acpi_ex_do_concatenate ( acpi_operand_object *obj_desc, acpi_operand_object *obj_desc2, @@ -216,15 +221,6 @@ acpi_integer operand1); acpi_status -acpi_ex_load_op ( - acpi_operand_object *rgn_desc, - acpi_operand_object *ddb_handle); - -acp