All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: dosemu 1.1.3.9 user report
From: Stas Sergeev @ 2002-12-16 19:58 UTC (permalink / raw)
  To: linux-msdos

Hello.

Peter Jay Salzman wrote:
> IIRC, there was talk about important dosemu related patches that are
> present in the most recent kernels.   i think it was said that the
> patches have been in the ac kernels for awhile, but have just recently
> made it into the vanilla 2.4 kernels.
Generally that patches are needed if
you have a "Segmentation fault" crash
without a "(core dumped)" when dosemu
is not in DPMI mode.
Also if you are going to do some weird
thing like starting WinNT installer
under dosemu, you'll need one of those
patches.
Another one is required if you have
problems using a direct hardware access
under dosemu (this one was even considered
a security-related by RedHat:
http://rhn.redhat.com/errata/RHSA-2002-158.html
)
There were also some other work, but in
general (unless the specified sympthomes
are matched) kernel upgrade may not be
necessary to get one or another program
to work under dosemu.


^ permalink raw reply

* Re: Can somebody help me with setting up a server behind a sdsl router?
From: Rahul Jadhav @ 2002-12-16 19:51 UTC (permalink / raw)
  To: Jason Corekin; +Cc: netfilter
In-Reply-To: <010801c2a527$782dcbd0$5d01a8c0@jason>

Jason!
Did you guys try
1. enabling 'nat translations' on the router.
2. setting up 'nat server list' and if one already exists, (which is 
generally the case) add your mail server's ip to the list.
I believe your problem can be solved by doing just that.
good luck!
Rahul

Jason Corekin wrote:

> I have a friend who is trying to setup a Netopia R7100 sdsl router.  I 
> know that this is not a netfilter specific question, but it is largely 
> the same stuff, just a different implementation. He has a few 
> different publicly registered static ip's and has had one of the 
> assigned to the dsl connection and has had it configured to pass the 
> connection then to another router that is NATing for his internal 
> network.  Now he wants to use another one of his publicly registered 
> static ip's for his mail server, which we are trying to plug into one 
> of the unused jacks on the built it hub on the R7100.  The problem is 
> that we can not get the R7100 to respond to more then one public 
> address.  Is there a way that we should be able to setup the R7100 
> such that it would route the second address through it to the mail 
> server?  How would the rest of the internet know to talk to the R7100 
> to get to his mail server?  This sounds like just a basic routing 
> issue but my knowledge is limited.
>  
> Thanks for any help you might offer
>  
> Jason Corekin



-- 
         __  __     __   __	
        /_/ /_ \  _/ /  /  \	Institute for Agriculture
       __  __/ / \  _/ / / /	and Trade Policy
      / / /   /  / /  / __/	2105 First Ave S
     / / / / /  / /_ / /	Minneapolis MN 55404
     \/  \__/   \__/ \/		http://www.iatp.org

       I N F O R M A T I O N   T E C H N O L O G Y

The best things in life are done by people with nowhere to turn.
                                -The Blind Assassin (Margaret Atwood)





^ permalink raw reply

* RE: DSDT in Dell i8200-- does acpi have the correct addres s?
From: James D Strandboge @ 2002-12-16 19:51 UTC (permalink / raw)
  To: Grover, Andrew; +Cc: acpi-devel-pyega4qmqnRoyOMFzWx49A
In-Reply-To: <EDC461A30AC4D511ADE10002A5072CAD04C7A5A8-OU+JdkIUtvd9zuciVAfUoVDQ4js95KgL@public.gmane.org>

On Mon, 2002-12-16 at 14:43, Grover, Andrew wrote:
> > From: James D Strandboge [mailto:jstrand1-aYIB8uWIUb2Vn7q6wjsIow@public.gmane.org] 
> > My i8200 has basic acpi functionality, with quite a few issues.  I
> > started poking around the Dell download site and came across this in a
> > description of a BIOS upgrade for my laptop:
> > 
> > ===================================================================
> > Systems:      Dell Inspiron 8200	(Memory location F000:E845)
> > Version:      A06                       (Memory location F000:E842)
> > Build Date:   08/17/02                  (Memory location FFFF:0005)
> > 
> > ...
> > 
> > Now, if I read my dsdt from /proc/acpi/dsdt, nd decompile it 
> > with iasl,
> > it shows a version from 1998.  I looked at dmesg and found:
> > 
> > ACPI: DSDT (v001 INT430 SYSFexxx 00000.04097) @ 0x00000000
> > ACPI: BIOS passes blacklist
> > 
> > 
> > The question is, should acpi be looking at a different memory location
> > for the proper DSDT?  I mean, can 0x00000000 be right?  What is the
> > 'Memory location' dell is referring to?  
> 
> I am so busted.
> 
> from drivers/acpi/tables.c:
> 
> /* 
>  * The DSDT is *not* in the RSDT (why not? no idea.) but we want
>  * to print its info, because this is what people usually blacklist
>  * against. Unfortunately, we don't know the phys_addr, so just
>  * print 0. Maybe no one will notice.
>  */
> if(!acpi_get_table_header_early(ACPI_DSDT, &header))
> 	acpi_table_print(header, 0);
> 
> Basically there was no clean way to get the DSDTs phys_addr at that point,
> so I punted. Rest assured your DSDT does have an address, and yes, it is
> stored in the BIOS, and subsequently copied to RAM, where we find it.
> 

Please bear with me, I am new to this.  From what I gather, you are
saying that this is simply a diagnostic message and is not reflecting
the true state of my dsdt, and that in fact, linux is using the correct
dsdt that is in the bios, rather than doing something else.  Is this
correct?

> Also note that this is printed in the first phase of ACPI init - table
> parsing. Just because your system's DSDT info is printed here does not mean
> it cannot be overridden before it is actually used. See
> http://www.poupinou.org/acpi/over.html .
> 
I have read about overriding the dsdt, but my thinking was that the
decompiled dsdt had a 1998 version, and that things may be wrong.  I
guess I am back to square one-- this DSDT is very unmanageable (cryptic
variable names and almost no comments).

Thanks for your reply.

Jamie

-- 
Email:        jstrand1-aYIB8uWIUb2Vn7q6wjsIow@public.gmane.org
GPG/PGP ID:   26384A3A
Fingerprint:  D9FF DF4A 2D46 A353 A289  E8F5 AA75 DCBE 2638 4A3A




-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/

^ permalink raw reply

* can't boot 2.5.52
From: Jeff Chua @ 2002-12-16 19:56 UTC (permalink / raw)
  To: Linux Kernel


Is it just me or someone else there having the same problem as well?

2.5.51 booted ok

2.5.52 can't boot

LOADING....

Now reading INITRD:
LOADING....

Uncompressing Linux... Ok, booting the kernel
[stops here]

I'm booting using loadlin16c

Thanks,
Jeff
[ jchua@fedex.com ]

^ permalink raw reply

* Re: dosemu 1.1.3.9 user report
From: Bart Oldeman @ 2002-12-16 19:49 UTC (permalink / raw)
  To: linux-msdos
In-Reply-To: <20021216191735.GA14829@dirac.org>

On Mon, 16 Dec 2002, Peter Jay Salzman wrote:

> have you been able to have xdosemu grab the mouse?  i've been having
> trouble playing redneck rampage because if the mouse "moves over" too
> far left or right, the mouse leaves the xdos window.

try ctrl-alt-home. I noticed in your dosemu.conf that you uncommented the
mgrab_key setting, but it should work by default.

Bart


^ permalink raw reply

* Re: Support for Arctic platform (405LP based)
From: Cort Dougan @ 2002-12-16 19:49 UTC (permalink / raw)
  To: Tom Rini; +Cc: Paul Mackerras, linuxppc-embedded
In-Reply-To: <20021216150442.GJ6095@opus.bloom.county>


} I'm not sure how that would stop the growth of the '_devel' tree, it
} would just split it up into 4xx, and everything else.  And my goal of
} the new few weeks is to try and move everything that's not 4xx that I
} can get my hands on to test into the _2_4 tree.  I'm not sure just how
} much of that I'll actually be able to do, but I'm going to try.

There would be no _devel tree in that case.  They'd all be based on
Marcelo's so moving back and forth would be easier.  There would also be
more trees and smaller patches.

Right now, if you want an embedded board to boot your only chance is to try
the wildly divergent - likely unstable - _devel tree.  Having something
like this would be much nicer:


marcelo ---> linuxppc_2_4 --- linuxppc_2_4_4xx
                  |                 |
		  |		    ---> linuxppc_2_4_4xx_walnut
		  |		    |
		  |		    ---> linuxppc_2_4_4xx_crazystuff
		  |		    |
		  |		    ---> linuxppc_2_4_4xx_some_whacky_port
		  |
		  |
		  |
		  |---> linuxppc_2_4_something

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply

* Re: Discovery II (was Re: Support for Arctic platform (405LP based))
From: Roland Dreier @ 2002-12-16 19:49 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-embedded
In-Reply-To: <3DFDCB00.7060509@mvista.com>


    Roland> This reminds me... can someone tell me what the status of
    Roland> Discovery II (MV64340) is at the moment?

    Mark> Rabeeh Khoury from Marvell has done a port to it and put it
    Mark> in the linux-galileo tree.  I have no hardware to test it
    Mark> but Rabeeh says that its been working fine for him for some
    Mark> time.

Thanks... my next question is where is the linux-galileo tree?  (I'm
sure this is well-known to people working with Discovery II but please
forgive my ignorance as I'm just starting to look at this platform)

Thanks,
  Roland

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply

* Re: Intel P6 vs P7 system call performance
From: H. Peter Anvin @ 2002-12-16 19:55 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Albert D. Cahalan, linux-kernel, terje.eggestad
In-Reply-To: <20021216111759.GA24196@atrey.karlin.mff.cuni.cz>

Pavel Machek wrote:
> 
>>The vsyscall stuff costs you on every syscall. It's nice for
> 
> 
> Well, the cost is basically one call. That's not *that* big cost.
> 

You absolutely, positively *need* the call anyway.  SYSENTER trashes EIP.

	-hpa



^ permalink raw reply

* Re: success with redneck rampage and a few questions
From: Stas Sergeev @ 2002-12-16 19:47 UTC (permalink / raw)
  To: linux-msdos

Hello.

Peter Jay Salzman wrote:
> how fast it is.  the sound is great.  very cool.   i see
> a lot of improvements in dosemu since last year.
Yes, great work indeed.
Lots of fundamental problems that
were ignored for years, were magically
resolved.

> 1. i already read in the mailing list archives that there
> is no full screen xdosemu.  it sounds like there never
> will be a fullscreen xdosemu either.
Not obviously. At least I think Emmanuel
Jeandel wrote an SDL frontend, which can
be used for full-screen graphics. I wonder
if it is still being developed or dropped
(which would be a shame).

> however, the game runs but no graphics show up on a
> console. i enabled svga in the configure process and made
> sure that svgalib shows up in ldd dosemu.bin.
Yes, SVGA driver for console (direct VESA)
is not yet. I was working on it a lot, but
stucked due to a linux kernel limitation.
I expect to return to the problem and
resolve the limitation one day.
For now you can still use a direct VESA
with some old cards like S3 or SiS.

> i've attached my config file below.   any advice?
For now - probably not:( Downgrade your
video card to S3 is only what comes in
a mind.

> 2. playing in an xdos box wouldn't be so bad if it would
> grab the any way to bind the mouse exclusively to the
> game?
Ctrl-Alt-Home works for me (not any
of the 2 Home buttons, but one works),
but it doesn't work for some people
for the so far unknown reasons.


^ permalink raw reply

* RE: DSDT in Dell i8200-- does acpi have the correct addres s?
From: Grover, Andrew @ 2002-12-16 19:43 UTC (permalink / raw)
  To: 'James D Strandboge'; +Cc: acpi-devel-pyega4qmqnRoyOMFzWx49A

> From: James D Strandboge [mailto:jstrand1-aYIB8uWIUb2Vn7q6wjsIow@public.gmane.org] 
> My i8200 has basic acpi functionality, with quite a few issues.  I
> started poking around the Dell download site and came across this in a
> description of a BIOS upgrade for my laptop:
> 
> ===================================================================
> Systems:      Dell Inspiron 8200	(Memory location F000:E845)
> Version:      A06                       (Memory location F000:E842)
> Build Date:   08/17/02                  (Memory location FFFF:0005)
> 
> ...
> 
> Now, if I read my dsdt from /proc/acpi/dsdt, nd decompile it 
> with iasl,
> it shows a version from 1998.  I looked at dmesg and found:
> 
> ACPI: DSDT (v001 INT430 SYSFexxx 00000.04097) @ 0x00000000
> ACPI: BIOS passes blacklist
> 
> 
> The question is, should acpi be looking at a different memory location
> for the proper DSDT?  I mean, can 0x00000000 be right?  What is the
> 'Memory location' dell is referring to?  

I am so busted.

from drivers/acpi/tables.c:

/* 
 * The DSDT is *not* in the RSDT (why not? no idea.) but we want
 * to print its info, because this is what people usually blacklist
 * against. Unfortunately, we don't know the phys_addr, so just
 * print 0. Maybe no one will notice.
 */
if(!acpi_get_table_header_early(ACPI_DSDT, &header))
	acpi_table_print(header, 0);

Basically there was no clean way to get the DSDTs phys_addr at that point,
so I punted. Rest assured your DSDT does have an address, and yes, it is
stored in the BIOS, and subsequently copied to RAM, where we find it.

Also note that this is printed in the first phase of ACPI init - table
parsing. Just because your system's DSDT info is printed here does not mean
it cannot be overridden before it is actually used. See
http://www.poupinou.org/acpi/over.html .

Regards -- Andy


-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/

^ permalink raw reply

* Re: Loding rules
From: Joel Newkirk @ 2002-12-16 19:42 UTC (permalink / raw)
  To: nedco, netfilter
In-Reply-To: <3df77ff9.7a14.0@unacs.bg>

On Wednesday 11 December 2002 01:12 pm, nedco@unacs.bg wrote:
> Hi,
>  How to load fast about 20000 rules in iptables.
>  If some document will be help , please let me know  :)
>
> Thanks a lot
> Nedco

As long as you don't need to dynamically define the rules (IE using a 
dynamic IP) iptables-save and iptables-restore should be your simple 
answer.  Oscar's tutorial explains save and restore at: 
http://iptables-tutorial.frozentux.net/chunkyhtml/saveandrestore.html

These will load the complete ruleset in a very few operations, instead of 
about 40000.  (based on your 20000 figure above)

j


^ permalink raw reply

* Re: [PATCH] BIN_TO_BCD consolidation
From: Hollis Blanchard @ 2002-12-16 19:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Linux Kernel Mailing List
In-Reply-To: <1040064165.10740.31.camel@granite.austin.ibm.com>

Hollis Blanchard wrote:
> 
> Has anyone else noticed the number of BCD_TO_BIN / BIN_TO_BCD
> definitions?

This is the updated version. Some users had already redefined the BCD
macros to not make assignments, but kept the same name.

