|
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_ */ |