diff options
Diffstat (limited to 'include/asm-m68k')
29 files changed, 1243 insertions, 628 deletions
diff --git a/include/asm-m68k/amigahw.h b/include/asm-m68k/amigahw.h index 39dd49979..d63ceca32 100644 --- a/include/asm-m68k/amigahw.h +++ b/include/asm-m68k/amigahw.h @@ -281,7 +281,7 @@ struct CIA { #define CHIP_PHYSADDR (0x000000) #define chipaddr ((unsigned long)(zTwoBase + CHIP_PHYSADDR)) void amiga_chip_init (void); -void *amiga_chip_alloc (long size); +void *amiga_chip_alloc (long size, const char *name); void amiga_chip_free (void *); unsigned long amiga_chip_avail( void ); /*MILAN*/ diff --git a/include/asm-m68k/apollodma.h b/include/asm-m68k/apollodma.h new file mode 100644 index 000000000..3abef61cb --- /dev/null +++ b/include/asm-m68k/apollodma.h @@ -0,0 +1,248 @@ +/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $ + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + */ + +#ifndef _ASM_APOLLO_DMA_H +#define _ASM_APOLLO_DMA_H + +#include <asm/apollohw.h> /* need byte IO */ +#include <asm/spinlock.h> /* And spinlocks */ +#include <linux/delay.h> + + +#define dma_outb(val,addr) (*((volatile unsigned char *)(addr+IO_BASE)) = (val)) +#define dma_inb(addr) (*((volatile unsigned char *)(addr+IO_BASE))) + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * DMA transfers are limited to the lower 16MB of _physical_ memory. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +#define MAX_DMA_CHANNELS 8 + +/* The maximum address that we can perform a DMA transfer to on this platform */#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000) + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x10C00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0x10D00 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG (IO_DMA1_BASE+0x08) /* command register (w) */ +#define DMA1_STAT_REG (IO_DMA1_BASE+0x08) /* status register (r) */ +#define DMA1_REQ_REG (IO_DMA1_BASE+0x09) /* request register (w) */ +#define DMA1_MASK_REG (IO_DMA1_BASE+0x0A) /* single-channel mask (w) */ +#define DMA1_MODE_REG (IO_DMA1_BASE+0x0B) /* mode register (w) */ +#define DMA1_CLEAR_FF_REG (IO_DMA1_BASE+0x0C) /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG (IO_DMA1_BASE+0x0D) /* Temporary Register (r) */ +#define DMA1_RESET_REG (IO_DMA1_BASE+0x0D) /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG (IO_DMA1_BASE+0x0E) /* Clear Mask */ +#define DMA1_MASK_ALL_REG (IO_DMA1_BASE+0x0F) /* all-channels mask (w) */ + +#define DMA2_CMD_REG (IO_DMA2_BASE+0x10) /* command register (w) */ +#define DMA2_STAT_REG (IO_DMA2_BASE+0x10) /* status register (r) */ +#define DMA2_REQ_REG (IO_DMA2_BASE+0x12) /* request register (w) */ +#define DMA2_MASK_REG (IO_DMA2_BASE+0x14) /* single-channel mask (w) */ +#define DMA2_MODE_REG (IO_DMA2_BASE+0x16) /* mode register (w) */ +#define DMA2_CLEAR_FF_REG (IO_DMA2_BASE+0x18) /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG (IO_DMA2_BASE+0x1A) /* Temporary Register (r) */ +#define DMA2_RESET_REG (IO_DMA2_BASE+0x1A) /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG (IO_DMA2_BASE+0x1C) /* Clear Mask */ +#define DMA2_MASK_ALL_REG (IO_DMA2_BASE+0x1E) /* all-channels mask (w) */ + +#define DMA_ADDR_0 (IO_DMA1_BASE+0x00) /* DMA address registers */ +#define DMA_ADDR_1 (IO_DMA1_BASE+0x02) +#define DMA_ADDR_2 (IO_DMA1_BASE+0x04) +#define DMA_ADDR_3 (IO_DMA1_BASE+0x06) +#define DMA_ADDR_4 (IO_DMA2_BASE+0x00) +#define DMA_ADDR_5 (IO_DMA2_BASE+0x04) +#define DMA_ADDR_6 (IO_DMA2_BASE+0x08) +#define DMA_ADDR_7 (IO_DMA2_BASE+0x0C) + +#define DMA_CNT_0 (IO_DMA1_BASE+0x01) /* DMA count registers */ +#define DMA_CNT_1 (IO_DMA1_BASE+0x03) +#define DMA_CNT_2 (IO_DMA1_BASE+0x05) +#define DMA_CNT_3 (IO_DMA1_BASE+0x07) +#define DMA_CNT_4 (IO_DMA2_BASE+0x02) +#define DMA_CNT_5 (IO_DMA2_BASE+0x06) +#define DMA_CNT_6 (IO_DMA2_BASE+0x0A) +#define DMA_CNT_7 (IO_DMA2_BASE+0x0E) + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + +#define DMA_8BIT 0 +#define DMA_16BIT 1 +#define DMA_BUSMASTER 2 + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr, DMA1_MASK_REG); + else + dma_outb(dmanr & 3, DMA2_MASK_REG); +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while holding the DMA lock ! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) +{ + if (dmanr <= 3) { + dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } +} + + +/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr<=3)? count : (count<<1); +} + + +/* These are in kernel/dma.c: */ +extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ +extern void free_dma(unsigned int dmanr); /* release it again */ + +/* These are in arch/m68k/apollo/dma.c: */ +extern unsigned short dma_map_page(unsigned long phys_addr,int count,int type); +extern void dma_unmap_page(unsigned short dma_addr); + +#endif /* _ASM_APOLLO_DMA_H */ diff --git a/include/asm-m68k/apollohw.h b/include/asm-m68k/apollohw.h index 54177aa3d..e12a638ca 100644 --- a/include/asm-m68k/apollohw.h +++ b/include/asm-m68k/apollohw.h @@ -3,6 +3,18 @@ #ifndef _ASMm68k_APOLLOHW_H_ #define _ASMm68k_APOLLOHW_H_ +/* + apollo models +*/ + +extern u_long apollo_model; + +#define APOLLO_UNKNOWN (0) +#define APOLLO_DN3000 (1) +#define APOLLO_DN3010 (2) +#define APOLLO_DN3500 (3) +#define APOLLO_DN4000 (4) +#define APOLLO_DN4500 (5) /* see scn2681 data sheet for more info. @@ -52,16 +64,42 @@ struct mc146818 { unsigned char month, year; }; + #define IO_BASE 0x80000000 -#define SIO01_PHYSADDR 0x10400 -#define SIO23_PHYSADDR 0x10500 -#define RTC_PHYSADDR 0x10900 -#define PICA 0x11000 -#define PICB 0x11100 -#define sio01 ((*(volatile struct SCN2681 *)(IO_BASE + SIO01_PHYSADDR))) -#define sio23 ((*(volatile struct SCN2681 *)(IO_BASE + SIO01_PHYSADDR))) -#define rtc (((volatile struct mc146818 *)(IO_BASE + RTC_PHYSADDR))) +extern u_long sio01_physaddr; +extern u_long sio23_physaddr; +extern u_long rtc_physaddr; +extern u_long pica_physaddr; +extern u_long picb_physaddr; +extern u_long cpuctrl_physaddr; +extern u_long timer_physaddr; + +#define SAU7_SIO01_PHYSADDR 0x10400 +#define SAU7_SIO23_PHYSADDR 0x10500 +#define SAU7_RTC_PHYSADDR 0x10900 +#define SAU7_PICA 0x11000 +#define SAU7_PICB 0x11100 +#define SAU7_CPUCTRL 0x10100 +#define SAU7_TIMER 0x010800 + +#define SAU8_SIO01_PHYSADDR 0x8400 +#define SAU8_RTC_PHYSADDR 0x8900 +#define SAU8_PICA 0x9400 +#define SAU8_PICB 0x9500 +#define SAU8_CPUCTRL 0x8100 +#define SAU8_TIMER 0x8800 + +#define sio01 ((*(volatile struct SCN2681 *)(IO_BASE + sio01_physaddr))) +#define sio23 ((*(volatile struct SCN2681 *)(IO_BASE + sio23_physaddr))) +#define rtc (((volatile struct mc146818 *)(IO_BASE + rtc_physaddr))) +#define cpuctrl (*(volatile unsigned int *)(IO_BASE + cpuctrl_physaddr)) +#define pica (IO_BASE + pica_physaddr) +#define picb (IO_BASE + picb_physaddr) +#define timer (IO_BASE + timer_physaddr) +#define addr_xlat_map ((unsigned short *)(IO_BASE + 0x17000)) + +#define isaIO2mem(x) (((((x) & 0x3f8) << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE) #define inb(addr) (*((volatile unsigned char *)(addr))) #define outb(val,addr) (*((volatile unsigned char *)(addr)) = (val)) diff --git a/include/asm-m68k/bootinfo.h b/include/asm-m68k/bootinfo.h index 871d051fe..19f340b5c 100644 --- a/include/asm-m68k/bootinfo.h +++ b/include/asm-m68k/bootinfo.h @@ -103,6 +103,30 @@ struct bi_record { #define ATARI_MACH_AB40 3 /* Afterburner040 on Falcon */ /* + * VME-specific tags + */ + +#define BI_VME_TYPE 0x8000 /* VME sub-architecture (u_long) */ +#define BI_VME_BRDINFO 0x8001 /* VME board information (struct) */ + +/* BI_VME_TYPE codes */ +#define VME_TYPE_TP34V 0x0034 /* Tadpole TP34V */ +#define VME_TYPE_MVME147 0x0147 /* Motorola MVME147 */ +#define VME_TYPE_MVME162 0x0162 /* Motorola MVME162 */ +#define VME_TYPE_MVME166 0x0166 /* Motorola MVME166 */ +#define VME_TYPE_MVME167 0x0167 /* Motorola MVME167 */ +#define VME_TYPE_MVME172 0x0172 /* Motorola MVME172 */ +#define VME_TYPE_MVME177 0x0177 /* Motorola MVME177 */ +#define VME_TYPE_BVME4000 0x4000 /* BVM Ltd. BVME4000 */ +#define VME_TYPE_BVME6000 0x6000 /* BVM Ltd. BVME6000 */ + +/* BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on + * Motorola VME boards. Contains board number, Bug version, board + * configuration options, etc. See include/asm/mvme16xhw.h for details. + */ + + + /* * Macintosh-specific tags (all u_long) */ @@ -184,6 +208,14 @@ extern struct mac_booter_data #endif /* + * Apollo-specific tags + */ + +#define BI_APOLLO_MODEL 0x8000 /* model (u_long) */ + + + + /* * Stuff for bootinfo interface versioning * * At the start of kernel code, a 'struct bootversion' is located. diff --git a/include/asm-m68k/bvme6000hw.h b/include/asm-m68k/bvme6000hw.h index 853120a04..28a859b03 100644 --- a/include/asm-m68k/bvme6000hw.h +++ b/include/asm-m68k/bvme6000hw.h @@ -95,6 +95,7 @@ typedef struct { #define BVME_SCC_A_ADDR 0xffb0000b #define BVME_SCC_B_ADDR 0xffb00003 +#define BVME_SCC_RTxC 7372800 #define BVME_CONFIG_REG 0xff500003 diff --git a/include/asm-m68k/cache.h b/include/asm-m68k/cache.h index 9e009ce18..52262e891 100644 --- a/include/asm-m68k/cache.h +++ b/include/asm-m68k/cache.h @@ -7,16 +7,4 @@ /* bytes per L1 cache line */ #define L1_CACHE_BYTES 16 -#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) - -#define SMP_CACHE_BYTES L1_CACHE_BYTES - -#ifdef MODULE -#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES))) -#else -#define __cacheline_aligned \ - __attribute__((__aligned__(L1_CACHE_BYTES), \ - __section__(".data.cacheline_aligned"))) -#endif - #endif diff --git a/include/asm-m68k/div64.h b/include/asm-m68k/div64.h new file mode 100644 index 000000000..16bf1f88d --- /dev/null +++ b/include/asm-m68k/div64.h @@ -0,0 +1,35 @@ +#ifndef _M68K_DIV64_H +#define _M68K_DIV64_H + +/* n = n / base; return rem; */ + +#if 1 +#define do_div(n, base) ({ \ + union { \ + unsigned long n32[2]; \ + unsigned long long n64; \ + } __n; \ + unsigned long __rem, __upper; \ + \ + __n.n64 = (n); \ + if ((__upper = __n.n32[0])) { \ + asm ("divul.l %2,%1:%0" \ + : "=d" (__n.n32[0]), "=d" (__upper) \ + : "d" (base), "0" (__n.n32[0])); \ + } \ + asm ("divu.l %2,%1:%0" \ + : "=d" (__n.n32[1]), "=d" (__rem) \ + : "d" (base), "1" (__upper), "0" (__n.n32[1])); \ + (n) = __n.n64; \ + __rem; \ +}) +#else +#define do_div(n,base) ({ \ + int __res; \ + __res = ((unsigned long) n) % (unsigned) base; \ + n = ((unsigned long) n) / (unsigned) base; \ + __res; \ +}) +#endif + +#endif /* _M68K_DIV64_H */ diff --git a/include/asm-m68k/dma.h b/include/asm-m68k/dma.h index af73a0f6f..d5266a886 100644 --- a/include/asm-m68k/dma.h +++ b/include/asm-m68k/dma.h @@ -1,12 +1,21 @@ #ifndef _M68K_DMA_H #define _M68K_DMA_H 1 -/* Don't define MAX_DMA_ADDRESS; it's useless on the m68k and any - occurrence should be flagged as an error. */ +#include <linux/config.h> + +/* it's useless on the m68k, but unfortunately needed by the new + bootmem allocator (but this should do it for this) */ +#define MAX_DMA_ADDRESS PAGE_OFFSET #define MAX_DMA_CHANNELS 8 extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ extern void free_dma(unsigned int dmanr); /* release it again */ +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + #endif /* _M68K_DMA_H */ diff --git a/include/asm-m68k/entry.h b/include/asm-m68k/entry.h index 56ab0dcf8..3575894b5 100644 --- a/include/asm-m68k/entry.h +++ b/include/asm-m68k/entry.h @@ -34,10 +34,6 @@ * the whole kernel. */ -#ifdef __ASSEMBLY__ - -#define curptr a2 - /* the following macro is used when enabling interrupts */ #if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES) /* block out HSYNC on the atari */ @@ -49,6 +45,10 @@ #define MAX_NOINT_IPL 0 #endif /* machine compilation types */ +#ifdef __ASSEMBLY__ + +#define curptr a2 + LFLUSH_I_AND_D = 0x00000808 LSIGTRAP = 5 @@ -162,7 +162,7 @@ PF_DTRACE_BIT = 5 #endif #define GET_CURRENT(tmp) \ "movel %%sp,"#tmp"\n\t" \ - "andw #-KTHREAD_SIZE,"#tmp"\n\t" \ + "andw #-"STR(KTHREAD_SIZE)","#tmp"\n\t" \ "movel "#tmp",%%a2" #endif diff --git a/include/asm-m68k/fcntl.h b/include/asm-m68k/fcntl.h index 2235bd5bb..b5780416f 100644 --- a/include/asm-m68k/fcntl.h +++ b/include/asm-m68k/fcntl.h @@ -18,6 +18,8 @@ #define FASYNC 020000 /* fcntl, for BSD compatibility */ #define O_DIRECTORY 040000 /* must be a directory */ #define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ +#define O_LARGEFILE 0400000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h index 6e8e0d4ac..0e3cd0c6f 100644 --- a/include/asm-m68k/hardirq.h +++ b/include/asm-m68k/hardirq.h @@ -10,8 +10,8 @@ extern unsigned int local_irq_count[NR_CPUS]; #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 irq_enter(cpu) (local_irq_count[cpu]++) +#define irq_exit(cpu) (local_irq_count[cpu]--) #define synchronize_irq() barrier() diff --git a/include/asm-m68k/mmu_context.h b/include/asm-m68k/mmu_context.h index a8a1dfc61..f54fbfa17 100644 --- a/include/asm-m68k/mmu_context.h +++ b/include/asm-m68k/mmu_context.h @@ -7,6 +7,7 @@ #include <asm/setup.h> #include <asm/page.h> +#include <asm/pgalloc.h> extern inline void init_new_context(struct task_struct *tsk, struct mm_struct *mm) diff --git a/include/asm-m68k/movs.h b/include/asm-m68k/movs.h index 67dbea369..540d3e60e 100644 --- a/include/asm-m68k/movs.h +++ b/include/asm-m68k/movs.h @@ -10,46 +10,46 @@ /* Set DFC register value */ #define SET_DFC(x) \ - __asm__ __volatile__ (" movec %0,%/dfc" : : "d" (x)); + __asm__ __volatile__ ("movec %0,%%dfc" : : "r" (x)) /* Get DFC register value */ #define GET_DFC(x) \ - __asm__ __volatile__ (" movec %/dfc, %0" : "=d" (x) : ); + __asm__ __volatile__ ("movec %%dfc,%0" : "=r" (x)) /* Set SFC register value */ #define SET_SFC(x) \ - __asm__ __volatile__ (" movec %0,%/sfc" : : "d" (x)); + __asm__ __volatile__ ("movec %0,%%sfc" : : "r" (x)) /* Get SFC register value */ #define GET_SFC(x) \ - __asm__ __volatile__ (" movec %/sfc, %0" : "=d" (x) : ); + __asm__ __volatile__ ("movec %%sfc,%0" : "=r" (x)) #define SET_VBR(x) \ - __asm__ __volatile__ (" movec %0,%/vbr" : : "r" (x)); + __asm__ __volatile__ ("movec %0,%%vbr" : : "r" (x)) #define GET_VBR(x) \ - __asm__ __volatile__ (" movec %/vbr, %0" : "=g" (x) : ); + __asm__ __volatile__ ("movec %%vbr,%0" : "=r" (x)) -/* Set a byte using the "movs" instruction */ +/* Set a byte using the "moves" instruction */ #define SET_CONTROL_BYTE(addr,value) \ - __asm__ __volatile__ (" movsb %0, %1@" : : "d" (value), "a" (addr)); + __asm__ __volatile__ ("movesb %1,%0" : "=m" (addr) : "d" (value)) -/* Get a byte using the "movs" instruction */ +/* Get a byte using the "moves" instruction */ #define GET_CONTROL_BYTE(addr,value) \ - __asm__ __volatile__ (" movsb %1@, %0" : "=d" (value) : "a" (addr)); + __asm__ __volatile__ ("movesb %1,%0" : "=d" (value) : "m" (addr)) -/* Set a (long)word using the "movs" instruction */ +/* Set a (long)word using the "moves" instruction */ #define SET_CONTROL_WORD(addr,value) \ - __asm__ __volatile__ (" movsl %0, %1@" : : "d" (value), "a" (addr)); + __asm__ __volatile__ ("movesl %1,%0" : "=m" (addr) : "r" (value)) -/* Get a (long)word using the "movs" instruction */ +/* Get a (long)word using the "moves" instruction */ #define GET_CONTROL_WORD(addr,value) \ - __asm__ __volatile__ (" movsl %1@, %0" : "=d" (value) : "a" (addr)); + __asm__ __volatile__ ("movesl %1,%0" : "=d" (value) : "m" (addr)) #endif diff --git a/include/asm-m68k/mvme147hw.h b/include/asm-m68k/mvme147hw.h index f57216b9e..195a50893 100644 --- a/include/asm-m68k/mvme147hw.h +++ b/include/asm-m68k/mvme147hw.h @@ -85,11 +85,12 @@ struct pcc_regs { #define M147_SCC_A_ADDR 0xfffe3002 #define M147_SCC_B_ADDR 0xfffe3000 +#define M147_SCC_PCLK 5000000 #define MVME147_IRQ_SCSI_PORT 0x45 #define MVME147_IRQ_SCSI_DMA 0x46 -/* SCC interrupts, for MVME162 */ +/* SCC interrupts, for MVME147 */ #define MVME147_IRQ_TYPE_PRIO 0 #define MVME147_IRQ_SCC_BASE 0x60 diff --git a/include/asm-m68k/mvme16xhw.h b/include/asm-m68k/mvme16xhw.h index 75a21d8a4..4102460fb 100644 --- a/include/asm-m68k/mvme16xhw.h +++ b/include/asm-m68k/mvme16xhw.h @@ -62,6 +62,7 @@ typedef struct { #define MVME_SCC_A_ADDR 0xfff45005 #define MVME_SCC_B_ADDR 0xfff45001 +#define MVME_SCC_PCLK 10000000 #define MVME162_IRQ_TYPE_PRIO 0 diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h index 6a3d9df66..23dd731c8 100644 --- a/include/asm-m68k/page.h +++ b/include/asm-m68k/page.h @@ -25,16 +25,14 @@ #ifndef __ASSEMBLY__ -#define STRICT_MM_TYPECHECKS - -#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) #define free_user_page(page, addr) free_page(addr) /* * We don't need to check for alignment etc. */ #ifdef CPU_M68040_OR_M68060_ONLY -static inline void copy_page(unsigned long to, unsigned long from) +static inline void copy_page(void *to, void *from) { unsigned long tmp; @@ -49,11 +47,10 @@ static inline void copy_page(unsigned long to, unsigned long from) ); } -static inline void clear_page(unsigned long page) +static inline void clear_page(void *page) { - unsigned long data, sp, tmp; - - sp = page; + unsigned long data, tmp; + void *sp = page; data = 0; @@ -75,11 +72,10 @@ static inline void clear_page(unsigned long page) } #else -#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) -#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) +#define clear_page(page) memset((page), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) #endif -#ifdef STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. */ @@ -98,55 +94,29 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) -#else -/* - * .. while these make it easier on the compiler - */ -typedef unsigned long pte_t; -typedef struct { unsigned long pmd[16]; } pmd_t; -typedef unsigned long pgd_t; -typedef unsigned long pgprot_t; +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -#define pte_val(x) (x) -#define pmd_val(x) ((&x)->pmd[0]) -#define pgd_val(x) (x) -#define pgprot_val(x) (x) +#endif /* !__ASSEMBLY__ */ -#define __pte(x) (x) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) (x) -#define __pgprot(x) (x) +#include <asm/page_offset.h> -#endif +#define PAGE_OFFSET (PAGE_OFFSET_RAW) -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) +#ifndef __ASSEMBLY__ -/* This handles the memory map.. */ #ifndef CONFIG_SUN3 -#define PAGE_OFFSET 0 + +#ifdef CONFIG_SINGLE_MEMORY_CHUNK +extern unsigned long m68k_memoffset; + +#define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset) +#define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset)) #else -#define PAGE_OFFSET 0x0E000000 +#define __pa(vaddr) virt_to_phys((void *)vaddr) +#define __va(paddr) phys_to_virt((unsigned long)paddr) #endif -#ifndef CONFIG_SUN3 -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -/* - * A hacky workaround for the problems with mmap() of frame buffer - * memory in the lower 16MB physical memoryspace. - * - * This is a short term solution, we will have to deal properly - * with this in 2.3.x. - */ -extern inline void *__va(unsigned long physaddr) -{ -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA && (physaddr < 16*1024*1024)) - return (void *)0xffffffff; - else -#endif - return (void *)(physaddr+PAGE_OFFSET); -} #else /* !CONFIG_SUN3 */ /* This #define is a horrible hack to suppress lots of warnings. --m */ #define __pa(x) ___pa((unsigned long)x) @@ -172,9 +142,7 @@ static inline void *__va(unsigned long x) } #endif /* CONFIG_SUN3 */ -#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) - -#endif /* !__ASSEMBLY__ */ +#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) #ifndef CONFIG_SUN3 #define BUG() do { \ @@ -192,6 +160,8 @@ static inline void *__va(unsigned long x) BUG(); \ } while (0) +#endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif /* _M68K_PAGE_H */ diff --git a/include/asm-m68k/page_offset.h b/include/asm-m68k/page_offset.h new file mode 100644 index 000000000..39e30499c --- /dev/null +++ b/include/asm-m68k/page_offset.h @@ -0,0 +1,9 @@ +#include <linux/config.h> + +/* This handles the memory map.. */ +#ifndef CONFIG_SUN3 +#define PAGE_OFFSET_RAW 0x00000000 +#else +#define PAGE_OFFSET_RAW 0x0E000000 +#endif + diff --git a/include/asm-m68k/pci.h b/include/asm-m68k/pci.h new file mode 100644 index 000000000..76915264d --- /dev/null +++ b/include/asm-m68k/pci.h @@ -0,0 +1,38 @@ +#ifndef _ASM_M68K_PCI_H +#define _ASM_M68K_PCI_H + +/* + * asm-m68k/pci_m68k.h - m68k specific PCI declarations. + * + * Written by Wout Klaren. + */ + +struct pci_ops; + +/* + * Structure with hardware dependent information and functions of the + * PCI bus. + */ + +struct pci_bus_info +{ + /* + * Resources of the PCI bus. + */ + + struct resource mem_space; + struct resource io_space; + + /* + * System dependent functions. + */ + + struct pci_ops *m68k_pci_ops; + + void (*fixup)(int pci_modify); + void (*conf_device)(unsigned char bus, unsigned char device_fn); +}; + +#define pcibios_assign_all_busses() 0 + +#endif /* _ASM_M68K_PCI_H */ diff --git a/include/asm-m68k/pgalloc.h b/include/asm-m68k/pgalloc.h new file mode 100644 index 000000000..3d2a2b87d --- /dev/null +++ b/include/asm-m68k/pgalloc.h @@ -0,0 +1,399 @@ +#ifndef _M68K_PGALLOC_H +#define _M68K_PGALLOC_H + +#include <asm/setup.h> +#include <asm/virtconvert.h> + +extern struct pgtable_cache_struct { + unsigned long *pmd_cache; + unsigned long *pte_cache; +/* This counts in units of pointer tables, of which can be eight per page. */ + unsigned long pgtable_cache_sz; +} quicklists; + +#define pgd_quicklist ((unsigned long *)0) +#define pmd_quicklist (quicklists.pmd_cache) +#define pte_quicklist (quicklists.pte_cache) +/* This isn't accurate because of fragmentation of allocated pages for + pointer tables, but that should not be a problem. */ +#define pgtable_cache_size ((quicklists.pgtable_cache_sz+7)/8) + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset); +extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset); + +extern pmd_t *get_pointer_table(void); +extern int free_pointer_table(pmd_t *); + +extern inline pte_t *get_pte_fast(void) +{ + unsigned long *ret; + + ret = pte_quicklist; + if (ret) { + pte_quicklist = (unsigned long *)*ret; + ret[0] = 0; + quicklists.pgtable_cache_sz -= 8; + } + return (pte_t *)ret; +} + +extern inline void free_pte_fast(pte_t *pte) +{ + *(unsigned long *)pte = (unsigned long)pte_quicklist; + pte_quicklist = (unsigned long *)pte; + quicklists.pgtable_cache_sz += 8; +} + +extern inline void free_pte_slow(pte_t *pte) +{ + cache_page((unsigned long)pte); + free_page((unsigned long) pte); +} + +extern inline pmd_t *get_pmd_fast(void) +{ + unsigned long *ret; + + ret = pmd_quicklist; + if (ret) { + pmd_quicklist = (unsigned long *)*ret; + ret[0] = 0; + quicklists.pgtable_cache_sz--; + } + return (pmd_t *)ret; +} + +extern inline void free_pmd_fast(pmd_t *pmd) +{ + *(unsigned long *)pmd = (unsigned long)pmd_quicklist; + pmd_quicklist = (unsigned long *) pmd; + quicklists.pgtable_cache_sz++; +} + +extern inline int free_pmd_slow(pmd_t *pmd) +{ + return free_pointer_table(pmd); +} + +/* The pgd cache is folded into the pmd cache, so these are dummy routines. */ +extern inline pgd_t *get_pgd_fast(void) +{ + return (pgd_t *)0; +} + +extern inline void free_pgd_fast(pgd_t *pgd) +{ +} + +extern inline void free_pgd_slow(pgd_t *pgd) +{ +} + +extern void __bad_pte(pmd_t *pmd); +extern void __bad_pmd(pgd_t *pgd); + +extern inline void pte_free(pte_t *pte) +{ + free_pte_fast(pte); +} + +extern inline pte_t *pte_alloc(pmd_t *pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t *page = get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_set(pmd,page); + return page + address; + } + if (pmd_bad(*pmd)) { + __bad_pte(pmd); + return NULL; + } + return (pte_t *)__pmd_page(*pmd) + address; +} + +extern inline void pmd_free(pmd_t *pmd) +{ + free_pmd_fast(pmd); +} + +extern inline pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address) +{ + address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + if (pgd_none(*pgd)) { + pmd_t *page = get_pmd_fast(); + + if (!page) + return get_pmd_slow(pgd, address); + pgd_set(pgd, page); + return page + address; + } + if (pgd_bad(*pgd)) { + __bad_pmd(pgd); + return NULL; + } + return (pmd_t *)__pgd_page(*pgd) + address; +} + +extern inline void pte_free_kernel(pte_t *pte) +{ + free_pte_fast(pte); +} + +extern inline pte_t *pte_alloc_kernel(pmd_t *pmd, unsigned long address) +{ + return pte_alloc(pmd, address); +} + +extern inline void pmd_free_kernel(pmd_t *pmd) +{ + free_pmd_fast(pmd); +} + +extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +{ + return pmd_alloc(pgd, address); +} + +extern inline void pgd_free(pgd_t *pgd) +{ + free_pmd_fast((pmd_t *)pgd); +} + +extern inline pgd_t *pgd_alloc(void) +{ + pgd_t *pgd = (pgd_t *)get_pmd_fast(); + if (!pgd) + pgd = (pgd_t *)get_pointer_table(); + return pgd; +} + +extern int do_check_pgt_cache(int, int); + +extern inline void set_pgdir(unsigned long address, pgd_t entry) +{ +} + + +/* + * Cache handling functions + */ + +#define flush_icache() \ +({ \ + if (CPU_IS_040_OR_060) \ + __asm__ __volatile__("nop\n\t" \ + ".chip 68040\n\t" \ + "cinva %%ic\n\t" \ + ".chip 68k" : ); \ + else { \ + unsigned long _tmp; \ + __asm__ __volatile__("movec %%cacr,%0\n\t" \ + "orw %1,%0\n\t" \ + "movec %0,%%cacr" \ + : "=&d" (_tmp) \ + : "id" (FLUSH_I)); \ + } \ +}) + +/* + * invalidate the cache for the specified memory range. + * It starts at the physical address specified for + * the given number of bytes. + */ +extern void cache_clear(unsigned long paddr, int len); +/* + * push any dirty cache in the specified memory range. + * It starts at the physical address specified for + * the given number of bytes. + */ +extern void cache_push(unsigned long paddr, int len); + +/* + * push and invalidate pages in the specified user virtual + * memory range. + */ +extern void cache_push_v(unsigned long vaddr, int len); + +/* cache code */ +#define FLUSH_I_AND_D (0x00000808) +#define FLUSH_I (0x00000008) + +/* This is needed whenever the virtual mapping of the current + process changes. */ +#define __flush_cache_all() \ +({ \ + if (CPU_IS_040_OR_060) \ + __asm__ __volatile__("nop\n\t" \ + ".chip 68040\n\t" \ + "cpusha %dc\n\t" \ + ".chip 68k"); \ + else { \ + unsigned long _tmp; \ + __asm__ __volatile__("movec %%cacr,%0\n\t" \ + "orw %1,%0\n\t" \ + "movec %0,%%cacr" \ + : "=&d" (_tmp) \ + : "di" (FLUSH_I_AND_D)); \ + } \ +}) + +#define __flush_cache_030() \ +({ \ + if (CPU_IS_020_OR_030) { \ + unsigned long _tmp; \ + __asm__ __volatile__("movec %%cacr,%0\n\t" \ + "orw %1,%0\n\t" \ + "movec %0,%%cacr" \ + : "=&d" (_tmp) \ + : "di" (FLUSH_I_AND_D)); \ + } \ +}) + +#define flush_cache_all() __flush_cache_all() + +extern inline void flush_cache_mm(struct mm_struct *mm) +{ + if (mm == current->mm) + __flush_cache_030(); +} + +extern inline void flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + if (mm == current->mm) + __flush_cache_030(); +} + +extern inline void flush_cache_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ + if (vma->vm_mm == current->mm) + __flush_cache_030(); +} + +/* Push the page at kernel virtual address and clear the icache */ +#define flush_page_to_ram(page) __flush_page_to_ram(page_address(page)) +extern inline void __flush_page_to_ram(unsigned long address) +{ + if (CPU_IS_040_OR_060) { + __asm__ __volatile__("nop\n\t" + ".chip 68040\n\t" + "cpushp %%dc,(%0)\n\t" + "cinvp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (__pa((void *)address))); + } else { + unsigned long _tmp; + __asm__ __volatile__("movec %%cacr,%0\n\t" + "orw %1,%0\n\t" + "movec %0,%%cacr" + : "=&d" (_tmp) + : "di" (FLUSH_I)); + } +} + +/* Push n pages at kernel virtual address and clear the icache */ +extern inline void flush_icache_range (unsigned long address, + unsigned long endaddr) +{ + if (CPU_IS_040_OR_060) { + short n = (endaddr - address + PAGE_SIZE - 1) / PAGE_SIZE; + + while (--n >= 0) { + __asm__ __volatile__("nop\n\t" + ".chip 68040\n\t" + "cpushp %%dc,(%0)\n\t" + "cinvp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (virt_to_phys((void *)address))); + address += PAGE_SIZE; + } + } else { + unsigned long tmp; + __asm__ __volatile__("movec %%cacr,%0\n\t" + "orw %1,%0\n\t" + "movec %0,%%cacr" + : "=&d" (tmp) + : "di" (FLUSH_I)); + } +} + + +/* + * flush all user-space atc entries. + */ +static inline void __flush_tlb(void) +{ + if (CPU_IS_040_OR_060) + __asm__ __volatile__(".chip 68040\n\t" + "pflushan\n\t" + ".chip 68k"); + else + __asm__ __volatile__("pflush #0,#4"); +} + +static inline void __flush_tlb_one(unsigned long addr) +{ + if (CPU_IS_040_OR_060) { + __asm__ __volatile__(".chip 68040\n\t" + "pflush (%0)\n\t" + ".chip 68k" + : : "a" (addr)); + } else + __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr)); +} + +#define flush_tlb() __flush_tlb() + +/* + * flush all atc entries (both kernel and user-space entries). + */ +static inline void flush_tlb_all(void) +{ + if (CPU_IS_040_OR_060) + __asm__ __volatile__(".chip 68040\n\t" + "pflusha\n\t" + ".chip 68k"); + else + __asm__ __volatile__("pflusha"); +} + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + if (mm == current->mm) + __flush_tlb(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) +{ + if (vma->vm_mm == current->mm) + __flush_tlb_one(addr); +} + +static inline void flush_tlb_range(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + if (mm == current->mm) + __flush_tlb(); +} + +extern inline void flush_tlb_kernel_page(unsigned long addr) +{ + if (CPU_IS_040_OR_060) { + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + __asm__ __volatile__(".chip 68040\n\t" + "pflush (%0)\n\t" + ".chip 68k" + : : "a" (addr)); + set_fs(old_fs); + } else + __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); +} + +#endif /* _M68K_PGALLOC_H */ diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index c94acfc38..9df773f9f 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -15,226 +15,6 @@ #include <asm/virtconvert.h> -/* - * Cache handling functions - */ - -#define flush_icache() \ -do { \ - if (CPU_IS_040_OR_060) \ - asm __volatile__ ("nop\n\t" \ - ".chip 68040\n\t" \ - "cinva %%ic\n\t" \ - ".chip 68k" : ); \ - else { \ - unsigned long _tmp; \ - asm __volatile__ ("movec %%cacr,%0\n\t" \ - "orw %1,%0\n\t" \ - "movec %0,%%cacr" \ - : "=&d" (_tmp) \ - : "id" (FLUSH_I)); \ - } \ -} while (0) - -/* - * invalidate the cache for the specified memory range. - * It starts at the physical address specified for - * the given number of bytes. - */ -extern void cache_clear (unsigned long paddr, int len); -/* - * push any dirty cache in the specified memory range. - * It starts at the physical address specified for - * the given number of bytes. - */ -extern void cache_push (unsigned long paddr, int len); - -/* - * push and invalidate pages in the specified user virtual - * memory range. - */ -extern void cache_push_v (unsigned long vaddr, int len); - -/* cache code */ -#define FLUSH_I_AND_D (0x00000808) -#define FLUSH_I (0x00000008) - -/* This is needed whenever the virtual mapping of the current - process changes. */ -#define __flush_cache_all() \ - do { \ - if (CPU_IS_040_OR_060) \ - __asm__ __volatile__ ("nop\n\t" \ - ".chip 68040\n\t" \ - "cpusha %dc\n\t" \ - ".chip 68k"); \ - else { \ - unsigned long _tmp; \ - __asm__ __volatile__ ("movec %%cacr,%0\n\t" \ - "orw %1,%0\n\t" \ - "movec %0,%%cacr" \ - : "=&d" (_tmp) \ - : "di" (FLUSH_I_AND_D)); \ - } \ - } while (0) - -#define __flush_cache_030() \ - do { \ - if (CPU_IS_020_OR_030) { \ - unsigned long _tmp; \ - __asm__ __volatile__ ("movec %%cacr,%0\n\t" \ - "orw %1,%0\n\t" \ - "movec %0,%%cacr" \ - : "=&d" (_tmp) \ - : "di" (FLUSH_I_AND_D)); \ - } \ - } while (0) - -#define flush_cache_all() __flush_cache_all() - -extern inline void flush_cache_mm(struct mm_struct *mm) -{ - if (mm == current->mm) - __flush_cache_030(); -} - -extern inline void flush_cache_range(struct mm_struct *mm, - unsigned long start, - unsigned long end) -{ - if (mm == current->mm) - __flush_cache_030(); -} - -extern inline void flush_cache_page(struct vm_area_struct *vma, - unsigned long vmaddr) -{ - if (vma->vm_mm == current->mm) - __flush_cache_030(); -} - -/* Push the page at kernel virtual address and clear the icache */ -extern inline void flush_page_to_ram (unsigned long address) -{ - if (CPU_IS_040_OR_060) { - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - "cinvp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (virt_to_phys((void *)address))); - } - else { - unsigned long _tmp; - __asm volatile ("movec %%cacr,%0\n\t" - "orw %1,%0\n\t" - "movec %0,%%cacr" - : "=&d" (_tmp) - : "di" (FLUSH_I)); - } -} - -/* Push n pages at kernel virtual address and clear the icache */ -extern inline void flush_icache_range (unsigned long address, - unsigned long endaddr) -{ - if (CPU_IS_040_OR_060) { - short n = (endaddr - address + PAGE_SIZE - 1) / PAGE_SIZE; - - while (n--) { - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - "cinvp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (virt_to_phys((void *)address))); - address += PAGE_SIZE; - } - } - else { - unsigned long _tmp; - __asm volatile ("movec %%cacr,%0\n\t" - "orw %1,%0\n\t" - "movec %0,%%cacr" - : "=&d" (_tmp) - : "di" (FLUSH_I)); - } -} - - -/* - * flush all user-space atc entries. - */ -static inline void __flush_tlb(void) -{ - if (CPU_IS_040_OR_060) - __asm__ __volatile__(".chip 68040\n\t" - "pflushan\n\t" - ".chip 68k"); - else - __asm__ __volatile__("pflush #0,#4"); -} - -static inline void __flush_tlb_one(unsigned long addr) -{ - if (CPU_IS_040_OR_060) { - __asm__ __volatile__(".chip 68040\n\t" - "pflush (%0)\n\t" - ".chip 68k" - : : "a" (addr)); - } else - __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr)); -} - -#define flush_tlb() __flush_tlb() - -/* - * flush all atc entries (both kernel and user-space entries). - */ -static inline void flush_tlb_all(void) -{ - if (CPU_IS_040_OR_060) - __asm__ __volatile__(".chip 68040\n\t" - "pflusha\n\t" - ".chip 68k"); - else - __asm__ __volatile__("pflusha"); -} - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm == current->mm) - __flush_tlb(); -} - -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long addr) -{ - if (vma->vm_mm == current->mm) - __flush_tlb_one(addr); -} - -static inline void flush_tlb_range(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - if (mm == current->mm) - __flush_tlb(); -} - -extern inline void flush_tlb_kernel_page(unsigned long addr) -{ - if (CPU_IS_040_OR_060) { - mm_segment_t old_fs = get_fs(); - set_fs(KERNEL_DS); - __asm__ __volatile__(".chip 68040\n\t" - "pflush (%0)\n\t" - ".chip 68k" - : : "a" (addr)); - set_fs(old_fs); - } else - __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); -} - /* Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following * hook is made available. @@ -391,7 +171,7 @@ extern pte_t * __bad_pagetable(void); #define BAD_PAGETABLE __bad_pagetable() #define BAD_PAGE __bad_page() -#define ZERO_PAGE(vaddr) empty_zero_page +#define ZERO_PAGE(vaddr) (mem_map + MAP_NR(empty_zero_page)) /* number of bits that fit into a memory pointer */ #define BITS_PER_PTR (8*sizeof(unsigned long)) @@ -403,67 +183,78 @@ extern pte_t * __bad_pagetable(void); /* 64-bit machines, beware! SRB. */ #define SIZEOF_PTR_LOG2 2 -/* to find an entry in a page-table */ -#define PAGE_PTR(address) \ -((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) - /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */ -#define mk_pte(page, pgprot) \ -({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)page) + pgprot_val(pgprot); __pte; }) +#define __mk_pte(page, pgprot) \ +({ \ + pte_t __pte; \ + \ + pte_val(__pte) = __pa((void *)page) + pgprot_val(pgprot); \ + __pte; \ +}) +#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot)) #define mk_pte_phys(physpage, pgprot) \ -({ pte_t __pte; pte_val(__pte) = (unsigned long)physpage + pgprot_val(pgprot); __pte; }) +({ \ + pte_t __pte; \ + \ + pte_val(__pte) = (physpage) + pgprot_val(pgprot); \ + __pte; \ +}) extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) { - int i; - unsigned long ptbl; - ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED; - for (i = 0; i < 16; i++, ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16)) - pmdp->pmd[i] = ptbl; + unsigned long ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED; + unsigned long *ptr = pmdp->pmd; + short i = 16; + while (--i >= 0) { + *ptr++ = ptbl; + ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16); + } } extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | virt_to_phys(pmdp); } - -extern inline unsigned long pte_page(pte_t pte) -{ return (unsigned long)phys_to_virt(pte_val(pte) & PAGE_MASK); } - -extern inline unsigned long pmd_page2(pmd_t *pmd) -{ return (unsigned long)phys_to_virt(pmd_val(*pmd) & _TABLE_MASK); } -#define pmd_page(pmd) pmd_page2(&(pmd)) - -extern inline unsigned long pgd_page(pgd_t pgd) -{ return (unsigned long)phys_to_virt(pgd_val(pgd) & _TABLE_MASK); } - -extern inline int pte_none(pte_t pte) { return !pte_val(pte); } -extern inline int pte_present(pte_t pte) { return pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER); } -extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } - -extern inline int pmd_none2(pmd_t *pmd) { return !pmd_val(*pmd); } -#define pmd_none(pmd) pmd_none2(&(pmd)) -extern inline int pmd_bad2(pmd_t *pmd) { return (pmd_val(*pmd) & _DESCTYPE_MASK) != _PAGE_TABLE; } -#define pmd_bad(pmd) pmd_bad2(&(pmd)) -extern inline int pmd_present2(pmd_t *pmd) { return pmd_val(*pmd) & _PAGE_TABLE; } -#define pmd_present(pmd) pmd_present2(&(pmd)) -extern inline void pmd_clear(pmd_t * pmdp) -{ - short i; - - for (i = 15; i >= 0; i--) - pmdp->pmd[i] = 0; -} - -extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE; } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_TABLE; } - -extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } +{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp); } + +#define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK)) +#define __pmd_page(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK)) +#define __pgd_page(pgd) ((unsigned long)__va(pgd_val(pgd) & _TABLE_MASK)) + +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER)) +#define pte_clear(ptep) ({ pte_val(*(ptep)) = 0; }) +#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT) + +#define pmd_none(pmd) (!pmd_val(pmd)) +#define pmd_bad(pmd) ((pmd_val(pmd) & _DESCTYPE_MASK) != _PAGE_TABLE) +#define pmd_present(pmd) (pmd_val(pmd) & _PAGE_TABLE) +#define pmd_clear(pmdp) ({ \ + unsigned long *__ptr = pmdp->pmd; \ + short __i = 16; \ + while (--__i >= 0) \ + *__ptr++ = 0; \ +}) + +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pgd_bad(pgd) ((pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE) +#define pgd_present(pgd) (pgd_val(pgd) & _PAGE_TABLE) +#define pgd_clear(pgdp) ({ pgd_val(*pgdp) = 0; }) + +/* Permanent address of a page. */ +#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; }) +#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT)) +#define pte_page(pte) (mem_map+pte_pagenr(pte)) + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), pte_val(e)) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %p(%08lx).\n", __FILE__, __LINE__, &(e), pmd_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) /* * The following only work if pte_present() is true. @@ -512,13 +303,13 @@ extern inline pgd_t * pgd_offset_k(unsigned long address) /* Find an entry in the second-level page table.. */ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { - return (pmd_t *) pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1)); + return (pmd_t *)__pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1)); } /* Find an entry in the third-level page table.. */ extern inline pte_t * pte_offset(pmd_t * pmdp, unsigned long address) { - return (pte_t *) pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); + return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); } /* @@ -559,178 +350,6 @@ static inline void cache_page (unsigned long vaddr) } } -extern struct pgtable_cache_struct { - unsigned long *pmd_cache; - unsigned long *pte_cache; -/* This counts in units of pointer tables, of which can be eight per page. */ - unsigned long pgtable_cache_sz; -} quicklists; - -#define pgd_quicklist ((unsigned long *)0) -#define pmd_quicklist (quicklists.pmd_cache) -#define pte_quicklist (quicklists.pte_cache) -/* This isn't accurate because of fragmentation of allocated pages for - pointer tables, but that should not be a problem. */ -#define pgtable_cache_size ((quicklists.pgtable_cache_sz+7)/8) - -extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset); -extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset); - -extern pmd_t *get_pointer_table(void); -extern int free_pointer_table(pmd_t *); - -extern __inline__ pte_t *get_pte_fast(void) -{ - unsigned long *ret; - - ret = pte_quicklist; - if (ret) { - pte_quicklist = (unsigned long *)*ret; - ret[0] = 0; - quicklists.pgtable_cache_sz -= 8; - } - return (pte_t *)ret; -} - -extern __inline__ void free_pte_fast(pte_t *pte) -{ - *(unsigned long *)pte = (unsigned long)pte_quicklist; - pte_quicklist = (unsigned long *)pte; - quicklists.pgtable_cache_sz += 8; -} - -extern __inline__ void free_pte_slow(pte_t *pte) -{ - cache_page((unsigned long)pte); - free_page((unsigned long) pte); -} - -extern __inline__ pmd_t *get_pmd_fast(void) -{ - unsigned long *ret; - - ret = pmd_quicklist; - if (ret) { - pmd_quicklist = (unsigned long *)*ret; - ret[0] = 0; - quicklists.pgtable_cache_sz--; - } - return (pmd_t *)ret; -} - -extern __inline__ void free_pmd_fast(pmd_t *pmd) -{ - *(unsigned long *)pmd = (unsigned long)pmd_quicklist; - pmd_quicklist = (unsigned long *) pmd; - quicklists.pgtable_cache_sz++; -} - -extern __inline__ int free_pmd_slow(pmd_t *pmd) -{ - return free_pointer_table(pmd); -} - -/* The pgd cache is folded into the pmd cache, so these are dummy routines. */ -extern __inline__ pgd_t *get_pgd_fast(void) -{ - return (pgd_t *)0; -} - -extern __inline__ void free_pgd_fast(pgd_t *pgd) -{ -} - -extern __inline__ void free_pgd_slow(pgd_t *pgd) -{ -} - -extern void __bad_pte(pmd_t *pmd); -extern void __bad_pmd(pgd_t *pgd); - -extern inline void pte_free(pte_t * pte) -{ - free_pte_fast(pte); -} - -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = get_pte_fast(); - - if (!page) - return get_pte_slow(pmd, address); - pmd_set(pmd,page); - return page + address; - } - if (pmd_bad(*pmd)) { - __bad_pte(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; -} - -extern inline void pmd_free(pmd_t * pmd) -{ - free_pmd_fast(pmd); -} - -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) -{ - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = get_pmd_fast(); - - if (!page) - return get_pmd_slow(pgd, address); - pgd_set(pgd, page); - return page + address; - } - if (pgd_bad(*pgd)) { - __bad_pmd(pgd); - return NULL; - } - return (pmd_t *) pgd_page(*pgd) + address; -} - -extern inline void pte_free_kernel(pte_t * pte) -{ - free_pte_fast(pte); -} - -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) -{ - return pte_alloc(pmd, address); -} - -extern inline void pmd_free_kernel(pmd_t * pmd) -{ - free_pmd_fast(pmd); -} - -extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) -{ - return pmd_alloc(pgd, address); -} - -extern inline void pgd_free(pgd_t * pgd) -{ - free_pmd_fast((pmd_t *)pgd); -} - -extern inline pgd_t * pgd_alloc(void) -{ - pgd_t *pgd = (pgd_t *)get_pmd_fast(); - if (!pgd) - pgd = (pgd_t *)get_pointer_table(); - return pgd; -} - -extern int do_check_pgt_cache(int, int); - -extern inline void set_pgdir(unsigned long address, pgd_t entry) -{ -} /* * Check if the addr/len goes up to the end of a physical @@ -760,21 +379,12 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, { } -/* - * I don't know what is going on here, but since these were changed, - * swapping hasn't been working on the 68040. - */ -/* With the new handling of PAGE_NONE the old definitions definitely - don't work any more. */ - -#define SWP_TYPE(entry) (((entry) >> 2) & 0x7f) -#if 0 -#define SWP_OFFSET(entry) ((entry) >> 9) -#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9)) -#else -#define SWP_OFFSET(entry) ((entry) >> PAGE_SHIFT) -#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << PAGE_SHIFT)) -#endif +/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ +#define SWP_TYPE(x) (((x).val >> 1) & 0xff) +#define SWP_OFFSET(x) ((x).val >> 10) +#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) }) +#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* __ASSEMBLY__ */ diff --git a/include/asm-m68k/poll.h b/include/asm-m68k/poll.h index f66153a74..32dcf6490 100644 --- a/include/asm-m68k/poll.h +++ b/include/asm-m68k/poll.h @@ -11,6 +11,7 @@ #define POLLWRNORM POLLOUT #define POLLRDBAND 128 #define POLLWRBAND 256 +#define POLLMSG 0x0400 struct pollfd { int fd; diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h index cb4f38230..16ab57862 100644 --- a/include/asm-m68k/semaphore.h +++ b/include/asm-m68k/semaphore.h @@ -1,6 +1,8 @@ #ifndef _M68K_SEMAPHORE_H #define _M68K_SEMAPHORE_H +#ifndef __ASSEMBLY__ + #include <linux/linkage.h> #include <linux/wait.h> #include <linux/spinlock.h> @@ -9,13 +11,14 @@ #include <asm/atomic.h> /* - * SMP- and interrupt-safe semaphores.. + * Interrupt-safe semaphores.. * * (C) Copyright 1996 Linus Torvalds * * m68k version by Andreas Schwab */ + struct semaphore { atomic_t count; atomic_t waking; @@ -180,4 +183,174 @@ extern inline void up(struct semaphore * sem) : "memory"); } + +/* rw mutexes (should that be mutices? =) -- throw rw + * spinlocks and semaphores together, and this is what we + * end up with... + * + * m68k version by Roman Zippel + */ + +struct rw_semaphore { + atomic_t count; + volatile unsigned char write_bias_granted; + volatile unsigned char read_bias_granted; + volatile unsigned char pad1; + volatile unsigned char pad2; + wait_queue_head_t wait; + wait_queue_head_t write_bias_wait; +#if WAITQUEUE_DEBUG + long __magic; + atomic_t readers; + atomic_t writers; +#endif +}; +#endif /* __ASSEMBLY__ */ + +#define RW_LOCK_BIAS 0x01000000 + +#ifndef __ASSEMBLY__ + +extern inline void down_read(struct rw_semaphore *sem) +{ + register struct rw_semaphore *__sem __asm__ ("%a1") = sem; + +#if WAITQUEUE_DEBUG + if (sem->__magic != (long)&sem->__magic) + BUG(); +#endif + __asm__ __volatile__( + "| atomic down_read operation\n\t" + "subql #1,%0@\n\t" + "jmi 2f\n" + "1:\n" + ".section .text.lock,\"ax\"\n" + ".even\n" + "2:\n\t" + "pea 1b\n\t" + "jbra __down_read_failed\n" + ".previous" + : /* no outputs */ + : "a" (__sem) + : "memory"); +#if WAITQUEUE_DEBUG + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_inc(&sem->readers); +#endif +} + +extern inline void down_write(struct rw_semaphore *sem) +{ + register struct rw_semaphore *__sem __asm__ ("%a1") = sem; + +#if WAITQUEUE_DEBUG + if (sem->__magic != (long)&sem->__magic) + BUG(); +#endif + __asm__ __volatile__( + "| atomic down_write operation\n\t" + "subl %1,%0@\n\t" + "jne 2f\n" + "1:\n" + ".section .text.lock,\"ax\"\n" + ".even\n" + "2:\n\t" + "pea 1b\n\t" + "jbra __down_write_failed\n" + ".previous" + : /* no outputs */ + : "a" (__sem), "id" (RW_LOCK_BIAS) + : "memory"); +#if WAITQUEUE_DEBUG + if (atomic_read(&sem->writers)) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + if (sem->read_bias_granted) + BUG(); + if (sem->write_bias_granted) + BUG(); + atomic_inc(&sem->writers); +#endif +} + +/* When a reader does a release, the only significant + * case is when there was a writer waiting, and we've + * bumped the count to 0: we must wake the writer up. + */ +extern inline void __up_read(struct rw_semaphore *sem) +{ + register struct rw_semaphore *__sem __asm__ ("%a1") = sem; + + __asm__ __volatile__( + "| atomic up_read operation\n\t" + "addql #1,%0@\n\t" + "jeq 2f\n" + "1:\n" + ".section .text.lock,\"ax\"\n" + ".even\n" + "2:\n\t" + "pea 1b\n\t" + "jbra __rwsem_wake\n" + ".previous" + : /* no outputs */ + : "a" (__sem) + : "memory"); +} + +extern inline void up_read(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_dec(&sem->readers); +#endif + __up_read(sem); +} + +/* releasing the writer is easy -- just release it and + * wake up any sleepers. + */ +extern inline void __up_write(struct rw_semaphore *sem) +{ + register struct rw_semaphore *__sem __asm__ ("%a1") = sem; + + __asm__ __volatile__( + "| atomic up_write operation\n\t" + "addl %1,%0@\n\t" + "jcs 2f\n" + "1:\n" + ".section .text.lock,\"ax\"\n" + ".even\n" + "2:\n\t" + "pea 1b\n\t" + "jbra __rwsem_wake\n" + ".previous" + : /* no outputs */ + : "a" (__sem), "id" (RW_LOCK_BIAS) + : "memory"); +} + +extern inline void up_write(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + if (sem->read_bias_granted) + BUG(); + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + if (atomic_read(&sem->writers) != 1) + BUG(); + atomic_dec(&sem->writers); +#endif + __up_write(sem); +} +#endif /* __ASSEMBLY__ */ + #endif diff --git a/include/asm-m68k/setup.h b/include/asm-m68k/setup.h index b2b11ed76..6d198bc5f 100644 --- a/include/asm-m68k/setup.h +++ b/include/asm-m68k/setup.h @@ -246,6 +246,9 @@ extern unsigned long m68k_machtype; extern unsigned long m68k_cputype; extern unsigned long m68k_fputype; extern unsigned long m68k_mmutype; /* Not really used yet */ +#ifdef CONFIG_VME +extern unsigned long vme_brdtype; +#endif /* * m68k_is040or060 is != 0 for a '040 or higher; diff --git a/include/asm-m68k/siginfo.h b/include/asm-m68k/siginfo.h index 2dac2b063..4061e6f72 100644 --- a/include/asm-m68k/siginfo.h +++ b/include/asm-m68k/siginfo.h @@ -24,8 +24,7 @@ typedef struct siginfo { /* kill() */ struct { pid_t _pid; /* sender's pid */ - old_uid_t _uid; /* backwards compatibility */ - uid_t _uid32; /* sender's uid */ + uid_t _uid; /* sender's uid */ } _kill; /* POSIX.1b timers */ @@ -37,19 +36,17 @@ typedef struct siginfo { /* POSIX.1b signals */ struct { pid_t _pid; /* sender's pid */ - old_uid_t _uid; /* backwards compatibility */ + uid_t _uid; /* sender's uid */ sigval_t _sigval; - uid_t _uid32; /* sender's uid */ } _rt; /* SIGCHLD */ struct { pid_t _pid; /* which child */ - old_uid_t _uid; /* backwards compatibility */ + uid_t _uid; /* sender's uid */ int _status; /* exit code */ clock_t _utime; clock_t _stime; - uid_t _uid32; /* sender's uid */ } _sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ @@ -65,18 +62,11 @@ typedef struct siginfo { } _sifields; } siginfo_t; -#define UID16_SIGINFO_COMPAT_NEEDED - /* * How these fields are to be accessed. */ #define si_pid _sifields._kill._pid -#ifdef __KERNEL__ -#define si_uid _sifields._kill._uid32 -#define si_uid16 _sifields._kill._uid -#else #define si_uid _sifields._kill._uid -#endif /* __KERNEL__ */ #define si_status _sifields._sigchld._status #define si_utime _sifields._sigchld._utime #define si_stime _sifields._sigchld._stime diff --git a/include/asm-m68k/stat.h b/include/asm-m68k/stat.h index c2145c33d..b28ce37c5 100644 --- a/include/asm-m68k/stat.h +++ b/include/asm-m68k/stat.h @@ -38,8 +38,40 @@ struct stat { unsigned long __unused5; }; -/* stat64 struct goes here -- someone please make - * it mesh with whatever glibc does in userland on - * m68k's. +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. */ +struct stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long __pad5; + + unsigned long st_mtime; + unsigned long __pad6; + + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + + unsigned long __unused1; + unsigned long __unused2; +}; + #endif /* _M68K_STAT_H */ diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h index 7d1afa286..7b6ae7d16 100644 --- a/include/asm-m68k/system.h +++ b/include/asm-m68k/system.h @@ -4,6 +4,7 @@ #include <linux/config.h> /* get configuration macros */ #include <linux/linkage.h> #include <asm/segment.h> +#include <asm/entry.h> #define prepare_to_switch() do { } while(0) @@ -44,36 +45,52 @@ asmlinkage void resume(void); (last) = _last; \ } + +/* interrupt control.. */ +#if 0 +#define __sti() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory") +#else +#include <asm/hardirq.h> +#define __sti() ({ \ + if (!local_irq_count[smp_processor_id()]) \ + asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \ +}) +#endif +#define __cli() asm volatile ("oriw #0x0700,%%sr": : : "memory") +#define __save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory") +#define __restore_flags(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory") + +/* For spinlocks etc */ +#define local_irq_save(x) ({ __save_flags(x); __cli(); }) +#define local_irq_restore(x) __restore_flags(x) +#define local_irq_disable() __cli() +#define local_irq_enable() __sti() + +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) + + +/* + * Force strict CPU ordering. + * Not really required on m68k... + */ +#define nop() asm volatile ("nop"::) +#define mb() asm volatile ("" : : :"memory") +#define rmb() asm volatile ("" : : :"memory") +#define wmb() asm volatile ("" : : :"memory") +#define set_rmb(var, value) do { xchg(&var, value); } while (0) +#define set_mb(var, value) set_rmb(var, value) +#define set_wmb(var, value) do { var = value; wmb(); } while (0) + + #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) ((volatile struct __xchg_dummy *)(x)) -#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES) -/* block out HSYNC on the atari */ -#define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory") -#else /* portable version */ -#define __sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory") -#endif /* machine compilation types */ -#define __cli() __asm__ __volatile__ ("oriw #0x0700,%/sr": : : "memory") -#define nop() __asm__ __volatile__ ("nop"::) -#define mb() __asm__ __volatile__ ("" : : :"memory") -#define rmb() __asm__ __volatile__ ("" : : :"memory") -#define wmb() __asm__ __volatile__ ("" : : :"memory") - -#define __save_flags(x) \ -__asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory") - -#define __restore_flags(x) \ -__asm__ __volatile__("movew %0,%/sr": /* no outputs */ :"d" (x) : "memory") - -#define cli() __cli() -#define sti() __sti() -#define save_flags(x) __save_flags(x) -#define restore_flags(x) __restore_flags(x) -#define save_and_cli(flags) do { save_flags(flags); cli(); } while(0) - #ifndef CONFIG_RMW_INSNS static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { diff --git a/include/asm-m68k/termios.h b/include/asm-m68k/termios.h index 07f6b8585..0f127c134 100644 --- a/include/asm-m68k/termios.h +++ b/include/asm-m68k/termios.h @@ -43,6 +43,9 @@ struct termio { #define TIOCM_DSR 0x100 #define TIOCM_CD TIOCM_CAR #define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index 548ce9ede..82897ade9 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -799,33 +799,46 @@ strncpy_from_user(char *dst, const char *src, long count) /* * Return the size of a string (including the ending 0) * - * Return 0 for error + * Return 0 on exception, a value greater than N if too long */ -static inline long strlen_user(const char * src) +static inline long strnlen_user(const char *src, long n) { - long res = -(long) src; - __asm__ __volatile__ - ("1: movesb (%1)+,%%d0\n" - "12:tstb %%d0\n" - " jne 1b\n" - " addl %1,%0\n" - "2:\n" - ".section .fixup,\"ax\"\n" - " .even\n" - "3: moveq %2,%0\n" - " jra 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,3b\n" - " .long 12b,3b\n" - ".previous" - : "=d"(res), "=a"(src) - : "i"(0), "0"(res), "1"(src) - : "d0"); - return res; + long res; + + res = -(long)src; + __asm__ __volatile__ + ("1:\n" + " tstl %2\n" + " jeq 3f\n" + "2: movesb (%1)+,%%d0\n" + "22:\n" + " subql #1,%2\n" + " tstb %%d0\n" + " jne 1b\n" + " jra 4f\n" + "3:\n" + " addql #1,%0\n" + "4:\n" + " addl %1,%0\n" + "5:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "6: moveq %3,%0\n" + " jra 5b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,6b\n" + " .long 22b,6b\n" + ".previous" + : "=d"(res), "=a"(src), "=d"(n) + : "i"(0), "0"(res), "1"(src), "2"(n) + : "d0"); + return res; } +#define strlen_user(str) strnlen_user(str, 32767) + /* * Zero Userspace */ diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h index 302308d88..4841264ab 100644 --- a/include/asm-m68k/virtconvert.h +++ b/include/asm-m68k/virtconvert.h @@ -9,6 +9,7 @@ #include <linux/config.h> #include <asm/setup.h> +#include <asm/page.h> #ifdef CONFIG_AMIGA #include <asm/amigahw.h> @@ -34,22 +35,22 @@ extern inline unsigned long mm_ptov(unsigned long paddr) #endif #ifdef CONFIG_SINGLE_MEMORY_CHUNK -extern inline unsigned long virt_to_phys(volatile void * address) +extern inline unsigned long virt_to_phys(volatile void *vaddr) { - unsigned long voff = (unsigned long) address; + unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET; if (voff < m68k_memory[0].size) - return m68k_memory[0].addr + voff; - else - return mm_vtop_fallback(voff); + return voff + m68k_memory[0].addr; + return mm_vtop_fallback((unsigned long)vaddr); } extern inline void * phys_to_virt(unsigned long paddr) { - unsigned long base = m68k_memory[0].addr; + unsigned long poff = paddr - m68k_memory[0].addr; + + if (poff < m68k_memory[0].size) + return (void *)(poff + PAGE_OFFSET); - if ((paddr >= base) && (paddr < (base + m68k_memory[0].size))) - return (void *)(paddr - base); #ifdef CONFIG_AMIGA /* * if on an amiga and address is in first 16M, move it |