-Hollis
-- 
PowerPC Linux
IBM Linux Technology Center

 arch/alpha/kernel/time.c              |    1
 arch/arm/kernel/time.c                |    8 -------
 arch/cris/drivers/ds1302.c            |    1
 arch/cris/kernel/time.c               |    1
 arch/i386/kernel/time.c               |    1
 arch/m68k/atari/time.c                |    1
 arch/m68k/sun3x/time.c                |   32 +++++++++++++----------------
 arch/mips/ddb5xxx/common/rtc_ds1386.c |   37 ++++++++++++++--------------------
 arch/mips/dec/time.c                  |    1
 arch/mips/kernel/old-time.c           |    1
 arch/mips64/sgi-ip27/ip27-rtc.c       |    1
 arch/mips64/sgi-ip27/ip27-timer.c     |    1
 arch/ppc/iSeries/mf.c                 |    1
 arch/ppc/platforms/chrp_time.c        |    1
 arch/ppc/platforms/gemini_setup.c     |    1
 arch/ppc/platforms/prep_time.c        |    1
 arch/ppc/syslib/todc_time.c           |    1
 arch/ppc64/kernel/mf.c                |    1
 arch/ppc64/kernel/rtc.c               |    1
 arch/sh/kernel/rtc.c                  |    9 --------
 arch/sparc64/kernel/time.c            |    9 --------
 arch/x86_64/kernel/time.c             |    1
 drivers/acorn/char/pcf8583.c          |    1
 drivers/acpi/sleep.c                  |    1
 drivers/char/rtc.c                    |    1
 drivers/scsi/sr_vendor.c              |   15 ++++++-------
 drivers/sgi/char/ds1286.c             |    1
 include/asm-arm/arch-ebsa285/time.h   |    1
 include/asm-cris/rtc.h                |    5 ----
 include/asm-generic/rtc.h             |    1
 include/asm-mips/ds1286.h             |   11 ----------
 include/asm-mips64/ds1286.h           |   11 ----------
 include/asm-mips64/m48t35.h           |    8 -------
 include/asm-ppc/m48t35.h              |    9 --------
 include/asm-ppc/mk48t59.h             |    8 -------
 include/asm-ppc/nvram.h               |    8 -------
 include/asm-ppc/todc.h                |    8 -------
 include/asm-ppc64/nvram.h             |    8 -------
 include/linux/bcd.h                   |   20 ++++++++++++++++++
 include/linux/mc146818rtc.h           |   11 ----------
 40 files changed, 83 insertions(+), 157 deletions(-)

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.744   -> 1.746  
#	include/asm-ppc/m48t35.h	1.5     -> 1.6    
#	drivers/acpi/sleep.c	1.8     -> 1.9    
#	arch/ppc/platforms/chrp_time.c	1.7     -> 1.8    
#	include/asm-cris/rtc.h	1.2     -> 1.3    
#	include/asm-ppc/mk48t59.h	1.4     -> 1.5    
#	drivers/sgi/char/ds1286.c	1.6     -> 1.7    
#	arch/mips64/sgi-ip27/ip27-timer.c	1.3     -> 1.4    
#	  drivers/char/rtc.c	1.18    -> 1.19   
#	include/asm-ppc64/nvram.h	1.2     -> 1.3    
#	include/asm-generic/rtc.h	1.1     -> 1.2    
#	arch/ppc/iSeries/mf.c	1.2     -> 1.3    
#	arch/mips64/sgi-ip27/ip27-rtc.c	1.5     -> 1.6    
#	drivers/scsi/sr_vendor.c	1.10    -> 1.12   
#	arch/i386/kernel/time.c	1.22    -> 1.23   
#	arch/ppc/platforms/prep_time.c	1.7     -> 1.8    
#	arch/sparc64/kernel/time.c	1.18    -> 1.19   
#	include/asm-mips64/m48t35.h	1.1     -> 1.2    
#	arch/ppc/platforms/gemini_setup.c	1.12    -> 1.13   
#	arch/alpha/kernel/time.c	1.11    -> 1.12   
#	arch/cris/kernel/time.c	1.6     -> 1.7    
#	arch/ppc64/kernel/rtc.c	1.3     -> 1.4    
#	include/asm-mips/ds1286.h	1.1     -> 1.2    
#	arch/m68k/sun3x/time.c	1.4     -> 1.6    
#	include/asm-mips64/ds1286.h	1.2     -> 1.3    
#	arch/x86_64/kernel/time.c	1.5     -> 1.6    
#	arch/arm/kernel/time.c	1.11    -> 1.12   
#	arch/mips/kernel/old-time.c	1.3     -> 1.4    
#	arch/ppc64/kernel/mf.c	1.3     -> 1.4    
#	include/asm-ppc/todc.h	1.1     -> 1.2    
#	arch/ppc/syslib/todc_time.c	1.4     -> 1.5    
#	arch/m68k/atari/time.c	1.3     -> 1.4    
#	arch/mips/dec/time.c	1.2     -> 1.3    
#	arch/mips/ddb5xxx/common/rtc_ds1386.c	1.1     -> 1.3    
#	include/linux/mc146818rtc.h	1.2     -> 1.3    
#	arch/sh/kernel/rtc.c	1.5     -> 1.6    
#	arch/cris/drivers/ds1302.c	1.4     -> 1.5    
#	drivers/acorn/char/pcf8583.c	1.5     -> 1.6    
#	include/asm-ppc/nvram.h	1.4     -> 1.5    
#	include/asm-arm/arch-ebsa285/time.h	1.5     -> 1.6    
#	               (new)	        -> 1.1     include/linux/bcd.h
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/12/12	hollis@granite.austin.ibm.com	1.745
# consolidate all the BCD_TO_BIN / BIN_TO_BCD definitions into bcd.h
# --------------------------------------------
# 02/12/16	hollis@granite.austin.ibm.com	1.746
# some people had already redefined the old BCD macros without the
# assignment. fix those places to use the new bcd.h
# --------------------------------------------
#
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/alpha/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -37,6 +37,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/bcd.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/arm/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -47,14 +47,6 @@
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY	(1000000/HZ)
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 static int dummy_set_rtc(void)
 {
 	return 0;
diff -Nru a/arch/cris/drivers/ds1302.c b/arch/cris/drivers/ds1302.c
--- a/arch/cris/drivers/ds1302.c	Mon Dec 16 13:49:27 2002
+++ b/arch/cris/drivers/ds1302.c	Mon Dec 16 13:49:27 2002
@@ -97,6 +97,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
+#include <linux/bcd.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
--- a/arch/cris/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/cris/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/delay.h>
+#include <linux/bcd.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/i386/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -43,6 +43,7 @@
 #include <linux/smp.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/bcd.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
diff -Nru a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
--- a/arch/m68k/atari/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/m68k/atari/time.c	Mon Dec 16 13:49:27 2002
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/rtc.h>
+#include <linux/bcd.h>
 
 #include <asm/rtc.h>
 
diff -Nru a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
--- a/arch/m68k/sun3x/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/m68k/sun3x/time.c	Mon Dec 16 13:49:27 2002
@@ -11,6 +11,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
+#include <linux/bcd.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -36,9 +37,6 @@
 #define C_SIGN    0x20
 #define C_CALIB   0x1f
 
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) (((val/10) << 4) | (val % 10))
-
 int sun3x_hwclk(int set, struct rtc_time *t)
 {
 	volatile struct mostek_dt *h = 
@@ -49,23 +47,23 @@
 	
 	if(set) {
 		h->csr |= C_WRITE;
-		h->sec = BIN_TO_BCD(t->tm_sec);
-		h->min = BIN_TO_BCD(t->tm_min);
-		h->hour = BIN_TO_BCD(t->tm_hour);
-		h->wday = BIN_TO_BCD(t->tm_wday);
-		h->mday = BIN_TO_BCD(t->tm_mday);
-		h->month = BIN_TO_BCD(t->tm_mon);
-		h->year = BIN_TO_BCD(t->tm_year);
+		h->sec = BIN2BCD(t->tm_sec);
+		h->min = BIN2BCD(t->tm_min);
+		h->hour = BIN2BCD(t->tm_hour);
+		h->wday = BIN2BCD(t->tm_wday);
+		h->mday = BIN2BCD(t->tm_mday);
+		h->month = BIN2BCD(t->tm_mon);
+		h->year = BIN2BCD(t->tm_year);
 		h->csr &= ~C_WRITE;
 	} else {
 		h->csr |= C_READ;
-		t->tm_sec = BCD_TO_BIN(h->sec);
-		t->tm_min = BCD_TO_BIN(h->min);
-		t->tm_hour = BCD_TO_BIN(h->hour);
-		t->tm_wday = BCD_TO_BIN(h->wday);
-		t->tm_mday = BCD_TO_BIN(h->mday);
-		t->tm_mon = BCD_TO_BIN(h->month);
-		t->tm_year = BCD_TO_BIN(h->year);
+		t->tm_sec = BCD2BIN(h->sec);
+		t->tm_min = BCD2BIN(h->min);
+		t->tm_hour = BCD2BIN(h->hour);
+		t->tm_wday = BCD2BIN(h->wday);
+		t->tm_mday = BCD2BIN(h->mday);
+		t->tm_mon = BCD2BIN(h->month);
+		t->tm_year = BCD2BIN(h->year);
 		h->csr &= ~C_READ;
 	}
 
diff -Nru a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
--- a/arch/mips/ddb5xxx/common/rtc_ds1386.c	Mon Dec 16 13:49:27 2002
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c	Mon Dec 16 13:49:27 2002
@@ -20,6 +20,7 @@
 
 #include <linux/types.h>
 #include <linux/time.h>
+#include <linux/bcd.h>
 
 #include <asm/time.h>
 #include <asm/addrspace.h>
@@ -28,12 +29,6 @@
 
 #define	EPOCH		2000
 
-#undef BCD_TO_BIN
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-
-#undef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
 #define	READ_RTC(x)	*(volatile unsigned char*)(rtc_base+x)
 #define	WRITE_RTC(x, y)	*(volatile unsigned char*)(rtc_base+x) = y
 
@@ -52,11 +47,11 @@
 	WRITE_RTC(0xB, byte);
 
 	/* read time data */
-	year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH;
-	month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f);
-	day = BCD_TO_BIN(READ_RTC(0x8));
-	minute = BCD_TO_BIN(READ_RTC(0x2));
-	second = BCD_TO_BIN(READ_RTC(0x1));
+	year = BCD2BIN(READ_RTC(0xA)) + EPOCH;
+	month = BCD2BIN(READ_RTC(0x9) & 0x1f);
+	day = BCD2BIN(READ_RTC(0x8));
+	minute = BCD2BIN(READ_RTC(0x2));
+	second = BCD2BIN(READ_RTC(0x1));
 
 	/* hour is special - deal with it later */
 	temp = READ_RTC(0x4);
@@ -68,11 +63,11 @@
 	/* calc hour */
 	if (temp & 0x40) {
 		/* 12 hour format */
-		hour = BCD_TO_BIN(temp & 0x1f);
+		hour = BCD2BIN(temp & 0x1f);
 		if (temp & 0x20) hour += 12; 		/* PM */
 	} else {
 		/* 24 hour format */
-		hour = BCD_TO_BIN(temp & 0x3f);
+		hour = BCD2BIN(temp & 0x3f);
 	}
 
 	return mktime(year, month, day, hour, minute, second);
@@ -95,19 +90,19 @@
 	to_tm(t, &tm);
 
 	/* check each field one by one */
-	year = BIN_TO_BCD(tm.tm_year - EPOCH);
+	year = BIN2BCD(tm.tm_year - EPOCH);
 	if (year != READ_RTC(0xA)) {
 		WRITE_RTC(0xA, year);
 	}
 
 	temp = READ_RTC(0x9);
-	month = BIN_TO_BCD(tm.tm_mon);
+	month = BIN2BCD(tm.tm_mon);
 	if (month != (temp & 0x1f)) {
 		WRITE_RTC( 0x9,
 			   (month & 0x1f) | (temp & ~0x1f) );
 	}
 
-	day = BIN_TO_BCD(tm.tm_mday);
+	day = BIN2BCD(tm.tm_mday);
 	if (day != READ_RTC(0x8)) {
 		WRITE_RTC(0x8, day);
 	}
@@ -117,22 +112,22 @@
 		/* 12 hour format */
 		hour = 0x40;
 		if (tm.tm_hour > 12) {
-			hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f);
+			hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
 		} else {
-			hour |= BIN_TO_BCD(tm.tm_hour);
+			hour |= BIN2BCD(tm.tm_hour);
 		}
 	} else {
 		/* 24 hour format */
-		hour = BIN_TO_BCD(tm.tm_hour) & 0x3f;
+		hour = BIN2BCD(tm.tm_hour) & 0x3f;
 	}
 	if (hour != temp) WRITE_RTC(0x4, hour);
 
-	minute = BIN_TO_BCD(tm.tm_min);
+	minute = BIN2BCD(tm.tm_min);
 	if (minute != READ_RTC(0x2)) {
 		WRITE_RTC(0x2, minute);
 	}
 
-	second = BIN_TO_BCD(tm.tm_sec);
+	second = BIN2BCD(tm.tm_sec);
 	if (second != READ_RTC(0x1)) {
 		WRITE_RTC(0x1, second);
 	}
diff -Nru a/arch/mips/dec/time.c b/arch/mips/dec/time.c
--- a/arch/mips/dec/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/mips/dec/time.c	Mon Dec 16 13:49:27 2002
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/bcd.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
diff -Nru a/arch/mips/kernel/old-time.c b/arch/mips/kernel/old-time.c
--- a/arch/mips/kernel/old-time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/mips/kernel/old-time.c	Mon Dec 16 13:49:27 2002
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
diff -Nru a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c
--- a/arch/mips64/sgi-ip27/ip27-rtc.c	Mon Dec 16 13:49:27 2002
+++ b/arch/mips64/sgi-ip27/ip27-rtc.c	Mon Dec 16 13:49:27 2002
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/smp_lock.h>
+#include <linux/bcd.h>
 
 #include <asm/m48t35.h>
 #include <asm/sn/ioc3.h>
diff -Nru a/arch/mips64/sgi-ip27/ip27-timer.c b/arch/mips64/sgi-ip27/ip27-timer.c
--- a/arch/mips64/sgi-ip27/ip27-timer.c	Mon Dec 16 13:49:27 2002
+++ b/arch/mips64/sgi-ip27/ip27-timer.c	Mon Dec 16 13:49:27 2002
@@ -11,6 +11,7 @@
 #include <linux/param.h>
 #include <linux/timex.h>
 #include <linux/mm.h>		
+#include <linux/bcd.h>		
 
 #include <asm/pgtable.h>
 #include <asm/sgialib.h>
diff -Nru a/arch/ppc/iSeries/mf.c b/arch/ppc/iSeries/mf.c
--- a/arch/ppc/iSeries/mf.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc/iSeries/mf.c	Mon Dec 16 13:49:27 2002
@@ -40,6 +40,7 @@
 #include <asm/iSeries/iSeries_proc.h>
 #include <asm/uaccess.h>
 #include <linux/pci.h>
+#include <linux/bcd.h>
 

 /*
diff -Nru a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
--- a/arch/ppc/platforms/chrp_time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc/platforms/chrp_time.c	Mon Dec 16 13:49:27 2002
@@ -20,6 +20,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/init.h>
+#include <linux/bcd.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
diff -Nru a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
--- a/arch/ppc/platforms/gemini_setup.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc/platforms/gemini_setup.c	Mon Dec 16 13:49:27 2002
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/bcd.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/ppc/platforms/prep_time.c b/arch/ppc/platforms/prep_time.c
--- a/arch/ppc/platforms/prep_time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc/platforms/prep_time.c	Mon Dec 16 13:49:27 2002
@@ -19,6 +19,7 @@
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/bcd.h>
 
 #include <asm/sections.h>
 #include <asm/segment.h>
diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
--- a/arch/ppc/syslib/todc_time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc/syslib/todc_time.c	Mon Dec 16 13:49:27 2002
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/timex.h>
+#include <linux/bcd.h>
 
 #include <asm/machdep.h>
 #include <asm/io.h>
diff -Nru a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
--- a/arch/ppc64/kernel/mf.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc64/kernel/mf.c	Mon Dec 16 13:49:27 2002
@@ -40,6 +40,7 @@
 #include <asm/iSeries/iSeries_proc.h>
 #include <asm/uaccess.h>
 #include <linux/pci.h>
+#include <linux/bcd.h>
 
 extern struct pci_dev * iSeries_vio_dev;
 
diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
--- a/arch/ppc64/kernel/rtc.c	Mon Dec 16 13:49:27 2002
+++ b/arch/ppc64/kernel/rtc.c	Mon Dec 16 13:49:27 2002
@@ -32,6 +32,7 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
+#include <linux/bcd.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/sh/kernel/rtc.c b/arch/sh/kernel/rtc.c
--- a/arch/sh/kernel/rtc.c	Mon Dec 16 13:49:27 2002
+++ b/arch/sh/kernel/rtc.c	Mon Dec 16 13:49:27 2002
@@ -9,17 +9,10 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/bcd.h>
 
 #include <asm/io.h>
 #include <asm/rtc.h>
-
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
 
 void sh_rtc_gettimeofday(struct timeval *tv)
 {
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/sparc64/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -23,6 +23,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/delay.h>
 #include <linux/profile.h>
+#include <linux/bcd.h>
 
 #include <asm/oplib.h>
 #include <asm/mostek.h>
@@ -329,14 +330,6 @@
 
 	return (data1 == data2);	/* Was the write blocked? */
 }
-
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-#endif
 
 /* Probe for the real time clock chip. */
 static void __init set_system_time(void)
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	Mon Dec 16 13:49:27 2002
+++ b/arch/x86_64/kernel/time.c	Mon Dec 16 13:49:27 2002
@@ -21,6 +21,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/bcd.h>
 #include <asm/vsyscall.h>
 #include <asm/timex.h>
 
diff -Nru a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
--- a/drivers/acorn/char/pcf8583.c	Mon Dec 16 13:49:27 2002
+++ b/drivers/acorn/char/pcf8583.c	Mon Dec 16 13:49:27 2002
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/mc146818rtc.h>
 #include <linux/init.h>
+#include <linux/bcd.h>
 
 #include "pcf8583.h"
 
diff -Nru a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Mon Dec 16 13:49:27 2002
+++ b/drivers/acpi/sleep.c	Mon Dec 16 13:49:27 2002
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/seq_file.h>
+#include <linux/bcd.h>
 
 #include <asm/uaccess.h>
 #include <asm/acpi.h>
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Mon Dec 16 13:49:27 2002
+++ b/drivers/char/rtc.c	Mon Dec 16 13:49:27 2002
@@ -72,6 +72,7 @@
 #include <linux/spinlock.h>
 #include <linux/sysctl.h>
 #include <linux/wait.h>
+#include <linux/bcd.h>
 
 #include <asm/current.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
--- a/drivers/scsi/sr_vendor.c	Mon Dec 16 13:49:27 2002
+++ b/drivers/scsi/sr_vendor.c	Mon Dec 16 13:49:27 2002
@@ -37,6 +37,7 @@
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/bcd.h>
 
 #include <linux/blk.h>
 #include "scsi.h"
@@ -151,8 +152,6 @@
 /* This function gets called after a media change. Checks if the CD is
    multisession, asks for offset etc. */
 
-#define BCD_TO_BIN(x)    ((((int)x & 0xf0) >> 4)*10 + ((int)x & 0x0f))
-
 int sr_cd_check(struct cdrom_device_info *cdi)
 {
 	Scsi_CD *cd = cdi->handle;
@@ -223,9 +222,9 @@
 				no_multi = 1;
 				break;
 			}
-			min = BCD_TO_BIN(buffer[15]);
-			sec = BCD_TO_BIN(buffer[16]);
-			frame = BCD_TO_BIN(buffer[17]);
+			min = BCD2BIN(buffer[15]);
+			sec = BCD2BIN(buffer[16]);
+			frame = BCD2BIN(buffer[17]);
 			sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
 			break;
 		}
@@ -252,9 +251,9 @@
 			}
 			if (rc != 0)
 				break;
-			min = BCD_TO_BIN(buffer[1]);
-			sec = BCD_TO_BIN(buffer[2]);
-			frame = BCD_TO_BIN(buffer[3]);
+			min = BCD2BIN(buffer[1]);
+			sec = BCD2BIN(buffer[2]);
+			frame = BCD2BIN(buffer[3]);
 			sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
 			if (sector)
 				sector -= CD_MSF_OFFSET;
diff -Nru a/drivers/sgi/char/ds1286.c b/drivers/sgi/char/ds1286.c
--- a/drivers/sgi/char/ds1286.c	Mon Dec 16 13:49:27 2002
+++ b/drivers/sgi/char/ds1286.c	Mon Dec 16 13:49:27 2002
@@ -36,6 +36,7 @@
 #include <linux/poll.h>
 #include <linux/rtc.h>
 #include <linux/spinlock.h>
+#include <linux/bcd.h>
 
 #include <asm/ds1286.h>
 #include <asm/io.h>
diff -Nru a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h
--- a/include/asm-arm/arch-ebsa285/time.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-arm/arch-ebsa285/time.h	Mon Dec 16 13:49:27 2002
@@ -18,6 +18,7 @@
 #define RTC_ALWAYS_BCD		0
 
 #include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
 
 #include <asm/hardware/dec21285.h>
 #include <asm/leds.h>
diff -Nru a/include/asm-cris/rtc.h b/include/asm-cris/rtc.h
--- a/include/asm-cris/rtc.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-cris/rtc.h	Mon Dec 16 13:49:27 2002
@@ -39,11 +39,6 @@
 #define RTC_INIT() (-1)
 #endif
 
-/* conversions to and from the stupid RTC internal format */
-
-#define BCD_TO_BIN(x) x = (((x & 0xf0) >> 3) * 5 + (x & 0xf))
-#define BIN_TO_BCD(x) x = (x % 10) | ((x / 10) << 4) 
-
 /*
  * The struct used to pass data via the following ioctl. Similar to the
  * struct tm in <time.h>, but it needs to be here so that the kernel 
diff -Nru a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
--- a/include/asm-generic/rtc.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-generic/rtc.h	Mon Dec 16 13:49:27 2002
@@ -16,6 +16,7 @@
 
 #include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
+#include <linux/bcd.h>
 
 #define RTC_PIE 0x40		/* periodic interrupt enable */
 #define RTC_AIE 0x20		/* alarm interrupt enable */
diff -Nru a/include/asm-mips/ds1286.h b/include/asm-mips/ds1286.h
--- a/include/asm-mips/ds1286.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-mips/ds1286.h	Mon Dec 16 13:49:27 2002
@@ -57,15 +57,4 @@
 #define RTC_IPSW		0x40
 #define RTC_TE			0x80
 
-/*
- * Conversion between binary and BCD.
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 #endif /* _ASM_DS1286_h */
diff -Nru a/include/asm-mips64/ds1286.h b/include/asm-mips64/ds1286.h
--- a/include/asm-mips64/ds1286.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-mips64/ds1286.h	Mon Dec 16 13:49:27 2002
@@ -56,15 +56,4 @@
 #define RTC_IPSW		0x40
 #define RTC_TE			0x80
 
