From 09f1c96e1703438b1bf936389d82e22245c6536b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:36:42 -0500 Subject: [PATCH] Import 2.4.0-test4pre5 --- Documentation/DocBook/parportbook.tmpl | 31 +- Documentation/kernel-parameters.txt | 62 +- arch/arm/config.in | 19 +- arch/i386/config.in | 18 +- arch/i386/kernel/smp.c | 13 +- arch/ia64/config.in | 28 +- arch/m68k/config.in | 18 +- arch/mips/cobalt/reset.c | 1 - arch/mips/config.in | 15 +- arch/mips/dec/time.c | 579 ++++++----- arch/mips/kernel/mips_ksyms.c | 1 + arch/mips/ld.script.big | 9 + arch/mips/ld.script.little | 9 + arch/mips/orion/misc.c | 2 - arch/mips/orion/setup.c | 2 - arch/mips64/config.in | 17 +- arch/mips64/kernel/head.S | 8 +- arch/mips64/kernel/mips64_ksyms.c | 1 + arch/mips64/kernel/process.c | 7 +- arch/mips64/kernel/r4k_tlb.S | 3 +- arch/mips64/kernel/signal32.c | 4 +- arch/mips64/ld.script.elf32 | 9 + arch/mips64/ld.script.elf64 | 9 + arch/mips64/sgi-ip27/ip27-setup.c | 1 + arch/ppc/config.in | 18 +- arch/s390/config.in | 16 +- arch/sh/config.in | 18 +- arch/sparc64/solaris/timod.c | 2 +- drivers/acpi/Makefile | 2 +- drivers/acpi/cpu.c | 307 ++++++ drivers/acpi/driver.c | 388 +++++++ drivers/acpi/driver.h | 115 +++ drivers/acpi/ec.c | 192 ++++ drivers/acpi/os.c | 380 +++++++ drivers/acpi/osd.c | 1319 ------------------------ drivers/acpi/sys.c | 183 ++++ drivers/acpi/tables.c | 304 ++++++ drivers/block/ll_rw_blk.c | 22 +- drivers/block/md.c | 4 +- drivers/block/paride/paride.c | 27 +- drivers/char/cyclades.c | 173 +++- drivers/char/i2c-parport.c | 2 +- drivers/char/ppdev.c | 83 +- drivers/mtd/Config.in | 90 +- drivers/parport/ChangeLog | 38 +- drivers/parport/init.c | 4 + drivers/parport/share.c | 253 ++++- drivers/scsi/scsi_scan.c | 4 + drivers/usb/devices.c | 116 ++- drivers/video/Makefile | 2 +- drivers/video/vga_font.c | 352 ------- fs/dcache.c | 3 + fs/inode.c | 1 + fs/jffs/inode-v23.c | 11 +- fs/select.c | 11 +- include/asm-mips/param.h | 47 +- include/asm-mips64/dma.h | 3 +- include/asm-mips64/param.h | 8 +- include/asm-mips64/sn/addrs.h | 8 +- include/asm-mips64/sn/agent.h | 7 +- include/asm-mips64/sn/io.h | 5 +- include/asm-mips64/sn/klconfig.h | 38 +- include/asm-mips64/sn/kldir.h | 8 +- include/asm-sparc/bitops.h | 1 - include/asm-sparc64/elf.h | 2 +- include/asm-sparc64/semaphore.h | 1 + include/linux/parport.h | 17 +- include/linux/pci_ids.h | 4 + kernel/sched.c | 4 +- mm/slab.c | 2 +- net/ipv4/tcp_ipv4.c | 6 +- 71 files changed, 3019 insertions(+), 2448 deletions(-) create mode 100644 drivers/acpi/cpu.c create mode 100644 drivers/acpi/driver.c create mode 100644 drivers/acpi/driver.h create mode 100644 drivers/acpi/ec.c create mode 100644 drivers/acpi/os.c delete mode 100644 drivers/acpi/osd.c create mode 100644 drivers/acpi/sys.c create mode 100644 drivers/acpi/tables.c delete mode 100644 drivers/video/vga_font.c diff --git a/Documentation/DocBook/parportbook.tmpl b/Documentation/DocBook/parportbook.tmpl index 754f1a96b653..ef8c07d33760 100644 --- a/Documentation/DocBook/parportbook.tmpl +++ b/Documentation/DocBook/parportbook.tmpl @@ -386,7 +386,7 @@ announces it. The parport_announce_port function walks down the list of parallel port device drivers (struct parport_drivers) calling the - attach function of each. + attach function of each (which may block). @@ -394,7 +394,7 @@ registering a port with the parport_unregister_port function, and device drivers are notified using the detach - callback. + callback (which may not block). @@ -656,9 +656,31 @@ struct parport_driver { to the attach function when it is called, or alternatively can be found from the list of detected parallel ports directly with the (now deprecated) - parport_enumerate function. + parport_enumerate function. A better way of + doing this is with parport_find_number or + parport_find_base functions, which find ports + by number and by base I/O address respectively. + + +#include <parport.h> + + + struct parport *parport_find_number + int number + + + + +#include <parport.h> + + + struct parport *parport_find_base + unsigned long base + + + The next three parameters, pf, kf, and irq_func, are @@ -2202,6 +2224,9 @@ ssize_t write_printer (int fd, const void *ptr, size_t count) !Fdrivers/parport/daisy.c parport_find_class !Fdrivers/parport/share.c parport_register_driver !Fdrivers/parport/share.c parport_unregister_driver +!Fdrivers/parport/share.c parport_get_port +!Fdrivers/parport/share.c parport_put_port +!Fdrivers/parport/share.c parport_find_number parport_find_base !Fdrivers/parport/share.c parport_register_device !Fdrivers/parport/share.c parport_unregister_device !Fdrivers/parport/daisy.c parport_open diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 611d8be802cc..072508d51048 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1,4 +1,4 @@ -June 2000 Kernel Parameters v2.4.0 +July 2000 Kernel Parameters v2.4.0 ~~~~~~~~~~~~~~~~~ The following is a consolidated list of the kernel parameters as implemented @@ -80,6 +80,8 @@ running once the system is up. AM53C974= [HW,SCSI] + amijoy= [HW,JOY] Amiga joystick support + apm= [APM] Advanced Power Management. applicom= [HW] @@ -139,6 +141,12 @@ running once the system is up. dasd= [HW,NET] + db9= [HW,JOY] + + db9_2= [HW,JOY] + + db9_3= [HW,JOY] + debug [KNL] Enable kernel debugging (events log level). decnet= [HW,NET] @@ -179,6 +187,12 @@ running once the system is up. ftape= [HW] Floppy Tape subsystem debugging options. + gc= [HW,JOY] + + gc_2= [HW,JOY] + + gc_3= [HW,JOY] + gdth= [HW,SCSI] gscd= [HW,CD] @@ -194,10 +208,6 @@ running once the system is up. hisax= [HW,ISDN] - in2000= [HW,SCSI] - - init= [KNL] - ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter. icn= [HW,ISDN] @@ -208,40 +218,20 @@ running once the system is up. idebus= [HW] (E)IDE subsystem : VLB/PCI bus speed. + idle= [HW] + + in2000= [HW,SCSI] + + init= [KNL] + ip= [PNP] isp16= [HW,CD] iucv= [HW,NET] - js_am= [HW,JOY] - - js_an= [HW,JOY] - - js_as= [HW.JOY] - - js_console= [HW,JOY] - - js_console2= [HW,JOY] - - js_console3= [HW,JOY] - - js_db9= [HW,JOY] - - js_db9_2= [HW,JOY] - - js_db9_3= [HW,JOY] - - js_l4= [HW,JOY] - - js_pci= [HW,JOY,PCI] + js= [HW,JOY] Analog joystick - js_tg= [HW,JOY] - - js_tg_2= [HW,JOY] - - js_tg_3= [HW,JOY] - kbd-reset [VT] load_ramdisk= [RAM] List of ramdisks to load from floppy. @@ -354,6 +344,8 @@ running once the system is up. nosync [HW, M68K] Disables sync negotiation for all devices. + notsc [BUGS=ix86] Disable Time Stamp Counter + nowb [ARM] opl3= [HW,SOUND] @@ -484,6 +476,12 @@ running once the system is up. tdfx= [HW,DRM] + tgfx= [HW,JOY] + + tgfx_2= [HW,JOY] + + tgfx_3= [HW,JOY] + tmc8xx= [HW,SCSI] tmscsim= [HW,SCSI] diff --git a/arch/arm/config.in b/arch/arm/config.in index e270007f9f3e..7e7e337b6178 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -15,6 +15,14 @@ bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL bool 'Prompt for obsolete code/drivers' CONFIG_OBSOLETE endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu mainmenu_option next_comment comment 'System Type' @@ -157,17 +165,6 @@ else fi endmenu - -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - - mainmenu_option next_comment comment 'General setup' source drivers/pci/Config.in diff --git a/arch/i386/config.in b/arch/i386/config.in index 6557d822d908..d9fcd91db9a7 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -15,6 +15,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Processor type and features' choice 'Processor family' \ @@ -145,15 +154,6 @@ if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then fi endmenu -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all module symbols' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - mainmenu_option next_comment comment 'General setup' diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index e08418fe0675..b11b629fe4b5 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -392,6 +392,8 @@ void smp_send_reschedule(int cpu) * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. */ +static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; + static volatile struct call_data_struct { void (*func) (void *info); void *info; @@ -422,9 +424,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, { struct call_data_struct data; int ret, cpus = smp_num_cpus-1; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; - if(cpus == 0) + if (!cpus) return 0; data.func = func; @@ -434,21 +435,21 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, if (wait) atomic_set(&data.finished, 0); - spin_lock_bh(&lock); + spin_lock_bh(&call_lock); call_data = &data; /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(CALL_FUNCTION_VECTOR); /* Wait for response */ - /* FIXME: lock-up detection, backtrace on lock-up */ - while(atomic_read(&data.started) != cpus) + while (atomic_read(&data.started) != cpus) barrier(); ret = 0; if (wait) while (atomic_read(&data.finished) != cpus) barrier(); - spin_unlock_bh(&lock); + spin_unlock_bh(&call_lock); + return 0; } diff --git a/arch/ia64/config.in b/arch/ia64/config.in index e17fbd6af543..09131fac7a14 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -3,6 +3,20 @@ # mainmenu_name "Kernel configuration of Linux for IA-64 machines" +mainmenu_option next_comment + comment 'Code maturity level options' + bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +endmenu + +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'General setup' @@ -67,20 +81,6 @@ else define_bool CONFIG_PCMCIA n fi -mainmenu_option next_comment - comment 'Code maturity level options' - bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL -endmenu - -mainmenu_option next_comment - comment 'Loadable module support' - bool 'Enable loadable module support' CONFIG_MODULES - if [ "$CONFIG_MODULES" = "y" ]; then - bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool 'Kernel module loader' CONFIG_KMOD - fi -endmenu - source drivers/parport/Config.in endmenu diff --git a/arch/m68k/config.in b/arch/m68k/config.in index bde3a370a67e..076d9107cd33 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -12,6 +12,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Platform dependent setup' @@ -136,15 +145,6 @@ fi endmenu -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - source drivers/mtd/Config.in source drivers/block/Config.in diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c index 6f7cb0a883e3..b91c51fe5a67 100644 --- a/arch/mips/cobalt/reset.c +++ b/arch/mips/cobalt/reset.c @@ -1,7 +1,6 @@ /* * Reset a Cobalt Qube. */ -#include #include #include #include diff --git a/arch/mips/config.in b/arch/mips/config.in index 07ab5da42902..b064607cae61 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -9,6 +9,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Machine selection' if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -159,12 +168,6 @@ comment 'General setup' source drivers/parport/Config.in - bool 'Enable loadable module support' CONFIG_MODULES - if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD - fi - if [ "$CONFIG_DECSTATION" = "y" ]; then bool 'TURBOchannel support' CONFIG_TC # if [ "$CONFIG_TC" = "y" ]; then diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 9f009680d648..151ce507e80b 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -25,7 +25,8 @@ #include #include -extern volatile unsigned long lost_ticks; +extern volatile unsigned long wall_jiffies; +extern rwlock_t xtime_lock; /* * Change this if you have some constant time drift @@ -47,69 +48,69 @@ static unsigned int timerhi = 0, timerlo = 0; */ static unsigned long do_fast_gettimeoffset(void) { - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies = 0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient = 0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=&r"(quotient) - : "r"(timerhi), - "m"(timerlo), - "r"(tmp), - "r"(USECS_PER_JIFFY) - : "$1"); - cached_quotient = quotient; - } - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies = 0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient = 0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r"(quotient) + :"r"(timerhi), + "m"(timerlo), + "r"(tmp), + "r"(USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; //printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - : "=r"(res) - : "r"(count), - "r"(quotient)); + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r"(res) + :"r"(count), + "r"(quotient)); - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; - return res; + return res; } /* This function must be called with interrupts disabled @@ -148,11 +149,11 @@ static unsigned long do_fast_gettimeoffset(void) static unsigned long do_slow_gettimeoffset(void) { - /* - * This is a kludge until I find a way for the - * DECstations without bus cycle counter. HK - */ - return 0; + /* + * This is a kludge until I find a way for the + * DECstations without bus cycle counter. HK + */ + return 0; } static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; @@ -162,47 +163,47 @@ static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags; - save_and_cli(flags); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); + read_lock_irqsave(&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); - /* - * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the timer bottom half hasnt executed yet. - */ - if (lost_ticks) - tv->tv_usec += USECS_PER_JIFFY; + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; - restore_flags(flags); + read_unlock_irqrestore(&xtime_lock, flags); - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } } void do_settimeofday(struct timeval *tv) { - cli(); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; - sti(); + write_lock_irq(&xtime_lock); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + write_unlock_irq(&xtime_lock); } /* @@ -214,53 +215,57 @@ void do_settimeofday(struct timeval *tv) */ static int set_rtc_mmss(unsigned long nowtime) { - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds, RTC_SECONDS); + CMOS_WRITE(real_minutes, RTC_MINUTES); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; } - CMOS_WRITE(real_seconds, RTC_SECONDS); - CMOS_WRITE(real_minutes, RTC_MINUTES); - } else - retval = -1; - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; } /* last time the cmos clock got updated */ @@ -271,40 +276,74 @@ static long last_rtc_update = 0; * as well as call the "do_timer()" routine every clocktick */ static void inline - timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - volatile unsigned char dummy; - - dummy = CMOS_READ(RTC_REG_C); /* ACK RTC Interrupt */ - do_timer(regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + volatile unsigned char dummy; + + dummy = CMOS_READ(RTC_REG_C); /* ACK RTC Interrupt */ + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *) & prof_buffer[pc]); + } + } + do_timer(regs); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + read_lock(&xtime_lock); + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 500000 - (tick >> 1) && + xtime.tv_usec < 500000 + (tick >> 1)) + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + /* As we return to user mode fire off the other CPU schedulers.. this is + basically because we don't yet share IRQ's around. This message is + rigged to be safe on the 386 - basically it's a hack, so don't look + closely for now.. */ + /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ + read_unlock(&xtime_lock); } static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned int count; - - /* - * The cycle counter is only 32 bit which is good for about - * a minute at current count rates of upto 150MHz or so. - */ - count = read_32bit_cp0_register(CP0_COUNT); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - - timer_interrupt(irq, dev_id, regs); + unsigned int count; + + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_32bit_cp0_register(CP0_COUNT); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + + timer_interrupt(irq, dev_id, regs); + + if (!jiffies) { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -326,114 +365,114 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, unsigned int day, unsigned int hour, unsigned int min, unsigned int sec) { - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ - year -= 1; - } - return ((( - (unsigned long) (year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + - year * 365 - 719499 - ) * 24 + hour /* now have hours */ - ) * 60 + min /* now have minutes */ - ) * 60 + sec; /* finally seconds */ + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( + (unsigned long) (year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + + year * 365 - 719499 + ) * 24 + hour /* now have hours */ + ) * 60 + min /* now have minutes */ + ) * 60 + sec; /* finally seconds */ } char cyclecounter_available; static inline void init_cycle_counter(void) { - switch (mips_cputype) { - case CPU_UNKNOWN: - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3041: - case CPU_R3051: - case CPU_R3052: - case CPU_R3081: - case CPU_R3081E: - case CPU_R6000: - case CPU_R6000A: - case CPU_R8000: /* Not shure about that one, play safe */ - cyclecounter_available = 0; - break; - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4200: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - case CPU_R4600: - case CPU_R10000: - case CPU_R4300: - case CPU_R4650: - case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: - case CPU_R4640: - case CPU_NEVADA: - cyclecounter_available = 1; - break; - } + switch (mips_cputype) { + case CPU_UNKNOWN: + case CPU_R2000: + case CPU_R3000: + case CPU_R3000A: + case CPU_R3041: + case CPU_R3051: + case CPU_R3052: + case CPU_R3081: + case CPU_R3081E: + case CPU_R6000: + case CPU_R6000A: + case CPU_R8000: /* Not shure about that one, play safe */ + cyclecounter_available = 0; + break; + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4200: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R4600: + case CPU_R10000: + case CPU_R4300: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_R5000A: + case CPU_R4640: + case CPU_NEVADA: + cyclecounter_available = 1; + break; + } } -struct irqaction irq0 = -{timer_interrupt, SA_INTERRUPT, 0, - "timer", NULL, NULL}; - +struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; void (*board_time_init) (struct irqaction * irq); void __init time_init(void) { - unsigned int year, mon, day, hour, min, sec; - int i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - /* - * The DECstation RTC is used as a TOY (Time Of Year). - * The PROM will reset the year to either '70, '71 or '72. - * This hack will only work until Dec 31 2001. - */ - year += 1927; - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; - - init_cycle_counter(); - - if (cyclecounter_available) { - write_32bit_cp0_register(CP0_COUNT, 0); - do_gettimeoffset = do_fast_gettimeoffset; - irq0.handler = r4k_timer_interrupt; - } - board_time_init(&irq0); + unsigned int year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + /* + * The DECstation RTC is used as a TOY (Time Of Year). + * The PROM will reset the year to either '70, '71 or '72. + * This hack will only work until Dec 31 2001. + */ + year += 1928; + + write_lock_irq(&xtime_lock); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + write_unlock_irq(&xtime_lock); + + init_cycle_counter(); + + if (cyclecounter_available) { + write_32bit_cp0_register(CP0_COUNT, 0); + do_gettimeoffset = do_fast_gettimeoffset; + irq0.handler = r4k_timer_interrupt; + } + board_time_init(&irq0); } diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 1948a67c2cc6..b58272f46f43 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -49,6 +49,7 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL(simple_strtol); EXPORT_SYMBOL_NOVERS(strcat); EXPORT_SYMBOL_NOVERS(strchr); EXPORT_SYMBOL_NOVERS(strlen); diff --git a/arch/mips/ld.script.big b/arch/mips/ld.script.big index 68ac485280a8..27a5bade56ed 100644 --- a/arch/mips/ld.script.big +++ b/arch/mips/ld.script.big @@ -91,6 +91,15 @@ SECTIONS _end = . ; PROVIDE (end = .); } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + /* These are needed for ELF backends which have not yet been converted to the new style linker. */ .stab 0 : { *(.stab) } diff --git a/arch/mips/ld.script.little b/arch/mips/ld.script.little index 5ee17215d7c9..48f9bc5fe6f1 100644 --- a/arch/mips/ld.script.little +++ b/arch/mips/ld.script.little @@ -91,6 +91,15 @@ SECTIONS _end = . ; PROVIDE (end = .); } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + /* These are needed for ELF backends which have not yet been converted to the new style linker. */ .stab 0 : { *(.stab) } diff --git a/arch/mips/orion/misc.c b/arch/mips/orion/misc.c index 1c6d9e2fa5d4..0d88810581bf 100644 --- a/arch/mips/orion/misc.c +++ b/arch/mips/orion/misc.c @@ -35,10 +35,8 @@ #include #include #include -#include #include #include -#include #include char arcs_cmdline[CL_SIZE] = {0, }; diff --git a/arch/mips/orion/setup.c b/arch/mips/orion/setup.c index 8d4cc54f0ff6..c247d6b528ae 100644 --- a/arch/mips/orion/setup.c +++ b/arch/mips/orion/setup.c @@ -35,10 +35,8 @@ #include #include #include -#include #include #include -#include #include #include diff --git a/arch/mips64/config.in b/arch/mips64/config.in index 70e375fed2e3..162fa671ec22 100644 --- a/arch/mips64/config.in +++ b/arch/mips64/config.in @@ -10,6 +10,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Machine selection' bool 'Support for SGI IP22' CONFIG_SGI_IP22 @@ -109,14 +118,6 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC endmenu -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool 'Kernel module loader' CONFIG_KMOD -fi - source drivers/pci/Config.in if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/arch/mips64/kernel/head.S b/arch/mips64/kernel/head.S index c7c4744795eb..4a47176aff74 100644 --- a/arch/mips64/kernel/head.S +++ b/arch/mips64/kernel/head.S @@ -100,10 +100,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point ARC64_TWIDDLE_PC - /* Note that all firmware passed argument registers still - have their values. */ - jal prom_init # initialize firmware - CLI # disable interrupts mfc0 t0, CP0_STATUS @@ -127,6 +123,10 @@ NESTED(kernel_entry, 16, sp) # kernel entry point dsrl32 t0, t0, 0 mtc0 t0, CP0_WATCHHI #endif + /* Note that all firmware passed argument registers still + have their values. */ + jal prom_init # initialize firmware + jal start_kernel 1: b 1b # just in case ... END(kernel_entry) diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c index c65f05865fa6..284e831b4614 100644 --- a/arch/mips64/kernel/mips64_ksyms.c +++ b/arch/mips64/kernel/mips64_ksyms.c @@ -46,6 +46,7 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL(simple_strtol); EXPORT_SYMBOL_NOVERS(strcat); EXPORT_SYMBOL_NOVERS(strchr); EXPORT_SYMBOL_NOVERS(strlen); diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c index 54c400609721..924140719785 100644 --- a/arch/mips64/kernel/process.c +++ b/arch/mips64/kernel/process.c @@ -1,11 +1,10 @@ -/* $Id: process.c,v 1.4 2000/01/16 01:34:01 ralf 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) 1994 - 1999 by Ralf Baechle and others. - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include diff --git a/arch/mips64/kernel/r4k_tlb.S b/arch/mips64/kernel/r4k_tlb.S index 9089c13336c6..ca0ab79dc8b9 100644 --- a/arch/mips64/kernel/r4k_tlb.S +++ b/arch/mips64/kernel/r4k_tlb.S @@ -1,5 +1,4 @@ -/* $Id: r4k_tlb.S,v 1.3 2000/06/30 00:48:29 kanoj 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. diff --git a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c index 39e0d99ef212..1988b681cc02 100644 --- a/arch/mips64/kernel/signal32.c +++ b/arch/mips64/kernel/signal32.c @@ -4,8 +4,8 @@ * for more details. * * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994 - 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1994 - 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include diff --git a/arch/mips64/ld.script.elf32 b/arch/mips64/ld.script.elf32 index 659e3761ae50..a67b3449a2ec 100644 --- a/arch/mips64/ld.script.elf32 +++ b/arch/mips64/ld.script.elf32 @@ -83,6 +83,15 @@ SECTIONS *(COMMON) _end = . ; } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + /* These are needed for ELF backends which have not yet been converted to the new style linker. */ .stab 0 : { *(.stab) } diff --git a/arch/mips64/ld.script.elf64 b/arch/mips64/ld.script.elf64 index 47f638b4a4dc..2b3ff38c6152 100644 --- a/arch/mips64/ld.script.elf64 +++ b/arch/mips64/ld.script.elf64 @@ -92,6 +92,15 @@ SECTIONS *(COMMON) _end = . ; } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + /* These are needed for ELF backends which have not yet been converted to the new style linker. */ .stab 0 : { *(.stab) } diff --git a/arch/mips64/sgi-ip27/ip27-setup.c b/arch/mips64/sgi-ip27/ip27-setup.c index 1525855e8ac1..fbd8d1fa77df 100644 --- a/arch/mips64/sgi-ip27/ip27-setup.c +++ b/arch/mips64/sgi-ip27/ip27-setup.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Check against user dumbness. */ #ifdef CONFIG_VT diff --git a/arch/ppc/config.in b/arch/ppc/config.in index 33f6eaa95375..2371da8e45b0 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -11,6 +11,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y @@ -76,15 +85,6 @@ if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then fi endmenu -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all module symbols' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - mainmenu_option next_comment comment 'General setup' diff --git a/arch/s390/config.in b/arch/s390/config.in index 9e946365ffeb..7835a0162b88 100644 --- a/arch/s390/config.in +++ b/arch/s390/config.in @@ -13,21 +13,21 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu -mainmenu_option next_comment -comment 'Processor type and features' -bool 'Symmetric multi-processing support' CONFIG_SMP -bool 'IEEE FPU emulation' CONFIG_IEEEFPU_EMULATION -endmenu - mainmenu_option next_comment comment 'Loadable module support' bool 'Enable loadable module support' CONFIG_MODULES if [ "$CONFIG_MODULES" = "y" ]; then - bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool 'Kernel module loader' CONFIG_KMOD + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD fi endmenu +mainmenu_option next_comment +comment 'Processor type and features' +bool 'Symmetric multi-processing support' CONFIG_SMP +bool 'IEEE FPU emulation' CONFIG_IEEEFPU_EMULATION +endmenu + mainmenu_option next_comment comment 'General setup' bool 'Fast IRQ handling' CONFIG_FAST_IRQ diff --git a/arch/sh/config.in b/arch/sh/config.in index 025e8a8ea4d8..0a83038dcb40 100644 --- a/arch/sh/config.in +++ b/arch/sh/config.in @@ -13,6 +13,15 @@ comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + mainmenu_option next_comment comment 'Processor type and features' choice 'SuperH system type' \ @@ -47,15 +56,6 @@ else fi endmenu -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool 'Kernel module loader' CONFIG_KMOD -fi -endmenu - mainmenu_option next_comment comment 'General setup' diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c index aedb0f17d7c6..946b20fae7c9 100644 --- a/arch/sparc64/solaris/timod.c +++ b/arch/sparc64/solaris/timod.c @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.8 2000/07/12 00:51:06 davem Exp $ +/* $Id: timod.c,v 1.9 2000/07/12 23:21:02 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c8b888ff1bfa..2c96066632a2 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -11,7 +11,7 @@ O_TARGET := acpi.o O_OBJS := M_OBJS := -ACPI_OBJS := osd.o +ACPI_OBJS := driver.o ec.o cpu.o os.o sys.o tables.o ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard */*.c)) EXTRA_CFLAGS += -I./include -D_LINUX diff --git a/drivers/acpi/cpu.c b/drivers/acpi/cpu.c new file mode 100644 index 000000000000..f1feeb12b60c --- /dev/null +++ b/drivers/acpi/cpu.c @@ -0,0 +1,307 @@ +/* + * cpu.c - Processor handling + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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.h" +#include "driver.h" + +unsigned long acpi_c2_exit_latency = ACPI_INFINITE; +unsigned long acpi_c3_exit_latency = ACPI_INFINITE; +unsigned long acpi_c2_enter_latency = ACPI_INFINITE; +unsigned long acpi_c3_enter_latency = ACPI_INFINITE; + +static unsigned long acpi_pblk = ACPI_INVALID; +static int acpi_c2_tested = 0; +static int acpi_c3_tested = 0; + +/* + * Clear busmaster activity flag + */ +static inline void +acpi_clear_bm_activity(struct acpi_facp *facp) +{ + acpi_write_pm1_status(facp, ACPI_BM); +} + +/* + * Returns 1 if there has been busmaster activity + */ +static inline int +acpi_bm_activity(struct acpi_facp *facp) +{ + return acpi_read_pm1_status(facp) & ACPI_BM; +} + +/* + * Set system to sleep through busmaster requests + */ +static void +acpi_sleep_on_busmaster(struct acpi_facp *facp) +{ + u32 pm1_cntr = acpi_read_pm1_control(facp); + if (pm1_cntr & ACPI_BM_RLD) { + pm1_cntr &= ~ACPI_BM_RLD; + acpi_write_pm1_control(facp, pm1_cntr); + } +} + +/* + * Set system to wake on busmaster requests + */ +static void +acpi_wake_on_busmaster(struct acpi_facp *facp) +{ + u32 pm1_cntr = acpi_read_pm1_control(facp); + if (!(pm1_cntr & ACPI_BM_RLD)) { + pm1_cntr |= ACPI_BM_RLD; + acpi_write_pm1_control(facp, pm1_cntr); + } + acpi_clear_bm_activity(facp); +} + +/* The ACPI timer is just the low 24 bits */ +#define TIME_BEGIN(tmr) inl(tmr) +#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff) + +/* + * Idle loop (uniprocessor only) + */ +static void +acpi_idle(void) +{ + static int sleep_level = 1; + struct acpi_facp *facp = &acpi_facp; + + if (!facp + || facp->hdr.signature != ACPI_FACP_SIG + || !facp->pm_tmr + || !acpi_pblk) + goto not_initialized; + + /* + * start from the previous sleep level.. + */ + if (sleep_level == 1) + goto sleep1; + if (sleep_level == 2) + goto sleep2; + sleep3: + sleep_level = 3; + if (!acpi_c3_tested) { + printk(KERN_DEBUG "ACPI C3 works\n"); + acpi_c3_tested = 1; + } + acpi_wake_on_busmaster(facp); + if (facp->pm2_cnt) + goto sleep3_with_arbiter; + + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + if (acpi_bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); + inb(acpi_pblk + ACPI_P_LVL3); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + + __sti(); + if (time < acpi_c3_exit_latency) + goto sleep2; + } + + sleep3_with_arbiter: + for (;;) { + unsigned long time; + u8 arbiter; + unsigned int pm2_cntr = facp->pm2_cnt; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + if (acpi_bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); + arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS; + /* Disable arbiter, park on CPU */ + outb(arbiter | ACPI_ARB_DIS, pm2_cntr); + inb(acpi_pblk + ACPI_P_LVL3); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + /* Enable arbiter again.. */ + outb(arbiter, pm2_cntr); + + __sti(); + if (time < acpi_c3_exit_latency) + goto sleep2; + } + + sleep2: + sleep_level = 2; + if (!acpi_c2_tested) { + printk(KERN_DEBUG "ACPI C2 works\n"); + acpi_c2_tested = 1; + } + acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */ + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + + time = TIME_BEGIN(pm_tmr); + inb(acpi_pblk + ACPI_P_LVL2); + /* Dummy read, force synchronization with the PMU */ + inl(pm_tmr); + time = TIME_END(pm_tmr, time); + + __sti(); + if (time < acpi_c2_exit_latency) + goto sleep1; + if (acpi_bm_activity(facp)) { + acpi_clear_bm_activity(facp); + continue; + } + if (time > acpi_c3_enter_latency) + goto sleep3; + } + + sleep1: + sleep_level = 1; + acpi_sleep_on_busmaster(facp); + for (;;) { + unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + + __cli(); + if (current->need_resched) + goto out; + time = TIME_BEGIN(pm_tmr); + safe_halt(); + time = TIME_END(pm_tmr, time); + if (time > acpi_c2_enter_latency) + goto sleep2; + } + + not_initialized: + for (;;) { + __cli(); + if (current->need_resched) + goto out; + safe_halt(); + } + + out: + __sti(); +} + +/* + * Get processor information + */ +static ACPI_STATUS +acpi_find_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value) +{ + ACPI_OBJECT obj; + ACPI_CX_STATE lat[4]; + ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE]; + ACPI_BUFFER buf; + int i, count; + + buf.length = sizeof(obj); + buf.pointer = &obj; + if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf))) + return AE_OK; + + printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n", + obj.processor.proc_id, + obj.processor.pblk_address, + obj.processor.pblk_length); + if (acpi_pblk != ACPI_INVALID + || !obj.processor.pblk_address + || obj.processor.pblk_length != 6) + return AE_OK; + + acpi_pblk = obj.processor.pblk_address; + + buf.length = sizeof(lat); + buf.pointer = lat; + if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf))) + return AE_OK; + + if (lat[2].latency < MAX_CX_STATE_LATENCY) { + printk(KERN_INFO "ACPI: C2 supported\n"); + acpi_c2_exit_latency = lat[2].latency; + } + if (lat[3].latency < MAX_CX_STATE_LATENCY) { + printk(KERN_INFO "ACPI: C3 supported\n"); + acpi_c3_exit_latency = lat[3].latency; + } + + memset(throttle, 0, sizeof(throttle)); + buf.length = sizeof(throttle); + buf.pointer = throttle; + + if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf))) + return AE_OK; + + for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) { + if (throttle[i].percent_of_clock) + count++; + } + count--; + if (count > 0) + printk(KERN_INFO "ACPI: %d throttling states\n", count); + + return AE_OK; +} + +int +acpi_cpu_init(void) +{ + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, + ACPI_ROOT_OBJECT, + ACPI_INT32_MAX, + acpi_find_cpu, + NULL, + NULL); + +#ifdef CONFIG_SMP + if (smp_num_cpus == 1) + pm_idle = acpi_idle; +#else + pm_idle = acpi_idle; +#endif + + return 0; +} diff --git a/drivers/acpi/driver.c b/drivers/acpi/driver.c new file mode 100644 index 000000000000..0c668f59bdb5 --- /dev/null +++ b/drivers/acpi/driver.c @@ -0,0 +1,388 @@ +/* + * driver.c - ACPI driver + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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 "acpi.h" +#include "driver.h" + +struct acpi_run_entry +{ + void (*callback)(void*); + void *context; + struct tq_struct task; +}; + +static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; +static volatile u32 acpi_event_status = 0; +static volatile acpi_sstate_t acpi_event_state = ACPI_S0; +static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); + +static volatile int acpi_thread_pid = -1; +static DECLARE_TASK_QUEUE(acpi_thread_run); +static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait); + +static struct ctl_table_header *acpi_sysctl = NULL; + +/* + * Examine/modify value + */ +static int +acpi_do_ulong(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + char str[2 * sizeof(unsigned long) + 4], *strend; + unsigned long val; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = *(unsigned long *) ctl->data; + size = sprintf(str, "0x%08lx\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else { + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + *(unsigned long *) ctl->data = val; + } + + file->f_pos += *len; + return 0; +} + +/* + * Handle ACPI event + */ +static u32 +acpi_event(void *context) +{ + unsigned long flags; + int event = (int) context; + int mask = 0; + + switch (event) { + case ACPI_EVENT_POWER_BUTTON: mask = ACPI_PWRBTN; break; + case ACPI_EVENT_SLEEP_BUTTON: mask = ACPI_SLPBTN; break; + default: return AE_ERROR; + } + + if (mask) { + // notify process waiting on /dev/acpi + spin_lock_irqsave(&acpi_event_lock, flags); + acpi_event_status |= mask; + spin_unlock_irqrestore(&acpi_event_lock, flags); + acpi_event_state = acpi_sleep_state; + wake_up_interruptible(&acpi_event_wait); + } + + return AE_OK; +} + +/* + * Wait for next event + */ +static int +acpi_do_event(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + u32 event_status = 0; + acpi_sstate_t event_state = 0; + char str[27]; + int size; + + if (write) + return -EPERM; + if (*len < sizeof(str)) { + *len = 0; + return 0; + } + + for (;;) { + unsigned long flags; + + // we need an atomic exchange here + spin_lock_irqsave(&acpi_event_lock, flags); + event_status = acpi_event_status; + acpi_event_status = 0; + spin_unlock_irqrestore(&acpi_event_lock, flags); + event_state = acpi_event_state; + + if (event_status) + break; + + // wait for an event to arrive + interruptible_sleep_on(&acpi_event_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + size = sprintf(str, + "0x%08x 0x%08x 0x%01x\n", + event_status, + 0, + event_state); + copy_to_user(buffer, str, size); + *len = size; + file->f_pos += size; + + return 0; +} + +/* + * Enter system sleep state + */ +static int +acpi_do_sleep(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + } + else { +#ifdef CONFIG_ACPI_S1_SLEEP + int status = acpi_enter_sx(ACPI_S1); + if (status) + return status; +#endif + } + file->f_pos += *len; + return 0; +} + +/* + * Run queued callback + */ +static void +acpi_run_exec(void *context) +{ + struct acpi_run_entry *entry + = (struct acpi_run_entry*) context; + (*entry->callback)(entry->context); + kfree(entry); +} + +/* + * Queue for execution by the ACPI thread + */ +int +acpi_run(void (*callback)(void*), void *context) +{ + struct acpi_run_entry *entry; + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return -1; + + memset(entry, 0, sizeof(entry)); + entry->callback = callback; + entry->context = context; + entry->task.routine = acpi_run_exec; + entry->task.data = entry; + + queue_task(&entry->task, &acpi_thread_run); + + if (waitqueue_active(&acpi_thread_wait)) + wake_up(&acpi_thread_wait); + + return 0; +} + +static struct ctl_table acpi_table[] = +{ + {ACPI_P_LVL2_LAT, "c2_exit_latency", + &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_ENTER_LVL2_LAT, "c2_enter_latency", + &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL3_LAT, "c3_exit_latency", + &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_ENTER_LVL3_LAT, "c3_enter_latency", + &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, + + {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, + + {0} +}; + +static struct ctl_table acpi_dir_table[] = +{ + {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, + {0} +}; + +/* + * Initialize and run interpreter within a kernel thread + */ +static int +acpi_thread(void *context) +{ + /* + * initialize + */ + exit_files(current); + daemonize(); + strcpy(current->comm, "acpi"); + + if (!ACPI_SUCCESS(acpi_initialize(NULL))) { + printk(KERN_ERR "ACPI: initialize failed\n"); + return -ENODEV; + } + + if (acpi_load_tables()) + return -ENODEV; + + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "ACPI: APM is already active.\n"); + acpi_terminate(); + return -ENODEV; + } + + pm_active = 1; + + if (!ACPI_SUCCESS(acpi_enable())) { + printk(KERN_ERR "ACPI: enable failed\n"); + acpi_terminate(); + return -ENODEV; + } + + acpi_cpu_init(); + acpi_sys_init(); + acpi_ec_init(); + + if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, + acpi_event, + (void *) ACPI_EVENT_POWER_BUTTON))) { + printk(KERN_ERR "ACPI: power button enable failed\n"); + } + if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, + acpi_event, + (void *) ACPI_EVENT_SLEEP_BUTTON))) { + printk(KERN_ERR "ACPI: sleep button enable failed\n"); + } + + acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); + + /* + * run + */ + for (;;) { + interruptible_sleep_on(&acpi_thread_wait); + if (signal_pending(current)) + break; + do { + run_task_queue(&acpi_thread_run); + } while (acpi_thread_run); + } + + /* + * terminate + */ + unregister_sysctl_table(acpi_sysctl); + acpi_terminate(); + + acpi_thread_pid = -1; + + return 0; +} + +/* + * Start the interpreter + */ +int __init +acpi_init(void) +{ + acpi_thread_pid = kernel_thread(acpi_thread, + NULL, + (CLONE_FS | CLONE_FILES + | CLONE_SIGHAND | SIGCHLD)); + return ((acpi_thread_pid >= 0) ? 0:-ENODEV); +} + +/* + * Terminate the interpreter + */ +void __exit +acpi_exit(void) +{ + int count; + + if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) { + // wait until thread terminates (at most 5 seconds) + count = 5 * HZ; + while (acpi_thread_pid >= 0 && --count) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + } + + pm_idle = NULL; + pm_power_off = NULL; + pm_active = 0; +} + +module_init(acpi_init); +module_exit(acpi_exit); diff --git a/drivers/acpi/driver.h b/drivers/acpi/driver.h new file mode 100644 index 000000000000..a26402b4097d --- /dev/null +++ b/drivers/acpi/driver.h @@ -0,0 +1,115 @@ +/* + * driver.h - ACPI driver + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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 __DRIVER_H +#define __DRIVER_H + +#include +#include +#include +#include +#include + +#define ACPI_MAX_THROTTLE 10 +#define ACPI_INVALID ~0UL +#define ACPI_INFINITE ~0UL + +/* + * cpu.c + */ +int acpi_cpu_init(void); + +extern unsigned long acpi_c2_exit_latency; +extern unsigned long acpi_c3_exit_latency; +extern unsigned long acpi_c2_enter_latency; +extern unsigned long acpi_c3_enter_latency; + +/* + * driver.c + */ +int acpi_run(void (*callback)(void*), void *context); + +/* + * ec.c + */ +int acpi_ec_init(void); +int acpi_ec_read(int addr, int *value); +int acpi_ec_write(int addr, int value); + +/* + * sys.c + */ +int acpi_sys_init(void); +int acpi_enter_sx(acpi_sstate_t state); + +extern volatile acpi_sstate_t acpi_sleep_state; + +/* + * tables.c + */ +extern struct acpi_facp acpi_facp; + +int acpi_load_tables(void); + +/* + * access ACPI registers + */ + +extern inline u32 +acpi_read_pm1_control(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_cnt) + value = inw(facp->pm1a_cnt); + if (facp->pm1b_cnt) + value |= inw(facp->pm1b_cnt); + return value; +} + +extern inline void +acpi_write_pm1_control(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_cnt) + outw(value, facp->pm1a_cnt); + if (facp->pm1b_cnt) + outw(value, facp->pm1b_cnt); +} + +extern inline u32 +acpi_read_pm1_status(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt); + if (facp->pm1b_evt) + value |= inw(facp->pm1b_evt); + return value; +} + +extern inline void +acpi_write_pm1_status(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt); + if (facp->pm1b_evt) + outw(value, facp->pm1b_evt); +} + +#endif /* __DRIVER_H */ diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c new file mode 100644 index 000000000000..b6be7d8a24e0 --- /dev/null +++ b/drivers/acpi/ec.c @@ -0,0 +1,192 @@ +/* + * ec.c - Embedded controller support + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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 "acpi.h" +#include "driver.h" + +enum +{ + ACPI_EC_HID = 0x090cd041, +}; + +enum +{ + ACPI_EC_SMI = 0x40, + ACPI_EC_SCI = 0x20, + ACPI_EC_BURST = 0x10, + ACPI_EC_CMD = 0x08, + ACPI_EC_IBF = 0x02, + ACPI_EC_OBF = 0x01 +}; + +enum +{ + ACPI_EC_READ = 0x80, + ACPI_EC_WRITE = 0x81, + ACPI_EC_BURST_ENABLE = 0x82, + ACPI_EC_BURST_DISABLE = 0x83, + ACPI_EC_QUERY = 0x84, +}; + + +static int acpi_ec_data = 0; +static int acpi_ec_status = 0; +static DECLARE_WAIT_QUEUE_HEAD(acpi_ec_wait); + +/* + * handle GPE + */ +static void +acpi_ec_gpe(void *context) +{ + printk(KERN_INFO "ACPI: EC GPE\n"); + if (waitqueue_active(&acpi_ec_wait)) + wake_up_interruptible(&acpi_ec_wait); +} + +/* + * wait for read/write status to clear + */ +static void +acpi_ec_wait_control(void) +{ + udelay(1); + while(inb(acpi_ec_status) & ACPI_EC_IBF) + udelay(10); +} + +/* + * read a byte from the EC + */ +int +acpi_ec_read(int addr, int *value) +{ + if (!acpi_ec_data || !acpi_ec_status) + return -1; + + outb(ACPI_EC_READ, acpi_ec_status); + acpi_ec_wait_control(); + outb(addr, acpi_ec_data); + acpi_ec_wait_control(); + interruptible_sleep_on(&acpi_ec_wait); + *value = inb(acpi_ec_data); + + return 0; +} + +/* + * write a byte to the EC + */ +int +acpi_ec_write(int addr, int value) +{ + if (!acpi_ec_data || !acpi_ec_status) + return -1; + + outb(ACPI_EC_WRITE, acpi_ec_status); + acpi_ec_wait_control(); + outb(addr, acpi_ec_data); + acpi_ec_wait_control(); + outb(value, acpi_ec_data); + acpi_ec_wait_control(); + interruptible_sleep_on(&acpi_ec_wait); + + return 0; +} + +/* + * Get processor information + */ +static ACPI_STATUS +acpi_find_ec(ACPI_HANDLE handle, u32 level, void *ctx, void **value) +{ + ACPI_BUFFER buf; + ACPI_OBJECT obj; + RESOURCE *res; + int gpe; + + buf.length = sizeof(obj); + buf.pointer = &obj; + if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_HID", NULL, &buf)) + || obj.type != ACPI_TYPE_NUMBER + || obj.number.value != ACPI_EC_HID) + return AE_OK; + + buf.length = 0; + buf.pointer = NULL; + if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW) + return AE_OK; + + buf.pointer = kmalloc(buf.length, GFP_KERNEL); + if (!buf.pointer) + return AE_OK; + + if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) { + kfree(buf.pointer); + return AE_OK; + } + + res = (RESOURCE*) buf.pointer; + acpi_ec_data = (int) res->data.io.min_base_address; + res = (RESOURCE*)((u8*) buf.pointer + res->length); + acpi_ec_status = (int) res->data.io.min_base_address; + + kfree(buf.pointer); + + buf.length = sizeof(obj); + buf.pointer = &obj; + if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf)) + || obj.type != ACPI_TYPE_NUMBER) + return AE_OK; + gpe = (int) obj.number.value; + + printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,%d)\n", + acpi_ec_data, acpi_ec_status, gpe); + + if (!ACPI_SUCCESS(acpi_install_gpe_handler( + gpe, + (ACPI_EVENT_LEVEL_TRIGGERED + | ACPI_EVENT_EDGE_TRIGGERED), + acpi_ec_gpe, + NULL))) + return AE_OK; + + return AE_OK; +} + +int +acpi_ec_init(void) +{ + acpi_walk_namespace(ACPI_TYPE_DEVICE, + ACPI_ROOT_OBJECT, + ACPI_INT32_MAX, + acpi_find_ec, + NULL, + NULL); + return 0; +} diff --git a/drivers/acpi/os.c b/drivers/acpi/os.c new file mode 100644 index 000000000000..d5c11426f961 --- /dev/null +++ b/drivers/acpi/os.c @@ -0,0 +1,380 @@ +/* + * os.c - OS-dependent functions + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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 "acpi.h" +#include "driver.h" + +static int acpi_irq_irq = 0; +static OSD_HANDLER acpi_irq_handler = NULL; +static void *acpi_irq_context = NULL; + +char * +strupr(char *str) +{ + char *s = str; + while (*s) { + *s = TOUPPER(*s); + s++; + } + return str; +} + +ACPI_STATUS +acpi_os_initialize(void) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_terminate(void) +{ + if (acpi_irq_handler) { + acpi_os_remove_interrupt_handler(acpi_irq_irq, + acpi_irq_handler); + } + return AE_OK; +} + +s32 +acpi_os_printf(const char *fmt,...) +{ + s32 size; + va_list args; + va_start(args, fmt); + size = acpi_os_vprintf(fmt, args); + va_end(args); + return size; +} + +s32 +acpi_os_vprintf(const char *fmt, va_list args) +{ + static char buffer[512]; + int size = vsprintf(buffer, fmt, args); + printk(KERN_DEBUG "ACPI: %s", buffer); + return size; +} + +void * +acpi_os_allocate(u32 size) +{ + return kmalloc(size, GFP_KERNEL); +} + +void * +acpi_os_callocate(u32 size) +{ + void *ptr = acpi_os_allocate(size); + if (ptr) + memset(ptr, 0, size); + return ptr; +} + +void +acpi_os_free(void *ptr) +{ + kfree(ptr); +} + +ACPI_STATUS +acpi_os_map_memory(void *phys, u32 size, void **virt) +{ + if ((unsigned long) phys < virt_to_phys(high_memory)) { + *virt = phys_to_virt((unsigned long) phys); + return AE_OK; + } + + *virt = ioremap((unsigned long) phys, size); + if (!*virt) + return AE_ERROR; + + return AE_OK; +} + +void +acpi_os_unmap_memory(void *virt, u32 size) +{ + if (virt >= high_memory) + iounmap(virt); +} + +static void +acpi_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + (*acpi_irq_handler)(acpi_irq_context); +} + +ACPI_STATUS +acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) +{ + acpi_irq_irq = irq; + acpi_irq_handler = handler; + acpi_irq_context = context; + if (request_irq(irq, + acpi_irq, + SA_INTERRUPT | SA_SHIRQ, + "acpi", + acpi_irq)) { + printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq); + return AE_ERROR; + } + return AE_OK; +} + +ACPI_STATUS +acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +{ + if (acpi_irq_handler) { + free_irq(irq, acpi_irq); + acpi_irq_handler = NULL; + } + return AE_OK; +} + +/* + * Running in interpreter thread context, safe to sleep + */ + +void +acpi_os_sleep(u32 sec, u32 ms) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ * sec + (ms * HZ) / 1000); +} + +void +acpi_os_sleep_usec(u32 us) +{ + udelay(us); +} + +u8 +acpi_os_in8(ACPI_IO_ADDRESS port) +{ + return inb(port); +} + +u16 +acpi_os_in16(ACPI_IO_ADDRESS port) +{ + return inw(port); +} + +u32 +acpi_os_in32(ACPI_IO_ADDRESS port) +{ + return inl(port); +} + +void +acpi_os_out8(ACPI_IO_ADDRESS port, u8 val) +{ + outb(val, port); +} + +void +acpi_os_out16(ACPI_IO_ADDRESS port, u16 val) +{ + outw(val, port); +} + +void +acpi_os_out32(ACPI_IO_ADDRESS port, u32 val) +{ + outl(val, port); +} + +ACPI_STATUS +acpi_os_read_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_byte(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_word(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 * val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!val || !dev || pci_read_config_dword(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_byte(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_word(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 val) +{ + int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); + if (!dev || pci_write_config_dword(dev, addr, val)) + return AE_ERROR; + return AE_OK; +} + +/* + * Queue for interpreter thread + */ + +ACPI_STATUS +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context) +{ + if (acpi_run(callback, context)) + return AE_ERROR; + return AE_OK; +} + +/* + * Semaphores are unused, interpreter access is single threaded + */ + +ACPI_STATUS +acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle) +{ + *handle = (ACPI_HANDLE) 0; + return AE_OK; +} + +ACPI_STATUS +acpi_os_delete_semaphore(ACPI_HANDLE handle) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units) +{ + return AE_OK; +} + +ACPI_STATUS +acpi_os_breakpoint(char *msg) +{ + acpi_os_printf("breakpoint: %s", msg); + return AE_OK; +} + +void +acpi_os_dbg_trap(char *msg) +{ + acpi_os_printf("trap: %s", msg); +} + +void +acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg) +{ + acpi_os_printf("assert: %s", msg); +} + +u32 +acpi_os_get_line(char *buffer) +{ + return 0; +} + +/* + * We just have to assume we're dealing with valid memory + */ + +BOOLEAN +acpi_os_readable(void *ptr, u32 len) +{ + return 1; +} + +BOOLEAN +acpi_os_writable(void *ptr, u32 len) +{ + return 1; +} diff --git a/drivers/acpi/osd.c b/drivers/acpi/osd.c deleted file mode 100644 index 402df75d7afc..000000000000 --- a/drivers/acpi/osd.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * osd.c - Linux specific code - * - * Copyright (C) 2000 Andrew Henroid - * - * This program is free software; you can redistribute it and/or 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 "acpi.h" - -#define ACPI_MAX_THROTTLE 10 -#define ACPI_INVALID ~0UL -#define ACPI_INFINITE ~0UL - -static struct acpi_facp *acpi_facp = NULL; - -static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; -static volatile u32 acpi_event_status = 0; -static volatile acpi_sstate_t acpi_event_state = ACPI_S0; -static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); -static int acpi_irq_irq = 0; -static OSD_HANDLER acpi_irq_handler = NULL; -static void *acpi_irq_context = NULL; - -static unsigned long acpi_pblk = ACPI_INVALID; -static unsigned long acpi_c2_exit_latency = ACPI_INFINITE; -static unsigned long acpi_c3_exit_latency = ACPI_INFINITE; -static unsigned long acpi_c2_enter_latency = ACPI_INFINITE; -static unsigned long acpi_c3_enter_latency = ACPI_INFINITE; -static int acpi_c2_tested = 0; -static int acpi_c3_tested = 0; - -struct acpi_intrp_entry -{ - int priority; - OSD_EXECUTION_CALLBACK callback; - void *context; - struct list_head list; -}; - -struct acpi_enter_sx_ctx -{ - wait_queue_head_t wait; - int state; -}; - -static volatile int acpi_intrp_pid = -1; -static DECLARE_WAIT_QUEUE_HEAD(acpi_intrp_wait); -static LIST_HEAD(acpi_intrp_exec); -static spinlock_t acpi_intrp_exec_lock = SPIN_LOCK_UNLOCKED; - -#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb)) -#define ACPI_SLP_TYPA(value) \ - ((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) -#define ACPI_SLP_TYPB(value) \ - ((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) - -static volatile acpi_sstate_t acpi_sleep_state = ACPI_S0; -static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,}; - -static struct ctl_table_header *acpi_sysctl = NULL; - -static int acpi_do_ulong(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len); -static int acpi_do_sleep(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len); -static int acpi_do_event(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len); - -static struct ctl_table acpi_table[] = -{ - {ACPI_P_LVL2_LAT, "c2_exit_latency", - &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL2_LAT, "c2_enter_latency", - &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_P_LVL3_LAT, "c3_exit_latency", - &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL3_LAT, "c3_enter_latency", - &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, - - {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, - - {0} -}; - -static struct ctl_table acpi_dir_table[] = -{ - {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, - {0} -}; - -static u32 FASTCALL(acpi_read_pm1_control(struct acpi_facp *)); -static u32 FASTCALL(acpi_read_pm1_status(struct acpi_facp *)); -static void FASTCALL(acpi_write_pm1_control(struct acpi_facp *, u32)); -static void FASTCALL(acpi_write_pm1_status(struct acpi_facp *, u32)); - -/* - * Get the value of the PM1 control register (ACPI_SCI_EN, ...) - */ -static u32 -acpi_read_pm1_control(struct acpi_facp *facp) -{ - u32 value = 0; - if (facp->pm1a_cnt) - value = inw(facp->pm1a_cnt); - if (facp->pm1b_cnt) - value |= inw(facp->pm1b_cnt); - return value; -} - -/* - * Set the value of the PM1 control register (ACPI_BM_RLD, ...) - */ -static void -acpi_write_pm1_control(struct acpi_facp *facp, u32 value) -{ - if (facp->pm1a_cnt) - outw(value, facp->pm1a_cnt); - if (facp->pm1b_cnt) - outw(value, facp->pm1b_cnt); -} - -/* - * Get the value of the fixed event status register - */ -static u32 -acpi_read_pm1_status(struct acpi_facp *facp) -{ - u32 value = 0; - if (facp->pm1a_evt) - value = inw(facp->pm1a_evt); - if (facp->pm1b_evt) - value |= inw(facp->pm1b_evt); - return value; -} - -/* - * Set the value of the fixed event status register (clear events) - */ -static void -acpi_write_pm1_status(struct acpi_facp *facp, u32 value) -{ - if (facp->pm1a_evt) - outw(value, facp->pm1a_evt); - if (facp->pm1b_evt) - outw(value, facp->pm1b_evt); -} - -/* - * Examine/modify value - */ -static int -acpi_do_ulong(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - char str[2 * sizeof(unsigned long) + 4], *strend; - unsigned long val; - int size; - - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - - val = *(unsigned long *) ctl->data; - size = sprintf(str, "0x%08lx\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - } - else { - size = sizeof(str) - 1; - if (size > *len) - size = *len; - copy_from_user(str, buffer, size); - str[size] = '\0'; - val = simple_strtoul(str, &strend, 0); - if (strend == str) - return -EINVAL; - *(unsigned long *) ctl->data = val; - } - - file->f_pos += *len; - return 0; -} - -/* - * Handle ACPI event - */ -u32 -acpi_event(void *context) -{ - unsigned long flags; - int event = (int) context; - int mask = 0; - - switch (event) { - case ACPI_EVENT_POWER_BUTTON: - mask = ACPI_PWRBTN; - break; - case ACPI_EVENT_SLEEP_BUTTON: - mask = ACPI_SLPBTN; - break; - } - - if (mask) { - // notify process waiting on /dev/acpi - spin_lock_irqsave(&acpi_event_lock, flags); - acpi_event_status |= mask; - spin_unlock_irqrestore(&acpi_event_lock, flags); - acpi_event_state = acpi_sleep_state; - wake_up_interruptible(&acpi_event_wait); - } - - return AE_OK; -} - -/* - * Wait for next event - */ -int -acpi_do_event(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - u32 event_status = 0; - acpi_sstate_t event_state = 0; - char str[27]; - int size; - - if (write) - return -EPERM; - if (*len < sizeof(str)) { - *len = 0; - return 0; - } - - for (;;) { - unsigned long flags; - - // we need an atomic exchange here - spin_lock_irqsave(&acpi_event_lock, flags); - event_status = acpi_event_status; - acpi_event_status = 0; - spin_unlock_irqrestore(&acpi_event_lock, flags); - event_state = acpi_event_state; - - if (event_status) - break; - - // wait for an event to arrive - interruptible_sleep_on(&acpi_event_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - size = sprintf(str, - "0x%08x 0x%08x 0x%01x\n", - event_status, - 0, - event_state); - copy_to_user(buffer, str, size); - *len = size; - file->f_pos += size; - - return 0; -} - -/* - * Enter system sleep state - */ -static void -acpi_enter_sx(void *context) -{ - struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context; - struct acpi_facp *facp = acpi_facp; - ACPI_OBJECT_LIST arg_list; - ACPI_OBJECT arg; - u16 value; - - /* - * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. - */ - - // run the _PTS method - memset(&arg_list, 0, sizeof(arg_list)); - arg_list.count = 1; - arg_list.pointer = &arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = ACPI_TYPE_NUMBER; - arg.number.value = ctx->state; - - acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); - - // clear wake status - acpi_write_pm1_status(facp, ACPI_WAK); - - acpi_sleep_state = ctx->state; - - // set ACPI_SLP_TYPA/b and ACPI_SLP_EN - __cli(); - if (facp->pm1a_cnt) { - value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; - value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state]) - | ACPI_SLP_EN); - outw(value, facp->pm1a_cnt); - } - if (facp->pm1b_cnt) { - value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; - value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state]) - | ACPI_SLP_EN); - outw(value, facp->pm1b_cnt); - } - __sti(); - - if (ctx->state != ACPI_S1) { - printk(KERN_ERR "ACPI: S%d failed\n", ctx->state); - goto out; - } - - // wait until S1 is entered - while (!(acpi_read_pm1_status(facp) & ACPI_WAK)) - safe_halt(); - - // run the _WAK method - memset(&arg_list, 0, sizeof(arg_list)); - arg_list.count = 1; - arg_list.pointer = &arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = ACPI_TYPE_NUMBER; - arg.number.value = ctx->state; - - acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL); - - out: - acpi_sleep_state = ACPI_S0; - - if (waitqueue_active(&ctx->wait)) - wake_up_interruptible(&ctx->wait); -} - -/* - * Enter system sleep state and wait for completion - */ -static int -acpi_enter_sx_and_wait(acpi_sstate_t state) -{ - struct acpi_enter_sx_ctx ctx; - - if (!acpi_facp - || acpi_facp->hdr.signature != ACPI_FACP_SIG - || acpi_slptyp[state] == ACPI_INVALID) - return -EINVAL; - - init_waitqueue_head(&ctx.wait); - ctx.state = state; - - if (acpi_os_queue_for_execution(0, acpi_enter_sx, &ctx)) - return -1; - - interruptible_sleep_on(&ctx.wait); - if (signal_pending(current)) - return -ERESTARTSYS; - - return 0; -} - -/* - * Enter system sleep state - */ -static int -acpi_do_sleep(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - } - else { -#ifdef CONFIG_ACPI_S1_SLEEP - int status = acpi_enter_sx_and_wait(ACPI_S1); - if (status) - return status; -#endif - } - file->f_pos += *len; - return 0; -} - -/* - * Clear busmaster activity flag - */ -static inline void -acpi_clear_bm_activity(struct acpi_facp *facp) -{ - acpi_write_pm1_status(facp, ACPI_BM); -} - -/* - * Returns 1 if there has been busmaster activity - */ -static inline int -acpi_bm_activity(struct acpi_facp *facp) -{ - return acpi_read_pm1_status(facp) & ACPI_BM; -} - -/* - * Set system to sleep through busmaster requests - */ -static void -acpi_sleep_on_busmaster(struct acpi_facp *facp) -{ - u32 pm1_cntr = acpi_read_pm1_control(facp); - if (pm1_cntr & ACPI_BM_RLD) { - pm1_cntr &= ~ACPI_BM_RLD; - acpi_write_pm1_control(facp, pm1_cntr); - } -} - -/* - * Set system to wake on busmaster requests - */ -static void -acpi_wake_on_busmaster(struct acpi_facp *facp) -{ - u32 pm1_cntr = acpi_read_pm1_control(facp); - if (!(pm1_cntr & ACPI_BM_RLD)) { - pm1_cntr |= ACPI_BM_RLD; - acpi_write_pm1_control(facp, pm1_cntr); - } - acpi_clear_bm_activity(facp); -} - -/* The ACPI timer is just the low 24 bits */ -#define TIME_BEGIN(tmr) inl(tmr) -#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff) - -/* - * Idle loop (uniprocessor only) - */ -void -acpi_idle(void) -{ - static int sleep_level = 1; - struct acpi_facp *facp = acpi_facp; - - if (!facp - || facp->hdr.signature != ACPI_FACP_SIG - || !facp->pm_tmr - || !acpi_pblk) - goto not_initialized; - - /* - * start from the previous sleep level.. - */ - if (sleep_level == 1) - goto sleep1; - if (sleep_level == 2) - goto sleep2; - sleep3: - sleep_level = 3; - if (!acpi_c3_tested) { - printk(KERN_DEBUG "ACPI C3 works\n"); - acpi_c3_tested = 1; - } - acpi_wake_on_busmaster(facp); - if (facp->pm2_cnt) - goto sleep3_with_arbiter; - - for (;;) { - unsigned long time; - unsigned int pm_tmr = facp->pm_tmr; - - __cli(); - if (current->need_resched) - goto out; - if (acpi_bm_activity(facp)) - goto sleep2; - - time = TIME_BEGIN(pm_tmr); - inb(acpi_pblk + ACPI_P_LVL3); - /* Dummy read, force synchronization with the PMU */ - inl(pm_tmr); - time = TIME_END(pm_tmr, time); - - __sti(); - if (time < acpi_c3_exit_latency) - goto sleep2; - } - - sleep3_with_arbiter: - for (;;) { - unsigned long time; - u8 arbiter; - unsigned int pm2_cntr = facp->pm2_cnt; - unsigned int pm_tmr = facp->pm_tmr; - - __cli(); - if (current->need_resched) - goto out; - if (acpi_bm_activity(facp)) - goto sleep2; - - time = TIME_BEGIN(pm_tmr); - arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS; - /* Disable arbiter, park on CPU */ - outb(arbiter | ACPI_ARB_DIS, pm2_cntr); - inb(acpi_pblk + ACPI_P_LVL3); - /* Dummy read, force synchronization with the PMU */ - inl(pm_tmr); - time = TIME_END(pm_tmr, time); - /* Enable arbiter again.. */ - outb(arbiter, pm2_cntr); - - __sti(); - if (time < acpi_c3_exit_latency) - goto sleep2; - } - - sleep2: - sleep_level = 2; - if (!acpi_c2_tested) { - printk(KERN_DEBUG "ACPI C2 works\n"); - acpi_c2_tested = 1; - } - acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */ - for (;;) { - unsigned long time; - unsigned int pm_tmr = facp->pm_tmr; - - __cli(); - if (current->need_resched) - goto out; - - time = TIME_BEGIN(pm_tmr); - inb(acpi_pblk + ACPI_P_LVL2); - /* Dummy read, force synchronization with the PMU */ - inl(pm_tmr); - time = TIME_END(pm_tmr, time); - - __sti(); - if (time < acpi_c2_exit_latency) - goto sleep1; - if (acpi_bm_activity(facp)) { - acpi_clear_bm_activity(facp); - continue; - } - if (time > acpi_c3_enter_latency) - goto sleep3; - } - - sleep1: - sleep_level = 1; - acpi_sleep_on_busmaster(facp); - for (;;) { - unsigned long time; - unsigned int pm_tmr = facp->pm_tmr; - - __cli(); - if (current->need_resched) - goto out; - time = TIME_BEGIN(pm_tmr); - safe_halt(); - time = TIME_END(pm_tmr, time); - if (time > acpi_c2_enter_latency) - goto sleep2; - } - - not_initialized: - for (;;) { - __cli(); - if (current->need_resched) - goto out; - safe_halt(); - } - - out: - __sti(); -} - -/* - * Enter soft-off (S5) - */ -static void -acpi_power_off(void) -{ - struct acpi_enter_sx_ctx ctx; - - if (!acpi_facp - || acpi_facp->hdr.signature != ACPI_FACP_SIG - || acpi_slptyp[ACPI_S5] == ACPI_INVALID) - return; - - init_waitqueue_head(&ctx.wait); - ctx.state = ACPI_S5; - acpi_enter_sx(&ctx); -} - -/* - * Get processor information - */ -static ACPI_STATUS -acpi_get_cpu_info(ACPI_HANDLE handle, u32 level, void *ctx, void **value) -{ - ACPI_OBJECT obj; - ACPI_CX_STATE lat[4]; - ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE]; - ACPI_BUFFER buf; - int i, count; - - buf.length = sizeof(obj); - buf.pointer = &obj; - if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf))) - return AE_OK; - - printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n", - obj.processor.proc_id, - obj.processor.pblk_address, - obj.processor.pblk_length); - if (acpi_pblk != ACPI_INVALID - || !obj.processor.pblk_address - || obj.processor.pblk_length != 6) - return AE_OK; - - acpi_pblk = obj.processor.pblk_address; - - buf.length = sizeof(lat); - buf.pointer = lat; - if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf))) - return AE_OK; - - if (lat[2].latency < MAX_CX_STATE_LATENCY) { - printk(KERN_INFO "ACPI: C2 supported\n"); - acpi_c2_exit_latency = lat[2].latency; - } - if (lat[3].latency < MAX_CX_STATE_LATENCY) { - printk(KERN_INFO "ACPI: C3 supported\n"); - acpi_c3_exit_latency = lat[3].latency; - } - - memset(throttle, 0, sizeof(throttle)); - buf.length = sizeof(throttle); - buf.pointer = throttle; - - if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf))) - return AE_OK; - - for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) { - if (throttle[i].percent_of_clock) - count++; - } - count--; - if (count > 0) - printk(KERN_INFO "ACPI: %d throttling states\n", count); - - return AE_OK; -} - -/* - * Fetch the FACP information - */ -static int -acpi_fetch_facp(void) -{ - ACPI_BUFFER buffer; - - buffer.pointer = acpi_facp; - buffer.length = sizeof(*acpi_facp); - if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) { - printk(KERN_ERR "ACPI: no FACP\n"); - kfree(acpi_facp); - return -ENODEV; - } - - if (acpi_facp->p_lvl2_lat - && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { - acpi_c2_exit_latency - = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl2_lat); - acpi_c2_enter_latency - = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); - } - if (acpi_facp->p_lvl3_lat - && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { - acpi_c3_exit_latency - = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat); - acpi_c3_enter_latency - = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat * 5); - } - - return 0; -} - -/* - * Execute callbacks (interpret methods) - */ -static void -acpi_intrp_run(void) -{ - for (;;) { - struct acpi_intrp_entry *entry; - unsigned long flags; - - interruptible_sleep_on(&acpi_intrp_wait); - if (signal_pending(current)) - return; - - for (;;) { - entry = NULL; - - spin_lock_irqsave(&acpi_intrp_exec_lock, flags); - if (!list_empty(&acpi_intrp_exec)) { - entry = list_entry(acpi_intrp_exec.next, - struct acpi_intrp_entry, - list); - list_del(&entry->list); - } - spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags); - - if (!entry) - break; - - (*entry->callback)(entry->context); - - kfree(entry); - } - } -} - -/* - * Initialize and run interpreter within a kernel thread - */ -static int -acpi_intrp_thread(void *context) -{ - ACPI_STATUS status; - u8 sx, typa, typb; - - /* - * initialize interpreter - */ - exit_files(current); - daemonize(); - strcpy(current->comm, "acpi"); - - if (!ACPI_SUCCESS(acpi_initialize(NULL))) { - printk(KERN_ERR "ACPI: initialize failed\n"); - return -ENODEV; - } - - if (!ACPI_SUCCESS(acpi_load_firmware_tables())) { - printk(KERN_ERR "ACPI: table load failed\n"); - acpi_terminate(); - return -ENODEV; - } - - if (acpi_fetch_facp()) { - acpi_terminate(); - return -ENODEV; - } - - status = acpi_load_namespace(); - if (!ACPI_SUCCESS(status) && status != AE_CTRL_PENDING) { - printk(KERN_ERR "ACPI: namespace load failed\n"); - acpi_terminate(); - return -ENODEV; - } - - printk(KERN_INFO "ACPI: ACPI support found\n"); - - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, - ACPI_INT32_MAX, - acpi_get_cpu_info, - NULL, - NULL); - - for (sx = ACPI_S0; sx <= ACPI_S5; sx++) { - int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1); - if (ACPI_SUCCESS( - acpi_hw_obtain_sleep_type_register_data(ca_sx, - &typa, - &typb))) - acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb); - else - acpi_slptyp[sx] = ACPI_INVALID; - } - if (acpi_slptyp[ACPI_S1] != ACPI_INVALID) - printk(KERN_INFO "ACPI: S1 supported\n"); - if (acpi_slptyp[ACPI_S5] != ACPI_INVALID) - printk(KERN_INFO "ACPI: S5 supported\n"); - - if (!ACPI_SUCCESS(acpi_enable())) { - printk(KERN_ERR "ACPI: enable failed\n"); - acpi_terminate(); - return -ENODEV; - } - - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_POWER_BUTTON, - acpi_event, - (void *) ACPI_EVENT_POWER_BUTTON))) { - printk(KERN_ERR "ACPI: power button enable failed\n"); - } - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_SLEEP_BUTTON, - acpi_event, - (void *) ACPI_EVENT_SLEEP_BUTTON))) { - printk(KERN_ERR "ACPI: sleep button enable failed\n"); - } - -#ifdef CONFIG_SMP - if (smp_num_cpus == 1) - pm_idle = acpi_idle; -#else - pm_idle = acpi_idle; -#endif - pm_power_off = acpi_power_off; - - acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); - - /* - * run interpreter - */ - acpi_intrp_run(); - - /* - * terminate interpreter - */ - unregister_sysctl_table(acpi_sysctl); - acpi_terminate(); - - acpi_intrp_pid = -1; - - return 0; -} - -/* - * Start the interpreter - */ -int __init -acpi_init(void) -{ - acpi_facp = kmalloc(sizeof(*acpi_facp), GFP_KERNEL); - if (!acpi_facp) - return -ENOMEM; - memset(acpi_facp, 0, sizeof(*acpi_facp)); - - acpi_intrp_pid = kernel_thread(acpi_intrp_thread, - NULL, - (CLONE_FS | CLONE_FILES - | CLONE_SIGHAND | SIGCHLD)); - return ((acpi_intrp_pid >= 0) ? 0:-ENODEV); -} - -/* - * Terminate the interpreter - */ -void __exit -acpi_exit(void) -{ - int count; - - if (!kill_proc(acpi_intrp_pid, SIGTERM, 1)) { - // wait until interpreter thread terminates (at most 5 seconds) - count = 5 * HZ; - while (acpi_intrp_pid >= 0 && --count) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - } - - // clean up after the interpreter - - if (acpi_irq_handler) { - acpi_os_remove_interrupt_handler(acpi_irq_irq, - acpi_irq_handler); - } - - if (pm_power_off == acpi_power_off) - pm_power_off = NULL; - if (pm_idle == acpi_idle) - pm_idle = NULL; - - kfree(acpi_facp); -} - -module_init(acpi_init); -module_exit(acpi_exit); - -/* - * OS-dependent functions - * - */ - -char * -strupr(char *str) -{ - char *s = str; - while (*s) { - *s = TOUPPER(*s); - s++; - } - return str; -} - -ACPI_STATUS -acpi_os_initialize(void) -{ - return AE_OK; -} - -ACPI_STATUS -acpi_os_terminate(void) -{ - return AE_OK; -} - -s32 -acpi_os_printf(const char *fmt,...) -{ - s32 size; - va_list args; - va_start(args, fmt); - size = acpi_os_vprintf(fmt, args); - va_end(args); - return size; -} - -s32 -acpi_os_vprintf(const char *fmt, va_list args) -{ - static char buffer[512]; - int size = vsprintf(buffer, fmt, args); - printk(KERN_DEBUG "%s", buffer); - return size; -} - -void * -acpi_os_allocate(u32 size) -{ - return kmalloc(size, GFP_KERNEL); -} - -void * -acpi_os_callocate(u32 size) -{ - void *ptr = acpi_os_allocate(size); - if (ptr) - memset(ptr, 0, size); - return ptr; -} - -void -acpi_os_free(void *ptr) -{ - kfree(ptr); -} - -ACPI_STATUS -acpi_os_map_memory(void *phys, u32 size, void **virt) -{ - if ((unsigned long) phys < virt_to_phys(high_memory)) { - *virt = phys_to_virt((unsigned long) phys); - return AE_OK; - } - - *virt = ioremap((unsigned long) phys, size); - if (!*virt) - return AE_ERROR; - - return AE_OK; -} - -void -acpi_os_unmap_memory(void *virt, u32 size) -{ - if (virt >= high_memory) - iounmap(virt); -} - -static void -acpi_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - (*acpi_irq_handler)(acpi_irq_context); -} - -ACPI_STATUS -acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) -{ - acpi_irq_irq = irq; - acpi_irq_handler = handler; - acpi_irq_context = context; - if (request_irq(irq, - acpi_irq, - SA_INTERRUPT | SA_SHIRQ, - "acpi", - acpi_irq)) { - printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq); - return AE_ERROR; - } - return AE_OK; -} - -ACPI_STATUS -acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) -{ - if (acpi_irq_handler) { - free_irq(irq, acpi_irq); - acpi_irq_handler = NULL; - } - return AE_OK; -} - -/* - * Running in interpreter thread context, safe to sleep - */ - -void -acpi_os_sleep(u32 sec, u32 ms) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ * sec + (ms * HZ) / 1000); -} - -void -acpi_os_sleep_usec(u32 us) -{ - udelay(us); -} - -u8 -acpi_os_in8(ACPI_IO_ADDRESS port) -{ - return inb(port); -} - -u16 -acpi_os_in16(ACPI_IO_ADDRESS port) -{ - return inw(port); -} - -u32 -acpi_os_in32(ACPI_IO_ADDRESS port) -{ - return inl(port); -} - -void -acpi_os_out8(ACPI_IO_ADDRESS port, u8 val) -{ - outb(val, port); -} - -void -acpi_os_out16(ACPI_IO_ADDRESS port, u16 val) -{ - outw(val, port); -} - -void -acpi_os_out32(ACPI_IO_ADDRESS port, u32 val) -{ - outl(val, port); -} - -ACPI_STATUS -acpi_os_read_pci_cfg_byte( - u32 bus, - u32 func, - u32 addr, - u8 * val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!val || !dev || pci_read_config_byte(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -ACPI_STATUS -acpi_os_read_pci_cfg_word( - u32 bus, - u32 func, - u32 addr, - u16 * val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!val || !dev || pci_read_config_word(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -ACPI_STATUS -acpi_os_read_pci_cfg_dword( - u32 bus, - u32 func, - u32 addr, - u32 * val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!val || !dev || pci_read_config_dword(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -ACPI_STATUS -acpi_os_write_pci_cfg_byte( - u32 bus, - u32 func, - u32 addr, - u8 val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!dev || pci_write_config_byte(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -ACPI_STATUS -acpi_os_write_pci_cfg_word( - u32 bus, - u32 func, - u32 addr, - u16 val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!dev || pci_write_config_word(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -ACPI_STATUS -acpi_os_write_pci_cfg_dword( - u32 bus, - u32 func, - u32 addr, - u32 val) -{ - int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); - struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); - if (!dev || pci_write_config_dword(dev, addr, val)) - return AE_ERROR; - return AE_OK; -} - -/* - * Queue for interpreter thread - */ - -ACPI_STATUS -acpi_os_queue_for_execution( - u32 priority, - OSD_EXECUTION_CALLBACK callback, - void *context) -{ - struct acpi_intrp_entry *entry; - unsigned long flags; - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) - return AE_ERROR; - - memset(entry, 0, sizeof(entry)); - entry->priority = priority; - entry->callback = callback; - entry->context = context; - INIT_LIST_HEAD(&entry->list); - - if (!waitqueue_active(&acpi_intrp_wait)) { - kfree(entry); - return AE_ERROR; - } - - spin_lock_irqsave(&acpi_intrp_exec_lock, flags); - list_add(&entry->list, &acpi_intrp_exec); - wake_up(&acpi_intrp_wait); - spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags); - - return AE_OK; -} - -/* - * Semaphores are unused, interpreter access is single threaded - */ - -ACPI_STATUS -acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle) -{ - *handle = (ACPI_HANDLE) 0; - return AE_OK; -} - -ACPI_STATUS -acpi_os_delete_semaphore(ACPI_HANDLE handle) -{ - return AE_OK; -} - -ACPI_STATUS -acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout) -{ - return AE_OK; -} - -ACPI_STATUS -acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units) -{ - return AE_OK; -} - -ACPI_STATUS -acpi_os_breakpoint(char *msg) -{ - acpi_os_printf("breakpoint: %s", msg); - return AE_OK; -} - -void -acpi_os_dbg_trap(char *msg) -{ - acpi_os_printf("trap: %s", msg); -} - -void -acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg) -{ - acpi_os_printf("assert: %s", msg); -} - -u32 -acpi_os_get_line(char *buffer) -{ - return 0; -} - -/* - * We just have to assume we're dealing with valid memory - */ - -BOOLEAN -acpi_os_readable(void *ptr, u32 len) -{ - return 1; -} - -BOOLEAN -acpi_os_writable(void *ptr, u32 len) -{ - return 1; -} diff --git a/drivers/acpi/sys.c b/drivers/acpi/sys.c new file mode 100644 index 000000000000..40ce078c7123 --- /dev/null +++ b/drivers/acpi/sys.c @@ -0,0 +1,183 @@ +/* + * sys.c - System management (suspend, ...) + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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.h" +#include "driver.h" + +#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb)) +#define ACPI_SLP_TYPA(value) \ + ((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) +#define ACPI_SLP_TYPB(value) \ + ((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK) + +struct acpi_enter_sx_ctx +{ + wait_queue_head_t wait; + int state; +}; + +volatile acpi_sstate_t acpi_sleep_state = ACPI_S0; +static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,}; + +/* + * Enter system sleep state + */ +static void +acpi_enter_sx_async(void *context) +{ + struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context; + struct acpi_facp *facp = &acpi_facp; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u16 value; + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + + // run the _PTS method + memset(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_NUMBER; + arg.number.value = ctx->state; + + acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); + + // clear wake status + acpi_write_pm1_status(facp, ACPI_WAK); + + acpi_sleep_state = ctx->state; + + // set ACPI_SLP_TYPA/b and ACPI_SLP_EN + __cli(); + if (facp->pm1a_cnt) { + value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; + value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state]) + | ACPI_SLP_EN); + outw(value, facp->pm1a_cnt); + } + if (facp->pm1b_cnt) { + value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; + value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state]) + | ACPI_SLP_EN); + outw(value, facp->pm1b_cnt); + } + __sti(); + + if (ctx->state != ACPI_S1) { + printk(KERN_ERR "ACPI: S%d failed\n", ctx->state); + goto out; + } + + // wait until S1 is entered + while (!(acpi_read_pm1_status(facp) & ACPI_WAK)) + safe_halt(); + + // run the _WAK method + memset(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_NUMBER; + arg.number.value = ctx->state; + + acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL); + + out: + acpi_sleep_state = ACPI_S0; + + if (waitqueue_active(&ctx->wait)) + wake_up_interruptible(&ctx->wait); +} + +/* + * Enter soft-off (S5) + */ +static void +acpi_power_off(void) +{ + struct acpi_enter_sx_ctx ctx; + + if (acpi_facp.hdr.signature != ACPI_FACP_SIG + || acpi_slptyp[ACPI_S5] == ACPI_INVALID) + return; + + init_waitqueue_head(&ctx.wait); + ctx.state = ACPI_S5; + acpi_enter_sx_async(&ctx); +} + +/* + * Enter system sleep state and wait for completion + */ +int +acpi_enter_sx(acpi_sstate_t state) +{ + struct acpi_enter_sx_ctx ctx; + + if (acpi_facp.hdr.signature != ACPI_FACP_SIG + || acpi_slptyp[state] == ACPI_INVALID) + return -EINVAL; + + init_waitqueue_head(&ctx.wait); + ctx.state = state; + + if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx)) + return -1; + + interruptible_sleep_on(&ctx.wait); + if (signal_pending(current)) + return -ERESTARTSYS; + + return 0; +} + +int +acpi_sys_init(void) +{ + u8 sx, typa, typb; + + for (sx = ACPI_S0; sx <= ACPI_S5; sx++) { + int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1); + if (ACPI_SUCCESS( + acpi_hw_obtain_sleep_type_register_data(ca_sx, + &typa, + &typb))) + acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb); + else + acpi_slptyp[sx] = ACPI_INVALID; + } + if (acpi_slptyp[ACPI_S1] != ACPI_INVALID) + printk(KERN_INFO "ACPI: S1 supported\n"); + if (acpi_slptyp[ACPI_S5] != ACPI_INVALID) + printk(KERN_INFO "ACPI: S5 supported\n"); + + pm_power_off = acpi_power_off; + + return 0; +} diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c new file mode 100644 index 000000000000..96214909d043 --- /dev/null +++ b/drivers/acpi/tables.c @@ -0,0 +1,304 @@ +/* + * tables.c - ACPI tables, chipset, and errata handling + * + * Copyright (C) 2000 Andrew Henroid + * + * This program is free software; you can redistribute it and/or 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.h" +#include "driver.h" + +struct acpi_facp acpi_facp; + +#define ACPI_DUMMY_CHECKSUM 9 +#define ACPI_DUMMY_PBLK 51 + +static u8 acpi_dummy_dsdt[] = +{ + 0x44, 0x53, 0x44, 0x54, // "DSDT" + 0x38, 0x00, 0x00, 0x00, // length + 0x01, // revision + 0x00, // checksum + 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x00, // "LINUX" + 0x44, 0x55, 0x4d, 0x4d, 0x59, 0x00, 0x00, 0x00, // "DUMMY" + 0x01, 0x00, 0x00, 0x00, // OEM rev + 0x4c, 0x4e, 0x55, 0x58, // "LNUX" + 0x01, 0x00, 0x00, 0x00, // creator rev + 0x10, // Scope + 0x13, // PkgLength + 0x5c, 0x5f, 0x50, 0x52, 0x5f, // \_PR_ + 0x5b, 0x83, // Processor + 0x0b, // PkgLength + 0x43, 0x50, 0x55, 0x30, // CPU0 + 0x00, // ID + 0x00, 0x00, 0x00, 0x00, // PBLK + 0x06 // PBLK size +}; + +/* + * Calculate and set ACPI table checksum + */ +static void +acpi_set_checksum(u8 *table, int size) +{ + int i, sum = 0; + for (i = 0; i < size; i++) + sum += (int) table[i]; + sum = (0x100 - ((sum - table[ACPI_DUMMY_CHECKSUM]) & 0xff)); + table[ACPI_DUMMY_CHECKSUM] = sum; +} + +/* + * Init PIIX4 device, create a fake FACP + */ +static int +acpi_init_piix4(struct pci_dev *dev) +{ + u32 base, pblk; + u16 cmd; + u8 pmregmisc; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_IO)) + return -ENODEV; + + pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc); + if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) + return -ENODEV; + + base = pci_resource_start (dev, PCI_BRIDGE_RESOURCES); + if (!base) + return -ENODEV; + + printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base); + + memset(&acpi_facp, 0, sizeof(acpi_facp)); + acpi_facp.hdr.signature = ACPI_FACP_SIG; + acpi_facp.hdr.length = sizeof(acpi_facp); + acpi_facp.int_model = ACPI_PIIX4_INT_MODEL; + acpi_facp.sci_int = ACPI_PIIX4_SCI_INT; + acpi_facp.smi_cmd = ACPI_PIIX4_SMI_CMD; + acpi_facp.acpi_enable = ACPI_PIIX4_ACPI_ENABLE; + acpi_facp.acpi_disable = ACPI_PIIX4_ACPI_DISABLE; + acpi_facp.s4bios_req = ACPI_PIIX4_S4BIOS_REQ; + acpi_facp.pm1a_evt = base + ACPI_PIIX4_PM1_EVT; + acpi_facp.pm1a_cnt = base + ACPI_PIIX4_PM1_CNT; + acpi_facp.pm2_cnt = ACPI_PIIX4_PM2_CNT; + acpi_facp.pm_tmr = base + ACPI_PIIX4_PM_TMR; + acpi_facp.gpe0 = base + ACPI_PIIX4_GPE0; + acpi_facp.pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN; + acpi_facp.pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN; + acpi_facp.pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN; + acpi_facp.pm_tm_len = ACPI_PIIX4_PM_TM_LEN; + acpi_facp.gpe0_len = ACPI_PIIX4_GPE0_LEN; + acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT; + acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT; + + acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp)); + acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp); + + pblk = base + ACPI_PIIX4_P_BLK; + memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk)); + acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt)); + acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt); + + return 0; +} + +/* + * Init VIA ACPI device and create a fake FACP + */ +static int +acpi_init_via(struct pci_dev *dev) +{ + u32 base, pblk; + u8 tmp, irq; + + pci_read_config_byte(dev, 0x41, &tmp); + if (!(tmp & 0x80)) + return -ENODEV; + + base = pci_resource_start(dev, PCI_BRIDGE_RESOURCES); + if (!base) { + base = pci_resource_start(dev, PCI_BASE_ADDRESS_4); + if (!base) + return -ENODEV; + } + + pci_read_config_byte(dev, 0x42, &irq); + + printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base); + + memset(&acpi_facp, 0, sizeof(acpi_facp)); + acpi_facp.hdr.signature = ACPI_FACP_SIG; + acpi_facp.hdr.length = sizeof(acpi_facp); + acpi_facp.int_model = ACPI_VIA_INT_MODEL; + acpi_facp.sci_int = irq; + acpi_facp.smi_cmd = base + ACPI_VIA_SMI_CMD; + acpi_facp.acpi_enable = ACPI_VIA_ACPI_ENABLE; + acpi_facp.acpi_disable = ACPI_VIA_ACPI_DISABLE; + acpi_facp.pm1a_evt = base + ACPI_VIA_PM1_EVT; + acpi_facp.pm1a_cnt = base + ACPI_VIA_PM1_CNT; + acpi_facp.pm_tmr = base + ACPI_VIA_PM_TMR; + acpi_facp.gpe0 = base + ACPI_VIA_GPE0; + + acpi_facp.pm1_evt_len = ACPI_VIA_PM1_EVT_LEN; + acpi_facp.pm1_cnt_len = ACPI_VIA_PM1_CNT_LEN; + acpi_facp.pm_tm_len = ACPI_VIA_PM_TM_LEN; + acpi_facp.gpe0_len = ACPI_VIA_GPE0_LEN; + acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT; + acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT; + + acpi_facp.duty_offset = ACPI_VIA_DUTY_OFFSET; + acpi_facp.duty_width = ACPI_VIA_DUTY_WIDTH; + + acpi_facp.day_alarm = ACPI_VIA_DAY_ALARM; + acpi_facp.mon_alarm = ACPI_VIA_MON_ALARM; + acpi_facp.century = ACPI_VIA_CENTURY; + + acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp)); + acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp); + + pblk = base + ACPI_VIA_P_BLK; + memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk)); + acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt)); + acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt); + + return 0; +} + +typedef enum +{ + CH_UNKNOWN = 0, + CH_INTEL_PIIX4, + CH_VIA_586, + CH_VIA_686A, +} acpi_chip_t; + +/* indexed by value of each enum in acpi_chip_t */ +const static struct +{ + int (*chip_init)(struct pci_dev *dev); +} acpi_chip_info[] = +{ + {NULL,}, + {acpi_init_piix4}, + {acpi_init_via}, + {acpi_init_via}, +}; + +static struct pci_device_id acpi_pci_tbl[] = +{ + {0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4}, + {0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586}, + {0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A}, + {0,} /* terminate list */ +}; + +static int +acpi_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return acpi_chip_info[id->driver_data].chip_init(dev); +} + +static struct pci_driver acpi_driver = +{ + name: "acpi", + id_table: acpi_pci_tbl, + probe: acpi_probe, +}; +static int acpi_driver_registered = 0; + +/* + * Locate a known ACPI chipset + */ +static int +acpi_find_chipset(void) +{ + if (pci_register_driver(&acpi_driver) < 1) + return -ENODEV; + acpi_driver_registered = 1; + return 0; +} + +/* + * Fetch the FACP information + */ +static int +acpi_fetch_facp(void) +{ + ACPI_BUFFER buffer; + + memset(&acpi_facp, 0, sizeof(acpi_facp)); + buffer.pointer = &acpi_facp; + buffer.length = sizeof(acpi_facp); + if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) { + printk(KERN_ERR "ACPI: missing FACP\n"); + return -ENODEV; + } + + if (acpi_facp.p_lvl2_lat + && acpi_facp.p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { + acpi_c2_exit_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl2_lat); + acpi_c2_enter_latency + = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); + } + if (acpi_facp.p_lvl3_lat + && acpi_facp.p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { + acpi_c3_exit_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat); + acpi_c3_enter_latency + = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat * 5); + } + + return 0; +} + +/* + * Find and load ACPI tables + */ +int +acpi_load_tables(void) +{ + if (ACPI_SUCCESS(acpi_load_firmware_tables())) + { + printk(KERN_INFO "ACPI: support found\n"); + } + else if (acpi_find_chipset()) { + acpi_terminate(); + return -1; + } + + if (acpi_fetch_facp()) { + acpi_terminate(); + return -1; + } + + if (!ACPI_SUCCESS(acpi_load_namespace())) { + printk(KERN_ERR "ACPI: namespace load failed\n"); + acpi_terminate(); + return -1; + } + + return 0; +} diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 37e50dbcdaef..47cf8c69efca 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -792,8 +792,7 @@ int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh) device. Currently the only restriction is that all buffers must belong to the same device */ -static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[], - int haslock) +void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]) { struct buffer_head *bh; request_queue_t *q; @@ -840,13 +839,9 @@ static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[], bh = bhs[i]; /* Only one thread can actually submit the I/O. */ - if (haslock) { - if (!buffer_locked(bh)) - BUG(); - } else { - if (test_and_set_bit(BH_Lock, &bh->b_state)) - continue; - } + if (test_and_set_bit(BH_Lock, &bh->b_state)) + continue; + set_bit(BH_Req, &bh->b_state); /* @@ -865,15 +860,6 @@ sorry: buffer_IO_error(bhs[i]); } -void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) -{ - __ll_rw_block(rw, nr, bh, 0); -} - -void ll_rw_block_locked(int rw, int nr, struct buffer_head * bh[]) -{ - __ll_rw_block(rw, nr, bh, 1); -} #ifdef CONFIG_STRAM_SWAP extern int stram_device_init (void); diff --git a/drivers/block/md.c b/drivers/block/md.c index 651c3dd6dfed..087b5aee180d 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -3412,7 +3412,7 @@ repeat: currspeed = (j-mddev->resync_mark_cnt)/((jiffies-mddev->resync_mark)/HZ +1) +1; if (currspeed > sysctl_speed_limit_min) { - current->priority = 19; + current->nice = 19; if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { @@ -3422,7 +3422,7 @@ repeat: goto repeat; } } else - current->priority = -20; + current->nice = -20; } fsync_dev(read_disk); printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c index 2315e1d300c0..b36fdab11207 100644 --- a/drivers/block/paride/paride.c +++ b/drivers/block/paride/paride.c @@ -13,10 +13,11 @@ 1.02 GRG 1998.05.05 init_proto, release_proto, ktti 1.03 GRG 1998.08.15 eliminate compiler warning 1.04 GRG 1998.11.28 added support for FRIQ - + 1.05 TMW 2000.06.06 use parport_find_number instead of + parport_enumerate */ -#define PI_VERSION "1.04" +#define PI_VERSION "1.05" #include #include @@ -238,22 +239,25 @@ static void pi_register_parport( PIA *pi, int verbose) { #ifdef CONFIG_PARPORT - struct parport *pp; - - pp = parport_enumerate(); + struct parport *port; - while((pp)&&(pp->base != pi->port)) pp = pp->next; + port = parport_find_base (pi->port); + if (!port) return; - if (!pp) return; + pi->pardev = parport_register_device(port, + pi->device,NULL, + pi_wake_up,NULL, + 0,(void *)pi); + parport_put_port (port); + if (!pi->pardev) return; - pi->pardev = (void *) parport_register_device( - pp,pi->device,NULL,pi_wake_up,NULL,0,(void *)pi); init_waitqueue_head(&pi->parq); - if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name); + if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port, + port->name); - pi->parname = (char *)pp->name; + pi->parname = (char *)port->name; #endif } @@ -406,6 +410,7 @@ int init_module(void) { int k; for (k=0;k 0){ if (!info->xmit_cnt){ - cy_writeb((u_long)base_addr+(CySRER<xmit_buf == 0){ @@ -3176,6 +3188,30 @@ cy_chars_in_buffer(struct tty_struct *tty) * ------------------------------------------------------------ */ +static void +cyy_baud_calc(struct cyclades_port *info, uclong baud) +{ + int co, co_val, bpr; + uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000); + + if (baud == 0) { + info->tbpr = info->tco = info->rbpr = info->rco = 0; + return; + } + + /* determine which prescaler to use */ + for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { + if (cy_clock / co_val / baud > 63) + break; + } + + bpr = (cy_clock / co_val * 2 / baud + 1) / 2; + if (bpr > 255) + bpr = 255; + + info->tbpr = info->rbpr = bpr; + info->tco = info->rco = co; +} /* * This routine finds or computes the various line characteristics. @@ -3189,7 +3225,7 @@ set_line_char(struct cyclades_port * info) int card,chip,channel,index; unsigned cflag, iflag; unsigned short chip_number; - int baud; + int baud, baud_rate = 0; int i; @@ -3225,12 +3261,14 @@ set_line_char(struct cyclades_port * info) index = cy_card[card].bus_index; /* baud rate */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { - baud = info->baud; - } else { - baud = tty_get_baud_rate(info->tty); - } - if (baud > CD1400_MAX_SPEED) { + baud = tty_get_baud_rate(info->tty); + if ((baud == 38400) && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CD1400_MAX_SPEED) { baud = CD1400_MAX_SPEED; } /* find the baud index */ @@ -3243,22 +3281,29 @@ set_line_char(struct cyclades_port * info) i = 19; /* CD1400_MAX_SPEED */ } - - if(info->chip_rev >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[i]; /* Tx BPR */ - info->tco = baud_co_60[i]; /* Tx CO */ - info->rbpr = baud_bpr_60[i]; /* Rx BPR */ - info->rco = baud_co_60[i]; /* Rx CO */ + if ((baud == 38400) && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + cyy_baud_calc(info, baud_rate); } else { - info->tbpr = baud_bpr_25[i]; /* Tx BPR */ - info->tco = baud_co_25[i]; /* Tx CO */ - info->rbpr = baud_bpr_25[i]; /* Rx BPR */ - info->rco = baud_co_25[i]; /* Rx CO */ + if(info->chip_rev >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[i]; /* Tx BPR */ + info->tco = baud_co_60[i]; /* Tx CO */ + info->rbpr = baud_bpr_60[i]; /* Rx BPR */ + info->rco = baud_co_60[i]; /* Rx CO */ + } else { + info->tbpr = baud_bpr_25[i]; /* Tx BPR */ + info->tco = baud_co_25[i]; /* Tx CO */ + info->rbpr = baud_bpr_25[i]; /* Rx BPR */ + info->rco = baud_co_25[i]; /* Rx CO */ + } } if (baud_table[i] == 134) { - info->timeout = (info->xmit_fifo_size*HZ*15/269) + 2; /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; + } else if ((baud == 38400) && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; } else if (baud_table[i]) { info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; /* this needs to be propagated into the card info */ @@ -3447,19 +3492,24 @@ set_line_char(struct cyclades_port * info) buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; /* baud rate */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { - baud = info->baud; - } else { - baud = tty_get_baud_rate(info->tty); - } - if (baud > CYZ_MAX_SPEED) { + baud = tty_get_baud_rate(info->tty); + if ((baud == 38400) && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CYZ_MAX_SPEED) { baud = CYZ_MAX_SPEED; } cy_writel(&ch_ctrl->comm_baud , baud); if (baud == 134) { - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; + } else if ((baud == 38400) && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { + info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; } else if (baud) { info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2; /* this needs to be propagated into the card info */ @@ -3549,8 +3599,6 @@ set_line_char(struct cyclades_port * info) clear_bit(TTY_IO_ERROR, &info->tty->flags); } } - - } /* set_line_char */ @@ -3571,7 +3619,7 @@ get_serial_info(struct cyclades_port * info, tmp.flags = info->flags; tmp.close_delay = info->close_delay; tmp.baud_base = info->baud; - tmp.custom_divisor = 0; /*!!!*/ + tmp.custom_divisor = info->custom_divisor; tmp.hub6 = 0; /*!!!*/ return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0; } /* get_serial_info */ @@ -3597,6 +3645,7 @@ set_serial_info(struct cyclades_port * info, info->flags = ((info->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; goto check_and_exit; } @@ -3607,6 +3656,7 @@ set_serial_info(struct cyclades_port * info, */ info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); info->close_delay = new_serial.close_delay * HZ/100; @@ -3621,6 +3671,43 @@ check_and_exit: } } /* set_serial_info */ +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct cyclades_port *info, unsigned int *value) +{ + int card, chip, channel, index; + unsigned char status; + unsigned int result; + unsigned long flags; + unsigned char *base_addr; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char *) + (cy_card[card].base_addr + (cy_chip_offset[chip]<tco = 0; info->rbpr = 0; info->rco = 0; + info->custom_divisor = 0; info->close_delay = 5*HZ/10; info->closing_wait = CLOSING_WAIT_DELAY; info->icount.cts = info->icount.dsr = @@ -5596,6 +5680,7 @@ cy_init(void) info->cor3 = 0x08; /* _very_ small rcv threshold */ info->cor4 = 0; info->cor5 = 0; + info->custom_divisor = 0; info->close_delay = 5*HZ/10; info->closing_wait = CLOSING_WAIT_DELAY; info->icount.cts = info->icount.dsr = diff --git a/drivers/char/i2c-parport.c b/drivers/char/i2c-parport.c index 8304a6ab5f47..00b574f60b9c 100644 --- a/drivers/char/i2c-parport.c +++ b/drivers/char/i2c-parport.c @@ -75,7 +75,7 @@ static void i2c_parport_attach(struct parport *port) struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus), GFP_KERNEL); b->i2c = parport_i2c_bus_template; - b->i2c.data = port; + b->i2c.data = parport_get_port (port); strncpy(b->i2c.name, port->name, 32); spin_lock(&bus_list_lock); b->next = bus_list; diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 4e2be3c8b324..1f0b9fddcddf 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -83,64 +83,6 @@ struct pp_struct { /* ROUND_UP macro from fs/select.c */ #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) -struct pp_port_list_struct { - struct parport *port; - struct pp_port_list_struct *next; -}; -static struct pp_port_list_struct *pp_port_list; -static DECLARE_MUTEX(pp_port_list_lock); - -/* pp_attach and pp_detach are for keeping a list of currently - * available ports, held under a mutex. We do this rather than - * using parport_enumerate because it stops a load of races. - */ - -static void pp_attach (struct parport *port) -{ - struct pp_port_list_struct *add; - - add = kmalloc (sizeof (struct pp_port_list_struct), GFP_KERNEL); - if (!add) { - printk (KERN_WARNING CHRDEV ": memory squeeze\n"); - return; - } - - add->port = port; - down (&pp_port_list_lock); - add->next = pp_port_list; - pp_port_list = add; - up (&pp_port_list_lock); -} - -static void pp_detach (struct parport *port) -{ - struct pp_port_list_struct *del; - - down (&pp_port_list_lock); - del = pp_port_list; - if (del->port == port) - pp_port_list = del->next; - else { - struct pp_port_list_struct *prev; - do { - prev = del; - del = del->next; - } while (del && del->port != port); - if (del) - prev->next = del->next; - } - up (&pp_port_list_lock); - - if (del) - kfree (del); -} - -static struct parport_driver ppdev_driver = { - name: CHRDEV, - attach: pp_attach, - detach: pp_detach -}; - static inline void pp_enable_irq (struct pp_struct *pp) { struct parport *port = pp->pdev->port; @@ -274,7 +216,7 @@ static void pp_irq (int irq, void * private, struct pt_regs * unused) static int register_device (int minor, struct pp_struct *pp) { - struct pp_port_list_struct *ports; + struct parport *port; struct pardevice * pdev = NULL; char *name; int fl; @@ -285,23 +227,17 @@ static int register_device (int minor, struct pp_struct *pp) sprintf (name, CHRDEV "%x", minor); - down (&pp_port_list_lock); - ports = pp_port_list; - while (ports && ports->port->number != minor) - ports = ports->next; - if (ports->port) { - fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device (ports->port, name, NULL, - NULL, pp_irq, fl, pp); - } - up (&pp_port_list_lock); - - if (!ports->port) { + port = parport_find_number (minor); + if (!port) { printk (KERN_WARNING "%s: no associated port!\n", name); kfree (name); return -ENXIO; } + fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + pdev = parport_register_device (port, name, NULL, + NULL, pp_irq, fl, pp); + parport_put_port (port); if (!pdev) { printk (KERN_WARNING "%s: failed to register device!\n", name); @@ -654,10 +590,6 @@ static devfs_handle_t devfs_handle = NULL; static int __init ppdev_init (void) { - if (parport_register_driver (&ppdev_driver)) { - printk (KERN_WARNING CHRDEV ": unable to register driver\n"); - return -EIO; - } if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { printk (KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); @@ -678,7 +610,6 @@ static void __exit ppdev_cleanup (void) /* Clean up all parport stuff */ devfs_unregister (devfs_handle); devfs_unregister_chrdev (PP_MAJOR, CHRDEV); - parport_unregister_driver (&ppdev_driver); } module_init(ppdev_init); diff --git a/drivers/mtd/Config.in b/drivers/mtd/Config.in index e2af3489a415..450405fa3e25 100644 --- a/drivers/mtd/Config.in +++ b/drivers/mtd/Config.in @@ -1,59 +1,61 @@ + +# $Id: Config.in,v 1.18 2000/07/12 13:43:24 dwmw2 Exp $ + mainmenu_option next_comment comment 'Memory Technology Devices (MTD)' tristate 'Memory Technology Device (MTD) support' CONFIG_MTD if [ "$CONFIG_MTD" != "n" ]; then - dep_tristate 'M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD - dep_tristate 'M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD - dep_tristate 'M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD - if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then - define_bool CONFIG_MTD_DOCPROBE y - else - if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then - define_bool CONFIG_MTD_DOCPROBE m - else - define_bool CONFIG_MTD_DOCPROBE n - fi - fi - dep_tristate 'Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD - dep_tristate 'Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD - if [ "$CONFIG_MTD_PMC551" != "n" ]; then - bool 'PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX - fi - dep_tristate 'Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD + if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then + define_tristate CONFIG_MTD_DOCPROBE y + else + if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then + define_tristate CONFIG_MTD_DOCPROBE m + else + define_tristate CONFIG_MTD_DOCPROBE n + fi + fi + dep_tristate ' Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD + dep_tristate ' Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD + if [ "$CONFIG_MTD_PMC551" != "n" ]; then + bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX + fi + dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD -mainmenu_option next_comment comment 'MTD drivers for mapped chips' + dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD + dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI - dep_tristate 'Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD - dep_tristate 'CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_CFI - define_bool CONFIG_MTD_JEDEC n - define_bool CONFIG_MTD_RAM n - define_bool CONFIG_MTD_ROM n -mainmenu_option next_comment -comment 'Drivers for chip mappings' +# These will later become config-options +define_bool CONFIG_MTD_JEDEC n +define_bool CONFIG_MTD_RAM n +define_bool CONFIG_MTD_ROM n - dep_tristate 'Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI - if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then - hex ' Physical start location of flash chip mapping (0x8000000)' CONFIG_MTD_PHYSMAP_START 0x8000000 - hex ' Physical length of flash chip mapping (0x4000000)' CONFIG_MTD_PHYSMAP_LEN 0x4000000 - fi - dep_tristate 'Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC - dep_tristate 'Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI - dep_tristate 'Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC - dep_tristate 'Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI - dep_tristate 'Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC + dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI + if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then + hex 'Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 + hex 'Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 + fi + +comment 'Drivers for chip mappings' + dep_tristate ' Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC + dep_tristate ' Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI + dep_tristate ' Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC + dep_tristate ' Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI + dep_tristate ' Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC -mainmenu_option next_comment comment 'User modules and translation layers for MTD devices' - dep_tristate 'Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD - dep_tristate 'Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD - dep_tristate 'FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD - dep_tristate 'NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD - if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then - bool 'Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW - fi + dep_tristate ' Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD + dep_tristate ' Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD + dep_tristate ' FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD + dep_tristate ' NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD + if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then + bool ' Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW + fi fi endmenu diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index d408c8796902..34446db013b5 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,4 +1,40 @@ -2000-06-30 Gunther Mayer +2000-07-12 Tim Waugh + + * share.c: Documentation for parport_{get,port}_port, + parport_find_{number,base}. + +2000-07-12 Tim Waugh + + * share.c (parport_unregister_device): Remove unneeded locking + (test cad==dev). + (parport_claim): Likewise. + (parport_find_number): New function. + +2000-07-12 Tim Waugh + + * share.c (parport_register_port): Hold the parportlist_lock while + looking for a free parport number. + (parport_register_driver): Make sure that attach can block. + (attach_driver_chain): Likewise. + +2000-07-12 Tim Waugh + + * share.c (call_driver_chain): Do reference counting things. + (parport_get_port): New function. + (parport_put_port): New function. + (parport_register_port): Initialise reference count to zero. + (parport_unregister_port): Check reference count rather than + driver list to see if we can free the port. + +2000-07-12 Tim Waugh + + * share.c: Clarifications in doc comments. + +2000-07-12 Tim Waugh + + * share.c (parport_unregister_port): Fix typo in comment. + +2000-07-11 Gunther Mayer * parport_pc.c: Support for the full range of Timedia cards. diff --git a/drivers/parport/init.c b/drivers/parport/init.c index 416ca51cb72e..90280e37176c 100644 --- a/drivers/parport/init.c +++ b/drivers/parport/init.c @@ -180,6 +180,10 @@ EXPORT_SYMBOL(parport_unregister_driver); EXPORT_SYMBOL(parport_register_device); EXPORT_SYMBOL(parport_unregister_device); EXPORT_SYMBOL(parport_enumerate); +EXPORT_SYMBOL(parport_get_port); +EXPORT_SYMBOL(parport_put_port); +EXPORT_SYMBOL(parport_find_number); +EXPORT_SYMBOL(parport_find_base); EXPORT_SYMBOL(parport_negotiate); EXPORT_SYMBOL(parport_write); EXPORT_SYMBOL(parport_read); diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 9fe0bb4be1c8..50eb808429c8 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -88,17 +88,57 @@ static struct parport_operations dead_ops = { dead_read /* byte */ }; -static void call_driver_chain(int attach, struct parport *port) +/* Call attach(port) for each registered driver. */ +static void attach_driver_chain(struct parport *port) { struct parport_driver *drv; + void (**attach) (struct parport *); + int count = 0, i; + + /* This is complicated because attach() must be able to block, + * but we can't let it do that while we're holding a + * spinlock. */ spin_lock (&driverlist_lock); - for (drv = driver_chain; drv; drv = drv->next) { - if (attach) - drv->attach (port); - else - drv->detach (port); + for (drv = driver_chain; drv; drv = drv->next) + count++; + spin_unlock (&driverlist_lock); + + /* Drivers can unregister here; that's okay. If they register + * they'll be given an attach during parport_register_driver, + * so that's okay too. The only worry is that someone might + * get given an attach twice if they registered just before + * this function gets called. */ + + /* Hmm, this could be fixed with a generation number.. + * FIXME */ + + attach = kmalloc (sizeof (void(*)(struct parport *)) * count, + GFP_KERNEL); + if (!attach) { + printk (KERN_WARNING "parport: not enough memory to attach\n"); + return; } + + spin_lock (&driverlist_lock); + for (i = 0, drv = driver_chain; drv && i < count; drv = drv->next) + attach[i] = drv->attach; + spin_unlock (&driverlist_lock); + + for (count = 0; count < i; count++) + (*attach[i]) (port); + + kfree (attach); +} + +/* Call detach(port) for each registered driver. */ +static void detach_driver_chain(struct parport *port) +{ + struct parport_driver *drv; + + spin_lock (&driverlist_lock); + for (drv = driver_chain; drv; drv = drv->next) + drv->detach (port); spin_unlock (&driverlist_lock); } @@ -121,28 +161,63 @@ static void get_lowlevel_driver (void) * The @drv structure is allocated by the caller and must not be * deallocated until after calling parport_unregister_driver(). * + * The driver's attach() function may block. The port that + * attach() is given will be valid for the duration of the + * callback, but if the driver wants to take a copy of the + * pointer it must call parport_get_port() to do so. Calling + * parport_register_device() on that port will do this for you. + * + * The driver's detach() function may not block. The port that + * detach() is given will be valid for the duration of the + * callback, but if the driver wants to take a copy of the + * pointer it must call parport_get_port() to do so. + * * Returns 0 on success. Currently it always succeeds. **/ int parport_register_driver (struct parport_driver *drv) { struct parport *port; - - spin_lock (&driverlist_lock); - drv->next = driver_chain; - driver_chain = drv; - spin_unlock (&driverlist_lock); + struct parport **ports; + int count = 0, i; /* We have to take the portlist lock for this to be sure * that port is valid for the duration of the callback. */ + + /* This is complicated by the fact that attach must be allowed + * to block, so we can't be holding any spinlocks when we call + * it. But we need to hold a spinlock to iterate over the + * list of ports.. */ + spin_lock (&parportlist_lock); for (port = portlist; port; port = port->next) - drv->attach (port); + count++; spin_unlock (&parportlist_lock); + ports = kmalloc (sizeof (struct parport *) * count, GFP_KERNEL); + if (!ports) + printk (KERN_WARNING "parport: not enough memory to attach\n"); + else { + spin_lock (&parportlist_lock); + for (i = 0, port = portlist; port && i < count; + port = port->next) + ports[i] = port; + spin_unlock (&parportlist_lock); + + for (count = 0; count < i; count++) + drv->attach (ports[count]); + + kfree (ports); + } + if (!portlist) get_lowlevel_driver (); + spin_lock (&driverlist_lock); + drv->next = driver_chain; + driver_chain = drv; + spin_unlock (&driverlist_lock); + return 0; } @@ -162,6 +237,11 @@ int parport_register_driver (struct parport_driver *drv) * If the caller's attach() function can block, it is their * responsibility to make sure to wait for it to exit before * unloading. + * + * All the driver's detach() calls are guaranteed to have + * finished by the time this function returns. + * + * The driver's detach() call is not allowed to block. **/ void parport_unregister_driver (struct parport_driver *arg) @@ -194,6 +274,57 @@ void parport_unregister_driver (struct parport_driver *arg) } } +static void free_port (struct parport *port) +{ + int d; + for (d = 0; d < 5; d++) { + if (port->probe_info[d].class_name) + kfree (port->probe_info[d].class_name); + if (port->probe_info[d].mfr) + kfree (port->probe_info[d].mfr); + if (port->probe_info[d].model) + kfree (port->probe_info[d].model); + if (port->probe_info[d].cmdset) + kfree (port->probe_info[d].cmdset); + if (port->probe_info[d].description) + kfree (port->probe_info[d].description); + } + + kfree(port->name); + kfree(port); +} + +/** + * parport_get_port - increment a port's reference count + * @port: the port + * + * This ensure's that a struct parport pointer remains valid + * until the matching parport_put_port() call. + **/ + +struct parport *parport_get_port (struct parport *port) +{ + atomic_inc (&port->ref_count); + return port; +} + +/** + * parport_put_port - decrement a port's reference count + * @port: the port + * + * This should be called once for each call to parport_get_port(), + * once the port is no longer needed. + **/ + +void parport_put_port (struct parport *port) +{ + if (atomic_dec_and_test (&port->ref_count)) + /* Can destroy it now. */ + free_port (port); + + return; +} + /** * parport_enumerate - return a list of the system's parallel ports * @@ -260,6 +391,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, } /* Search for the lowest free parport number. */ + + spin_lock_irq (&parportlist_lock); for (portnum = 0; ; portnum++) { struct parport *itr = portlist; while (itr) { @@ -274,6 +407,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, /* Got to the end of the list. */ break; } + spin_unlock_irq (&parportlist_lock); /* Init our structure */ memset(tmp, 0, sizeof(struct parport)); @@ -296,6 +430,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */ tmp->spintime = parport_default_spintime; + atomic_set (&tmp->ref_count, 1); name = kmalloc(15, GFP_KERNEL); if (!name) { @@ -372,27 +507,7 @@ void parport_announce_port (struct parport *port) #endif /* Let drivers know that a new port has arrived. */ - call_driver_chain (1, port); -} - -static void free_port (struct parport *port) -{ - int d; - for (d = 0; d < 5; d++) { - if (port->probe_info[d].class_name) - kfree (port->probe_info[d].class_name); - if (port->probe_info[d].mfr) - kfree (port->probe_info[d].mfr); - if (port->probe_info[d].model) - kfree (port->probe_info[d].model); - if (port->probe_info[d].cmdset) - kfree (port->probe_info[d].cmdset); - if (port->probe_info[d].description) - kfree (port->probe_info[d].description); - } - - kfree(port->name); - kfree(port); + attach_driver_chain (port); } /** @@ -421,7 +536,7 @@ void parport_unregister_port(struct parport *port) port->ops = &dead_ops; /* Spread the word. */ - call_driver_chain (0, port); + detach_driver_chain (port); #ifdef CONFIG_PARPORT_1284 /* Forget the IEEE1284.3 topology of the port. */ @@ -431,7 +546,7 @@ void parport_unregister_port(struct parport *port) spin_lock(&parportlist_lock); /* We are protected from other people changing the list, but - * they can see see it (using parport_enumerate). So be + * they can still see it (using parport_enumerate). So be * careful about the order of writes.. */ if (portlist == port) { if ((portlist = port->next) == NULL) @@ -449,8 +564,7 @@ void parport_unregister_port(struct parport *port) spin_unlock(&parportlist_lock); /* Yes, parport_enumerate _is_ unsafe. Don't use it. */ - if (!port->devices) - free_port (port); + parport_put_port (port); } /** @@ -552,6 +666,7 @@ parport_register_device(struct parport *port, const char *name, parport_register_device.. */ inc_parport_count(); port->ops->inc_use_count(); + parport_get_port (port); tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); if (tmp == NULL) { @@ -623,6 +738,7 @@ parport_register_device(struct parport *port, const char *name, out: dec_parport_count(); port->ops->dec_use_count(); + parport_put_port (port); return NULL; } @@ -636,7 +752,6 @@ parport_register_device(struct parport *port, const char *name, void parport_unregister_device(struct pardevice *dev) { struct parport *port; - unsigned long flags; #ifdef PARPORT_PARANOID if (dev == NULL) { @@ -649,14 +764,11 @@ void parport_unregister_device(struct pardevice *dev) port = dev->port->physport; - read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { - read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_DEBUG "%s: %s forgot to release port\n", port->name, dev->name); parport_release (dev); } - read_unlock_irqrestore (&port->cad_lock, flags); spin_lock(&port->pardevice_lock); if (dev->next) @@ -676,11 +788,7 @@ void parport_unregister_device(struct pardevice *dev) dec_parport_count(); port->ops->dec_use_count(); - - /* If this was the last device on a port that's already gone away, - * free up the resources. */ - if (port->ops == &dead_ops && !port->devices) - free_port (port); + parport_put_port (port); /* Yes, that's right, someone _could_ still have a pointer to * port, if they used parport_enumerate. That's why they @@ -688,6 +796,56 @@ void parport_unregister_device(struct pardevice *dev) */ } +/** + * parport_find_number - find a parallel port by number + * @number: parallel port number + * + * This returns the parallel port with the specified number, or + * %NULL if there is none. + * + * There is an implicit parport_get_port() done already; to throw + * away the reference to the port that parport_find_number() + * gives you, use parport_put_port(). + */ + +struct parport *parport_find_number (int number) +{ + struct parport *port, *result = NULL; + spin_lock (&parportlist_lock); + for (port = portlist; port; port = port->next) + if (port->number == number) { + result = parport_get_port (port); + break; + } + spin_unlock (&parportlist_lock); + return result; +} + +/** + * parport_find_base - find a parallel port by base address + * @base: base I/O address + * + * This returns the parallel port with the specified base + * address, or %NULL if there is none. + * + * There is an implicit parport_get_port() done already; to throw + * away the reference to the port that parport_find_base() + * gives you, use parport_put_port(). + */ + +struct parport *parport_find_base (unsigned long base) +{ + struct parport *port, *result = NULL; + spin_lock (&parportlist_lock); + for (port = portlist; port; port = port->next) + if (port->base == base) { + result = parport_get_port (port); + break; + } + spin_unlock (&parportlist_lock); + return result; +} + /** * parport_claim - claim access to a parallel port device * @dev: pointer to structure representing a device on the port @@ -706,14 +864,11 @@ int parport_claim(struct pardevice *dev) struct parport *port = dev->port->physport; unsigned long flags; - read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { - read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_INFO "%s: %s already owner\n", dev->port->name,dev->name); return 0; } - read_unlock_irqrestore (&port->cad_lock, flags); /* Preempt any current device */ write_lock_irqsave (&port->cad_lock, flags); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 056b2f1b50ee..fd705d425f44 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -138,6 +138,10 @@ static struct dev_info device_list[] = {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, {"TOSHIBA","CDROM","*", BLIST_ISROM}, {"MegaRAID", "LD", "*", BLIST_FORCELUN}, + {"DGC", "RAID", "*", BLIST_SPARSELUN}, // Dell PV 650F (tgt @ LUN 0) + {"DGC", "DISK", "*", BLIST_SPARSELUN}, // Dell PV 650F (no tgt @ LUN 0) + {"DELL", "PV530F", "*", BLIST_SPARSELUN}, // Dell PV 530F + {"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders /* * Must be at end of list... diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c index c99f86973278..df02bcf2a807 100644 --- a/drivers/usb/devices.c +++ b/drivers/usb/devices.c @@ -45,6 +45,9 @@ * up an eventual usbd * 2000-01-04: Thomas Sailer * Turned into its own filesystem + * 2000-07-05: Ashley Montanaro + * Converted file reading routine to dump to buffer once + * per device, not per bus * * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $ */ @@ -367,23 +370,40 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de /*****************************************************************/ -static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev, - struct usb_bus *bus, int level, int index, int count) +/* This is a recursive function. Parameters: + * buffer - the user-space buffer to write data into + * nbytes - the maximum number of bytes to write + * skip_bytes - the number of bytes to skip before writing anything + * file_offset - the offset into the devices file on completion + */ +static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, + struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) { int chix; - int cnt = 0; + int ret, cnt = 0; int parent_devnum = 0; - + char *pages_start, *data_end; + unsigned int length; + ssize_t total_written = 0; + + /* don't bother with anything else if we're not writing any data */ + if (*nbytes <= 0) + return 0; + if (level > MAX_TOPO_LEVEL) - return start; + return total_written; + /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */ + if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1))) + return -ENOMEM; + if (usbdev->parent && usbdev->parent->devnum != -1) parent_devnum = usbdev->parent->devnum; /* * So the root hub's parent is 0 and any device that is * plugged into the root hub has a parent of 0. */ - start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count, - usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); + data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count, + usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); /* * level = topology-tier level; * parent_devnum = parent device number; @@ -392,30 +412,58 @@ static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev, */ /* If this is the root hub, display the bandwidth information */ if (level == 0) - start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, + data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC, (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC, bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs); - start = usb_dump_desc(start, end, usbdev); - if (start > end) - return start + sprintf(start, "(truncated)\n"); + + data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev); + + if (data_end > (pages_start + (2 * PAGE_SIZE) - 256)) + data_end += sprintf(data_end, "(truncated)\n"); + + length = data_end - pages_start; + /* if we can start copying some data to the user */ + if (length > *skip_bytes) { + length -= *skip_bytes; + if (length > *nbytes) + length = *nbytes; + if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) { + free_pages((unsigned long)pages_start, 1); + + if (total_written == 0) + return -EFAULT; + return total_written; + } + *nbytes -= length; + *file_offset += length; + total_written += length; + *buffer += length; + *skip_bytes = 0; + } else + *skip_bytes -= length; + + free_pages((unsigned long)pages_start, 1); + /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { - if (start > end) - return start; - if (usbdev->children[chix]) - start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt); + if (usbdev->children[chix]) { + ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix], + bus, level + 1, chix, ++cnt); + if (ret == -EFAULT) + return total_written; + total_written += ret; + } } - return start; + return total_written; } static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { struct list_head *buslist; struct usb_bus *bus; - char *page, *end; - ssize_t ret = 0; - unsigned int pos, len; + ssize_t ret, total_written = 0; + loff_t skip_bytes = *ppos; if (*ppos < 0) return -EINVAL; @@ -423,34 +471,18 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff return 0; if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - if (!(page = (char*) __get_free_pages(GFP_KERNEL,1))) - return -ENOMEM; - pos = *ppos; + /* enumerate busses */ for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { /* print devices for this bus */ bus = list_entry(buslist, struct usb_bus, bus_list); - end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0); - len = end - page; - if (len > pos) { - len -= pos; - if (len > nbytes) - len = nbytes; - if (copy_to_user(buf, page + pos, len)) { - if (!ret) - ret = -EFAULT; - break; - } - nbytes -= len; - buf += len; - ret += len; - pos = 0; - *ppos += len; - } else - pos -= len; + /* recurse through all children of the root hub */ + ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); + if (ret < 0) + return ret; + total_written += ret; } - free_pages((unsigned long)page, 1); - return ret; + return total_written; } /* Kernel lock for "lastev" protection */ diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 940d47f52e79..886229370e78 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -33,7 +33,7 @@ obj- := # Each configuration option enables a list of files. obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o -obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o vga_font.o +obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o diff --git a/drivers/video/vga_font.c b/drivers/video/vga_font.c deleted file mode 100644 index d6683ee4b1c4..000000000000 --- a/drivers/video/vga_font.c +++ /dev/null @@ -1,352 +0,0 @@ -#include -#include -#include - - -#define cmapsz 8192 - -unsigned char vga_font[cmapsz] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - diff --git a/fs/dcache.c b/fs/dcache.c index 0f9c59c6c5c4..8c27b5f94a77 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -933,6 +933,9 @@ void d_move(struct dentry * dentry, struct dentry * target) /** * d_path - return the path of a dentry * @dentry: dentry to report + * @vfsmnt: vfsmnt to which the dentry belongs + * @root: root dentry + * @rootmnt: vfsmnt to which the root dentry belongs * @buffer: buffer to return value in * @buflen: buffer length * diff --git a/fs/inode.c b/fs/inode.c index 28fbd00985f3..62acffd58bce 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -261,6 +261,7 @@ static void sync_all_inodes(void) /** * write_inode_now - write an inode to disk * @inode: inode to write to disk + * @sync: whether the write should be synchronous or not * * This function commits an inode to disk immediately if it is * dirty. This is primarily needed by knfsd. diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index e088d7fba773..01500eeee993 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -8,7 +8,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * $Id: inode-v23.c,v 1.16 2000/07/06 14:38:10 dwmw2 Exp $ + * $Id: inode-v23.c,v 1.17 2000/07/06 20:35:19 prumpf Exp $ * * * Ported to Linux 2.3.x and MTD: @@ -24,7 +24,6 @@ * maybe other stuff do to. */ -#include #include #include #include @@ -1453,7 +1452,6 @@ static struct inode_operations jffs_file_inode_operations = static struct file_operations jffs_dir_operations = { - read: generic_read_dir, readdir: jffs_readdir, }; @@ -1533,16 +1531,19 @@ jffs_delete_inode(struct inode *inode) inode->i_size = 0; - unlock_kernel(); clear_inode(inode); + unlock_kernel(); } void jffs_write_super(struct super_block *sb) { #ifdef USE_GC - jffs_garbage_collect((struct jffs_control *)sb->u.generic_sbp); + struct jffs_control *c = (struct jffs_control *)sb->u.generic_sbp; + + if(!c->fmc->no_call_gc) + jffs_garbage_collect(c); #endif } diff --git a/fs/select.c b/fs/select.c index 427e7f0f7727..be09afdd7b61 100644 --- a/fs/select.c +++ b/fs/select.c @@ -164,6 +164,8 @@ int do_select(int n, fd_set_bits *fds, long *timeout) poll_initwait(&table); wait = &table; + if (!__timeout) + wait = NULL; retval = 0; for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -385,7 +387,7 @@ asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout) { int i, j, fdcount, err; struct pollfd **fds; - poll_table table; + poll_table table, *wait; int nchunks, nleft; /* Do a sanity check on nfds ... */ @@ -401,8 +403,11 @@ asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout) } poll_initwait(&table); - err = -ENOMEM; + wait = &table; + if (!timeout) + wait = NULL; + err = -ENOMEM; fds = NULL; if (nfds != 0) { fds = (struct pollfd **)kmalloc( @@ -437,7 +442,7 @@ asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout) goto out_fds1; } - fdcount = do_poll(nfds, nchunks, nleft, fds, &table, timeout); + fdcount = do_poll(nfds, nchunks, nleft, fds, wait, timeout); /* OK, now copy the revents fields back to user space. */ for(i=0; i < nchunks; i++) diff --git a/include/asm-mips/param.h b/include/asm-mips/param.h index 82110a4e0074..5487778ca7b9 100644 --- a/include/asm-mips/param.h +++ b/include/asm-mips/param.h @@ -1,37 +1,56 @@ -#ifndef __ASM_MIPS_PARAM_H -#define __ASM_MIPS_PARAM_H +#ifndef _ASM_PARAM_H +#define _ASM_PARAM_H #ifndef HZ +#ifdef __KERNEL__ + +/* Safeguard against user stupidity */ +#ifdef _SYS_PARAM_H +#error Do not include with __KERNEL__ defined! +#endif + #include #ifdef CONFIG_DECSTATION /* - * log2(HZ), change this here if you want another - * HZ value. This is also used in dec_time_init. - * Minimum is 1, Maximum is 15. + * log2(HZ), change this here if you want another HZ value. This is also + * used in dec_time_init. Minimum is 1, Maximum is 15. */ # define LOG_2_HZ 7 # define HZ (1 << LOG_2_HZ) /* * Ye olde division-by-multiplication trick. - * * This works only if 100 / HZ <= 1 */ # define QUOTIENT ((1UL << (32 - LOG_2_HZ)) * 100) -# define HZ_TO_STD(a) \ +# define hz_to_std(a) \ ({ unsigned int __res; \ - unsigned long lo; \ + unsigned long __lo; \ __asm__("multu\t%2,%3\n\t" \ - :"=h" (__res), "=l" (lo) \ + :"=h" (__res), "=l" (__lo) \ :"r" (a),"r" (QUOTIENT)); \ (__typeof__(a)) __res;}) -#else + +#else /* Not a DECstation */ + +/* This is the internal value of HZ, that is the rate at which the jiffies + counter is increasing. This value is independent from the external value + and can be changed in order to suit the hardware and application + requirements. */ # define HZ 100 -# define HZ_TO_STD(a) (a) -#endif +# define hz_to_std(a) (a) -#endif +#endif /* Not a DECstation */ + +#else /* defined(__KERNEL__) */ + +/* This is the external value of HZ as seen by user programs. Don't change + unless you know what you're doing - changing breaks binary compatibility. */ +#define HZ 100 + +#endif /* defined(__KERNEL__) */ +#endif /* defined(HZ) */ #define EXEC_PAGESIZE 4096 @@ -45,4 +64,4 @@ #define MAXHOSTNAMELEN 64 /* max length of hostname */ -#endif /* __ASM_MIPS_PARAM_H */ +#endif /* _ASM_PARAM_H */ diff --git a/include/asm-mips64/dma.h b/include/asm-mips64/dma.h index e1caa024a71c..2a0753dd2da9 100644 --- a/include/asm-mips64/dma.h +++ b/include/asm-mips64/dma.h @@ -1,5 +1,4 @@ -/* $Id: dma.h,v 1.5 2000/03/07 15:45:42 ralf Exp $ - * +/* * linux/include/asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. * High DMA channel support & info by Hannu Savolainen diff --git a/include/asm-mips64/param.h b/include/asm-mips64/param.h index f958c4d8acdb..5354eeb7df6e 100644 --- a/include/asm-mips64/param.h +++ b/include/asm-mips64/param.h @@ -1,10 +1,10 @@ -/* $Id: param.h,v 1.1 1999/08/18 23:37:51 ralf 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 1994 - 1999 Ralf Baechle (ralf@gnu.org) + * Copyright 1994 - 2000 Ralf Baechle (ralf@gnu.org) + * Copyright 2000 Silicon Graphics, Inc. */ #ifndef _ASM_PARAM_H #define _ASM_PARAM_H @@ -13,7 +13,7 @@ #define HZ 100 # define HZ 100 #ifdef __KERNEL__ -# define HZ_TO_STD(a) (a) +# define hz_to_std(a) (a) #endif #endif diff --git a/include/asm-mips64/sn/addrs.h b/include/asm-mips64/sn/addrs.h index e51ce04da258..66c57ab28803 100644 --- a/include/asm-mips64/sn/addrs.h +++ b/include/asm-mips64/sn/addrs.h @@ -1,16 +1,16 @@ -/* $Id$ - * +/* * 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, 1999 Silicon Graphics, Inc. - * Copyright (C) 1999 by Ralf Baechle + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle */ #ifndef _ASM_SN_ADDRS_H #define _ASM_SN_ADDRS_H #include + #if _LANGUAGE_C #include #endif /* _LANGUAGE_C */ diff --git a/include/asm-mips64/sn/agent.h b/include/asm-mips64/sn/agent.h index 76004336a241..2502069c2a35 100644 --- a/include/asm-mips64/sn/agent.h +++ b/include/asm-mips64/sn/agent.h @@ -1,13 +1,12 @@ -/* $Id$ - * +/* * 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. * * This file has definitions for the hub and snac interfaces. * - * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc. - * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1992 - 1997, 1999, 2000 Silcon Graphics, Inc. + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) */ #ifndef _ASM_SGI_SN_AGENT_H #define _ASM_SGI_SN_AGENT_H diff --git a/include/asm-mips64/sn/io.h b/include/asm-mips64/sn/io.h index b0f7a215193c..c8ff3c3c07c2 100644 --- a/include/asm-mips64/sn/io.h +++ b/include/asm-mips64/sn/io.h @@ -1,6 +1,4 @@ - -/* $Id: io.h,v 1.2 2000/02/02 16:35:57 ralf 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. @@ -12,6 +10,7 @@ #define _ASM_SN_IO_H #include + #if !defined(CONFIG_SGI_IO) #include diff --git a/include/asm-mips64/sn/klconfig.h b/include/asm-mips64/sn/klconfig.h index 4c5fa57e509b..493582fc5075 100644 --- a/include/asm-mips64/sn/klconfig.h +++ b/include/asm-mips64/sn/klconfig.h @@ -1,20 +1,17 @@ -/* $Id$ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Derived from IRIX . * - * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. - * Copyright (C) 1999 by Ralf Baechle + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle */ #ifndef _ASM_SN_KLCONFIG_H #define _ASM_SN_KLCONFIG_H -/* - * klconfig.h - */ +#include /* * The KLCONFIG structures store info about the various BOARDs found @@ -32,34 +29,37 @@ * that offsets of existing fields do not change. */ -#include #include #include -#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35) -#include -#include -#include -#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */ #if defined(CONFIG_SGI_IP27) #include //#include // XXX Stolen from : #define MAX_ROUTER_PORTS (6) /* Max. number of ports on a router */ #include +#include //#include +#include +#include //#include +#if defined(CONFIG_SGI_IO) +// The hack file has to be before vector and after sn0_fru.... +#include +#include +#include +#endif /* CONFIG_SGI_IO */ #elif defined(CONFIG_SGI_IP35) +#include #include +#include #include +#include #include +#include +#include #include -#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */ -#if (defined(CONFIG_SGI_IP27)&&defined(CONFIG_SGI_IO))||defined(CONFIG_SGI_IP35) -// The hack file has to be before vector and after sn0_fru.... -#include -#include #include -#endif /* (CONFIG_SGI_IP27 && CONFIG_SGI_IO) || CONFIG_SGI_IP35 */ +#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */ #define KLCFGINFO_MAGIC 0xbeedbabe diff --git a/include/asm-mips64/sn/kldir.h b/include/asm-mips64/sn/kldir.h index 3ca24005693a..b979205c2115 100644 --- a/include/asm-mips64/sn/kldir.h +++ b/include/asm-mips64/sn/kldir.h @@ -1,18 +1,18 @@ -/* $Id$ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Derived from IRIX , revision 1.21. * - * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc. - * Copyright (C) 1999 by Ralf Baechle + * Copyright (C) 1992 - 1997, 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999, 2000 by Ralf Baechle */ #ifndef _ASM_SN_KLDIR_H #define _ASM_SN_KLDIR_H #include + #if defined(CONFIG_SGI_IO) #include #endif diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h index af8d4a2d4c7c..59a57452c33a 100644 --- a/include/asm-sparc/bitops.h +++ b/include/asm-sparc/bitops.h @@ -8,7 +8,6 @@ #ifndef _SPARC_BITOPS_H #define _SPARC_BITOPS_H -#include #include #include diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h index 8a5404930b14..7e3adf02f44a 100644 --- a/include/asm-sparc64/elf.h +++ b/include/asm-sparc64/elf.h @@ -1,4 +1,4 @@ -/* $Id: elf.h,v 1.24 2000/04/14 09:59:04 davem Exp $ */ +/* $Id: elf.h,v 1.25 2000/07/12 01:27:08 davem Exp $ */ #ifndef __ASM_SPARC64_ELF_H #define __ASM_SPARC64_ELF_H diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h index 85ae21c9d9a9..5a53d342debe 100644 --- a/include/asm-sparc64/semaphore.h +++ b/include/asm-sparc64/semaphore.h @@ -7,6 +7,7 @@ #include #include #include +#include struct semaphore { atomic_t count; diff --git a/include/linux/parport.h b/include/linux/parport.h index 294464b657a8..27d813e9db10 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -309,6 +309,7 @@ struct parport { rwlock_t cad_lock; int spintime; + atomic_t ref_count; }; #define DEFAULT_SPIN_TIME 500 /* us */ @@ -337,12 +338,9 @@ void parport_announce_port (struct parport *port); /* Unregister a port. */ extern void parport_unregister_port(struct parport *port); -/* parport_in_use returns nonzero if there are devices attached to a - port. */ -#define parport_in_use(x) ((x)->devices != NULL) - /* parport_enumerate returns a pointer to the linked list of all the - ports in this machine. */ + ports in this machine. DON'T USE THIS. Use + parport_register_driver instead. */ struct parport *parport_enumerate(void); /* Register a new high-level driver. */ @@ -351,6 +349,15 @@ extern int parport_register_driver (struct parport_driver *); /* Unregister a high-level driver. */ extern void parport_unregister_driver (struct parport_driver *); +/* If parport_register_driver doesn't fit your needs, perhaps + * parport_find_xxx does. */ +extern struct parport *parport_find_number (int); +extern struct parport *parport_find_base (unsigned long); + +/* Reference counting for ports. */ +extern struct parport *parport_get_port (struct parport *); +extern void parport_put_port (struct parport *); + /* parport_register_device declares that a device is connected to a port, and tells the kernel all it needs to know. - pf is the preemption function (may be NULL for no callback) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 04ae938be5b9..a53a165b1ae9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1061,6 +1061,10 @@ #define PCI_DEVICE_ID_LAVA_SSERIAL 0x0500 /* 1x 16550 */ #define PCI_DEVICE_ID_LAVA_PORT_650 0x0600 /* 1x 16650 */ +#define PCI_VENDOR_ID_SYBA 0x1592 +#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782 +#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783 + #define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */ #define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */ diff --git a/kernel/sched.c b/kernel/sched.c index 38e79216700f..5208de0c3d6f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -233,7 +233,7 @@ static void reschedule_idle(struct task_struct * p, unsigned long flags) * its preferred CPU. (this is a shortcut): */ tsk = cpu_curr(best_cpu); - if (preemption_goodness(tsk, p, best_cpu) > 1) + if (preemption_goodness(tsk, p, best_cpu) > 0) goto preempt_now; } @@ -290,7 +290,7 @@ send_now_idle: * altogether, tsk->need_resched is actively watched by the * idle thread. */ - if (!tsk->need_resched) + if ((tsk->processor != current->processor) && !tsk->need_resched) smp_send_reschedule(tsk->processor); tsk->need_resched = 1; spin_unlock_irqrestore(&runqueue_lock, flags); diff --git a/mm/slab.c b/mm/slab.c index a24e465825cb..a31f0f7e78b5 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1966,7 +1966,7 @@ int slabinfo_read_proc (char *page, char **start, off_t off, #define MAX_SLABINFO_WRITE 128 /** * slabinfo_write_proc - SMP tuning for the slab allocator - * @file: + * @file: unused * @buffer: user buffer * @count: data len * @data: unused diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 282024cc92a1..46f5e57e826e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.208 2000/05/03 06:37:06 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.209 2000/07/12 03:49:30 davem Exp $ * * IPv4 specific functions * @@ -69,8 +69,8 @@ extern int sysctl_ip_dynaddr; #define ICMP_MIN_LENGTH 8 /* Socket used for sending RSTs */ -struct inode tcp_inode; -struct socket *tcp_socket=&tcp_inode.u.socket_i; +static struct inode tcp_inode; +static struct socket *tcp_socket=&tcp_inode.u.socket_i; void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, struct sk_buff *skb); -- 2.39.5