sysdep.h
changeset 0 c9b8efdb5369
equal deleted inserted replaced
-1:000000000000 0:c9b8efdb5369
       
     1 /*
       
     2  * sysdep.h -- centralizing compatibility issues between 2.0, 2.2, 2.4
       
     3  *
       
     4  * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
       
     5  * Copyright (C) 2001 O'Reilly & Associates
       
     6  *
       
     7  * The source code in this file can be freely used, adapted,
       
     8  * and redistributed in source or binary form, so long as an
       
     9  * acknowledgment appears in derived source files.  The citation
       
    10  * should list that the code comes from the book "Linux Device
       
    11  * Drivers" by Alessandro Rubini and Jonathan Corbet, published
       
    12  * by O'Reilly & Associates.   No warranty is attached;
       
    13  * we cannot take responsibility for errors or fitness for use.
       
    14  *
       
    15  * $Id$
       
    16  */
       
    17 
       
    18 
       
    19 #ifndef _SYSDEP_H_
       
    20 #define _SYSDEP_H_
       
    21 
       
    22 #ifndef LINUX_VERSION_CODE
       
    23 #  include <linux/version.h>
       
    24 #endif
       
    25 
       
    26 #ifndef KERNEL_VERSION /* pre-2.1.90 didn't have it */
       
    27 #  define KERNEL_VERSION(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) )
       
    28 #endif
       
    29 
       
    30 /* only allow 2.0.x  2.2.y and 2.4.z */
       
    31 
       
    32 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0) /* not < 2.0 */
       
    33 #  error "This kernel is too old: not supported by this file"
       
    34 #endif
       
    35 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* not > 2.4, by now */
       
    36 #  error "This kernel is too recent: not supported by this file"
       
    37 #endif
       
    38 #if (LINUX_VERSION_CODE & 0xff00) == 1 /* not 2.1 */
       
    39 #  error "Please don't use linux-2.1, use 2.2 or 2.4 instead"
       
    40 #endif
       
    41 #if (LINUX_VERSION_CODE & 0xff00) == 3 /* not 2.3 */
       
    42 #  error "Please don't use linux-2.3, use 2.4 instead"
       
    43 #endif
       
    44 
       
    45 /* remember about the current version */
       
    46 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
       
    47 #  define LINUX_20
       
    48 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
       
    49 #  define LINUX_22
       
    50 #else
       
    51 #  define LINUX_24
       
    52 #endif
       
    53 
       
    54 /* we can't support versioning in pre-2.4 because we #define some functions */
       
    55 #if !defined(LINUX_24) && defined(CONFIG_MODVERSIONS)
       
    56 #  error "This sysdep.h can't support CONFIG_MODVERSIONS"
       
    57 #  error "and old kernels at the same time."
       
    58 #  error "Either use 2.4 or avoid using versioning"
       
    59 #endif
       
    60 
       
    61 #ifndef LINUX_20 /* include vmalloc.h if this is 2.2/2.4 */
       
    62 #  ifdef VM_READ /* a typical flag defined by mm.h */
       
    63 #    include <linux/vmalloc.h>
       
    64 #  endif
       
    65 #endif
       
    66 
       
    67 #include <linux/sched.h>
       
    68 
       
    69 /* Modularization issues */
       
    70 #ifdef LINUX_20
       
    71 #  define __USE_OLD_SYMTAB__
       
    72 #  define EXPORT_NO_SYMBOLS register_symtab(NULL);
       
    73 #  define REGISTER_SYMTAB(tab) register_symtab(tab)
       
    74 #else
       
    75 #  define REGISTER_SYMTAB(tab) /* nothing */
       
    76 #endif
       
    77 
       
    78 #ifdef __USE_OLD_SYMTAB__
       
    79 #  define __MODULE_STRING(s)         /* nothing */
       
    80 #  define MODULE_PARM(v,t)           /* nothing */
       
    81 #  define MODULE_PARM_DESC(v,t)      /* nothing */
       
    82 #  define MODULE_AUTHOR(n)           /* nothing */
       
    83 #  define MODULE_DESCRIPTION(d)      /* nothing */
       
    84 #  define MODULE_SUPPORTED_DEVICE(n) /* nothing */
       
    85 #endif
       
    86 
       
    87 /*
       
    88  * In version 2.2 (up to 2.2.19, at least), the macro for request_module()
       
    89  * when no kmod is there is wrong. It's a "do {} while 0" but it shouldbe int
       
    90  */
       
    91 #ifdef LINUX_22
       
    92 #  ifndef CONFIG_KMOD
       
    93 #    undef request_module
       
    94 #    define request_module(name) -ENOSYS
       
    95 #  endif
       
    96 #endif
       
    97 
       
    98 
       
    99 #ifndef LINUX_20
       
   100 #  include <linux/init.h>     /* module_init/module_exit */
       
   101 #endif
       
   102 
       
   103 #ifndef module_init
       
   104 #  define module_init(x)        int init_module(void) { return x(); }
       
   105 #  define module_exit(x)        void cleanup_module(void) { x(); }
       
   106 #endif
       
   107 
       
   108 #ifndef SET_MODULE_OWNER
       
   109 #  define SET_MODULE_OWNER(structure) /* nothing */
       
   110 #endif
       
   111 
       
   112 /*
       
   113  * "select" changed in 2.1.23. The implementation is twin, but this
       
   114  * header is new
       
   115  *
       
   116  */
       
   117 #ifdef LINUX_20
       
   118 #  define __USE_OLD_SELECT__
       
   119 #else
       
   120 #  include <linux/poll.h>
       
   121 #endif
       
   122 
       
   123 #ifdef LINUX_20
       
   124 #  define INODE_FROM_F(filp) ((filp)->f_inode)
       
   125 #else
       
   126 #  define INODE_FROM_F(filp) ((filp)->f_dentry->d_inode)
       
   127 #endif
       
   128 
       
   129 /* Other changes in the fops are solved using wrappers */
       
   130 
       
   131 /*
       
   132  * Wait queues changed with 2.3
       
   133  */
       
   134 #ifndef DECLARE_WAIT_QUEUE_HEAD
       
   135 #  define DECLARE_WAIT_QUEUE_HEAD(head) struct wait_queue *head = NULL
       
   136    typedef  struct wait_queue *wait_queue_head_t;
       
   137 #  define init_waitqueue_head(head) (*(head)) = NULL
       
   138 
       
   139 /* offer wake_up_sync as an alias for wake_up */
       
   140 #  define wake_up_sync(head) wake_up(head)
       
   141 #  define wake_up_interruptible_sync(head) wake_up_interruptible(head)
       
   142 
       
   143 /* Pretend we have add_wait_queue_exclusive */
       
   144 #  define add_wait_queue_exclusive(q,entry) add_wait_queue ((q), (entry))
       
   145 
       
   146 #endif /* no DECLARE_WAIT_QUEUE_HEAD */
       
   147 
       
   148 /*
       
   149  * Define wait_event for 2.0 kernels.  (This ripped off directly from
       
   150  * the 2.2.18 sched.h)
       
   151  */
       
   152 #ifdef LINUX_20
       
   153 
       
   154 #define __wait_event(wq, condition) 					\
       
   155 do {									\
       
   156 	struct wait_queue __wait;					\
       
   157 									\
       
   158 	__wait.task = current;						\
       
   159 	add_wait_queue(&wq, &__wait);					\
       
   160 	for (;;) {							\
       
   161 		current->state = TASK_UNINTERRUPTIBLE;			\
       
   162 		mb();							\
       
   163 		if (condition)						\
       
   164 			break;						\
       
   165 		schedule();						\
       
   166 	}								\
       
   167 	current->state = TASK_RUNNING;					\
       
   168 	remove_wait_queue(&wq, &__wait);				\
       
   169 } while (0)
       
   170 
       
   171 #define wait_event(wq, condition) 					\
       
   172 do {									\
       
   173 	if (condition)	 						\
       
   174 		break;							\
       
   175 	__wait_event(wq, condition);					\
       
   176 } while (0)
       
   177 
       
   178 #define __wait_event_interruptible(wq, condition, ret)			\
       
   179 do {									\
       
   180 	struct wait_queue __wait;					\
       
   181 									\
       
   182 	__wait.task = current;						\
       
   183 	add_wait_queue(&wq, &__wait);					\
       
   184 	for (;;) {							\
       
   185 		current->state = TASK_INTERRUPTIBLE;			\
       
   186 		mb();							\
       
   187 		if (condition)						\
       
   188 			break;						\
       
   189 		if (!signal_pending(current)) {				\
       
   190 			schedule();					\
       
   191 			continue;					\
       
   192 		}							\
       
   193 		ret = -ERESTARTSYS;					\
       
   194 		break;							\
       
   195 	}								\
       
   196 	current->state = TASK_RUNNING;					\
       
   197 	remove_wait_queue(&wq, &__wait);				\
       
   198 } while (0)
       
   199 	
       
   200 #define wait_event_interruptible(wq, condition)				\
       
   201 ({									\
       
   202 	int __ret = 0;							\
       
   203 	if (!(condition))						\
       
   204 		__wait_event_interruptible(wq, condition, __ret);	\
       
   205 	__ret;								\
       
   206 })
       
   207 #endif
       
   208 
       
   209 
       
   210 /*
       
   211  * 2.3 added tasklets
       
   212  */
       
   213 #ifdef LINUX_24
       
   214 #  define HAVE_TASKLETS
       
   215 #endif
       
   216 
       
   217 
       
   218 
       
   219 
       
   220 /* FIXME: implement the other versions of wake_up etc */
       
   221 
       
   222 
       
   223 /*
       
   224  * access to user space: use the 2.2 functions,
       
   225  * and implement them as macros for 2.0
       
   226  */
       
   227 
       
   228 #ifdef LINUX_20
       
   229 #  include <asm/segment.h>
       
   230 #  define access_ok(t,a,sz)           (verify_area((t),(void *) (a),(sz)) ? 0 : 1)
       
   231 #  define verify_area_20              verify_area
       
   232 #  define   copy_to_user(t,f,n)         (memcpy_tofs((t), (f), (n)), 0)
       
   233 #  define copy_from_user(t,f,n)       (memcpy_fromfs((t), (f), (n)), 0)
       
   234 #  define   __copy_to_user(t,f,n)       copy_to_user((t), (f), (n))
       
   235 #  define __copy_from_user(t,f,n)     copy_from_user((t), (f), (n))
       
   236 
       
   237 #  define PUT_USER(val,add)           (put_user((val),(add)), 0)
       
   238 #  define __PUT_USER(val,add)         PUT_USER((val),(add))
       
   239 
       
   240 #  define GET_USER(dest,add)          ((dest)=get_user((add)), 0)
       
   241 #  define __GET_USER(dest,add)        GET_USER((dest),(add))
       
   242 #else
       
   243 #  include <asm/uaccess.h>
       
   244 #  include <asm/io.h>
       
   245 #  define verify_area_20(t,a,sz) (0) /* == success */
       
   246 #  define   PUT_USER   put_user
       
   247 #  define __PUT_USER __put_user
       
   248 #  define   GET_USER   get_user
       
   249 #  define __GET_USER __get_user
       
   250 #endif
       
   251 
       
   252 /*
       
   253  * Allocation issues
       
   254  */
       
   255 #ifdef GFP_USER /* only if mm.h has been included */
       
   256 #  ifdef LINUX_20
       
   257 #    define __GFP_DMA GFP_DMA /* 2.0 didn't have the leading __ */
       
   258 #  endif
       
   259 #  ifndef LINUX_24
       
   260 #    define __GFP_HIGHMEM  0  /* was not there */
       
   261 #    define GFP_HIGHUSER   0   /* idem */
       
   262 #  endif
       
   263 
       
   264 #  ifdef LINUX_20
       
   265 #    define __get_free_pages(a,b) __get_free_pages((a),(b),0)
       
   266 #  endif
       
   267 #  ifndef LINUX_24
       
   268 #    define get_zeroed_page get_free_page
       
   269 #  endif
       
   270 #endif
       
   271 
       
   272 /* ioremap */
       
   273 #if defined(LINUX_20) && defined(_LINUX_MM_H)
       
   274 #  define ioremap_nocache ioremap
       
   275 #  ifndef __i386__
       
   276    /* This simple approach works for non-PC platforms. */
       
   277 #    define ioremap vremap
       
   278 #    define iounmap vfree
       
   279 #  else /* the PC has <expletive> ISA; 2.2 and 2.4 remap it, 2.0 needs not */
       
   280 extern inline void *ioremap(unsigned long phys_addr, unsigned long size)
       
   281 {
       
   282     if (phys_addr >= 0xA0000 && phys_addr + size <= 0x100000)
       
   283         return (void *)phys_addr;
       
   284     return vremap(phys_addr, size);
       
   285 }
       
   286 
       
   287 extern inline void iounmap(void *addr)
       
   288 {
       
   289     if ((unsigned long)addr >= 0xA0000
       
   290             && (unsigned long)addr < 0x100000)
       
   291         return;
       
   292     vfree(addr);
       
   293 }
       
   294 #  endif
       
   295 #endif
       
   296 
       
   297 /* Also, define check_mem_region etc */
       
   298 #ifndef LINUX_24
       
   299 #  define check_mem_region(a,b)     0 /* success */
       
   300 #  define request_mem_region(a,b,c) /* nothing */
       
   301 #  define release_mem_region(a,b)   /* nothing */
       
   302 #endif
       
   303 
       
   304 /* implement capable() for 2.0 */
       
   305 #ifdef LINUX_20
       
   306 #  define capable(anything)  suser()
       
   307 #endif
       
   308 
       
   309 /* The use_count of exec_domain and binfmt changed in 2.1.23 */
       
   310 
       
   311 #ifdef LINUX_20
       
   312 #  define INCRCOUNT(p)  ((p)->module ? __MOD_INC_USE_COUNT((p)->module) : 0)
       
   313 #  define DECRCOUNT(p)  ((p)->module ? __MOD_DEC_USE_COUNT((p)->module) : 0)
       
   314 #  define CURRCOUNT(p)  ((p)->module && (p)->module->usecount)
       
   315 #else
       
   316 #  define INCRCOUNT(p)  ((p)->use_count++)
       
   317 #  define DECRCOUNT(p)  ((p)->use_count--)
       
   318 #  define CURRCOUNT(p)  ((p)->use_count)
       
   319 #endif
       
   320 
       
   321 /*
       
   322  * /proc has changed a lot across the versions...
       
   323  */
       
   324 #ifdef LINUX_20
       
   325 #  define USE_PROC_REGISTER
       
   326 #endif
       
   327 
       
   328 
       
   329 /*
       
   330  * 2.2 didn't have create_proc_{read|info}_entry yet.
       
   331  * And it looks like there are no other "interesting" entry point, as
       
   332  * the rest is somehow esotique (mknod, symlink, ...)
       
   333  */
       
   334 #ifdef LINUX_22
       
   335 #  ifdef PROC_SUPER_MAGIC  /* Only if procfs is being used */
       
   336 extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
       
   337                           mode_t mode, struct proc_dir_entry *base, 
       
   338                           read_proc_t *read_proc, void * data)
       
   339 {
       
   340     struct proc_dir_entry *res=create_proc_entry(name,mode,base);
       
   341     if (res) {
       
   342         res->read_proc=read_proc;
       
   343         res->data=data;
       
   344     }
       
   345     return res;
       
   346 }
       
   347 
       
   348 #    ifndef create_proc_info_entry /* added in 2.2.18 */
       
   349 typedef int (get_info_t)(char *, char **, off_t, int, int);
       
   350 extern inline struct proc_dir_entry *create_proc_info_entry(const char *name,
       
   351         mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
       
   352 {
       
   353         struct proc_dir_entry *res=create_proc_entry(name,mode,base);
       
   354         if (res) res->get_info=get_info;
       
   355         return res;
       
   356 }
       
   357 #    endif  /* no create_proc_info_entry */
       
   358 #  endif
       
   359 #endif
       
   360 
       
   361 #ifdef LINUX_20
       
   362 #  define test_and_set_bit(nr,addr)  test_bit((nr),(addr))
       
   363 #  define test_and_clear_bit(nr,addr) clear_bit((nr),(addr))
       
   364 #  define test_and_change_bit(nr,addr) change_bit((nr),(addr))
       
   365 #endif
       
   366 
       
   367 
       
   368 /* 2.0 had no read and write memory barriers, and 2.2 lacks the
       
   369    set_ functions */
       
   370 #ifndef LINUX_24
       
   371 #  ifdef LINUX_20
       
   372 #    define wmb() mb() /* this is a big penalty on non-reordering platfs */
       
   373 #    define rmb() mb() /* this is a big penalty on non-reordering platfs */
       
   374 #  endif /* LINUX_20 */
       
   375 
       
   376 #define set_mb() do { var = value; mb(); } while (0)
       
   377 #define set_wmb() do { var = value; wmb(); } while (0)
       
   378 #endif /* ! LINUX_24 */
       
   379 
       
   380 
       
   381 
       
   382 /* 2.1.30 removed these functions. Let's define them, just in case */
       
   383 #ifndef LINUX_20
       
   384 #  define queue_task_irq      queue_task
       
   385 #  define queue_task_irq_off  queue_task
       
   386 #endif
       
   387 
       
   388 /* 2.1.10 and 2.1.43 introduced new functions. They are worth using */
       
   389 
       
   390 #ifdef LINUX_20
       
   391 
       
   392 #  include <asm/byteorder.h>
       
   393 #  ifdef __LITTLE_ENDIAN
       
   394 #    define cpu_to_le16(x) (x)
       
   395 #    define cpu_to_le32(x) (x)
       
   396 #    define cpu_to_be16(x) htons((x))
       
   397 #    define cpu_to_be32(x) htonl((x))
       
   398 #  else
       
   399 #    define cpu_to_be16(x) (x)
       
   400 #    define cpu_to_be32(x) (x)
       
   401      extern inline __u16 cpu_to_le16(__u16 x) { return (x<<8) | (x>>8);}
       
   402      extern inline __u32 cpu_to_le32(__u32 x) { return (x>>24) |
       
   403              ((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24);}
       
   404 #  endif
       
   405 
       
   406 #  define le16_to_cpu(x)  cpu_to_le16(x)
       
   407 #  define le32_to_cpu(x)  cpu_to_le32(x)
       
   408 #  define be16_to_cpu(x)  cpu_to_be16(x)
       
   409 #  define be32_to_cpu(x)  cpu_to_be32(x)
       
   410 
       
   411 #  define cpu_to_le16p(addr) (cpu_to_le16(*(addr)))
       
   412 #  define cpu_to_le32p(addr) (cpu_to_le32(*(addr)))
       
   413 #  define cpu_to_be16p(addr) (cpu_to_be16(*(addr)))
       
   414 #  define cpu_to_be32p(addr) (cpu_to_be32(*(addr)))
       
   415 
       
   416    extern inline void cpu_to_le16s(__u16 *a) {*a = cpu_to_le16(*a);}
       
   417    extern inline void cpu_to_le32s(__u16 *a) {*a = cpu_to_le32(*a);}
       
   418    extern inline void cpu_to_be16s(__u16 *a) {*a = cpu_to_be16(*a);}
       
   419    extern inline void cpu_to_be32s(__u16 *a) {*a = cpu_to_be32(*a);}
       
   420 
       
   421 #  define le16_to_cpup(x) cpu_to_le16p(x)
       
   422 #  define le32_to_cpup(x) cpu_to_le32p(x)
       
   423 #  define be16_to_cpup(x) cpu_to_be16p(x)
       
   424 #  define be32_to_cpup(x) cpu_to_be32p(x)
       
   425 
       
   426 #  define le16_to_cpus(x) cpu_to_le16s(x)
       
   427 #  define le32_to_cpus(x) cpu_to_le32s(x)
       
   428 #  define be16_to_cpus(x) cpu_to_be16s(x)
       
   429 #  define be32_to_cpus(x) cpu_to_be32s(x)
       
   430 
       
   431 #endif
       
   432 
       
   433 #ifdef LINUX_20
       
   434 #  define __USE_OLD_REBUILD_HEADER__
       
   435 #endif
       
   436 
       
   437 /*
       
   438  * 2.0 didn't include sema_init, so we make our own - but only if it
       
   439  * looks like semaphore.h got included.
       
   440  */
       
   441 #ifdef LINUX_20
       
   442 #  ifdef MUTEX_LOCKED   /* Only if semaphore.h included */
       
   443      extern inline void sema_init (struct semaphore *sem, int val)
       
   444      {
       
   445          sem->count = val;
       
   446          sem->waking = sem->lock = 0;
       
   447          sem->wait = NULL;
       
   448      }
       
   449 #  endif
       
   450 #endif /* LINUX_20 */
       
   451 
       
   452 /*
       
   453  * In 2.0, there is no real need for spinlocks, and they weren't really
       
   454  * implemented anyway.
       
   455  *
       
   456  * XXX the _irqsave variant should be defined eventually to do the
       
   457  * right thing.
       
   458  */
       
   459 #ifdef LINUX_20
       
   460 typedef int spinlock_t;
       
   461 #  define spin_lock(lock)
       
   462 #  define spin_unlock(lock)
       
   463 #  define spin_lock_init(lock)
       
   464 
       
   465 #  define spin_lock_irqsave(lock,flags) do { \
       
   466         save_flags(flags); cli(); } while (0);
       
   467 #  define spin_unlock_irqrestore(lock,flags) restore_flags(flags);
       
   468 #endif
       
   469 
       
   470 /*
       
   471  * 2.1 stuffed the "flush" method into the middle of the file_operations
       
   472  * structure.  The FOP_NO_FLUSH symbol is for drivers that do not implement
       
   473  * flush (most of them), it can be inserted in initializers for all 2.x
       
   474  * kernel versions.
       
   475  */
       
   476 #ifdef LINUX_20
       
   477 #  define FOP_NO_FLUSH   /* nothing */
       
   478 #  define TAG_LLSEEK    lseek
       
   479 #  define TAG_POLL      select
       
   480 #else
       
   481 #  define FOP_NO_FLUSH  NULL,
       
   482 #  define TAG_LLSEEK    llseek
       
   483 #  define TAG_POLL      poll
       
   484 #endif
       
   485 
       
   486 
       
   487 
       
   488 /*
       
   489  * fasync changed in 2.2.
       
   490  */
       
   491 #ifdef LINUX_20
       
   492 /*  typedef struct inode *fasync_file; */
       
   493 #  define fasync_file struct inode *
       
   494 #else
       
   495   typedef int fasync_file;
       
   496 #endif
       
   497 
       
   498 /* kill_fasync had less arguments, and a different indirection in the first */
       
   499 #ifndef LINUX_24
       
   500 #  define kill_fasync(ptrptr,sig,band)  kill_fasync(*(ptrptr),(sig))
       
   501 #endif
       
   502 
       
   503 /* other things that are virtualized: define the new functions for the old k */
       
   504 #ifdef LINUX_20
       
   505 #  define in_interrupt() (intr_count!=0)
       
   506 #  define mdelay(x) udelay((x)*1000)
       
   507 #  define signal_pending(current)  ((current)->signal & ~(current)->blocked)
       
   508 #endif
       
   509 
       
   510 #ifdef LINUX_PCI_H /* only if PCI stuff is being used */
       
   511 #  ifdef LINUX_20
       
   512 #    include "pci-compat.h" /* a whole set of replacement functions */
       
   513 #  else
       
   514 #    define  pci_release_device(d) /* placeholder, used in 2.0 to free stuff */
       
   515 #  endif
       
   516 #endif
       
   517 
       
   518 
       
   519 
       
   520 /*
       
   521  * Some task state stuff
       
   522  */
       
   523 
       
   524 #ifndef set_current_state
       
   525 #  define set_current_state(s) current->state = (s);
       
   526 #endif
       
   527 
       
   528 #ifdef LINUX_20
       
   529 extern inline void schedule_timeout(int timeout)
       
   530 {
       
   531     current->timeout = jiffies + timeout;
       
   532     current->state = TASK_INTERRUPTIBLE;
       
   533     schedule();
       
   534     current->timeout = 0;
       
   535 }
       
   536 
       
   537 extern inline long sleep_on_timeout(wait_queue_head_t *q, signed long timeout)
       
   538 {
       
   539     signed long early = 0;
       
   540         
       
   541     current->timeout = jiffies + timeout;
       
   542     sleep_on (q);
       
   543     if (current->timeout > 0) {
       
   544         early = current->timeout - jiffies;
       
   545         current->timeout = 0;
       
   546     }
       
   547     return early;
       
   548 }
       
   549 
       
   550 
       
   551 extern inline long interruptible_sleep_on_timeout(wait_queue_head_t *q,
       
   552                 signed long timeout)
       
   553 {
       
   554     signed long early = 0;
       
   555         
       
   556     current->timeout = jiffies + timeout;
       
   557     interruptible_sleep_on (q);
       
   558     if (current->timeout > 0) {
       
   559         early = current->timeout - jiffies;
       
   560         current->timeout = 0;
       
   561     }
       
   562     return early;
       
   563 }
       
   564 
       
   565 #endif /* LINUX_20 */
       
   566 
       
   567 /*
       
   568  * Schedule_task was a late 2.4 addition.
       
   569  */
       
   570 #ifndef LINUX_24
       
   571 extern inline int schedule_task(struct tq_struct *task)
       
   572 {
       
   573         queue_task(task, &tq_scheduler);
       
   574         return 1;
       
   575 }
       
   576 #endif
       
   577 
       
   578 
       
   579 /*
       
   580  * Timing issues
       
   581  */
       
   582 #ifdef LINUX_20
       
   583 #  define get_fast_time do_gettimeofday
       
   584 #endif
       
   585 
       
   586 #ifdef _LINUX_DELAY_H /* only if linux/delay.h is included */
       
   587 #  ifndef mdelay /* linux-2.0 */
       
   588 #    ifndef MAX_UDELAY_MS
       
   589 #      define MAX_UDELAY_MS   5
       
   590 #    endif
       
   591 #    define mdelay(n) (\
       
   592         (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
       
   593         ({unsigned long msec=(n); while (msec--) udelay(1000);}))
       
   594 #  endif /* mdelay */
       
   595 #endif /* _LINUX_DELAY_H */
       
   596 
       
   597 
       
   598 /*
       
   599  * No del_timer_sync before 2.4
       
   600  */
       
   601 #ifndef LINUX_24
       
   602 #  define del_timer_sync(timer) del_timer(timer)  /* and hope */
       
   603 #endif
       
   604 
       
   605 /*
       
   606  * mod_timer wasn't present in 2.0
       
   607  */
       
   608 #ifdef LINUX_20
       
   609 static inline int mod_timer(struct timer_list *timer, unsigned long expires)
       
   610 {
       
   611     int pending = del_timer(timer);
       
   612     if (pending) {
       
   613         timer->expires = expires;
       
   614         add_timer(timer);
       
   615     }
       
   616     return pending;
       
   617 }
       
   618 #endif
       
   619 /*
       
   620  * Various changes in mmap and friends.
       
   621  */
       
   622 
       
   623 #ifndef NOPAGE_SIGBUS
       
   624 #  define NOPAGE_SIGBUS  NULL  /* return value of the nopage memory method */
       
   625 #  define NOPAGE_OOM     NULL  /* No real equivalent in older kernels */
       
   626 #endif
       
   627 
       
   628 #ifndef VM_RESERVED            /* Added 2.4.0-test10 */
       
   629 #  define VM_RESERVED 0
       
   630 #endif
       
   631 
       
   632 #ifdef LINUX_24 /* use "vm_pgoff" to get an offset */
       
   633 #define VMA_OFFSET(vma)  ((vma)->vm_pgoff << PAGE_SHIFT)
       
   634 #else /* use "vm_offset" */
       
   635 #define VMA_OFFSET(vma)  ((vma)->vm_offset)
       
   636 #endif
       
   637 
       
   638 #ifdef MAP_NR
       
   639 #define virt_to_page(page) (mem_map + MAP_NR(page))
       
   640 #endif
       
   641 
       
   642 #ifndef get_page
       
   643 #  define get_page(p) atomic_inc(&(p)->count)
       
   644 #endif
       
   645 
       
   646 /*
       
   647  * No DMA lock in 2.0.
       
   648  */
       
   649 #ifdef LINUX_20
       
   650 static inline unsigned long claim_dma_lock(void)
       
   651 {
       
   652     unsigned long flags;
       
   653     save_flags(flags);
       
   654     cli();
       
   655     return flags;
       
   656 }
       
   657 
       
   658 static inline void release_dma_lock(unsigned long flags)
       
   659 {
       
   660     restore_flags(flags);
       
   661 }
       
   662 #endif
       
   663 
       
   664 
       
   665 /*
       
   666  * I/O memory was not managed by ealier kernels, define them as success
       
   667  */
       
   668 
       
   669 #if 0 /* FIXME: what is the right way to do request_mem_region? */
       
   670 #ifndef LINUX_24
       
   671 #  define check_mem_region(start, len)          0
       
   672 #  define request_mem_region(start, len, name)  0
       
   673 #  define release_mem_region(start, len)        0
       
   674 
       
   675    /*
       
   676     * Also, request_ and release_ region used to return void. Return 0 instead
       
   677     */
       
   678 #  define request_region(s, l, n)  ({request_region((s),(l),(n));0;})
       
   679 #  define release_region(s, l)     ({release_region((s),(l));0;})
       
   680 
       
   681 #endif /* not LINUX_24 */
       
   682 #endif
       
   683 
       
   684 /*
       
   685  * Block layer stuff.
       
   686  */
       
   687 #ifndef LINUX_24
       
   688 
       
   689 /* BLK_DEFAULT_QUEUE for use with these macros only!!!! */
       
   690 #define BLK_DEFAULT_QUEUE(major) blk_dev[(major)].request_fn
       
   691 #define blk_init_queue(where,request_fn) where = request_fn;
       
   692 #define blk_cleanup_queue(where) where = NULL;
       
   693 
       
   694 /* No QUEUE_EMPTY in older kernels */
       
   695 #ifndef QUEUE_EMPTY  /* Driver can redefine it too */
       
   696 #  define QUEUE_EMPTY (CURRENT != NULL)
       
   697 #endif
       
   698 
       
   699 #ifdef RO_IOCTLS
       
   700 static inline int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
       
   701 {
       
   702     int err;
       
   703 
       
   704     switch (cmd) {
       
   705       case BLKRAGET: /* return the readahead value */
       
   706         if (!arg)  return -EINVAL;
       
   707         err = ! access_ok(VERIFY_WRITE, arg, sizeof(long));
       
   708         if (err) return -EFAULT;
       
   709         PUT_USER(read_ahead[MAJOR(dev)],(long *) arg);
       
   710         return 0;
       
   711 
       
   712       case BLKRASET: /* set the readahead value */
       
   713         if (!capable(CAP_SYS_ADMIN)) return -EACCES;
       
   714         if (arg > 0xff) return -EINVAL; /* limit it */
       
   715         read_ahead[MAJOR(dev)] = arg;
       
   716         return 0;
       
   717 
       
   718       case BLKFLSBUF: /* flush */
       
   719         if (! capable(CAP_SYS_ADMIN)) return -EACCES; /* only root */
       
   720         fsync_dev(dev);
       
   721         invalidate_buffers(dev);
       
   722         return 0;
       
   723 
       
   724         RO_IOCTLS(dev, arg);
       
   725     }
       
   726     return -ENOTTY;
       
   727 }
       
   728 #endif  /* RO_IOCTLS */
       
   729 
       
   730 #ifdef LINUX_EXTENDED_PARTITION /* defined in genhd.h */
       
   731 static inline void register_disk(struct gendisk *gdev, kdev_t dev,
       
   732                 unsigned minors, struct file_operations *ops, long size)
       
   733 {
       
   734     if (! gdev)
       
   735         return;
       
   736     resetup_one_dev(gdev, MINOR(dev) >> gdev->minor_shift);
       
   737 }
       
   738 #endif /* LINUX_EXTENDED_PARTITION */
       
   739 
       
   740 
       
   741 #else  /* it is Linux 2.4 */
       
   742 #define HAVE_BLKPG_H
       
   743 #endif /* LINUX_24 */
       
   744 
       
   745 
       
   746 
       
   747 #ifdef LINUX_20 /* physical and virtual addresses had the same value */
       
   748 #  define __pa(a) (a)
       
   749 #  define __va(a) (a)
       
   750 #endif
       
   751 
       
   752 /*
       
   753  * Network driver compatibility
       
   754  */
       
   755 
       
   756 /*
       
   757  * 2.0 dev_kfree_skb had an extra arg.  The following is a little dangerous
       
   758  * in that it assumes that FREE_WRITE is always wanted.  Very few 2.0 drivers
       
   759  * use FREE_READ, but the number is *not* zero...
       
   760  *
       
   761  * Also: implement the non-checking versions of a couple skb functions -
       
   762  * but they still check in 2.0.
       
   763  */
       
   764 #ifdef LINUX_20
       
   765 #  define dev_kfree_skb(skb) dev_kfree_skb((skb), FREE_WRITE);
       
   766 
       
   767 #  define __skb_push(skb, len) skb_push((skb), (len))
       
   768 #  define __skb_put(skb, len)  skb_put((skb), (len))
       
   769 #endif
       
   770 
       
   771 /*
       
   772  * Softnet changes in 2.4
       
   773  */
       
   774 #ifndef LINUX_24
       
   775 #  ifdef _LINUX_NETDEVICE_H /* only if netdevice.h was included */
       
   776 #  define netif_start_queue(dev) clear_bit(0, (void *) &(dev)->tbusy);
       
   777 #  define netif_stop_queue(dev)  set_bit(0, (void *) &(dev)->tbusy);
       
   778 
       
   779 static inline void netif_wake_queue(struct device *dev)
       
   780 {
       
   781     clear_bit(0, (void *) &(dev)->tbusy);
       
   782     mark_bh(NET_BH);
       
   783 }
       
   784 
       
   785 /* struct device became struct net_device */
       
   786 #  define net_device device
       
   787 #  endif /* netdevice.h */
       
   788 #endif /* ! LINUX_24 */
       
   789 
       
   790 /*
       
   791  * Memory barrier stuff, define what's missing from older kernel versions
       
   792  */
       
   793 #ifdef switch_to /* this is always a macro, defined in <asm/sysstem.h> */
       
   794 
       
   795 #  ifndef set_mb
       
   796 #    define set_mb(var, value) do {(var) = (value); mb();}  while 0
       
   797 #  endif
       
   798 #  ifndef set_rmb
       
   799 #    define set_rmb(var, value) do {(var) = (value); rmb();}  while 0
       
   800 #  endif
       
   801 #  ifndef set_wmb
       
   802 #    define set_wmb(var, value) do {(var) = (value); wmb();}  while 0
       
   803 #  endif
       
   804 
       
   805 /* The hw barriers are defined as sw barriers. A correct thing if this
       
   806    specific kernel/platform is supported but has no specific instruction */
       
   807 #  ifndef mb
       
   808 #    define mb barrier
       
   809 #  endif
       
   810 #  ifndef rmb
       
   811 #    define rmb barrier
       
   812 #  endif
       
   813 #  ifndef wmb
       
   814 #    define wmb barrier
       
   815 #  endif
       
   816 
       
   817 #endif /* switch to (i.e. <asm/system.h>) */
       
   818 
       
   819 
       
   820 #endif /* _SYSDEP_H_ */