-/*
- * Conversion between binary and BCD.
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 #endif /* _ASM_DS1286_h */
diff -Nru a/include/asm-mips64/m48t35.h b/include/asm-mips64/m48t35.h
--- a/include/asm-mips64/m48t35.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-mips64/m48t35.h	Mon Dec 16 13:49:27 2002
@@ -21,12 +21,4 @@
 #define M48T35_RTC_STOPPED  0x80
 #define M48T35_RTC_READ     0x40
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(x)   ((x)=((x)&15) + ((x)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(x)   ((x)=(((x)/10)<<4) + (x)%10)
-#endif
-
 #endif
diff -Nru a/include/asm-ppc/m48t35.h b/include/asm-ppc/m48t35.h
--- a/include/asm-ppc/m48t35.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-ppc/m48t35.h	Mon Dec 16 13:49:27 2002
@@ -74,13 +74,4 @@
 #define M48T35_RTC_READ     0x40
 

-/* read/write conversions */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(x)   ((x)=((x)&15) + ((x)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(x)   ((x)=(((x)/10)<<4) + (x)%10)
-#endif
-
 #endif
diff -Nru a/include/asm-ppc/mk48t59.h b/include/asm-ppc/mk48t59.h
--- a/include/asm-ppc/mk48t59.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-ppc/mk48t59.h	Mon Dec 16 13:49:27 2002
@@ -24,12 +24,4 @@
 #define MK48T59_RTC_CONTROLB		0x1FF9
 #define MK48T59_RTC_CB_STOP		0x80
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 #endif /* _PPC_MK48T59_H */
diff -Nru a/include/asm-ppc/nvram.h b/include/asm-ppc/nvram.h
--- a/include/asm-ppc/nvram.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-ppc/nvram.h	Mon Dec 16 13:49:27 2002
@@ -23,14 +23,6 @@
 #define MOTO_RTC_CONTROLA            0x1FF8
 #define MOTO_RTC_CONTROLB            0x1FF9
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 /* PowerMac specific nvram stuffs */
 
 enum {
diff -Nru a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h
--- a/include/asm-ppc/todc.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-ppc/todc.h	Mon Dec 16 13:49:27 2002
@@ -355,14 +355,6 @@
 	todc_info->flags         = clock_type ##_FLAGS;			\
 }
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 extern todc_info_t *todc_info;
 
 unsigned char todc_direct_read_val(int addr);
diff -Nru a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h
--- a/include/asm-ppc64/nvram.h	Mon Dec 16 13:49:27 2002
+++ b/include/asm-ppc64/nvram.h	Mon Dec 16 13:49:27 2002
@@ -28,12 +28,4 @@
 #define MOTO_RTC_CONTROLA       0x1FF8
 #define MOTO_RTC_CONTROLB       0x1FF9
 
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 #endif /* _PPC64_NVRAM_H */
diff -Nru a/include/linux/bcd.h b/include/linux/bcd.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/bcd.h	Mon Dec 16 13:49:27 2002
@@ -0,0 +1,20 @@
+/* Permission is hereby granted to copy, modify and redistribute this code
+ * in terms of the GNU Library General Public License, Version 2 or later,
+ * at your option.
+ */
+
+/* macros to translate to/from binary and binary-coded decimal (frequently
+ * found in RTC chips).
+ */
+
+#ifndef _BCD_H
+#define _BCD_H
+
+#define BCD2BIN(val)	(((val) & 0x0f) + ((val)>>4)*10)
+#define BIN2BCD(val)	((((val)/10)<<4) + (val)%10)
+
+/* backwards compat */
+#define BCD_TO_BIN(val) ((val)=BCD2BIN(val))
+#define BIN_TO_BCD(val) ((val)=BIN2BCD(val))
+
+#endif /* _BCD_H */
diff -Nru a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
--- a/include/linux/mc146818rtc.h	Mon Dec 16 13:49:27 2002
+++ b/include/linux/mc146818rtc.h	Mon Dec 16 13:49:27 2002
@@ -87,15 +87,4 @@
 # define RTC_VRT 0x80		/* valid RAM and time */
 /**********************************************************************/
 
-/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) 
- * determines if the following two #defines are needed
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
 #endif /* _MC146818RTC_H */


^ permalink raw reply

* Re: DSDT in Dell i8200-- does acpi have the correct address?
From: James D Strandboge @ 2002-12-16 19:38 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1040066279.2070.18.camel-Ty44UuN9vPJ5T2F9fCU5s856D9/Od9gv@public.gmane.org>

On Mon, 2002-12-16 at 14:17, James D Strandboge wrote:

> 
> Now, if I read my dsdt from /proc/acpi/dsdt, nd decompile it with iasl,
> it shows a version from 1998.  I looked at dmesg and found:
> 
> ACPI: DSDT (v001 INT430 SYSFexxx 00000.04097) @ 0x00000000
> ACPI: BIOS passes blacklist
> 

I meant to also include from dmesg:

ACPI: have wakeup address 0xc0001000
ACPI: RSDP (v000 DELL                       ) @ 0x000fde50
ACPI: RSDT (v001 DELL    CPi R   10194.01801) @ 0x000fde64
ACPI: FADT (v001 DELL    CPi R   10194.01801) @ 0x000fde90
ACPI: DSDT (v001 INT430 SYSFexxx 00000.04097) @ 0x00000000
ACPI: BIOS passes blacklist

>From what I can tell, all the tables other than DSDT are falling within
the range of what Dell has listed on their site.  The (I assume) dates
and vendor also correspond-- but the DSDT is different here too.

Jamie

-- 
Email:        jstrand1-aYIB8uWIUb2Vn7q6wjsIow@public.gmane.org
GPG/PGP ID:   26384A3A
Fingerprint:  D9FF DF4A 2D46 A353 A289  E8F5 AA75 DCBE 2638 4A3A




-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/

^ permalink raw reply

* Re: L2 Cache problem
From: Xavier LaRue @ 2002-12-16 19:31 UTC (permalink / raw)
  To: linux-kernel
In-Reply-To: <Pine.LNX.4.33.0212161347580.25857-100000@router.windsormachine.com>

On Mon, 16 Dec 2002 13:56:09 -0500 (EST)
Mike Dresser <mdresser_l@windsormachine.com> wrote:

> On Mon, 16 Dec 2002, Xavier LaRue wrote:
> 
> > my dmesg will be online at http://paxl.no-ip.org/~paxl/dmesg.txt if somone mind.
> >
> >
> > Another fuzzy thing .. compiling my kernel normaly ( -j 1 ) take 30min
> > and when I make it with -j 2/8/16 it take 25min, I think this is due to
> > my L2 cache problem but that not normal, if somone have an idea.. I
> > should be realy interested.
> 
> sounds like you've got your l2 turned off in the bios to me.

There is no option in my bios to enable or disable L2 cache..
And at boot I get this

DSP Microcode OK ...... L2 512KB OK
AS#1 Microcode OK ...... L2 512KB OK

So I assume that the bios enable it, do there is a way to Force the kernel to use it even if he can't detect it ??

Thank you for your time and answer :)
Xavier LaRue

^ permalink raw reply

* Re: "iptables: Invalid argument" with kernel 2.4.20
From: Joel Newkirk @ 2002-12-16 19:35 UTC (permalink / raw)
  To: cees-bart, netfilter
In-Reply-To: <Pine.LNX.4.44.0212161717490.11632-100000@flex.cs.kun.nl>

On Monday 16 December 2002 11:25 am, cees-bart wrote:
> hi all,

> -A OUTPUT -d MYMACHINE -p udp -m udp --dport 27960 -j DNAT \
>                            --to-destination OTHERMACHINE:30000

> this setup works fine on kernel 2.4.19 with iptables 1.2.6a.
>
> BUT, the last rule (OUTPUT) fails with message "iptables: Invalid
> argument" when running under 2.4.20.
>
> i tried iptables 1.2.7a as well, but the result is the same.
>
> am i doing something wrong?

Have you tried manually creating the rule, or are you restoring from a 
save made with the earlier version?  Since you list it in a save format, 
(dated November 12) and said it won't load, this strikes me as likely.  
I don't know, but it's possible this won't work.  Just try a:

/sbin/iptables -t nat -A OUTPUT -d MYMACHING -p udp --dport 27960 \
	-j DNAT --to OTHERMACHINE:30000

and see if it accepts it.  If so, then there must have been some change 
in the save file structure or handling (possibly fixing a flaw) that 
prevents newer netfilter form restoring from the older save.

If you require the ability to use the same save under both versions, it's 
possible that saving from the new will be restorable in the old, even if 
the reverse turns out to be broken.

j


^ permalink raw reply

* Re: aic7xxx woes in 2.5
From: Justin T. Gibbs @ 2002-12-16 19:26 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-scsi
In-Reply-To: <3DFE24BE.A8E3755F@digeo.com>

>> Since you are running 2.5.X, the ahc_unlock never occurs.
>> In 2.4.X, ahd_midlayer_entrypoint_lock() saves the cpu flags
>> for us, so the variable is never uninitialized in the case
>> where it actually is compiled in.
> 
> In 2.5.52 uniprocessor a
> 
> 	make drivers/scsi/aic7xxx/aic7xxx_linux.i
> 
> gives:
> 
> static __inline void
> ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
> {
>         do { do { (void)(  &ahc->platform_data->spin_lock  ); } while(0)
> ; __asm__ __volatile__("pushl %0 ; popfl":   :"g" (   *flags  ):"memory",
> "cc") ; do { } while (0) ; } while (0) ; }
> 
> Which is loading *flags into the CPU's interrupt status register.

Since I wrote the routine, I'm well aware of how it operates.

> And it is being called from ahc_linux_queue_recovery_cmd:
> 
>         if (wait) {
>                 struct timer_list timer;
>                 int ret;
> 
>                 ahc_unlock(ahc, &s);
>                 init_timer(&timer);

You must have botched the integration of the latest driver from here:
http://people.FreeBSD.org/~gibbs/linux/SRC.

I just downloaded it again (both the archive from the 10th and the 13th)
and neither use ahc_unlock under 2.5.X in ahc_linux_queue_recovery_cmd().
What are the $Id$ strings at the top of the file?

--
Justin

^ permalink raw reply

* Re: system hangs after reboot
From: Arno Seitzinger @ 2002-12-16 19:25 UTC (permalink / raw)
  To: linux-newbie
In-Reply-To: <1040055299.2905.19.camel@zebra.vil.ite.mee.com>

Hi Ray and Paul,
thanks for your interest.

I investigated a little bit deeper, but am stil clueless:

_changed 20:20 CET: no more clueless._ A couple of days ago I removed the 
PCMCIA CAN-Card which was innocently sitting in my cardslot for months. 
Maybe it received a different configuration when I re-inserted it. After 
removal of the CAN-Card, the system reboots as usual. Thank you for your 
assistance.


> 1. If you change /etc/init.tab so that the system boots into run level
> 3, then reboot, do you get any errors?

Errors (errormessages), no, but the system hangs like before.


> 3. It sounds like you have a network thing going on. If you wait long
> enough, it might start anyway. sendmail often does this when your host
> table doesn't agree with your IP address. Other programs also have this
> problem. Therefore, check that you have an "/etc/hosts" file and that it
> is correct and complete (at least as far as info about the problem
> machine goes).

I also think it is a network problem because if I boot into a runlevel w/o 
network, the system does not freeze. It also does not freeze when I remove 
the network card from the configuration.
My /etc/hosts is
127.0.0.1       localhost
::1             localhost ipv6-localhost ipv6-loopback
fe00::0         ipv6-localnet
ff00::0         ipv6-mcastprefix
ff02::1         ipv6-allnodes
ff02::2         ipv6-allrouters
ff02::3         ipv6-allhosts
127.0.0.2       esw44.mdom1     esw44
and was set up automatically by yast-setuptool

When the freeze occurs, the cursor stops blinking, the animated ball on the 
boot screen stops jumping and the system won't react to anything (ctrl-c, 
ctrl-alt-del etc), only power-off and display brightness. A cold boot 
always works, and it also boots up correctly when I do a warm reboot 
(shutdown -r now) but switch off the power the moment the bios screen 
appears.


>> 1. In the "good init" sequence, what happens next? You're asking us to
>> compare a bad init to nothing (as regards the part that is bad).

In the "bad init" sequence, the file ends after 
<notice>/etc/init.d/rc5.d/S05network start

In the "good init" sequence, I cut the rest of the file after the 
configuration of eth0. ppp0 is started next (manual dialup w/ cellphone).
After that, hotplugging services are started.


>> 2. When you say the system "hangs" and "freezes", how carefully have you
>> assessed that? How long have you waited before giving up? What happens if
>> you CRTL-C when the system is "hung"?

I waited for about 15 minutes. ctrl-c does not do anything... but it doesn't 
do anything elsewhere in the bootup process anyhow...
I will let the machine sit overnight trying to boot, but I dont think it 
will bring us further. Is there a possibility to redirect

>> 3. What is eth0 and how does it connect to the Internet? If the problem
>> is associated with a DHCP failure of some type, the details of the
>> interface it is using may matter.

eth0 is the only ethernet port on that machine (builtin Accton EN1216 card).
The problem is not associated with a DHCP failure because the freeze also 
occurs when the machine is assigned a fixed IP-address


>> 4. Is the problem only associated with a soft ("shutdown -r") reboot? If
>> you do a power-down reboot, does the system boot and init properly?

2*Yes


Greets and thanks

Arno





-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs



-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply

* [PATCH] The alternate Posix timers patch8
From: Jim Houston @ 2002-12-16 19:31 UTC (permalink / raw)
  To: torvalds, linux-kernel, george, high-res-timers-discourse


Hi Everyone,

This is the 8th version of my spin on the Posix timers.  This patch
works with linux-2.5.51.  

This version fixes problems found using the Open Posix test suite
(http://posixtest.sourceforge.net/).  In particular, I fixed problems
with overruns and interactions between pending timers and
setting the time.  Thanks Julie and everyone else involved in 
writing these tests.

This patch is based on George Anzinger's Posix timers patch.  My
kernel work still relies on his user library and test code.  Please
see his page here:
	http://sourceforge.net/projects/high-res-timers

Here is a summary of my changes:

     -	I keep the timers in seconds and nano-seconds.  The mechanism
	to expire the timers will work either with a periodic interrupt
	or a programable timer.  This patch provides high resolution
	by sharing the local APIC timer.

     -	Changes to the arch/i386/kernel/timers code to use nanoseconds
	consistently.  I added do_[get/set]timeofday_ns() to get/set time
	in nanoseconds.  I also added a monotonic time since boot clock
	do_gettime_sinceboot_ns().

     -	The posix timers are queued in their own queue.  This avoids
	interactions with the jiffie based timers.
	I implemented this priority queue as a sorted list with a rbtree
	to index the list.  It is deterministic and fast.  
	I want my posix timers to have low jitter so I will expire them
	directly from the interrupt.  Having a separate queue gives
	me this flexibilty.
	
     -	A new id allocator/lookup mechanism based on a radix tree.  It
	includes  a bitmap to summarize the portion of the tree which is
	in use.  (George picked this up from me.)  My version doesn't
	immediately re-use the id when it is freed.  This is intended
	to catch application errors e.g. continuing to use a timer
	after it is destroyed.

     -	Code to limit the rate at which timers expire.  Without this, an
	errant program could swamp the system with interrupts.  I added
	a sysctl interface to adjust the parameters which control this.
	It includes the resolution for posix timers and nanosleep
	and three values which set a duty cycle for timer expiry.
	It limits the number of timers expired from a single interrupt.
	If the system hits this limit, it waits a recovery time before
	expiring more timers.

     - 	Uses the new ERESTART_RESTARTBLOCK interface to restart 
	nanosleep and clock_nanosleep calls which are interrupted
	but not delivered (e.g. debug signals).

	Actually I use clock_nanosleep to implement nanosleep.  This
	lets me play with the resolution which nanosleep supports.

      -	Andrea Arcangeli convinced me that the remaining time for
	an interrupted nanosleep has to be precise not rounded to the
	nearest clock tick.  This is fixed and the ltp nanosleep02 test
	passes.

Since I rely on the standard time, I have been seeing the existing
problems with time keeping (bugzilla.kernel.org bug #100 and #105).
I find that switching HZ back to 100 helps.

Jim Houston - Concurrent Computer Corp.

diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/apic.c linux-2.5.51.timers/arch/i386/kernel/apic.c
--- linux-2.5.51.orig/arch/i386/kernel/apic.c	Thu Dec 12 16:10:38 2002
+++ linux-2.5.51.timers/arch/i386/kernel/apic.c	Tue Dec 10 14:50:16 2002
@@ -32,6 +32,7 @@
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include "mach_apic.h"
+#include <asm/div64.h>
 
 void __init apic_intr_init(void)
 {
@@ -807,7 +808,7 @@
 	unsigned int lvtt1_value, tmp_value;
 
 	lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
-			APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
+			LOCAL_TIMER_VECTOR;
 	apic_write_around(APIC_LVTT, lvtt1_value);
 
 	/*
@@ -916,6 +917,31 @@
 
 static unsigned int calibration_result;
 
+/*
+ * Set the APIC timer for a one shot expiry in nanoseconds.
+ * This is called from the posix-timers code.
+ */
+int ns2clock;
+void set_APIC_timer(int ns)
+{
+	long long tmp;
+	int clocks;
+	unsigned int  tmp_value;
+
+	if (!ns2clock) {
+		tmp = (calibration_result * HZ);
+		tmp = tmp << 32;
+		do_div(tmp, 1000000000);
+		ns2clock = (int)tmp;
+		clocks = ((long long)ns2clock * ns) >> 32;
+	}
+	clocks = ((long long)ns2clock * ns) >> 32;
+	tmp_value = apic_read(APIC_TMCCT);
+	if (!tmp_value || clocks/APIC_DIVISOR < tmp_value)
+		apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
+}
+
+
 int dont_use_local_apic_timer __initdata = 0;
 
 void __init setup_boot_APIC_clock(void)
@@ -1005,9 +1031,17 @@
  * value into /proc/profile.
  */
 
+long get_eip(void *regs)
+{
+	return(((struct pt_regs *)regs)->eip);
+}
+
 inline void smp_local_timer_interrupt(struct pt_regs * regs)
 {
 	int cpu = smp_processor_id();
+
+	if (!run_posix_timers((void *)regs)) 
+		return;
 
 	x86_do_profile(regs);
 
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/entry.S linux-2.5.51.timers/arch/i386/kernel/entry.S
--- linux-2.5.51.orig/arch/i386/kernel/entry.S	Thu Dec 12 16:11:44 2002
+++ linux-2.5.51.timers/arch/i386/kernel/entry.S	Tue Dec 10 14:50:16 2002
@@ -743,6 +743,15 @@
 	.long sys_epoll_wait
  	.long sys_remap_file_pages
  	.long sys_set_tid_address
+ 	.long sys_timer_create
+	.long sys_timer_settime	/* 260 */
+	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime	/* 265 */
+ 	.long sys_clock_getres
+	.long sys_clock_nanosleep
 
 
 	.rept NR_syscalls-(.-sys_call_table)/4
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/smpboot.c linux-2.5.51.timers/arch/i386/kernel/smpboot.c
--- linux-2.5.51.orig/arch/i386/kernel/smpboot.c	Thu Dec 12 16:11:30 2002
+++ linux-2.5.51.timers/arch/i386/kernel/smpboot.c	Tue Dec 10 14:50:16 2002
@@ -181,8 +181,6 @@
 
 #define NR_LOOPS 5
 
-extern unsigned long fast_gettimeoffset_quotient;
-
 /*
  * accurate 64-bit/32-bit division, expanded to 32-bit divisions and 64-bit
  * multiplication. Not terribly optimized but we need it at boot time only
@@ -222,7 +220,7 @@
 
 	printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus());
 
-	one_usec = ((1<<30)/fast_gettimeoffset_quotient)*(1<<2);
+	one_usec = cpu_khz/1000;
 
 	atomic_set(&tsc_start_flag, 1);
 	wmb();
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/time.c linux-2.5.51.timers/arch/i386/kernel/time.c
--- linux-2.5.51.orig/arch/i386/kernel/time.c	Thu Dec 12 16:11:22 2002
+++ linux-2.5.51.timers/arch/i386/kernel/time.c	Tue Dec 10 14:50:16 2002
@@ -83,33 +83,70 @@
  * This version of gettimeofday has microsecond resolution
  * and better than microsecond precision on fast x86 machines with TSC.
  */
-void do_gettimeofday(struct timeval *tv)
+
+void do_gettime_offset(struct timespec *tv)
+{
+	unsigned long lost = jiffies - wall_jiffies;
+
+	tv->tv_sec = 0;
+	tv->tv_nsec = timer->get_offset();
+	if (lost)
+		tv->tv_nsec += lost * (1000000000 / HZ);
+	while (tv->tv_nsec >= 1000000000) {
+		tv->tv_nsec -= 1000000000;
+		tv->tv_sec++;
+	}
+}
+void do_gettimeofday_ns(struct timespec *tv)
 {
 	unsigned long flags;
-	unsigned long usec, sec;
+	struct timespec ts;
 
 	read_lock_irqsave(&xtime_lock, flags);
-	usec = timer->get_offset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += (xtime.tv_nsec / 1000);
+	do_gettime_offset(&ts);
+	ts.tv_sec += xtime.tv_sec;
+	ts.tv_nsec += xtime.tv_nsec;
 	read_unlock_irqrestore(&xtime_lock, flags);
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
+	if (ts.tv_nsec >= 1000000000) {
+		ts.tv_nsec -= 1000000000;
+		ts.tv_sec += 1;
 	}
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_nsec = ts.tv_nsec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	struct timespec ts;
 
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
+	do_gettimeofday_ns(&ts);
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec/1000;
 }
 
-void do_settimeofday(struct timeval *tv)
+
+void do_gettime_sinceboot_ns(struct timespec *tv)
+{
+	unsigned long flags;
+	struct timespec ts;
+
+	read_lock_irqsave(&xtime_lock, flags);
+	do_gettime_offset(&ts);
+	ts.tv_sec += ytime.tv_sec;
+	ts.tv_nsec +=ytime.tv_nsec;
+	read_unlock_irqrestore(&xtime_lock, flags);
+	if (ts.tv_nsec >= 1000000000) {
+		ts.tv_nsec -= 1000000000;
+		ts.tv_sec += 1;
+	}
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_nsec = ts.tv_nsec;
+}
+
+void do_settimeofday_ns(struct timespec *tv)
 {
+	struct timespec ts;
+
 	write_lock_irq(&xtime_lock);
 	/*
 	 * This is revolting. We need to set "xtime" correctly. However, the
@@ -117,16 +154,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_usec -= timer->get_offset();
-	tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
-
-	while (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
+	do_gettime_offset(&ts);
+	tv->tv_nsec -= ts.tv_nsec;
+	tv->tv_sec -= ts.tv_sec;
+	while (tv->tv_nsec < 0) {
+		tv->tv_nsec += 1000000000;
 		tv->tv_sec--;
 	}
-
 	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = (tv->tv_usec * 1000);
+	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -134,6 +170,15 @@
 	write_unlock_irq(&xtime_lock);
 }
 
+void do_settimeofday(struct timeval *tv)
+{
+	struct timespec ts;
+	ts.tv_sec = tv->tv_sec;
+	ts.tv_nsec = tv->tv_usec * 1000;
+
+	do_settimeofday_ns(&ts);
+}
+
 /*
  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
  * called 500 ms after the second nowtime has started, because when
@@ -351,6 +396,8 @@
 	
 	xtime.tv_sec = get_cmos_time();
 	xtime.tv_nsec = 0;
+	ytime.tv_sec = 0;
+	ytime.tv_nsec = 0;
 
 
 	timer = select_timer();
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/timers/timer_cyclone.c linux-2.5.51.timers/arch/i386/kernel/timers/timer_cyclone.c
--- linux-2.5.51.orig/arch/i386/kernel/timers/timer_cyclone.c	Thu Dec 12 16:10:34 2002
+++ linux-2.5.51.timers/arch/i386/kernel/timers/timer_cyclone.c	Tue Dec 10 14:50:16 2002
@@ -47,7 +47,7 @@
 	count |= inb(0x40) << 8;
 	spin_unlock(&i8253_lock);
 
-	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = ((LATCH-1) - count) * tick_nsec;
 	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
 }
 
@@ -64,11 +64,11 @@
 	/* .. relative to previous jiffy */
 	offset = offset - last_cyclone_timer;
 
-	/* convert cyclone ticks to microseconds */	
+	/* convert cyclone ticks to nanoseconds */	
 	/* XXX slow, can we speed this up? */
-	offset = offset/(CYCLONE_TIMER_FREQ/1000000);
+	offset = offset*(1000000000/CYCLONE_TIMER_FREQ);
 
-	/* our adjusted time offset in microseconds */
+	/* our adjusted time offset in nanoseconds */
 	return delay_at_last_interrupt + offset;
 }
 
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/timers/timer_pit.c linux-2.5.51.timers/arch/i386/kernel/timers/timer_pit.c
--- linux-2.5.51.orig/arch/i386/kernel/timers/timer_pit.c	Thu Dec 12 16:11:10 2002
+++ linux-2.5.51.timers/arch/i386/kernel/timers/timer_pit.c	Tue Dec 10 14:50:16 2002
@@ -115,7 +115,7 @@
 
 	count_p = count;
 
-	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = ((LATCH-1) - count) * tick_nsec;
 	count = (count + LATCH/2) / LATCH;
 
 	return count;
diff -X dontdiff -urN linux-2.5.51.orig/arch/i386/kernel/timers/timer_tsc.c linux-2.5.51.timers/arch/i386/kernel/timers/timer_tsc.c
--- linux-2.5.51.orig/arch/i386/kernel/timers/timer_tsc.c	Thu Dec 12 16:11:27 2002
+++ linux-2.5.51.timers/arch/i386/kernel/timers/timer_tsc.c	Tue Dec 10 14:50:16 2002
@@ -16,14 +16,14 @@
 extern spinlock_t i8253_lock;
 
 static int use_tsc;
-/* Number of usecs that the last interrupt was delayed */
+/* Number of nsecs that the last interrupt was delayed */
 static int delay_at_last_interrupt;
 
 static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
 
-/* Cached *multiplier* to convert TSC counts to microseconds.
+/* Cached *multiplier* to convert TSC counts to nanoseconds.
  * (see the equation below).
- * Equal to 2^32 * (1 / (clocks per usec) ).
+ * Equal to 2^22 * (1 / (clocks per nsec) ).
  * Initialized in time_init.
  */
 unsigned long fast_gettimeoffset_quotient;
@@ -41,19 +41,14 @@
 
 	/*
          * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
-         *             = (tsc_low delta) * (usecs_per_clock)
-         *             = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
 	 *
 	 * Using a mull instead of a divl saves up to 31 clock cycles
 	 * in the critical path.
          */
 
-	__asm__("mull %2"
-		:"=a" (eax), "=d" (edx)
-		:"rm" (fast_gettimeoffset_quotient),
-		 "0" (eax));
+	edx = ((long long)fast_gettimeoffset_quotient*eax) >> 22;
 
-	/* our adjusted time offset in microseconds */
+	/* our adjusted time offset in nanoseconds */
 	return delay_at_last_interrupt + edx;
 }
 
@@ -99,13 +94,13 @@
 		}
 	}
 
-	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = ((LATCH-1) - count) * tick_nsec;
 	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
 }
 
 
 /* ------ Calibrate the TSC ------- 
- * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Return 2^22 * (1 / (TSC clocks per nsec)) for do_fast_gettimeoffset().
  * Too much 64-bit arithmetic here to do this cleanly in C, and for
  * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
  * output busy loop as low as possible. We avoid reading the CTC registers
@@ -113,8 +108,13 @@
  * device.
  */
 
-#define CALIBRATE_LATCH	(5 * LATCH)
-#define CALIBRATE_TIME	(5 * 1000020/HZ)
+/*
+ * Pick the largest possible latch value (its a 16 bit counter)
+ * and calculate the corresponding time.
+ */
+#define CALIBRATE_LATCH	(0xffff)
+#define CALIBRATE_TIME	((int)((1000000000LL*CALIBRATE_LATCH + \
+			CLOCK_TICK_RATE/2) / CLOCK_TICK_RATE))
 
 static unsigned long __init calibrate_tsc(void)
 {
@@ -164,12 +164,14 @@
 			goto bad_ctc;
 
 		/* Error: ECPUTOOSLOW */
-		if (endlow <= CALIBRATE_TIME)
+		if (endlow <= (CALIBRATE_TIME>>10))
 			goto bad_ctc;
 
 		__asm__("divl %2"
 			:"=a" (endlow), "=d" (endhigh)
-			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
+			:"r" (endlow),
+			"0" (CALIBRATE_TIME<<22),
+			"1" (CALIBRATE_TIME>>10));
 
 		return endlow;
 	}
