From 8dc6d803a2f815d32525a98cb9e1fb1e006011d5 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 17 Aug 2001 23:33:36 +0000 Subject: 2001-08-18 Marcus Brinkmann * linux/src/drivers/net/eepro100.c: File updated to version in Linux 2.2.19. * linux/src/include/asm-i386/spinlock.h: New file from Linux 2.2.19. * linux/src/include/asm-i386/hardirq.h: Likewise. * linux/src/include/linux/spinlock.h: Likewise. * linux/src/include/linux/compatmac.h: Likewise. * linux/dev/drivers/net/eepro100.c: New file, modified version from the above to glue it in gnumach. Submitted by Kapil H. Paranjape . --- linux/src/include/asm-i386/hardirq.h | 65 +++++++++ linux/src/include/asm-i386/spinlock.h | 262 ++++++++++++++++++++++++++++++++++ linux/src/include/linux/compatmac.h | 152 ++++++++++++++++++++ linux/src/include/linux/spinlock.h | 4 + 4 files changed, 483 insertions(+) create mode 100644 linux/src/include/asm-i386/hardirq.h create mode 100644 linux/src/include/asm-i386/spinlock.h create mode 100644 linux/src/include/linux/compatmac.h create mode 100644 linux/src/include/linux/spinlock.h (limited to 'linux/src/include') diff --git a/linux/src/include/asm-i386/hardirq.h b/linux/src/include/asm-i386/hardirq.h new file mode 100644 index 0000000..5339613 --- /dev/null +++ b/linux/src/include/asm-i386/hardirq.h @@ -0,0 +1,65 @@ +#ifndef __ASM_HARDIRQ_H +#define __ASM_HARDIRQ_H + +#include + +extern unsigned int local_irq_count[NR_CPUS]; + +/* + * Are we in an interrupt context? Either doing bottom half + * or hardware interrupt processing? + */ +#define in_interrupt() ({ int __cpu = smp_processor_id(); \ + (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); }) + +#ifndef __SMP__ + +#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_endlock(cpu) do { } while (0) + +#define hardirq_enter(cpu) (local_irq_count[cpu]++) +#define hardirq_exit(cpu) (local_irq_count[cpu]--) + +#define synchronize_irq() barrier() + +#else + +#include + +extern unsigned char global_irq_holder; +extern unsigned volatile int global_irq_lock; +extern atomic_t global_irq_count; + +static inline void release_irqlock(int cpu) +{ + /* if we didn't own the irq lock, just ignore.. */ + if (global_irq_holder == (unsigned char) cpu) { + global_irq_holder = NO_PROC_ID; + clear_bit(0,&global_irq_lock); + } +} + +static inline void hardirq_enter(int cpu) +{ + ++local_irq_count[cpu]; + atomic_inc(&global_irq_count); +} + +static inline void hardirq_exit(int cpu) +{ + atomic_dec(&global_irq_count); + --local_irq_count[cpu]; +} + +static inline int hardirq_trylock(int cpu) +{ + return !atomic_read(&global_irq_count) && !test_bit(0,&global_irq_lock); +} + +#define hardirq_endlock(cpu) do { } while (0) + +extern void synchronize_irq(void); + +#endif /* __SMP__ */ + +#endif /* __ASM_HARDIRQ_H */ diff --git a/linux/src/include/asm-i386/spinlock.h b/linux/src/include/asm-i386/spinlock.h new file mode 100644 index 0000000..18119d4 --- /dev/null +++ b/linux/src/include/asm-i386/spinlock.h @@ -0,0 +1,262 @@ +#ifndef __ASM_SPINLOCK_H +#define __ASM_SPINLOCK_H + +#ifndef __SMP__ + +#define DEBUG_SPINLOCKS 0 /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */ + +#if (DEBUG_SPINLOCKS < 1) + +/* + * Your basic spinlocks, allowing only a single CPU anywhere + * + * Gcc-2.7.x has a nasty bug with empty initializers. + */ +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) + typedef struct { } spinlock_t; + #define SPIN_LOCK_UNLOCKED (spinlock_t) { } +#else + typedef struct { int gcc_is_buggy; } spinlock_t; + #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +#endif + +#define spin_lock_init(lock) do { } while(0) +#define spin_lock(lock) (void)(lock) /* Not "unused variable". */ +#define spin_trylock(lock) (1) +#define spin_unlock_wait(lock) do { } while(0) +#define spin_unlock(lock) do { } while(0) +#define spin_lock_irq(lock) cli() +#define spin_unlock_irq(lock) sti() + +#define spin_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define spin_unlock_irqrestore(lock, flags) \ + restore_flags(flags) + +#elif (DEBUG_SPINLOCKS < 2) + +typedef struct { + volatile unsigned int lock; +} spinlock_t; +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } + +#define spin_lock_init(x) do { (x)->lock = 0; } while (0) +#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) + +#define spin_lock(x) do { (x)->lock = 1; } while (0) +#define spin_unlock_wait(x) do { } while (0) +#define spin_unlock(x) do { (x)->lock = 0; } while (0) +#define spin_lock_irq(x) do { cli(); spin_lock(x); } while (0) +#define spin_unlock_irq(x) do { spin_unlock(x); sti(); } while (0) + +#define spin_lock_irqsave(x, flags) \ + do { save_flags(flags); spin_lock_irq(x); } while (0) +#define spin_unlock_irqrestore(x, flags) \ + do { spin_unlock(x); restore_flags(flags); } while (0) + +#else /* (DEBUG_SPINLOCKS >= 2) */ + +typedef struct { + volatile unsigned int lock; + volatile unsigned int babble; + const char *module; +} spinlock_t; +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ } + +#include + +#define spin_lock_init(x) do { (x)->lock = 0; } while (0) +#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) + +#define spin_lock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0) +#define spin_unlock_wait(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0) +#define spin_unlock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0) +#define spin_lock_irq(x) do {cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0) +#define spin_unlock_irq(x) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irq(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; sti();} while (0) + +#define spin_lock_irqsave(x,flags) do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0) +#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0) + +#endif /* DEBUG_SPINLOCKS */ + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + * + * Gcc-2.7.x has a nasty bug with empty initializers. + */ +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) + typedef struct { } rwlock_t; + #define RW_LOCK_UNLOCKED (rwlock_t) { } +#else + typedef struct { int gcc_is_buggy; } rwlock_t; + #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } +#endif + +#define read_lock(lock) (void)(lock) /* Not "unused variable." */ +#define read_unlock(lock) do { } while(0) +#define write_lock(lock) (void)(lock) /* Not "unused variable." */ +#define write_unlock(lock) do { } while(0) +#define read_lock_irq(lock) cli() +#define read_unlock_irq(lock) sti() +#define write_lock_irq(lock) cli() +#define write_unlock_irq(lock) sti() + +#define read_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define read_unlock_irqrestore(lock, flags) \ + restore_flags(flags) +#define write_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define write_unlock_irqrestore(lock, flags) \ + restore_flags(flags) + +#else /* __SMP__ */ + +/* + * Your basic spinlocks, allowing only a single CPU anywhere + */ + +typedef struct { + volatile unsigned int lock; +} spinlock_t; + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } + +#define spin_lock_init(x) do { (x)->lock = 0; } while(0) +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ + +#define spin_unlock_wait(x) do { barrier(); } while(((volatile spinlock_t *)(x))->lock) + +typedef struct { unsigned long a[100]; } __dummy_lock_t; +#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) + +/* + * Intel PIV would benefit from using 'rep nop' here but on older + * processors and non intel it is listed as 'undefined' so cannot be + * blindly used. On 2.4 we should add a PIV CPU type for this one. + */ +#define spin_lock_string \ + "\n1:\t" \ + "lock ; btsl $0,%0\n\t" \ + "jc 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\t" \ + "rep; nop\n\t" \ + "testb $1,%0\n\t" \ + "jne 2b\n\t" \ + "jmp 1b\n" \ + ".previous" + +#define spin_unlock_string \ + "lock ; btrl $0,%0" + +#define spin_lock(lock) \ +__asm__ __volatile__( \ + spin_lock_string \ + :"=m" (__dummy_lock(lock))) + +#define spin_unlock(lock) \ +__asm__ __volatile__( \ + spin_unlock_string \ + :"=m" (__dummy_lock(lock))) + +#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) + +#define spin_lock_irq(lock) \ + do { __cli(); spin_lock(lock); } while (0) + +#define spin_unlock_irq(lock) \ + do { spin_unlock(lock); __sti(); } while (0) + +#define spin_lock_irqsave(lock, flags) \ + do { __save_flags(flags); __cli(); spin_lock(lock); } while (0) + +#define spin_unlock_irqrestore(lock, flags) \ + do { spin_unlock(lock); __restore_flags(flags); } while (0) + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ +typedef struct { + volatile unsigned int lock; + unsigned long previous; +} rwlock_t; + +#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } + +/* + * On x86, we implement read-write locks as a 32-bit counter + * with the high bit (sign) being the "write" bit. + * + * The inline assembly is non-obvious. Think about it. + */ +#define read_lock(rw) \ + asm volatile("\n1:\t" \ + "lock ; incl %0\n\t" \ + "js 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tlock ; decl %0\n" \ + "3:\trep; nop\n\t" \ + "cmpl $0,%0\n\t" \ + "js 3b\n\t" \ + "jmp 1b\n" \ + ".previous" \ + :"=m" (__dummy_lock(&(rw)->lock))) + +#define read_unlock(rw) \ + asm volatile("lock ; decl %0" \ + :"=m" (__dummy_lock(&(rw)->lock))) + +#define write_lock(rw) \ + asm volatile("\n1:\t" \ + "lock ; btsl $31,%0\n\t" \ + "jc 4f\n" \ + "2:\ttestl $0x7fffffff,%0\n\t" \ + "jne 3f\n" \ + ".section .text.lock,\"ax\"\n" \ + "3:\tlock ; btrl $31,%0\n" \ + "4:\trep; nop\n\t" \ + "cmp $0,%0\n\t" \ + "jne 4b\n\t" \ + "jmp 1b\n" \ + ".previous" \ + :"=m" (__dummy_lock(&(rw)->lock))) + +#define write_unlock(rw) \ + asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock))) + +#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0) +#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0) +#define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0) +#define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0) + +#define read_lock_irqsave(lock, flags) \ + do { __save_flags(flags); __cli(); read_lock(lock); } while (0) +#define read_unlock_irqrestore(lock, flags) \ + do { read_unlock(lock); __restore_flags(flags); } while (0) +#define write_lock_irqsave(lock, flags) \ + do { __save_flags(flags); __cli(); write_lock(lock); } while (0) +#define write_unlock_irqrestore(lock, flags) \ + do { write_unlock(lock); __restore_flags(flags); } while (0) + +#endif /* __SMP__ */ +#endif /* __ASM_SPINLOCK_H */ diff --git a/linux/src/include/linux/compatmac.h b/linux/src/include/linux/compatmac.h new file mode 100644 index 0000000..5f9175d --- /dev/null +++ b/linux/src/include/linux/compatmac.h @@ -0,0 +1,152 @@ + /* + * This header tries to allow you to write 2.3-compatible drivers, + * but (using this header) still allows you to run them on 2.2 and + * 2.0 kernels. + * + * Sometimes, a #define replaces a "construct" that older kernels + * had. For example, + * + * DECLARE_MUTEX(name); + * + * replaces the older + * + * struct semaphore name = MUTEX; + * + * This file then declares the DECLARE_MUTEX macro to compile into the + * older version. + * + * In some cases, a macro or function changes the number of arguments. + * In that case, there is nothing we can do except define an access + * macro that provides the same functionality on both versions of Linux. + * + * This is the case for example with the "get_user" macro 2.0 kernels use: + * + * a = get_user (b); + * + * while newer kernels use + * + * get_user (a,b); + * + * This is unfortunate. We therefore define "Get_user (a,b)" which looks + * almost the same as the 2.2+ construct, and translates into the + * appropriate sequence for earlier constructs. + * + * Supported by this file are the 2.0 kernels, 2.2 kernels, and the + * most recent 2.3 kernel. 2.3 support will be dropped as soon when 2.4 + * comes out. 2.0 support may someday be dropped. But then again, maybe + * not. + * + * I'll try to maintain this, provided that Linus agrees with the setup. + * Feel free to mail updates or suggestions. + * + * -- R.E.Wolff@BitWizard.nl + * + */ + +#ifndef COMPATMAC_H +#define COMPATMAC_H + +#include + +#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */ +#define TWO_ZERO +#else +#if LINUX_VERSION_CODE < 0x020200 /* less than 2.2.x */ +#warning "Please use a 2.2.x kernel. " +#else +#if LINUX_VERSION_CODE < 0x020300 /* less than 2.3.x */ +#define TWO_TWO +#else +#define TWO_THREE +#endif +#endif +#endif + +#ifdef TWO_ZERO + +/* Here is the section that makes the 2.2 compatible driver source + work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, + and provide for compatibility stuff here if possible. */ + +/* Some 200 days (on intel) */ +#define MAX_SCHEDULE_TIMEOUT ((long)(~0UL>>1)) + +#include + +#define Get_user(a,b) a = get_user(b) +#define Put_user(a,b) 0,put_user(a,b) +#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) + +static inline int copy_from_user(void *to,const void *from, int c) +{ + memcpy_fromfs(to, from, c); + return 0; +} + +#define pci_present pcibios_present +#define pci_read_config_word pcibios_read_config_word +#define pci_read_config_dword pcibios_read_config_dword + +static inline unsigned char get_irq (unsigned char bus, unsigned char fn) +{ + unsigned char t; + pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t); + return t; +} + +static inline void *ioremap(unsigned long base, long length) +{ + if (base < 0x100000) return (void *)base; + return vremap (base, length); +} + +#define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x)) + +#define capable(x) suser() + +#define queue_task queue_task_irq_off +#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) +#define signal_pending(current) (current->signal & ~current->blocked) +#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) +#define time_after(t1,t2) (((long)t1-t2) > 0) + + +#define test_and_set_bit(nr, addr) set_bit(nr, addr) +#define test_and_clear_bit(nr, addr) clear_bit(nr, addr) + +/* Not yet implemented on 2.0 */ +#define ASYNC_SPD_SHI -1 +#define ASYNC_SPD_WARP -1 + + +/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it + to the "name" field that does exist. As long as the assignments are + done in the right order, there is nothing to worry about. */ +#define driver_name name + +/* Should be in a header somewhere. They are in tty.h on 2.2 */ +#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */ +#define TTY_HW_COOK_IN 15 /* in hardware - output and input */ + +/* The return type of a "close" routine. */ +#define INT void +#define NO_ERROR /* Nothing */ + +#else + +/* The 2.2.x compatibility section. */ +#include + + +#define Get_user(a,b) get_user(a,b) +#define Put_user(a,b) put_user(a,b) +#define get_irq(pdev) pdev->irq + +#define INT int +#define NO_ERROR 0 + +#define my_iounmap(x,b) (iounmap((char *)(b))) + +#endif + +#endif diff --git a/linux/src/include/linux/spinlock.h b/linux/src/include/linux/spinlock.h new file mode 100644 index 0000000..790ac18 --- /dev/null +++ b/linux/src/include/linux/spinlock.h @@ -0,0 +1,4 @@ +#ifndef __LINUX_SPINLOCK_H +#define __LINUX_SPINLOCK_H +#include +#endif -- cgit v1.2.3