@@ -179,6 +181,7 @@
 	 * or the CPU was so fast/slow that the quotient wouldn't fit in
 	 * 32 bits..
 	 */
+
 bad_ctc:
 	return 0;
 }
@@ -268,11 +271,14 @@
 			x86_udelay_tsc = 1;
 
 			/* report CPU clock rate in Hz.
-			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
+			 * The formula is 
+			 *    (10^6 * 2^22) / (2^22 * 1 / (clocks/ns)) =
 			 * clock/second. Our precision is about 100 ppm.
 			 */
-			{	unsigned long eax=0, edx=1000;
-				__asm__("divl %2"
+			{	unsigned long eax, edx;
+				eax = (long)(1000000LL<<22);
+				edx = (long)(1000000LL>>10);
+				__asm__("divl %2;"
 		       		:"=a" (cpu_khz), "=d" (edx)
         	       		:"r" (tsc_quotient),
 	                	"0" (eax), "1" (edx));
@@ -281,6 +287,7 @@
 #ifdef CONFIG_CPU_FREQ
 			cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
 #endif
+			mark_offset_tsc();
 			return 0;
 		}
 	}
diff -X dontdiff -urN linux-2.5.51.orig/fs/exec.c linux-2.5.51.timers/fs/exec.c
--- linux-2.5.51.orig/fs/exec.c	Thu Dec 12 16:11:46 2002
+++ linux-2.5.51.timers/fs/exec.c	Tue Dec 10 14:50:16 2002
@@ -779,6 +779,7 @@
 			
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
+	exit_itimers(current, 0);
 
 	return 0;
 
diff -X dontdiff -urN linux-2.5.51.orig/include/asm-generic/siginfo.h linux-2.5.51.timers/include/asm-generic/siginfo.h
--- linux-2.5.51.orig/include/asm-generic/siginfo.h	Thu Dec 12 16:10:42 2002
+++ linux-2.5.51.timers/include/asm-generic/siginfo.h	Tue Dec 10 14:50:16 2002
@@ -43,8 +43,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -86,8 +87,8 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
-#define si_timer1	_sifields._timer._timer1
-#define si_timer2	_sifields._timer._timer2
+#define si_tid		_sifields._timer._tid
+#define si_overrun	_sifields._timer._overrun
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -221,6 +222,7 @@
 #define SIGEV_SIGNAL	0	/* notify via signal */
 #define SIGEV_NONE	1	/* other notification: meaningless */
 #define SIGEV_THREAD	2	/* deliver via thread creation */
+#define SIGEV_THREAD_ID 4	/* deliver to thread */
 
 #define SIGEV_MAX_SIZE	64
 #ifndef SIGEV_PAD_SIZE
@@ -235,6 +237,7 @@
 	int sigev_notify;
 	union {
 		int _pad[SIGEV_PAD_SIZE];
+		 int _tid;
 
 		struct {
 			void (*_function)(sigval_t);
@@ -247,6 +250,7 @@
 
 #define sigev_notify_function	_sigev_un._sigev_thread._function
 #define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+#define sigev_notify_thread_id	 _sigev_un._tid
 
 #ifdef __KERNEL__
 
diff -X dontdiff -urN linux-2.5.51.orig/include/asm-i386/posix_types.h linux-2.5.51.timers/include/asm-i386/posix_types.h
--- linux-2.5.51.orig/include/asm-i386/posix_types.h	Tue Jan 18 01:22:52 2000
+++ linux-2.5.51.timers/include/asm-i386/posix_types.h	Tue Dec 10 14:50:16 2002
@@ -22,6 +22,8 @@
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned short	__kernel_uid16_t;
diff -X dontdiff -urN linux-2.5.51.orig/include/asm-i386/unistd.h linux-2.5.51.timers/include/asm-i386/unistd.h
--- linux-2.5.51.orig/include/asm-i386/unistd.h	Thu Dec 12 16:11:46 2002
+++ linux-2.5.51.timers/include/asm-i386/unistd.h	Tue Dec 10 14:50:16 2002
@@ -264,6 +264,15 @@
 #define __NR_epoll_wait		256
 #define __NR_remap_file_pages	257
 #define __NR_set_tid_address	258
+#define __NR_timer_create	259
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	(__NR_timer_create+5)
+#define __NR_clock_gettime	(__NR_timer_create+6)
+#define __NR_clock_getres	(__NR_timer_create+7)
+#define __NR_clock_nanosleep	(__NR_timer_create+8)
 
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/id2ptr.h linux-2.5.51.timers/include/linux/id2ptr.h
--- linux-2.5.51.orig/include/linux/id2ptr.h	Wed Dec 31 19:00:00 1969
+++ linux-2.5.51.timers/include/linux/id2ptr.h	Tue Dec 10 14:50:16 2002
@@ -0,0 +1,47 @@
+/*
+ * include/linux/id2ptr.h
+ * 
+ * 2002-10-18  written by Jim Houston jim.houston@ccur.com
+ *	Copyright (C) 2002 by Concurrent Computer Corporation
+ *	Distributed under the GNU GPL license version 2.
+ *
+ * Small id to pointer translation service avoiding fixed sized
+ * tables.
+ */
+
+#define ID_BITS 5
+#define ID_MASK ((1 << ID_BITS)-1)
+#define ID_FULL ((1 << (1 << ID_BITS))-1)
+
+/* Number of id_layer structs to leave in free list */
+#define ID_FREE_MAX 6
+
+struct id_layer {
+	unsigned int	bitmap;
+	struct id_layer	*ary[1<<ID_BITS];
+};
+
+struct id {
+	int		layers;
+	int		last;
+	int		count;
+	int		min_wrap;
+	struct id_layer *top;
+};
+
+void *id2ptr_lookup(struct id *idp, int id);
+int id2ptr_new(struct id *idp, void *ptr);
+void id2ptr_remove(struct id *idp, int id);
+void id2ptr_init(struct id *idp, int min_wrap);
+
+
+static inline void update_bitmap(struct id_layer *p, int bit)
+{
+	if (p->ary[bit] && p->ary[bit]->bitmap == 0xffffffff)
+		p->bitmap |= 1<<bit;
+	else
+		p->bitmap &= ~(1<<bit);
+}
+
+extern kmem_cache_t *id_layer_cache;
+
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/init_task.h linux-2.5.51.timers/include/linux/init_task.h
--- linux-2.5.51.orig/include/linux/init_task.h	Thu Dec 12 16:10:22 2002
+++ linux-2.5.51.timers/include/linux/init_task.h	Mon Dec 16 13:09:01 2002
@@ -93,6 +93,10 @@
 	.sig		= &init_signals,				\
 	.pending	= { NULL, &tsk.pending.head, {{0}}},		\
 	.blocked	= {{0}},					\
+	.posix_timers	= LIST_HEAD_INIT(tsk.posix_timers),		\
+	.nanosleep_tmr.it_v.it_interval.tv_sec = 0,			\
+	.nanosleep_tmr.it_v.it_interval.tv_nsec = 0,			\
+	.nanosleep_tmr.it_process = &tsk,				\
 	.alloc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/posix-timers.h linux-2.5.51.timers/include/linux/posix-timers.h
--- linux-2.5.51.orig/include/linux/posix-timers.h	Wed Dec 31 19:00:00 1969
+++ linux-2.5.51.timers/include/linux/posix-timers.h	Mon Dec 16 13:10:02 2002
@@ -0,0 +1,62 @@
+/*
+ * include/linux/posix-timers.h
+ * 
+ * 2002-10-22  written by Jim Houston jim.houston@ccur.com
+ *	Copyright (C) 2002 by Concurrent Computer Corporation
+ *	Distributed under the GNU GPL license version 2.
+ *
+ */
+
+#ifndef _linux_POSIX_TIMERS_H
+#define _linux_POSIX_TIMERS_H
+
+/* This should be in posix-timers.h - but this is easier now. */
+
+enum timer_type {
+	TIMER,
+	TICK,
+	NANOSLEEP,
+	NANOSLEEP_RESTART
+};
+
+struct k_itimer {
+	struct list_head	it_pq_list;	/* fields for timer priority queue. */
+	struct rb_node		it_pq_node;	
+	struct timer_pq		*it_pq;		/* pointer to the queue. */
+
+	struct list_head it_task_list;	/* list for exit_itimers */
+	spinlock_t it_lock;
+	clockid_t it_clock;		/* which timer type */
+	int	it_flags;		/* absolute time? */
+	timer_t it_id;			/* timer id */
+	int it_overrun;			/* overrun on pending signal  */
+	int it_overrun_last;		 /* overrun on last delivered signal */
+	int it_overrun_deferred;	 /* overrun on pending timer interrupt */
+	int it_sigev_notify;		 /* notify word of sigevent struct */
+	int it_sigev_signo;		 /* signo word of sigevent struct */
+	sigval_t it_sigev_value;	 /* value word of sigevent struct */
+	struct task_struct *it_process;	/* process to send signal to */
+	struct itimerspec it_v;		/* expiry time & interval */
+	enum timer_type it_type;
+};
+
+/*
+ * The priority queue is a sorted doubly linked list ordered by
+ * expiry time.  A rbtree is used as an index in to this list
+ * so that inserts are O(log2(n)).
+ */
+
+struct timer_pq {
+	struct list_head	head;
+	struct rb_root		rb_root;
+	spinlock_t		*lock;
+};
+
+#define TIMER_PQ_INIT(name)	{ \
+	.rb_root = RB_ROOT, \
+	.head = LIST_HEAD_INIT(name.head), \
+}
+
+asmlinkage int sys_timer_delete(timer_t timer_id);
+
+#endif
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/sched.h linux-2.5.51.timers/include/linux/sched.h
--- linux-2.5.51.orig/include/linux/sched.h	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/include/linux/sched.h	Mon Dec 16 13:07:26 2002
@@ -27,6 +27,7 @@
 #include <linux/compiler.h>
 #include <linux/completion.h>
 #include <linux/pid.h>
+#include <linux/posix-timers.h>
 
 struct exec_domain;
 
@@ -339,6 +340,9 @@
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 	struct timer_list real_timer;
+	struct list_head posix_timers; /* POSIX.1b Interval Timers */
+	struct k_itimer nanosleep_tmr;
+	struct timespec nanosleep_ts;	/* un-rounded completion time */
 	unsigned long utime, stime, cutime, cstime;
 	unsigned long start_time;
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
@@ -577,6 +581,7 @@
 
 extern void exit_mm(struct task_struct *);
 extern void exit_files(struct task_struct *);
+extern void exit_itimers(struct task_struct *, int);
 extern void exit_sighand(struct task_struct *);
 extern void __exit_sighand(struct task_struct *);
 
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/sys.h linux-2.5.51.timers/include/linux/sys.h
--- linux-2.5.51.orig/include/linux/sys.h	Thu Dec 12 16:11:03 2002
+++ linux-2.5.51.timers/include/linux/sys.h	Tue Dec 10 14:50:16 2002
@@ -4,7 +4,7 @@
 /*
  * system call entry points ... but not all are defined
  */
-#define NR_syscalls 260
+#define NR_syscalls 275
 
 /*
  * These are system calls that will be removed at some time
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/sysctl.h linux-2.5.51.timers/include/linux/sysctl.h
--- linux-2.5.51.orig/include/linux/sysctl.h	Thu Dec 12 16:11:25 2002
+++ linux-2.5.51.timers/include/linux/sysctl.h	Tue Dec 10 14:50:16 2002
@@ -129,6 +129,7 @@
 	KERN_CADPID=54,		/* int: PID of the process to notify on CAD */
 	KERN_PIDMAX=55,		/* int: PID # limit */
   	KERN_CORE_PATTERN=56,	/* string: pattern for core-file names */
+  	KERN_POSIX_TIMERS=57,	/* posix timer parameters */
 };
 
 
@@ -188,6 +189,16 @@
 	RANDOM_WRITE_THRESH=4,
 	RANDOM_BOOT_ID=5,
 	RANDOM_UUID=6
+};
+
+/* /proc/sys/kernel/posix-timers */
+enum
+{
+	POSIX_TIMERS_RESOLUTION=1,
+	POSIX_TIMERS_NANOSLEEP_RES=2,
+	POSIX_TIMERS_MAX_EXPIRIES=3,
+	POSIX_TIMERS_RECOVERY_TIME=4,
+	POSIX_TIMERS_MIN_DELAY=5
 };
 
 /* /proc/sys/bus/isa */
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/time.h linux-2.5.51.timers/include/linux/time.h
--- linux-2.5.51.orig/include/linux/time.h	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/include/linux/time.h	Tue Dec 10 14:50:16 2002
@@ -40,6 +40,19 @@
  */
 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
 
+/* Parameters used to convert the timespec values */
+#ifndef USEC_PER_SEC
+#define USEC_PER_SEC (1000000L)
+#endif
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC (1000000000L)
+#endif
+
+#ifndef NSEC_PER_USEC
+#define NSEC_PER_USEC (1000L)
+#endif
+
 static __inline__ unsigned long
 timespec_to_jiffies(struct timespec *value)
 {
@@ -119,7 +132,8 @@
 	)*60 + sec; /* finally seconds */
 }
 
-extern struct timespec xtime;
+extern struct timespec xtime;	/* time of day */
+extern struct timespec ytime;	/* time since boot */
 extern rwlock_t xtime_lock;
 
 static inline unsigned long get_seconds(void)
@@ -137,9 +151,15 @@
 
 #ifdef __KERNEL__
 extern void do_gettimeofday(struct timeval *tv);
+extern void do_gettimeofday_ns(struct timespec *tv);
 extern void do_settimeofday(struct timeval *tv);
+extern void do_settimeofday_ns(struct timespec *tv);
+extern void do_gettime_sinceboot_ns(struct timespec *tv);
 extern long do_nanosleep(struct timespec *t);
 extern long do_utimes(char * filename, struct timeval * times);
+#if 0
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+#endif
 #endif
 
 #define FD_SETSIZE		__FD_SETSIZE
@@ -165,5 +185,25 @@
 	struct	timeval it_interval;	/* timer interval */
 	struct	timeval it_value;	/* current value */
 };
+
+
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers).
+ */
+#define CLOCK_REALTIME		  0
+#define CLOCK_MONOTONIC	  1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID	 3
+#define CLOCK_REALTIME_HR	 4
+#define CLOCK_MONOTONIC_HR	  5
+
+#define MAX_CLOCKS 6
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+
 
 #endif
diff -X dontdiff -urN linux-2.5.51.orig/include/linux/types.h linux-2.5.51.timers/include/linux/types.h
--- linux-2.5.51.orig/include/linux/types.h	Thu Dec 12 16:10:36 2002
+++ linux-2.5.51.timers/include/linux/types.h	Tue Dec 10 14:50:16 2002
@@ -23,6 +23,8 @@
 typedef __kernel_daddr_t	daddr_t;
 typedef __kernel_key_t		key_t;
 typedef __kernel_suseconds_t	suseconds_t;
+typedef __kernel_timer_t	timer_t;
+typedef __kernel_clockid_t	clockid_t;
 
 #ifdef __KERNEL__
 typedef __kernel_uid32_t	uid_t;
diff -X dontdiff -urN linux-2.5.51.orig/kernel/Makefile linux-2.5.51.timers/kernel/Makefile
--- linux-2.5.51.orig/kernel/Makefile	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/kernel/Makefile	Tue Dec 10 14:50:16 2002
@@ -10,7 +10,7 @@
 	    exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \
-	    rcupdate.o intermodule.o extable.o
+	    rcupdate.o intermodule.o extable.o posix-timers.o id2ptr.o
 
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o
diff -X dontdiff -urN linux-2.5.51.orig/kernel/exit.c linux-2.5.51.timers/kernel/exit.c
--- linux-2.5.51.orig/kernel/exit.c	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/kernel/exit.c	Tue Dec 10 14:50:16 2002
@@ -659,6 +659,7 @@
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	exit_namespace(tsk);
+	exit_itimers(tsk, 1);
 	exit_thread();
 
 	if (current->leader)
diff -X dontdiff -urN linux-2.5.51.orig/kernel/fork.c linux-2.5.51.timers/kernel/fork.c
--- linux-2.5.51.orig/kernel/fork.c	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/kernel/fork.c	Mon Dec 16 13:05:03 2002
@@ -810,6 +810,12 @@
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
 		goto bad_fork_cleanup_fs;
+	INIT_LIST_HEAD(&p->posix_timers);
+	p->nanosleep_tmr.it_v.it_interval.tv_sec = 0;
+	p->nanosleep_tmr.it_v.it_interval.tv_nsec = 0;
+	p->nanosleep_tmr.it_process = p;
+	p->nanosleep_tmr.it_type = NANOSLEEP;
+	p->nanosleep_tmr.it_pq = 0;
 	if (copy_mm(clone_flags, p))
 		goto bad_fork_cleanup_sighand;
 	if (copy_namespace(clone_flags, p))
diff -X dontdiff -urN linux-2.5.51.orig/kernel/id2ptr.c linux-2.5.51.timers/kernel/id2ptr.c
--- linux-2.5.51.orig/kernel/id2ptr.c	Wed Dec 31 19:00:00 1969
+++ linux-2.5.51.timers/kernel/id2ptr.c	Tue Dec 10 14:50:16 2002
@@ -0,0 +1,225 @@
+/*
+ * linux/kernel/id2ptr.c
+ *
+ * 2002-10-18  written by Jim Houston jim.houston@ccur.com
+ *	Copyright (C) 2002 by Concurrent Computer Corporation
+ *	Distributed under the GNU GPL license version 2.
+ *
+ * Small id to pointer translation service.  
+ *
+ * It uses a radix tree like structure as a sparse array indexed 
+ * by the id to obtain the pointer.  A bit map is included in each
+ * level of the tree which identifies portions of the tree which
+ * are completely full.  This makes the process of allocating a
+ * new id quick.
+ */
+
+
+#include <linux/slab.h>
+#include <linux/id2ptr.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+static kmem_cache_t *id_layer_cache;
+spinlock_t id_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Since we can't allocate memory with spinlock held and dropping the
+ * lock to allocate gets ugly keep a free list which will satisfy the
+ * worst case allocation.
+ */
+
+struct id_layer *id_free;
+int id_free_cnt;
+
+static inline struct id_layer *alloc_layer(void)
+{
+	struct id_layer *p;
+
+	if (!(p = id_free))
+		BUG();
+	id_free = p->ary[0];
+	id_free_cnt--;
+	p->ary[0] = 0;
+	return(p);
+}
+
+static inline void free_layer(struct id_layer *p)
+{
+	p->ary[0] = id_free;
+	id_free = p;
+	id_free_cnt++;
+}
+
+/*
+ * Lookup the kernel pointer associated with a user supplied 
+ * id value.
+ */
+void *id2ptr_lookup(struct id *idp, int id)
+{
+	int n;
+	struct id_layer *p;
+
+	if (id <= 0)
+		return(NULL);
+	id--;
+	spin_lock_irq(&id_lock);
+	n = idp->layers * ID_BITS;
+	p = idp->top;
+	if (id >= (1 << n)) {
+		spin_unlock_irq(&id_lock);
+		return(NULL);
+	}
+
+	while (n > 0 && p) {
+		n -= ID_BITS;
+		p = p->ary[(id >> n) & ID_MASK];
+	}
+	spin_unlock_irq(&id_lock);
+	return((void *)p);
+}
+
+static int sub_alloc(struct id_layer *p, int shift, int id, void *ptr)
+{
+	int n = (id >> shift) & ID_MASK;
+	int bitmap = p->bitmap;
+	int id_base = id & ~((1 << (shift+ID_BITS))-1);
+	int v;
+	
+	for ( ; n <= ID_MASK; n++, id = id_base + (n << shift)) {
+		if (bitmap & (1 << n))
+			continue;
+		if (shift == 0) {
+			p->ary[n] = (struct id_layer *)ptr;
+			p->bitmap |= 1<<n;
+			return(id);
+		}
+		if (!p->ary[n])
+			p->ary[n] = alloc_layer();
+		if ((v = sub_alloc(p->ary[n], shift-ID_BITS, id, ptr))) {
+			update_bitmap(p, n);
+			return(v);
+		}
+	}
+	return(0);
+}
+
+/*
+ * Allocate a new id associate the value ptr with this new id.
+ */
+int id2ptr_new(struct id *idp, void *ptr)
+{
+	int n, last, id, v;
+	struct id_layer *new;
+	
+	spin_lock_irq(&id_lock);
+	n = idp->layers * ID_BITS;
+	last = idp->last;
+	while (id_free_cnt < n+1) {
+		spin_unlock_irq(&id_lock);
+		/* If the allocation fails giveup. */
+		if (!(new = kmem_cache_alloc(id_layer_cache, GFP_KERNEL)))
+			return(0);
+		spin_lock_irq(&id_lock);
+		memset(new, 0, sizeof(struct id_layer));
+		free_layer(new);
+	}
+	/*
+	 * Add a new layer if the array is full or the last id
+	 * was at the limit and we don't want to wrap.
+	 */
+	if ((last == ((1 << n)-1) && last < idp->min_wrap) ||
+		idp->count == (1 << n)) {
+		++idp->layers;
+		n += ID_BITS;
+		new = alloc_layer();
+		new->ary[0] = idp->top;
+		idp->top = new;
+		update_bitmap(new, 0);
+	}
+	if (last >= ((1 << n)-1))
+		last = 0;
+
+	/*
+	 * Search for a free id starting after last id allocated.
+	 * If that fails wrap back to start.
+	 */
+	id = last+1;
+	if (!(v = sub_alloc(idp->top, n-ID_BITS, id, ptr)))
+		v = sub_alloc(idp->top, n-ID_BITS, 1, ptr);
+	idp->last = v;
+	idp->count++;
+	spin_unlock_irq(&id_lock);
+	return(v+1);
+}
+
+
+static int sub_remove(struct id_layer *p, int shift, int id)
+{
+	int n = (id >> shift) & ID_MASK;
+	int i, bitmap, rv;
+	
+	rv = 0;
+	bitmap = p->bitmap & ~(1<<n);
+	p->bitmap = bitmap;
+	if (shift == 0) {
+		p->ary[n] = NULL;
+		rv = !bitmap;
+	} else {
+		if (sub_remove(p->ary[n], shift-ID_BITS, id)) {
+			free_layer(p->ary[n]);
+			p->ary[n] = 0;
+			for (i = 0; i < (1 << ID_BITS); i++)
+				if (p->ary[i])
+					break;
+			if (i == (1 << ID_BITS))
+				rv = 1;
+		}
+	}
+	return(rv);
+}
+
+/*
+ * Remove (free) an id value and break the association with
+ * the kernel pointer.
+ */
+void id2ptr_remove(struct id *idp, int id)
+{
+	struct id_layer *p;
+
+	if (id <= 0)
+		return;
+	id--;
+	spin_lock_irq(&id_lock);
+	sub_remove(idp->top, (idp->layers-1)*ID_BITS, id);
+	idp->count--;
+	if (id_free_cnt >= ID_FREE_MAX) {
+		
+		p = alloc_layer();
+		spin_unlock_irq(&id_lock);
+		kmem_cache_free(id_layer_cache, p);
+		return;
+	}
+	spin_unlock_irq(&id_lock);
+}
+
+void init_id_cache(void)
+{
+	if (!id_layer_cache)
+		id_layer_cache = kmem_cache_create("id_layer_cache", 
+			sizeof(struct id_layer), 0, 0, 0, 0);
+}
+
+void id2ptr_init(struct id *idp, int min_wrap)
+{
+	init_id_cache();
+	idp->count = 1;
+	idp->last = 0;
+	idp->layers = 1;
+	idp->top = kmem_cache_alloc(id_layer_cache, GFP_KERNEL);
+	memset(idp->top, 0, sizeof(struct id_layer));
+	idp->top->bitmap = 0;
+	idp->min_wrap = min_wrap;
+}
+
+__initcall(init_id_cache);
diff -X dontdiff -urN linux-2.5.51.orig/kernel/posix-timers.c linux-2.5.51.timers/kernel/posix-timers.c
--- linux-2.5.51.orig/kernel/posix-timers.c	Wed Dec 31 19:00:00 1969
+++ linux-2.5.51.timers/kernel/posix-timers.c	Mon Dec 16 13:06:59 2002
@@ -0,0 +1,1200 @@
+/*
+ * linux/kernel/posix_timers.c
+ *
+ * The alternative posix timers - Jim Houston jim.houston@attbi.com
+ *	Copyright (C) 2002 by Concurrent Computer Corp.
+ * 
+ * Based on: * Posix Clocks & timers by George Anzinger
+ *	Copyright (C) 2002 by MontaVista Software.
+ *
+ * Posix timers are the alarm clock for the kernel that has everything.
+ * They allow applications to request periodic signal delivery 
+ * starting at a specific time.  The initial time and period are
+ * specified in seconds and nanoseconds.  They also provide nanosecond
+ * resolution interface to clocks and an extended nanosleep interface
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/nmi.h>
+#include <linux/compiler.h>
+#include <linux/id2ptr.h>
+#include <linux/rbtree.h>
+#include <linux/posix-timers.h>
+#include <linux/sysctl.h>
+#include <asm/div64.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+
+
+#define MAXLOG 0x1000
+struct log {
+	long	flag;
+	long	tsc;
+	long	a, b;
+} mylog[MAXLOG];
+int myoffset;
+
+void logit(long flag, long a, long b)
+{
+	register unsigned long eax, edx;
+	int i;
+
+	i = myoffset;
+	myoffset = (i+1) % (MAXLOG-1);
+	rdtsc(eax,edx);
+	mylog[i].flag = flag << 16 | edx;
+	mylog[i].tsc = eax;
+	mylog[i].a = a;
+	mylog[i].b = b;
+}
+
+extern long get_eip(void *);
+
+/*
+ * Lets keep our timers in a slab cache :-)
+ */
+static kmem_cache_t *posix_timers_cache;
+struct id posix_timers_id;
+
+struct posix_timers_percpu {
+	spinlock_t	lock;
+	struct timer_pq	clock_monotonic;
+	struct timer_pq	clock_realtime;
+	struct k_itimer	tick;
+};
+typedef struct posix_timers_percpu pt_base_t;
+static DEFINE_PER_CPU(pt_base_t, pt_base);
+
+static int timer_insert_nolock(struct timer_pq *, struct k_itimer *);
+
+static void __init init_posix_timers_cpu(int cpu)
+{
+	pt_base_t *base;
+	struct k_itimer *t;
+
+	base = &per_cpu(pt_base, cpu);
+	spin_lock_init(&base->lock);
+	INIT_LIST_HEAD(&base->clock_realtime.head);
+	base->clock_realtime.rb_root = RB_ROOT;
+	base->clock_realtime.lock = &base->lock;
+	INIT_LIST_HEAD(&base->clock_monotonic.head);
+	base->clock_monotonic.rb_root = RB_ROOT;
+	base->clock_monotonic.lock = &base->lock;
+	t = &base->tick;
+	memset(t, 0, sizeof(struct k_itimer));
+	t->it_v.it_value.tv_sec = 0;
+	t->it_v.it_value.tv_nsec = 0;
+	t->it_v.it_interval.tv_sec = 0;
+	t->it_v.it_interval.tv_nsec = 1000000000/HZ;
+	t->it_type = TICK;
+	t->it_clock = CLOCK_MONOTONIC;
+	t->it_pq = 0;
+	timer_insert_nolock(&base->clock_monotonic, t);
+}
+
+static int __devinit posix_timers_cpu_notify(struct notifier_block *self, 
+				unsigned long action, void *hcpu)
+{
+	long cpu = (long)hcpu;
+	switch(action) {
+	case CPU_UP_PREPARE:
+		init_posix_timers_cpu(cpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata posix_timers_nb = {
+	.notifier_call	= posix_timers_cpu_notify,
+};
+
+/*
+ * This is ugly.  It seems the register_cpu_notifier() needs to
+ * be called early in the boot before its safe to setup the slab 
+ * cache.
+ */
+
+void __init init_posix_timers(void)
+{
+	posix_timers_cpu_notify(&posix_timers_nb, (unsigned long)CPU_UP_PREPARE,
+				(void *)(long)smp_processor_id());
+	register_cpu_notifier(&posix_timers_nb);
+}
+
+static int  __init init_posix_timers2(void)
+{
+	posix_timers_cache = kmem_cache_create("posix_timers_cache",
+		sizeof(struct k_itimer), 0, 0, 0, 0);
+	id2ptr_init(&posix_timers_id, 1000);
+	return 0;
+}
+__initcall(init_posix_timers2);
+
+inline int valid_clock(int clock)
+{
+	switch (clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_REALTIME_HR:
+	case CLOCK_MONOTONIC:
+	case CLOCK_MONOTONIC_HR:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+inline struct timer_pq *get_pq(pt_base_t *base, struct k_itimer *t)
+{
+	switch (t->it_clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_REALTIME_HR:
+		if (t->it_flags & TIMER_ABSTIME)
+			return(&base->clock_realtime);
+		else
+			return(&base->clock_monotonic);
+	case CLOCK_MONOTONIC:
+	case CLOCK_MONOTONIC_HR:
+		return(&base->clock_monotonic);
+	}
+	return(NULL);
+}
+
+static inline int do_posix_gettime(int clock, struct timespec *tp)
+{
+	switch(clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_REALTIME_HR:
+		do_gettimeofday_ns(tp);
+		return 0;
+	case CLOCK_MONOTONIC:
+	case CLOCK_MONOTONIC_HR:
+		do_gettime_sinceboot_ns(tp);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+
+/*
+ * The following parameters are set through sysctl or
+ * using the files in /proc/sys/kernel/posix-timers directory.
+ */
+static int posix_timers_res = 1000;	/* resolution for posix timers */
+static int nanosleep_res = 1000000;	/* resolution for nanosleep */
+
+/*
+ * These parameters limit the timer interrupt load if the 
+ * timers are over commited.  
+ */
+static int max_expiries = 20;		/* Maximum timers to expire from */
+					/* a single timer interrupt */
+static int recovery_time = 100000;	/* Recovery time used if we hit the */						/* timer expiry limit above. */
+static int min_delay = 10000;		/* Minimum delay before next timer */
+					/* interrupt in nanoseconds.*/
+
+
+static int min_posix_timers_res = 1000;
+static int max_posix_timers_res = 10000000;
+static int min_max_expiries = 5;
+static int max_max_expiries = 1000;
+static int min_recovery_time = 5000;
+static int max_recovery_time = 1000000;
+
+ctl_table posix_timers_table[] = {
+	{POSIX_TIMERS_RESOLUTION, "resolution", &posix_timers_res,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	&min_posix_timers_res, &max_posix_timers_res},
+	{POSIX_TIMERS_NANOSLEEP_RES, "nanosleep_res", &nanosleep_res,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	&min_posix_timers_res, &max_posix_timers_res},
+	{POSIX_TIMERS_MAX_EXPIRIES, "max_expiries", &max_expiries,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	&min_max_expiries, &max_max_expiries},
+	{POSIX_TIMERS_RECOVERY_TIME, "recovery_time", &recovery_time,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	&min_recovery_time, &max_recovery_time},
+	{POSIX_TIMERS_MIN_DELAY, "min_delay", &min_delay,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	&min_recovery_time, &max_recovery_time},
+	{0}
+};
+
+extern void set_APIC_timer(int);
+
+/*
+ * Setup hardware timer for fractional tick delay.  This is called
+ * when a new timer is inserted at the front of the priority queue.
+ * Since there are two queues and we don't look at both queues
+ * the hardware specific layer needs to read the timer and only
+ * set a new value if it is smaller than the current count.
+ */
+void set_hw_timer(int clock, struct k_itimer *timr)
+{
+	struct timespec ts;
+
+	if (timr->it_flags & TIMER_ABSTIME)
+		do_posix_gettime(timr->it_clock, &ts);
+	else
+		do_gettime_sinceboot_ns(&ts);
+	ts.tv_sec = timr->it_v.it_value.tv_sec - ts.tv_sec;
+	ts.tv_nsec = timr->it_v.it_value.tv_nsec - ts.tv_nsec;
+	if (ts.tv_nsec < 0) {
+		ts.tv_nsec += 1000000000;
+		ts.tv_sec--;
+	}
+	if (ts.tv_sec > 0 || ts.tv_nsec > (1000000000/HZ))
+		return;
+	if (ts.tv_sec < 0 || ts.tv_nsec < min_delay)
+		ts.tv_nsec = min_delay;
+	set_APIC_timer(ts.tv_nsec);
+}
+
+/*
+ * Insert a timer into a priority queue.  This is a sorted
+ * list of timers.  A rbtree is used to index the list.
+ */
+
+static int timer_insert_nolock(struct timer_pq *pq, struct k_itimer *t)
+{
+	struct rb_node ** p = &pq->rb_root.rb_node;
+	struct rb_node * parent = NULL;
+	struct k_itimer *cur;
+	struct list_head *prev;
+	prev = &pq->head;
+
+	t->it_pq = pq;
+	while (*p) {
+		parent = *p;
+		cur = rb_entry(parent, struct k_itimer , it_pq_node);
+
+		/*
+		 * We allow non unique entries.  This works
+		 * but there might be opportunity to do something
+		 * clever.
+		 */
+		if (t->it_v.it_value.tv_sec < cur->it_v.it_value.tv_sec  ||
+			(t->it_v.it_value.tv_sec == cur->it_v.it_value.tv_sec &&
+			 t->it_v.it_value.tv_nsec < cur->it_v.it_value.tv_nsec))
+			p = &(*p)->rb_left;
+		else {
+			prev = &cur->it_pq_list;
+			p = &(*p)->rb_right;
+		}
+	}
+	/* link into rbtree. */
+	rb_link_node(&t->it_pq_node, parent, p);
+	rb_insert_color(&t->it_pq_node, &pq->rb_root);
+	/* link it into the list */
+	list_add(&t->it_pq_list, prev);
+	/*
+	 * We need to setup a timer interrupt if the new timer is
+	 * at the head of the queue.
+	 */
+	return(pq->head.next == &t->it_pq_list);
+}
+
+static inline void timer_remove_nolock(struct k_itimer *t)
+{
+	struct timer_pq *pq;
+
+	if (!(pq = t->it_pq))
+		return;
+	rb_erase(&t->it_pq_node, &pq->rb_root);
+	list_del(&t->it_pq_list);
+}
+
+static void timer_remove(struct k_itimer *t)
+{
+	struct timer_pq *pq = t->it_pq;
+	unsigned long flags;
+
+	if (!pq)
+		return;
+	spin_lock_irqsave(pq->lock, flags);
+	timer_remove_nolock(t);
+	t->it_pq = 0;
+	spin_unlock_irqrestore(pq->lock, flags);
+}
+
+
+static void timer_insert(struct k_itimer *t)
+{
+	int cpu = get_cpu();
+	pt_base_t *base = &per_cpu(pt_base, cpu);
+	unsigned long flags;
+	int rv;
+
+	spin_lock_irqsave(&base->lock, flags);
+	if (t->it_pq)
+		BUG();
+	rv = timer_insert_nolock(get_pq(base, t), t);
+	if (rv) 
+		set_hw_timer(t->it_clock, t);
+	spin_unlock_irqrestore(&base->lock, flags);
+	put_cpu();
+}
+
+/*
+ * If we are late delivering a periodic timer we may 
+ * have missed several expiries.  We want to calculate the 
+ * number we have missed both as the overrun count but also
+ * so that we can pick next expiry.
+ *
+ * You really need this if you schedule a high frequency timer
+ * and then make a big change to the current time.
+ */
+
+int handle_overrun(struct k_itimer *t, struct timespec dt)
+{
+	int ovr;
+	long long ldt, in;
+	long sec, nsec;
+
+	in =  (long long)t->it_v.it_interval.tv_sec*1000000000 +
+		t->it_v.it_interval.tv_nsec;
+	ldt = (long long)dt.tv_sec * 1000000000 + dt.tv_nsec;
+	/* scale ldt and in so that in fits in 32 bits. */
+	while (in > (1LL << 31)) {
+		in >>= 1;
+		ldt >>= 1;
+	}
+	/*
+	 * ovr = ldt/in + 1;
+	 * ldt = (long long)t->it_v.it_interval.tv_nsec * ovr;
+	 */
+	do_div(ldt, (long)in);
+	ldt++;
+	ovr = (long)ldt;
+	ldt *= t->it_v.it_interval.tv_nsec;
+	/*
+	 * nsec = ldt % 1000000000;
+	 * sec = ldt / 1000000000;
+	 */
+	nsec = do_div(ldt, 1000000000);
+	sec = (long)ldt;
+	sec += ovr * t->it_v.it_interval.tv_sec;
+	nsec += t->it_v.it_value.tv_nsec;
+	sec +=  t->it_v.it_value.tv_sec;
+	if (nsec > 1000000000) {
+		sec++;
+		nsec -= 1000000000;
+	}
+	t->it_v.it_value.tv_sec = sec;
+	t->it_v.it_value.tv_nsec = nsec;
+	return(ovr);
+}
+
+int sending_signal_failed;
+
+static void timer_notify_task(struct k_itimer *timr, int ovr)
+{
+	struct siginfo info;
+	int ret;
+
+	timr->it_overrun_deferred = ovr-1;
+	if (! (timr->it_sigev_notify & SIGEV_NONE)) {
+		memset(&info, 0, sizeof(info));
+		/* Send signal to the process that owns this timer. */
+		info.si_signo = timr->it_sigev_signo;
+		info.si_errno = 0;
+		info.si_code = SI_TIMER;
+		info.si_tid = timr->it_id;
+		info.si_value = timr->it_sigev_value;
+		info.si_overrun = timr->it_overrun_deferred;
+		ret = send_sig_info(info.si_signo, &info, timr->it_process);
+		switch (ret) {
+		case 0:		/* all's well new signal queued */
+			timr->it_overrun_last = timr->it_overrun;
+			timr->it_overrun = timr->it_overrun_deferred;
+			break;
+		case 1:	/* signal from this timer was already in the queue */
+			timr->it_overrun += timr->it_overrun_deferred + 1;
+			break;
+		default:
+			sending_signal_failed++;
+			break;
+		}
+	}
+}
+
+/*
+ * Check if the timer at the head of the priority queue has 
+ * expired and handle the expiry.  Update the time in nsec till
+ * the next expiry.  We only really care about expiries
+ * before the next clock tick so we use a 32 bit int here.
+ */
+
+static int check_expiry(struct timer_pq *pq, struct timespec *tv,
+int *next_expiry, int *expiry_cnt, void *regs)
+{
+	struct k_itimer *t;
+	struct timespec dt;
+	int ovr;
+	long sec, nsec;
+	int tick_expired = 0;
+	int one_shot;
+	
+	ovr = 1;
+	while (!list_empty(&pq->head)) {
+		t = list_entry(pq->head.next, struct k_itimer, it_pq_list);
+		dt.tv_sec = tv->tv_sec - t->it_v.it_value.tv_sec;
+		dt.tv_nsec = tv->tv_nsec - t->it_v.it_value.tv_nsec;
+		if (dt.tv_sec < 0 || (dt.tv_sec == 0 && dt.tv_nsec < 0)) {
+			/*
+			 * It has not expired yet.  Update the time
+			 * till the next expiry if it's less than a 
+			 * second.
+			 */
+			if (dt.tv_sec >= -1) {
+				nsec = dt.tv_sec ? 1000000000-dt.tv_nsec :
+					 -dt.tv_nsec;
+				if (nsec < *next_expiry)
+					*next_expiry = nsec;
+			}
+			return(tick_expired);
+		}
+		/*
+		 * Its expired.  If this is a periodic timer we need to
+		 * setup for the next expiry.  We also check for overrun
+		 * here.  If the timer has already missed an expiry we want
+		 * deliver the overrun information and get back on schedule.
+		 */
+		if (dt.tv_nsec < 0) {
+			dt.tv_sec--;
+			dt.tv_nsec += 1000000000;
+		}
+if (dt.tv_sec || dt.tv_nsec > 50000) logit(8, dt.tv_nsec, get_eip(regs));
+		timer_remove_nolock(t);
+		one_shot = 1;
+		if (t->it_v.it_interval.tv_sec || t->it_v.it_interval.tv_nsec) {
+			if (dt.tv_sec > t->it_v.it_interval.tv_sec ||
+			   (dt.tv_sec == t->it_v.it_interval.tv_sec && 
+			    dt.tv_nsec > t->it_v.it_interval.tv_nsec)) {
+				ovr = handle_overrun(t, dt);
+			} else {
+				nsec = t->it_v.it_value.tv_nsec +
+					t->it_v.it_interval.tv_nsec;
+				sec = t->it_v.it_value.tv_sec +
+					t->it_v.it_interval.tv_sec;
+				if (nsec > 1000000000) {
+					nsec -= 1000000000;
+					sec++;
+				}
+				t->it_v.it_value.tv_sec = sec;
+				t->it_v.it_value.tv_nsec = nsec;
+			}
+			/*
+			 * It might make sense to leave the timer queue and
+			 * avoid the remove/insert for timers which stay
+			 * at the front of the queue.
+			 */
+			timer_insert_nolock(pq, t);
+			one_shot = 0;
+		}
+		switch (t->it_type) {
+		case TIMER:
+			timer_notify_task(t, ovr);
+			break;
+		/*
+		 * If a clock_nanosleep is interrupted by a signal we
+		 * leave the timer in the queue in case the nanosleep
+		 * is restarted.  The NANOSLEEP_RESTART case is this
+		 * abandoned timer.
+		 */
+		case NANOSLEEP:
+			wake_up_process(t->it_process);
+		case NANOSLEEP_RESTART:
+			break;
+		case TICK:
+			tick_expired = 1;
+		}
+		if (one_shot)
+			t->it_pq = 0;
+		/*
+		 * Limit the number of timers we expire from a 
+		 * single interrupt and allow a recovery time before
+		 * the next interrupt.
+		 */
+		if (++*expiry_cnt > max_expiries) {
+			*next_expiry = recovery_time;
+			break;
+		}
+	}
+	return(tick_expired);
+}
+
+/*
+ * kluge?  We should know the offset between clock_realtime and
+ * clock_monotonic so we don't need to get the time twice.
+ */
+
+extern int system_running;
+
+int run_posix_timers(void *regs)
+{
+	int cpu = get_cpu();
+	pt_base_t *base = &per_cpu(pt_base, cpu);
+	struct timer_pq *pq;
+	struct timespec now_rt;
+	struct timespec now_mon;
+	int next_expiry, expiry_cnt, ret;
+	unsigned long flags;
+
+#if 1
+	/*
+	 * hack alert!  We can't count on time to make sense during
+	 * start up.  If we are called from smp_local_timer_interrupt()
+	 * our return indicates if this is the real tick v.s. an extra
+	 * interrupt just for posix timers.  Without this check we
+	 * hang during boot.  
+	 */
+	if (!system_running) {
+		set_APIC_timer(1000000000/HZ);
+		put_cpu();
+		return(1);
+	}
+#endif
+	ret = 1;
+	next_expiry = 1000000000/HZ;
+	do_gettime_sinceboot_ns(&now_mon);
+	do_gettimeofday_ns(&now_rt);
+	expiry_cnt = 0;
+	
+	spin_lock_irqsave(&base->lock, flags);
+	pq = &base->clock_monotonic;
+	if (!list_empty(&pq->head))
+		ret = check_expiry(pq, &now_mon, &next_expiry, &expiry_cnt, regs);
+	pq = &base->clock_realtime;
+	if (!list_empty(&pq->head))
+		check_expiry(pq, &now_rt, &next_expiry, &expiry_cnt, regs);
+	spin_unlock_irqrestore(&base->lock, flags);
+if (!expiry_cnt) logit(7, next_expiry, 0);
+	if (next_expiry < min_delay)
+		next_expiry = min_delay;
+	set_APIC_timer(next_expiry);
+	put_cpu();
+	return ret;
+}
+	
+
+extern rwlock_t xtime_lock;
+
+
+
+static struct task_struct * good_sigevent(sigevent_t *event)
+{
+	struct task_struct * rtn = current;
+
+	if (event->sigev_notify & SIGEV_THREAD_ID) {
+		if ( !(rtn = find_task_by_pid(event->sigev_notify_thread_id)) ||
+		     rtn->tgid != current->tgid){
+			return NULL;
+		}
+	}
+	if (event->sigev_notify & SIGEV_SIGNAL) {
+		if ((unsigned)(event->sigev_signo > SIGRTMAX))
+			return NULL;
+	}
+	if (event->sigev_notify & ~(SIGEV_SIGNAL | SIGEV_THREAD_ID )) {
+		return NULL;
+	}
+	return rtn;
+}
+
+/* Create a POSIX.1b interval timer. */
+
+asmlinkage int
+sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
+				timer_t *created_timer_id)
+{
+	int error = 0;
+	struct k_itimer *new_timer = NULL;
+	int id;
+	struct task_struct * process = 0;
+	sigevent_t event;
+
+	if (!valid_clock(which_clock))
+		return -EINVAL;
+
+	if (!(new_timer = kmem_cache_alloc(posix_timers_cache, GFP_KERNEL)))
+		return -EAGAIN;
+	memset(new_timer, 0, sizeof(struct k_itimer));
+
+	if (!(id = id2ptr_new(&posix_timers_id, (void *)new_timer))) {
+		error = -EAGAIN;
+		goto out;
+	}
+	new_timer->it_id = id;
+	
+	if (copy_to_user(created_timer_id, &id, sizeof(id))) {
+		error = -EFAULT;
+		goto out;
+	}
+	spin_lock_init(&new_timer->it_lock);
+	if (timer_event_spec) {
+		if (copy_from_user(&event, timer_event_spec, sizeof(event))) {
+			error = -EFAULT;
+			goto out;
+		}
+		read_lock(&tasklist_lock);
+		if ((process = good_sigevent(&event))) {
+			/*
+			 * We may be setting up this timer for another
+			 * thread.  It may be exitiing.  To catch this
+			 * case the we clear posix_timers.next in 
+			 * exit_itimers.
+			 */
+			spin_lock(&process->alloc_lock);
+			if (process->posix_timers.next) {
+				list_add(&new_timer->it_task_list,
+					&process->posix_timers);
+				spin_unlock(&process->alloc_lock);
+			} else {
+				spin_unlock(&process->alloc_lock);
+				process = 0;
+			}
+		}
+		read_unlock(&tasklist_lock);
+		if (!process) {
+			error = -EINVAL;
+			goto out;
+		}
+		new_timer->it_sigev_notify = event.sigev_notify;
+		new_timer->it_sigev_signo = event.sigev_signo;
+		new_timer->it_sigev_value = event.sigev_value;
+	} else {
+		new_timer->it_sigev_notify = SIGEV_SIGNAL;
+		new_timer->it_sigev_signo = SIGALRM;
+		new_timer->it_sigev_value.sival_int = new_timer->it_id;
+		process = current;
+		spin_lock(&current->alloc_lock);
+		list_add(&new_timer->it_task_list, &current->posix_timers);
+		spin_unlock(&current->alloc_lock);
+	}
+	new_timer->it_clock = which_clock;
+	new_timer->it_overrun = 0;
+	new_timer->it_process = process;
+
+ out:
+	if (error) {
+		if (new_timer->it_id)
+			id2ptr_remove(&posix_timers_id, new_timer->it_id);
+		kmem_cache_free(posix_timers_cache, new_timer);
+	}
+	return error;
+}
+
+
+/*
+ * return  timer owned by the process, used by exit and exec
+ */
+void itimer_delete(struct k_itimer *timer)
+{
+	if (sys_timer_delete(timer->it_id)){
+		BUG();
+	}
+}
+
+/*
+ * This is call from both exec and exit to shutdown the
+ * timers.
+ */
+
+inline void exit_itimers(struct task_struct *tsk, int exit)
+{
+	struct	k_itimer *tmr;
+
+	if (!tsk->posix_timers.next)
+		return;
+	if (tsk->nanosleep_tmr.it_pq)
+		timer_remove(&tsk->nanosleep_tmr);
+	spin_lock(&tsk->alloc_lock);
+	while (tsk->posix_timers.next != &tsk->posix_timers){
+		spin_unlock(&tsk->alloc_lock);
+		 tmr = list_entry(tsk->posix_timers.next,struct k_itimer,
+			it_task_list);
+		itimer_delete(tmr);
+		spin_lock(&tsk->alloc_lock);
+	}
+	/*
+	 * sys_timer_create has the option to create a timer
+	 * for another thread.  There is the risk that as the timer
+	 * is being created that the thread that was supposed to handle
+	 * the signal is exiting.  We use the posix_timers.next field
+	 * as a flag so we can close this race.
+`	 */
+	if (exit)
+		tsk->posix_timers.next = 0;
+	spin_unlock(&tsk->alloc_lock);
+}
+
+/* good_timespec
+ *
+ * This function checks the elements of a timespec structure.
+ *
+ * Arguments:
+ * ts	     : Pointer to the timespec structure to check
+ *
+ * Return value:
+ * If a NULL pointer was passed in, or the tv_nsec field was less than 0 or
+ * greater than NSEC_PER_SEC, or the tv_sec field was less than 0, this
+ * function returns 0. Otherwise it returns 1.
+ */
+
+static int good_timespec(const struct timespec *ts)
+{
+	if ((ts == NULL) || 
+	    (ts->tv_sec < 0) ||
+	    ((unsigned)ts->tv_nsec >= NSEC_PER_SEC))
+		return 0;
+	return 1;
+}
+
+static inline void unlock_timer(struct k_itimer *timr)
+{
+	spin_unlock_irq(&timr->it_lock);
+}
+
+static struct k_itimer* lock_timer(timer_t id)
+{
+	struct  k_itimer *timr;
+
+	timr = (struct  k_itimer *)id2ptr_lookup(&posix_timers_id, (int)id);
+	if (timr) {
+		spin_lock_irq(&timr->it_lock);
+		/* Check if it's ours */
+		if (!timr->it_process || 
+		     timr->it_process->tgid != current->tgid) {
+			spin_unlock_irq(&timr->it_lock);
+			timr = NULL;
+		}
+	}
+	
+	return(timr);
+}
+
+/* 
+ * Get the time remaining on a POSIX.1b interval timer.
+ * This function is ALWAYS called with spin_lock_irq on the timer, thus
+ * it must not mess with irq.
+ */
+void inline do_timer_gettime(struct k_itimer *timr,
+			     struct itimerspec *cur_setting)
+{
+	struct timespec ts;
+
+	if (timr->it_flags & TIMER_ABSTIME)
+		do_posix_gettime(timr->it_clock, &ts);
+	else
+		do_gettime_sinceboot_ns(&ts);
+	ts.tv_sec = timr->it_v.it_value.tv_sec - ts.tv_sec;
+	ts.tv_nsec = timr->it_v.it_value.tv_nsec - ts.tv_nsec;
+	if (ts.tv_nsec < 0) {
+		ts.tv_nsec += 1000000000;
+		ts.tv_sec--;
+	}
+	if (ts.tv_sec < 0)
+		ts.tv_sec = ts.tv_nsec = 0;
+	cur_setting->it_value = ts;
+	cur_setting->it_interval = timr->it_v.it_interval;
+}
+
+/* Get the time remaining on a POSIX.1b interval timer. */
+asmlinkage int sys_timer_gettime(timer_t timer_id, struct itimerspec *setting)
+{
+	struct k_itimer *timr;
+	struct itimerspec cur_setting;
+
+	timr = lock_timer(timer_id);
+	if (!timr) return -EINVAL;
+	do_timer_gettime(timr, &cur_setting);
+	unlock_timer(timr);
+	if (copy_to_user(setting, &cur_setting, sizeof(cur_setting)))
+		return -EFAULT;
+	return 0;
+}
+/*
+ * Get the number of overruns of a POSIX.1b interval timer
+ * This is a bit messy as we don't easily know where he is in the delivery
+ * of possible multiple signals.  We are to give him the overrun on the
+ * last delivery.  If we have another pending, we want to make sure we
+ * use the last and not the current.  If there is not another pending
+ * then he is current and gets the current overrun.  We search both the
+ * shared and local queue.
+ */
+
+asmlinkage int sys_timer_getoverrun(timer_t timer_id)
+{
+	struct k_itimer *timr;
+	int overrun, i;
+	struct sigqueue *q;
+	struct sigpending *sig_queue;
+	struct task_struct * t;
+
+	timr = lock_timer( timer_id);
+	if (!timr) return -EINVAL;
+
+	t = timr->it_process;
+	overrun = timr->it_overrun;
+	spin_lock_irq(&t->sig->siglock);
+	for (sig_queue = &t->sig->shared_pending, i = 2; i; 
+	     sig_queue = &t->pending, i--){
+		for (q = sig_queue->head; q; q = q->next) {
+			if ((q->info.si_code == SI_TIMER) &&
+			    (q->info.si_tid == timr->it_id)) {
+
+				overrun = timr->it_overrun_last;
+				goto out;
+			}
+		}
+	}
+ out:
+	spin_unlock_irq(&t->sig->siglock);
+	
+	unlock_timer(timr);
+
+	return overrun;
+}
+
+/*
+ * If it is relative time, we need to add the current  time to it to
+ * get the proper expiry time.
+ */
+static int  adjust_rel_time(struct timespec *tp)
+{
+	struct timespec now;
+
+	do_gettime_sinceboot_ns(&now);
+	tp->tv_sec += now.tv_sec;
+	tp->tv_nsec += now.tv_nsec;
+	/* Normalize.  */
+	if (( tp->tv_nsec - NSEC_PER_SEC) >= 0){
+		tp->tv_nsec -= NSEC_PER_SEC;
+		tp->tv_sec++;
+	}
+	return 0;
+}
+
+/* Set a POSIX.1b interval timer. */
+/* timr->it_lock is taken. */
+static inline int do_timer_settime(struct k_itimer *timr, int flags,
+				   struct itimerspec *new_setting,
+				   struct itimerspec *old_setting)
+{
+	timer_remove(timr);
+	if (old_setting) {
+		do_timer_gettime(timr, old_setting);
+	}
+	
+	
+	/* switch off the timer when it_value is zero */
+	if ((new_setting->it_value.tv_sec == 0) &&
+		(new_setting->it_value.tv_nsec == 0)) {
+		timr->it_v = *new_setting;
+		return 0;
+	}
+
+	timr->it_flags = flags;
+	if (!(flags & TIMER_ABSTIME))
+		adjust_rel_time(&new_setting->it_value);
+
+	timr->it_v = *new_setting;
+	timr->it_overrun_deferred = 
+		timr->it_overrun_last = 
+		timr->it_overrun = 0;
+	timer_insert(timr);
+	return 0;
+}
+
+static inline void round_to_res(struct timespec *tp, int res)
+{
+	long nsec;
+
+	nsec = tp->tv_nsec;
+	nsec +=  res-1;
+	nsec -= nsec % res;
+	if (nsec > 1000000000) {
+		nsec -=1000000000;
+		tp->tv_sec++;
+	}
+	tp->tv_nsec = nsec;
+}
+
+
+/* Set a POSIX.1b interval timer */
+asmlinkage int sys_timer_settime(timer_t timer_id, int flags,
+				 const struct itimerspec *new_setting,
+				 struct itimerspec *old_setting)
+{
+	struct k_itimer *timr;
+	struct itimerspec new_spec, old_spec;
+	int error = 0;
+	int res;
+	struct itimerspec *rtn = old_setting ? &old_spec : NULL;
+
+
+	if (new_setting == NULL) {
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&new_spec, new_setting, sizeof(new_spec))) {
+		return -EFAULT;
+	}
+
+	if ((!good_timespec(&new_spec.it_interval)) ||
+	    (!good_timespec(&new_spec.it_value))) {
+		return -EINVAL;
+	}
+
+	timr = lock_timer( timer_id);
+	if (!timr)
+		return -EINVAL;
+	res = posix_timers_res;
+	round_to_res(&new_spec.it_interval, res);
+	round_to_res(&new_spec.it_value, res);
+
+	error = do_timer_settime(timr, flags, &new_spec, rtn );
+	unlock_timer(timr);
+
+	if (old_setting && ! error) {
+		if (copy_to_user(old_setting, &old_spec, sizeof(old_spec))) {
+			error = -EFAULT;
+		}
+	}
+	return error;
+}
+
+/* Delete a POSIX.1b interval timer. */
+asmlinkage int sys_timer_delete(timer_t timer_id)
+{
+	struct k_itimer *timer;
+
+	timer = lock_timer( timer_id);
+	if (!timer)
+		return -EINVAL;
+	timer_remove(timer);
+	spin_lock(&timer->it_process->alloc_lock);
+	list_del(&timer->it_task_list);
+	spin_unlock(&timer->it_process->alloc_lock);
+
+	/*
+	 * This keeps any tasks waiting on the spin lock from thinking
+	 * they got something (see the lock code above).
+	 */
+	timer->it_process = NULL;
+	if (timer->it_id)
+		id2ptr_remove(&posix_timers_id, timer->it_id);
+	unlock_timer(timer);
+	kmem_cache_free(posix_timers_cache, timer);
+	return 0;
+}
+
+asmlinkage int sys_clock_settime(clockid_t clock, const struct timespec *tp)
+{
+	struct timespec new_tp;
+
+	if (copy_from_user(&new_tp, tp, sizeof(*tp)))
+		return -EFAULT;
+	if (!good_timespec(&new_tp))
+		return -EINVAL;
+	/*
+	 * Only CLOCK_REALTIME may be set.
+	 */
+	if (!(clock == CLOCK_REALTIME || clock == CLOCK_REALTIME_HR))
+		return -EINVAL;
+	if (!capable(CAP_SYS_TIME))
+		return -EPERM;
+	do_settimeofday_ns(&new_tp);
+	return 0;
+}
+
+asmlinkage int sys_clock_gettime(clockid_t clock, struct timespec *tp)
+{
+	struct timespec rtn_tp;
+	int error = 0;
+
+	if (!(error = do_posix_gettime(clock, &rtn_tp))) {
+		if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) {
+			error = -EFAULT;
+		}
+	}
+	return error;
+		 
+}
+
+asmlinkage int	 sys_clock_getres(clockid_t clock, struct timespec *tp)
+{
+	struct timespec rtn_tp;
+
+	if (!valid_clock(clock))
+		return -EINVAL;
+	rtn_tp.tv_sec = 0;
+	rtn_tp.tv_nsec = posix_timers_res;
+	if (tp && copy_to_user(tp, &rtn_tp, sizeof(rtn_tp)))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * nanosleep is not supposed to leave early.  The problem is
+ * being woken by signals that are not delivered to the user.  Typically
+ * this means debug related signals.
+ *
+ * The solution is to leave the timer running and request that the system
+ * call be restarted using the -ERESTART_RESTARTBLOCK mechanism.
+ */
+
+extern long 
+clock_nanosleep_restart(struct restart_block *restart);
+
+static inline int __clock_nanosleep(clockid_t clock, int flags, 
+const struct timespec *rqtp, struct timespec *rmtp, int from_nanosleep, 
+int restart)
+{
+	struct restart_block *rb;
+	struct timer_pq *pq;
+	struct timespec ts;
+	struct k_itimer *t;
+	int active;
+	int res;
+
+	if (!valid_clock(clock))
+		return -EINVAL;
+	t = &current->nanosleep_tmr;
+	if (restart) {
+		/*
+		 * The timer was left running.  If it is still
+		 * queued we block and wait for it to expire.
+		 */
+		if ((pq = t->it_pq)) {
+			spin_lock_irqsave(pq->lock, flags);
+			if ((t->it_pq)) {
+				t->it_type = NANOSLEEP;
+				current->state = TASK_INTERRUPTIBLE;
+				spin_unlock_irqrestore(pq->lock, flags);
+				goto restart;
+			}
+			spin_unlock_irqrestore(pq->lock, flags);
+		}
+		/* The timer has expired no need to sleep. */
+		return 0;
+	}
+	/*
+	 * The timer may still be active from a previous nanosleep
+	 * which was interrupted by a real signal, so stop it now.
+	 */
+	if (t->it_pq) 
+		timer_remove(t);
+		
+	if(copy_from_user(&t->it_v.it_value, rqtp, sizeof(struct timespec)))
+		return -EFAULT;
+
+	if ((t->it_v.it_value.tv_nsec < 0) ||
+		(t->it_v.it_value.tv_nsec >= NSEC_PER_SEC) ||
+		(t->it_v.it_value.tv_sec < 0))
+		return -EINVAL;
+
+	t->it_clock = clock;
+	t->it_type = NANOSLEEP;
+	t->it_flags = flags;
+	if (!(flags & TIMER_ABSTIME))
+		adjust_rel_time(&t->it_v.it_value);
+	current->state = TASK_INTERRUPTIBLE;
+	/*
+	 * If the timer is interrupted and we return a remaining
+	 * time, it should not include the rounding to time resolution.
+	 * Save the un-rounded timespec in task_struct.  Its tempting
+	 * to use a local variable but that doesn't work if the system
+	 * call is restarted.
+	 */
+	current->nanosleep_ts = t->it_v.it_value;
+	res = from_nanosleep ? nanosleep_res : posix_timers_res;
+	round_to_res(&t->it_v.it_value, res);
+	timer_insert(t);
+restart:
+	schedule();
+	active = (t->it_pq != 0);
+	if (!(flags & TIMER_ABSTIME) && rmtp ) {
+		if (active) {
+			/*
+			 * Calculate the remaining time based on the
+			 * un-rounded version of the completion time.
+			 * If the rounded version is used a process
+			 * which recovers from an interrupted nanosleep
+			 * by doing a nanosleep for the remaining time 
+			 * may accumulate the rounding error adding 
+			 * the resolution each time it receives a
+			 * signal.
+			 */
+			do_gettime_sinceboot_ns(&ts);
+			ts.tv_sec = current->nanosleep_ts.tv_sec - ts.tv_sec;
+			ts.tv_nsec = current->nanosleep_ts.tv_nsec - ts.tv_nsec;
+			if (ts.tv_nsec < 0) {
+				ts.tv_nsec += 1000000000;
+				ts.tv_sec--;
+			}
+			if (ts.tv_sec < 0) {
+				ts.tv_sec = ts.tv_nsec = 0;
+				timer_remove(t);
+				active = 0;
+			}
+		} else {
+			ts.tv_sec = ts.tv_nsec  = 0;
+		}
+		if (copy_to_user(rmtp, &ts, sizeof(struct timespec)))
+			return -EFAULT;
+	}
+	if (active) {
+		/*
+		 * Leave the timer running we may restart this system call.
+		 * If the signal is real, setting type to NANOSLEEP_RESTART
+		 * will prevent the timer completion from doing an
+		 * unexpected wakeup.
+		 */
+		t->it_type = NANOSLEEP_RESTART;
+		rb = &current_thread_info()->restart_block;
+		rb->fn = clock_nanosleep_restart;
+		rb->arg0 = (unsigned long)rmtp;
+		rb->arg1 = clock;
+		rb->arg2 = flags;
+		return -ERESTART_RESTARTBLOCK;
+	}
+	return 0;
+}
+
+asmlinkage long 
+clock_nanosleep_restart(struct restart_block *rb)
+{
+	clockid_t which_clock;
+	int flags;
+	struct timespec *rmtp;
+	
+	rmtp = (struct timespec *)rb->arg0;
+	which_clock = rb->arg1;
+	flags = rb->arg2;
+	return(__clock_nanosleep(which_clock, flags, 0, rmtp, 0, 1));
+}
+
+asmlinkage long 
+sys_clock_nanosleep(clockid_t which_clock, int flags,
+const struct timespec *rqtp, struct timespec *rmtp)
+{
+	return(__clock_nanosleep(which_clock, flags, rqtp, rmtp, 0, 0));
+}
+
+int
+do_clock_nanosleep(clockid_t clock, int flags, 
+const struct timespec *rqtp, struct timespec *rmtp, int from_nanosleep)
+{
+	return(__clock_nanosleep(clock, flags, rqtp, rmtp, 0, 0));
+}
diff -X dontdiff -urN linux-2.5.51.orig/kernel/sched.c linux-2.5.51.timers/kernel/sched.c
--- linux-2.5.51.orig/kernel/sched.c	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/kernel/sched.c	Tue Dec 10 14:50:16 2002
@@ -2255,6 +2255,7 @@
 	wake_up_process(current);
 
 	init_timers();
+	init_posix_timers();
 
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
diff -X dontdiff -urN linux-2.5.51.orig/kernel/signal.c linux-2.5.51.timers/kernel/signal.c
--- linux-2.5.51.orig/kernel/signal.c	Thu Dec 12 16:11:47 2002
+++ linux-2.5.51.timers/kernel/signal.c	Mon Dec 16 10:04:35 2002
@@ -457,8 +457,6 @@
 		if (!collect_signal(sig, pending, info))
 			sig = 0;
 				
-		/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
-		   we need to xchg out the timer overrun values.  */
 	}
 	recalc_sigpending();
 
@@ -725,6 +723,7 @@
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t, int shared)
 {
 	int ret;
+	 struct sigpending *sig_queue;
 
 	if (!irqs_disabled())
 		BUG();
@@ -758,20 +757,43 @@
 	if (ignored_signal(sig, t))
 		goto out;
 
+	 sig_queue = shared ? &t->sig->shared_pending : &t->pending;
+
+	/*
+	 * In case of a POSIX timer generated signal you must check 
+	 * if a signal from this timer is already in the queue.
+	 * If that is true, just bump the overrun count.
+	 */
+	if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) {
+		struct sigqueue *q;
+		for (q = sig_queue->head; q; q = q->next) {
+			if ((q->info.si_code == SI_TIMER) &&
+			    (q->info.si_tid == info->si_tid)) {
+				 q->info.si_overrun += info->si_overrun + 1;
+				/* 
+				  * this special ret value (1) is recognized
+				  * only by posix_timer_fn() in itimer.c
+				  */
+				ret = 1;
+				goto out;
+			}
+		}
+	}
+
 #define LEGACY_QUEUE(sigptr, sig) \
 	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
+	 /*
+	  * Support queueing exactly one non-rt signal, so that we
+	  * can get more detailed information about the cause of
+	  * the signal.
+	  */
+	 if (LEGACY_QUEUE(sig_queue, sig))
+		 goto out;
 
 	if (!shared) {
-		/* Support queueing exactly one non-rt signal, so that we
-		   can get more detailed information about the cause of
-		   the signal. */
-		if (LEGACY_QUEUE(&t->pending, sig))
-			goto out;
 
 		ret = deliver_signal(sig, info, t);
 	} else {
-		if (LEGACY_QUEUE(&t->sig->shared_pending, sig))
-			goto out;
 		ret = send_signal(sig, info, &t->sig->shared_pending);
 	}
 out:
@@ -1477,8 +1499,9 @@
 		err |= __put_user(from->si_uid, &to->si_uid);
 		break;
 	case __SI_TIMER:
-		err |= __put_user(from->si_timer1, &to->si_timer1);
-		err |= __put_user(from->si_timer2, &to->si_timer2);
+		 err |= __put_user(from->si_tid, &to->si_tid);
+		 err |= __put_user(from->si_overrun, &to->si_overrun);
+		 err |= __put_user(from->si_ptr, &to->si_ptr);
 		break;
 	case __SI_POLL:
 		err |= __put_user(from->si_band, &to->si_band);
diff -X dontdiff -urN linux-2.5.51.orig/kernel/sysctl.c linux-2.5.51.timers/kernel/sysctl.c
--- linux-2.5.51.orig/kernel/sysctl.c	Thu Dec 12 16:11:25 2002
+++ linux-2.5.51.timers/kernel/sysctl.c	Tue Dec 10 14:50:16 2002
@@ -118,6 +118,7 @@
 static ctl_table debug_table[];
 static ctl_table dev_table[];
 extern ctl_table random_table[];
+extern ctl_table posix_timers_table[];
 
 /* /proc declarations: */
 
@@ -157,6 +158,7 @@
 	{0}
 };
 
+
 static ctl_table kern_table[] = {
 	{KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
 	 0444, NULL, &proc_doutsstring, &sysctl_string},
@@ -259,6 +261,7 @@
 #endif
 	{KERN_PIDMAX, "pid_max", &pid_max, sizeof (int),
 	 0600, NULL, &proc_dointvec},
+	{KERN_POSIX_TIMERS, "posix-timers", NULL, 0, 0555, posix_timers_table},
 	{0}
 };
 
diff -X dontdiff -urN linux-2.5.51.orig/kernel/timer.c linux-2.5.51.timers/kernel/timer.c
--- linux-2.5.51.orig/kernel/timer.c	Mon Dec 16 09:19:18 2002
+++ linux-2.5.51.timers/kernel/timer.c	Mon Dec 16 10:51:44 2002
@@ -49,12 +49,12 @@
 	struct list_head vec[TVR_SIZE];
 } tvec_root_t;
 
-typedef struct timer_list timer_t;
+typedef struct timer_list tmr_t;
 
 struct tvec_t_base_s {
 	spinlock_t lock;
 	unsigned long timer_jiffies;
-	timer_t *running_timer;
+	tmr_t *running_timer;
 	tvec_root_t tv1;
 	tvec_t tv2;
 	tvec_t tv3;
@@ -67,7 +67,7 @@
 /* Fake initialization */
 static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED };
 
-static void check_timer_failed(timer_t *timer)
+static void check_timer_failed(tmr_t *timer)
 {
 	static int whine_count;
 	if (whine_count < 16) {
@@ -85,13 +85,13 @@
 	timer->magic = TIMER_MAGIC;
 }
 
-static inline void check_timer(timer_t *timer)
+static inline void check_timer(tmr_t *timer)
 {
 	if (timer->magic != TIMER_MAGIC)
 		check_timer_failed(timer);
 }
 
-static inline void internal_add_timer(tvec_base_t *base, timer_t *timer)
+static inline void internal_add_timer(tvec_base_t *base, tmr_t *timer)
 {
 	unsigned long expires = timer->expires;
 	unsigned long idx = expires - base->timer_jiffies;
@@ -143,7 +143,7 @@
  * Timers with an ->expired field in the past will be executed in the next
  * timer tick. It's illegal to add an already pending timer.
  */
-void add_timer(timer_t *timer)
+void add_timer(tmr_t *timer)
 {
 	int cpu = get_cpu();
 	tvec_base_t *base = &per_cpu(tvec_bases, cpu);
@@ -201,7 +201,7 @@
  * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
  * active timer returns 1.)
  */
-int mod_timer(timer_t *timer, unsigned long expires)
+int mod_timer(tmr_t *timer, unsigned long expires)
 {
 	tvec_base_t *old_base, *new_base;
 	unsigned long flags;
@@ -278,7 +278,7 @@
  * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
  * active timer returns 1.)
  */
-int del_timer(timer_t *timer)
+int del_timer(tmr_t *timer)
 {
 	unsigned long flags;
 	tvec_base_t *base;
@@ -317,7 +317,7 @@
  *
  * The function returns whether it has deactivated a pending timer or not.
  */
-int del_timer_sync(timer_t *timer)
+int del_timer_sync(tmr_t *timer)
 {
 	tvec_base_t *base;
 	int i, ret = 0;
@@ -360,9 +360,9 @@
 	 * detach them individually, just clear the list afterwards.
 	 */
 	while (curr != head) {
-		timer_t *tmp;
+		tmr_t *tmp;
 
-		tmp = list_entry(curr, timer_t, entry);
+		tmp = list_entry(curr, tmr_t, entry);
 		if (tmp->base != base)
 			BUG();
 		next = curr->next;
@@ -401,9 +401,9 @@
 		if (curr != head) {
 			void (*fn)(unsigned long);
 			unsigned long data;
-			timer_t *timer;
+			tmr_t *timer;
 
-			timer = list_entry(curr, timer_t, entry);
+			timer = list_entry(curr, tmr_t, entry);
  			fn = timer->function;
  			data = timer->data;
 
@@ -439,6 +439,7 @@
 
 /* The current time */
 struct timespec xtime __attribute__ ((aligned (16)));
+struct timespec ytime __attribute__ ((aligned (16)));
 
 /* Don't completely fail for HZ > 500.  */
 int tickadj = 500/HZ ? : 1;		/* microsecs */
@@ -610,6 +611,12 @@
 	    time_adjust -= time_adjust_step;
 	}
 	xtime.tv_nsec += tick_nsec + time_adjust_step * 1000;
+	/* time since boot too */
+	ytime.tv_nsec += tick_nsec + time_adjust_step * 1000;
+	if (ytime.tv_nsec > 1000000000) {
+		ytime.tv_nsec -= 1000000000;
+		ytime.tv_sec++;
+	}
 	/*
 	 * Advance the phase, once it gets to one microsecond, then
 	 * advance the tick more.
@@ -965,7 +972,7 @@
  */
 signed long schedule_timeout(signed long timeout)
 {
-	timer_t timer;
+	tmr_t timer;
 	unsigned long expire;
 
 	switch (timeout)
@@ -1047,6 +1054,23 @@
 	return ret;
 }
 
+#undef NANOSLEEP_USE_CLOCK_NANOSLEEP
+#define NANOSLEEP_USE_CLOCK_NANOSLEEP 1
+#ifdef NANOSLEEP_USE_CLOCK_NANOSLEEP
+/*
+ * nanosleep is no supposed to return early if it is interrupted
+ * by a signal which is not delivered to the process.  This is 
+ * fixed in clock_nanosleep so lets use it.
+ */
+extern int do_clock_nanosleep(clockid_t which_clock, int flags, 
+const struct timespec *rqtp, struct timespec *rmtp, int from_nanosleep);
+
+asmlinkage long
+sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
+{
+	return(do_clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp, 1));
+}
+#else 
 asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
 {
 	struct timespec t;
@@ -1078,6 +1102,7 @@
 	}
 	return ret;
 }
+#endif
 
 /*
  * sys_sysinfo - fill in sysinfo struct

^ permalink raw reply

* subscription for dosemu?
From: Peter Jay Salzman @ 2002-12-16 19:24 UTC (permalink / raw)
  To: linux-msdos

has any of the developers thought of selling dosemu support ?

would the transgaming business model work with dosemu?   i'm pretty sure
there wouldn't be enough people to support a full time staff like winex,
but i think something like that would make the users very happy and
encourage faster development of dosemu.

just a thought.   although i'm a grad student and don't have much money,
i'd certainly be willing to pay 1) for support and 2) to help the dosemu
project along to encourage more development.  i'm sure others would do
the same.

pete

-- 
First they ignore you, then they laugh at you, then they fight you,
then you win. -- Gandhi, being prophetic about Linux.

Fingerprint: B9F1 6CF3 47C4 7CD8 D33E 70A9 A3B9 1945 67EA 951D

^ permalink raw reply

* Re: dosemu 1.1.3.9 user report
From: Stas Sergeev @ 2002-12-16 19:23 UTC (permalink / raw)
  To: linux-msdos

Hello.

Jan Willem Stumpel wrote:
> According to "top", 1.1.3.9 takes up 99 % CPU even when just
> displaying the C:> prompt.
[]
> $_hogthreshold = (800).
Sure with such a hogthreshold value.
Since 1.1.3.8 you don't need to set
most of the options manually, so just
delete the $_hogthreshold from your
dosemu.conf and you're fine.

> Wolfenstein 3D:
> 1.0.2.1, 1.1.3.7, 1.1.3.9 play with $_sound = (off) .
> 1.1.3.0 hangs (with or without sound) after displaying the
> start-up (setup) screen. Control-Alt-PgDn is the only way out.
> 1.1.3.7, 1.1.3.9 hang with $_sound = (on) .
Very strange... Wolf is the one of
those few progs that used to work with
sound even on early dosemus (like
1.0.2.1) and that was my main testcase
for the new sound engine and I think
I made wolf to sound flawlessly.
So I would suspect there are some
problems in your dosemu.conf again.
Probably XMS/EMS are too low.
Try to throw away all the options from
your dosemu.conf (except for the most
important ones like $_hdimage if you
use some non-standard booting methods)
because the default options are just fine.

> 1.1.3.7, 1.1.3.9 play, with $_sound = (on) and soundblaster
> selected in Duke Nukem Setup.
So you have applied some patches, havent you?

> (sounds, no music).
Well, getting sound and music together is
currently not always possible. But if
you have an SB Live card or some other
card with a hardware mixing abilities
(and the driver supports this), you can
get music working together with sound.
sound-usage.txt of 1.1.3.9 describes the
ways of doing that (thanks to Rob Komar
for the detailed instructions about getting
the music to work on ALSA).

> however, when I try to
> select the difficulty level the program hangs.
[]
> $_dpmi = (8192)
Too low. Remove that option from dosemu.conf
and see if it helps (Duke works perfectly
here most of the time) and if not - try this:
http://dosemu.sourceforge.net/stas/pic_prot.diff
However yes, 100% reliability of DPMI progs
is not yet.


^ permalink raw reply

* Re: [PATCH] kexec for 2.5.52
From: Eric W. Biederman @ 2002-12-16 19:29 UTC (permalink / raw)
  To: Andy Pfiffer; +Cc: linux-kernel@vger.kernel.org
In-Reply-To: <1040066196.2183.2.camel@andyp>

Andy Pfiffer <andyp@osdl.org> writes:

> On Mon, 2002-12-16 at 08:40, Eric W. Biederman wrote:
> > Linus will you please apply this?
> 
> Eric,
> 
> The patch applied cleanly for me.
> 
> Is there a new kexec-tools package for this, or should the 1.8 rev
> located here:
> http://www.xmission.com/~ebiederm/files/kexec/
> work okay?

1.8 should work.
 
> Also, is there a separate hwfixes patch as before?

The old hwfixes should work as well.  If the .48 version does not
patch cleanly holler.

Eric

^ permalink raw reply

* [PATCH] joydev: fix HZ->millisecond transformation
From: Bjorn Helgaas @ 2002-12-16 19:27 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: vojtech, linux-kernel

* fix a problem with HZ->millisecond transformation on
  non-x86 archs (from 2.5 change by vojtech@suse.cz)

Applies to 2.4.20.

diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	Mon Dec 16 12:16:32 2002
+++ b/drivers/input/joydev.c	Mon Dec 16 12:16:32 2002
@@ -50,6 +50,8 @@
 #define JOYDEV_MINORS		32
 #define JOYDEV_BUFFER_SIZE	64
 
+#define MSECS(t)	(1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
+
 struct joydev {
 	int exist;
 	int open;
@@ -134,7 +136,7 @@
 			return;
 	}  
 
-	event.time = jiffies * (1000 / HZ);
+	event.time = MSECS(jiffies);
 
 	while (list) {
 
@@ -279,7 +281,7 @@
 
 		struct js_event event;
 
-		event.time = jiffies * (1000/HZ);
+		event.time = MSECS(jiffies);
 
 		if (list->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;


^ permalink raw reply

* Re: increase base memory
From: John Elliott @ 2002-12-16 19:19 UTC (permalink / raw)
  To: linux-msdos
In-Reply-To: <no.id>

: Ralf Brown memory.lst states:
: --------V-MA0000000--------------------------
: MEM A000h:0000h - EGA+ GRAPHICS BUFFER
: Size:	65536 BYTEs
: 
: So it was always there.

  Well, at least since the EGA. I suppose if DOSEMU emulated an MDA or a
CGA, then it would make sense to use the memory up to B000:0 or B800:0
respectively. On an original XT, it was even possible to do this in
hardware:
<ftp://ftp.simtel.net/pub/simtelnet/msdos/info/896k-mem.txt>
 
: QEMM have a program called "vidram", which allows to use that region as a
: base memory by the cost of not being able to diplay graphics, but vidram
: will not work under dosemu because qemm itself doesn't work under dosemu.

  The same thing is true of DRDOS (the equivalent program is called MEMMAX).

--------m-2F12FFBX0006-----------------------
INT 2F U - DR DOS 6+, Novell DOS 7+ - EMM386.EXE - VIDEO MEMORY SPACE
CONTROL
        AX = 12FFh
        BX = 0006h
        DX = 0000h
        CX = function
            0000h get status of video memory space (MEMMAX /V)
            0001h map memory into video memory space (MEMMAX +V)
            0002h unmap memory from video memory space (MEMMAX -V)

: Increasing the base memory above 640Kb is definitely the bad idea, as it
: is used very rarely even in a pure DOS and will cost you the inability to
: display graphics.

  Except in the CGA modes :-)

-- 
John Elliott

^ permalink raw reply

* DSDT in Dell i8200-- does acpi have the correct address?
From: James D Strandboge @ 2002-12-16 19:17 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

My i8200 has basic acpi functionality, with quite a few issues.  I
started poking around the Dell download site and came across this in a
description of a BIOS upgrade for my laptop:

===================================================================
Systems:      Dell Inspiron 8200	(Memory location F000:E845)
Version:      A06                       (Memory location F000:E842)
Build Date:   08/17/02                  (Memory location FFFF:0005)

...

Now, if I read my dsdt from /proc/acpi/dsdt, nd decompile it with iasl,
it shows a version from 1998.  I looked at dmesg and found:

ACPI: DSDT (v001 INT430 SYSFexxx 00000.04097) @ 0x00000000
ACPI: BIOS passes blacklist


The question is, should acpi be looking at a different memory location
for the proper DSDT?  I mean, can 0x00000000 be right?  What is the
'Memory location' dell is referring to?  

For BIOS upgrades, dell has us flash the bios from outside of windows. 
This leads me to believe that the dsdt must be in the bios, and not
overridden by windows from a file.  I don't use windows, so I can't test
this hypothesis fully.

Can I somehow hardcode the address of the dsdt for testing purposes?  I
poked around in drivers/acpi, but didn't see where.

Thanks for any help.

Jamie Strandboge

-- 
Email:        jstrand1-aYIB8uWIUb2Vn7q6wjsIow@public.gmane.org
GPG/PGP ID:   26384A3A
Fingerprint:  D9FF DF4A 2D46 A353 A289  E8F5 AA75 DCBE 2638 4A3A




-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/

^ permalink raw reply

* Re: dosemu 1.1.3.9 user report
From: Peter Jay Salzman @ 2002-12-16 19:17 UTC (permalink / raw)
  To: Jan Willem Stumpel; +Cc: linux-msdos
In-Reply-To: <3DFE2055.5000802@my.home>

hi jan,

IIRC, there was talk about important dosemu related patches that are
present in the most recent kernels.   i think it was said that the
patches have been in the ac kernels for awhile, but have just recently
made it into the vanilla 2.4 kernels.

i have no idea what the patches do, but you can try using 2.4.20 and see
what happens.


btw, it sounds like you're playing in an xdos box.  have you been able
to play at all in console?

have you been able to have xdosemu grab the mouse?  i've been having
trouble playing redneck rampage because if the mouse "moves over" too
far left or right, the mouse leaves the xdos window.

pete



begin Jan Willem Stumpel <jstumpel@planet.nl> 
> According to "top", 1.1.3.9 takes up 99 % CPU even when just
> displaying the C:> prompt.
> 
> 1.1.3.7 does this also; but 1.1.3.0 and 1.0.2.1 do not. They
> hardly use any CPU when just displaying the prompt (or waiting for
> a keystroke in a text-mode program).
> 
> Wolfenstein 3D:
> 1.0.2.1, 1.1.3.7, 1.1.3.9 play with $_sound = (off) .
> 1.1.3.0 hangs (with or without sound) after displaying the
> start-up (setup) screen. Control-Alt-PgDn is the only way out.
> 1.1.3.7, 1.1.3.9 hang with $_sound = (on) .
> 
> Duke Nukem3D:
> 1.0.2.1 plays fine without sound.
> 1.1.3.0 plays without sound, but after a short while suddenly
> disappears (no more dosemu window).
> 1.1.3.7, 1.1.3.9 play, with $_sound = (on) and soundblaster
> selected in Duke Nukem Setup. I can see *and hear* the demo
> (sounds, no music). When I want to start a game, I can select the
> game type ("L.A. Meltdown" or whatever); however, when I try to
> select the difficulty level the program hangs.
> 
> All this with kernel 2.2.18pre21, $_dpmi = (8192) , $_hogthreshold
> = (800).
> 
> Regards, Jan
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-msdos" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
First they ignore you, then they laugh at you, then they fight you,
then you win. -- Gandhi, being prophetic about Linux.

Fingerprint: B9F1 6CF3 47C4 7CD8 D33E 70A9 A3B9 1945 67EA 951D

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.