add directory Linux-0.98
This commit is contained in:
96
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/bitops.h
Normal file
96
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/bitops.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef _ASM_BITOPS_H
|
||||
/*
|
||||
* Copyright 1992, Linus Torvalds.
|
||||
*/
|
||||
|
||||
#ifdef i386
|
||||
/*
|
||||
* These have to be done with inline assembly: that way the bit-setting
|
||||
* is guaranteed to be atomic. Both set_bit and clear_bit return 0
|
||||
* if the bit-setting went ok, != 0 if the bit already was set/cleared.
|
||||
*
|
||||
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
|
||||
*/
|
||||
extern inline int set_bit(int nr,int * addr)
|
||||
{
|
||||
char ok;
|
||||
|
||||
__asm__ __volatile__("btsl %1,%2\n\tsetb %0":
|
||||
"=q" (ok):"r" (nr),"m" (*(addr)));
|
||||
return ok;
|
||||
}
|
||||
|
||||
extern inline int clear_bit(int nr, int * addr)
|
||||
{
|
||||
char ok;
|
||||
|
||||
__asm__ __volatile__("btrl %1,%2\n\tsetnb %0":
|
||||
"=q" (ok):"r" (nr),"m" (*(addr)));
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine doesn't need to be atomic, but it's faster to code it
|
||||
* this way.
|
||||
*/
|
||||
extern inline int test_bit(int nr, int * addr)
|
||||
{
|
||||
char ok;
|
||||
|
||||
__asm__ __volatile__("btl %1,%2\n\tsetb %0":
|
||||
"=q" (ok):"r" (nr),"m" (*(addr)));
|
||||
return ok;
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* For the benefit of those who are trying to port Linux to another
|
||||
* architecture, here are some C-language equivalents. You should
|
||||
* recode these in the native assmebly language, if at all possible.
|
||||
* To guarantee atomicity, these routines call cli() and sti() to
|
||||
* disable interrupts while they operate. (You have to provide inline
|
||||
* routines to cli() and sti().)
|
||||
*
|
||||
* Also note, these routines assume that you have 32 bit integers.
|
||||
* You will have to change this if you are trying to port Linux to the
|
||||
* Alpha architecture or to a Cray. :-)
|
||||
*
|
||||
* C language equivalents written by Theodore Ts'o, 9/26/92
|
||||
*/
|
||||
|
||||
extern inline int set_bit(int nr,int * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
cli();
|
||||
retval = (mask & *addr) != 0;
|
||||
*addr |= mask;
|
||||
sti();
|
||||
return retval;
|
||||
}
|
||||
|
||||
extern inline int clear_bit(int nr, int * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
cli();
|
||||
retval = (mask & *addr) == 0;
|
||||
*addr &= ~mask;
|
||||
sti();
|
||||
return retval;
|
||||
}
|
||||
|
||||
extern inline int test_bit(int nr, int * addr)
|
||||
{
|
||||
int mask;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
return ((mask & *addr) != 0);
|
||||
}
|
||||
#endif /* i386 */
|
||||
#endif /* _ASM_BITOPS_H */
|
||||
192
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/dma.h
Normal file
192
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/dma.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* $Header: /sys/linux-0.97/include/asm/RCS/dma.h,v 1.4 1992/09/21 03:15:46 root Exp root $
|
||||
* linux/include/asm/dma.h: Defines for using and allocating dma channels.
|
||||
* Written by Hennus Bergman, 1992.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_DMA_H
|
||||
#define _ASM_DMA_H
|
||||
|
||||
#include <asm/io.h> /* need byte IO */
|
||||
#include <linux/kernel.h> /* need panic() [FIXME] */
|
||||
|
||||
|
||||
#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
|
||||
#define outb outb_p
|
||||
#endif
|
||||
|
||||
/* FIXME: better fix this code for dma channels>3!!!!!!! */
|
||||
|
||||
/*
|
||||
* The routines below should in most cases (with optimizing on) result
|
||||
* in equal or better code than similar code using macros.
|
||||
*
|
||||
* NOTE about DMA transfers: The DMA controller cannot handle transfers
|
||||
* that cross a 64k boundary. When the address reaches 0xNffff, it will wrap
|
||||
* around to 0xN0000, rather than increment to 0x(N+1)0000 !
|
||||
* Make sure you align your buffers properly! Runtime check recommended.
|
||||
*
|
||||
* NOTE2: DMA1..3 can only use the lower 1MB of physical memory. DMA4..7
|
||||
* can access the lower 16MB. There are people with >16MB, so beware!
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_DMA_CHANNELS 8
|
||||
|
||||
/* SOMEBODY should check the following:
|
||||
* Channels 0..3 are on the first DMA controller, channels 4..7 are
|
||||
* on the second. Channel 0 is for refresh, 4 is for cascading.
|
||||
* The first DMA controller uses bytes, the second words.
|
||||
*
|
||||
* Where are the page regs for the second DMA controller?????
|
||||
*/
|
||||
|
||||
|
||||
/* 8237 DMA controllers */
|
||||
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
|
||||
#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
|
||||
|
||||
/* DMA controller registers */
|
||||
#define DMA1_CMD_REG 0x08 /* DMA command register */
|
||||
#define DMA1_STAT_REG 0x08 /* DMA status register */
|
||||
#define DMA1_MASK_REG 0x0A /* mask individual channels */
|
||||
#define DMA1_MODE_REG 0x0B /* set modes for individual channels */
|
||||
#define DMA1_CLEAR_FF_REG 0x0C /* Write 0 for LSB, 1 for MSB */
|
||||
#define DMA1_RESET_REG 0x0D /* Write here to reset DMA controller */
|
||||
/* don't have much info on the second DMA controller... */
|
||||
#define DMA2_MASK_REG 0xD4
|
||||
#define DMA2_MODE_REG 0xD6
|
||||
/* #define DMA2_CLEAR_FF_REG 0xD8 -- pure guessing.... */
|
||||
|
||||
/************* #error This needs more work!!!!!!!*************/
|
||||
|
||||
#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 /* cascade mode (for DMA2 controller only) */
|
||||
|
||||
|
||||
/* enable/disable a specific DMA channel */
|
||||
static __inline__ void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr<=3)
|
||||
outb(dmanr, DMA1_MASK_REG);
|
||||
else
|
||||
outb(dmanr & 3, DMA2_MASK_REG);
|
||||
}
|
||||
|
||||
static __inline__ void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr<=3)
|
||||
outb(dmanr | 4, DMA1_MASK_REG);
|
||||
else
|
||||
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 know state.
|
||||
* After that, keep track of it. :-) In order to do that,
|
||||
* dma_set_addr() and dma_set_count() should only be used wile
|
||||
* interrupts are disbled.
|
||||
*/
|
||||
static __inline__ void clear_dma_ff(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr<=3)
|
||||
outb(0, DMA1_CLEAR_FF_REG);
|
||||
else
|
||||
#ifdef DMA2_CLEAR_FF_REG
|
||||
outb(0, DMA2_CLEAR_FF_REG);
|
||||
#else
|
||||
panic("dma.h: Don't have CLEAR_FF for high dma channels!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set mode (above) for a specific DMA channel */
|
||||
static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
|
||||
{
|
||||
if (dmanr<=3)
|
||||
outb(mode | dmanr, DMA1_MODE_REG);
|
||||
else
|
||||
outb(DMA_MODE_CASCADE | mode | (dmanr&3), DMA2_MODE_REG);
|
||||
}
|
||||
|
||||
/* Set only the page register bits of the transfer address.
|
||||
* This is used for successive transfers when we know the contents of
|
||||
* the lower 16 bits of the DMA current address register, but a 64k boundary
|
||||
* may have been crossed.
|
||||
*/
|
||||
static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
|
||||
{
|
||||
switch(dmanr) {
|
||||
case 0:
|
||||
outb(pagenr, 0x80);
|
||||
break;
|
||||
case 1:
|
||||
outb(pagenr, 0x83);
|
||||
break;
|
||||
case 2:
|
||||
outb(pagenr, 0x81);
|
||||
break;
|
||||
case 3:
|
||||
outb(pagenr, 0x82);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
panic("dma.h: don't know how to set DMA page regs for channels>3");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
|
||||
|
||||
set_dma_page(dmanr, a>>16);
|
||||
outb(a & 0xff, ((dmanr&3)<<1) + io_base);
|
||||
outb((a>>8) & 0xff, ((dmanr&3)<<1) + io_base);
|
||||
}
|
||||
|
||||
|
||||
/* Set transfer size (max 64k) 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.
|
||||
*/
|
||||
static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
|
||||
{
|
||||
unsigned int dc = count - 1;
|
||||
unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
|
||||
|
||||
outb(dc & 0xff, ((dmanr&3)<<1) + 1 + io_base);
|
||||
outb((dc>>8) & 0xff, ((dmanr&3)<<1) + 1 + io_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,
|
||||
* minus 1, modulo 64k.
|
||||
* Assumes DMA flip-flop is clear.
|
||||
*/
|
||||
static __inline__ short int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
|
||||
|
||||
return 1 + inb( ((dmanr&3)<<1) + 1 + io_base ) +
|
||||
( inb( ((dmanr&3)<<1) + 1 + io_base ) << 8 );
|
||||
}
|
||||
|
||||
/* These are in kernel/dma.c: */
|
||||
extern int request_dma(unsigned int dmanr); /* reserve a DMA channel */
|
||||
extern void free_dma(unsigned int dmanr); /* release it again */
|
||||
|
||||
|
||||
#endif /* _ASM_DMA_H */
|
||||
57
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/io.h
Normal file
57
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/io.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef _ASM_IO_H
|
||||
#define _ASM_IO_H
|
||||
|
||||
/*
|
||||
* Thanks to James van Artsdalen for a better timing-fix than
|
||||
* the two short jumps: using outb's to a nonexistent port seems
|
||||
* to guarantee better timings even on fast machines.
|
||||
*
|
||||
* On the other hand, I'd like to be sure of a non-existent port:
|
||||
* I feel a bit unsafe abou using 0x80.
|
||||
*
|
||||
* Linus
|
||||
*/
|
||||
|
||||
#ifdef SLOW_IO_BY_JUMPING
|
||||
#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
|
||||
#else
|
||||
#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
|
||||
#endif
|
||||
|
||||
#ifdef REALLY_SLOW_IO
|
||||
#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
|
||||
#else
|
||||
#define SLOW_DOWN_IO __SLOW_DOWN_IO
|
||||
#endif
|
||||
|
||||
extern void inline outb(char value, unsigned short port)
|
||||
{
|
||||
__asm__ __volatile__ ("outb %%al,%%dx"
|
||||
::"a" ((char) value),"d" ((unsigned short) port));
|
||||
}
|
||||
|
||||
extern unsigned int inline inb(unsigned short port)
|
||||
{
|
||||
unsigned int _v;
|
||||
__asm__ __volatile__ ("inb %%dx,%%al"
|
||||
:"=a" (_v):"d" ((unsigned short) port),"0" (0));
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern void inline outb_p(char value, unsigned short port)
|
||||
{
|
||||
__asm__ __volatile__ ("outb %%al,%%dx"
|
||||
::"a" ((char) value),"d" ((unsigned short) port));
|
||||
SLOW_DOWN_IO;
|
||||
}
|
||||
|
||||
extern unsigned int inline inb_p(unsigned short port)
|
||||
{
|
||||
unsigned int _v;
|
||||
__asm__ __volatile__ ("inb %%dx,%%al"
|
||||
:"=a" (_v):"d" ((unsigned short) port),"0" (0));
|
||||
SLOW_DOWN_IO;
|
||||
return _v;
|
||||
}
|
||||
|
||||
#endif
|
||||
147
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/irq.h
Normal file
147
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/irq.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef _ASM_IRQ_H
|
||||
#define _ASM_IRQ_H
|
||||
|
||||
/*
|
||||
* linux/include/asm/irq.h
|
||||
*
|
||||
* (C) 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#define SAVE_ALL \
|
||||
"cld\n\t" \
|
||||
"push %gs\n\t" \
|
||||
"push %fs\n\t" \
|
||||
"push %es\n\t" \
|
||||
"push %ds\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
"pushl %ebp\n\t" \
|
||||
"pushl %edi\n\t" \
|
||||
"pushl %esi\n\t" \
|
||||
"pushl %edx\n\t" \
|
||||
"pushl %ecx\n\t" \
|
||||
"pushl %ebx\n\t" \
|
||||
"movl $0x10,%edx\n\t" \
|
||||
"mov %dx,%ds\n\t" \
|
||||
"mov %dx,%es\n\t" \
|
||||
"movl $0x17,%edx\n\t" \
|
||||
"mov %dx,%fs\n\t"
|
||||
|
||||
/*
|
||||
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
|
||||
* installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
|
||||
* call the routines that do signal handling etc on return, and can have
|
||||
* more relaxed register-saving etc. They are also atomic, and are thus
|
||||
* suited for small, fast interrupts like the serial lines or the harddisk
|
||||
* drivers, which don't actually need signal handling etc.
|
||||
*
|
||||
* Also note that we actually save only those registers that are used in
|
||||
* C subroutines (%eax, %edx and %ecx), so if you do something weird,
|
||||
* you're on your own. The only segments that are saved (not counting the
|
||||
* automatic stack and code segment handling) are %ds and %es, and they
|
||||
* point to kernel space. No messing around with %fs here.
|
||||
*/
|
||||
#define SAVE_MOST \
|
||||
"cld\n\t" \
|
||||
"push %es\n\t" \
|
||||
"push %ds\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
"pushl %edx\n\t" \
|
||||
"pushl %ecx\n\t" \
|
||||
"movl $0x10,%edx\n\t" \
|
||||
"mov %dx,%ds\n\t" \
|
||||
"mov %dx,%es\n\t"
|
||||
|
||||
#define RESTORE_MOST \
|
||||
"popl %ecx\n\t" \
|
||||
"popl %edx\n\t" \
|
||||
"popl %eax\n\t" \
|
||||
"pop %ds\n\t" \
|
||||
"pop %es\n\t" \
|
||||
"iret"
|
||||
|
||||
#define ACK_FIRST(mask) \
|
||||
"inb $0x21,%al\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\torb $" #mask ",%al\n\t" \
|
||||
"outb %al,$0x21\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\tmovb $0x20,%al\n\t" \
|
||||
"outb %al,$0x20\n\t"
|
||||
|
||||
#define ACK_SECOND(mask) \
|
||||
"inb $0xA1,%al\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\torb $" #mask ",%al\n\t" \
|
||||
"outb %al,$0xA1\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\tmovb $0x20,%al\n\t" \
|
||||
"outb %al,$0xA0\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\toutb %al,$0x20\n\t"
|
||||
|
||||
#define UNBLK_FIRST(mask) \
|
||||
"inb $0x21,%al\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\tandb $~(" #mask "),%al\n\t" \
|
||||
"outb %al,$0x21\n\t"
|
||||
|
||||
#define UNBLK_SECOND(mask) \
|
||||
"inb $0xA1,%al\n\t" \
|
||||
"jmp 1f\n" \
|
||||
"1:\tjmp 1f\n" \
|
||||
"1:\tandb $~(" #mask "),%al\n\t" \
|
||||
"outb %al,$0xA1\n\t"
|
||||
|
||||
#define IRQ_NAME2(nr) nr##_interrupt()
|
||||
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
|
||||
#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
|
||||
#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
|
||||
|
||||
#define BUILD_IRQ(chip,nr,mask) \
|
||||
void IRQ_NAME(nr); \
|
||||
void FAST_IRQ_NAME(nr); \
|
||||
void BAD_IRQ_NAME(nr); \
|
||||
__asm__( \
|
||||
"\n.align 2\n" \
|
||||
"_IRQ" #nr "_interrupt:\n\t" \
|
||||
"pushl $-"#nr"-2\n\t" \
|
||||
SAVE_ALL \
|
||||
ACK_##chip(mask) \
|
||||
"sti\n\t" \
|
||||
"movl %esp,%ebx\n\t" \
|
||||
"pushl %ebx\n\t" \
|
||||
"pushl $" #nr "\n\t" \
|
||||
"call _do_IRQ\n\t" \
|
||||
"addl $8,%esp\n\t" \
|
||||
"testl %eax,%eax\n\t" \
|
||||
"jne ret_from_sys_call\n\t" \
|
||||
"cli\n\t" \
|
||||
UNBLK_##chip(mask) \
|
||||
"jmp ret_from_sys_call\n" \
|
||||
"\n.align 2\n" \
|
||||
"_fast_IRQ" #nr "_interrupt:\n\t" \
|
||||
SAVE_MOST \
|
||||
ACK_##chip(mask) \
|
||||
"pushl $" #nr "\n\t" \
|
||||
"call _do_fast_IRQ\n\t" \
|
||||
"addl $4,%esp\n\t" \
|
||||
"testl %eax,%eax\n\t" \
|
||||
"jne 2f\n\t" \
|
||||
"cli\n\t" \
|
||||
UNBLK_##chip(mask) \
|
||||
"\n2:\t" \
|
||||
RESTORE_MOST \
|
||||
"\n\n.align 2\n" \
|
||||
"_bad_IRQ" #nr "_interrupt:\n\t" \
|
||||
"pushl %eax\n\t" \
|
||||
ACK_##chip(mask) \
|
||||
"popl %eax\n\t" \
|
||||
"iret");
|
||||
|
||||
#endif
|
||||
39
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/memory.h
Normal file
39
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/memory.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
|
||||
* goes for all kernel functions (ds=es=kernel space, fs=local data,
|
||||
* gs=null), as well as for all well-behaving user programs (ds=es=
|
||||
* user data space). This is NOT a bug, as any user program that changes
|
||||
* es deserves to die if it isn't careful.
|
||||
*/
|
||||
#if 0
|
||||
#define memcpy(dest,src,n) ({ \
|
||||
void * _res = dest; \
|
||||
__asm__ __volatile__ ("cld;rep;movsb" \
|
||||
::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
|
||||
:"di","si","cx"); \
|
||||
_res; \
|
||||
})
|
||||
#else
|
||||
|
||||
/* this is basically memcpy_tofs. It should be faster.
|
||||
I've reorder it. This should be a little faster. -RAB */
|
||||
|
||||
#define memcpy(dest, src, n) f_memcpy(dest, src, n)
|
||||
extern inline void * f_memcpy(void * to, void * from, unsigned long n)
|
||||
{
|
||||
__asm__("cld\n\t"
|
||||
"movl %%edx, %%ecx\n\t"
|
||||
"shrl $2,%%ecx\n\t"
|
||||
"rep ; movsl\n\t"
|
||||
"testb $1,%%dl\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsb\n"
|
||||
"1:\ttestb $2,%%dl\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsw\n"
|
||||
"2:\n"
|
||||
::"d" (n),"D" ((long) to),"S" ((long) from)
|
||||
: "cx","di","si");
|
||||
return (to);
|
||||
}
|
||||
#endif
|
||||
99
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/segment.h
Normal file
99
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/segment.h
Normal file
@@ -0,0 +1,99 @@
|
||||
extern inline unsigned char get_fs_byte(const char * addr)
|
||||
{
|
||||
unsigned register char _v;
|
||||
|
||||
__asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern inline unsigned short get_fs_word(const unsigned short *addr)
|
||||
{
|
||||
unsigned short _v;
|
||||
|
||||
__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern inline unsigned long get_fs_long(const unsigned long *addr)
|
||||
{
|
||||
unsigned long _v;
|
||||
|
||||
__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern inline void put_fs_byte(char val,char *addr)
|
||||
{
|
||||
__asm__ ("movb %0,%%fs:%1"::"q" (val),"m" (*addr));
|
||||
}
|
||||
|
||||
extern inline void put_fs_word(short val,short * addr)
|
||||
{
|
||||
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
|
||||
}
|
||||
|
||||
extern inline void put_fs_long(unsigned long val,unsigned long * addr)
|
||||
{
|
||||
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
|
||||
}
|
||||
|
||||
extern inline void memcpy_tofs(void * to, const void * from, unsigned long n)
|
||||
{
|
||||
__asm__("cld\n\t"
|
||||
"push %%es\n\t"
|
||||
"push %%fs\n\t"
|
||||
"pop %%es\n\t"
|
||||
"testb $1,%%cl\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsb\n"
|
||||
"1:\ttestb $2,%%cl\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsw\n"
|
||||
"2:\tshrl $2,%%ecx\n\t"
|
||||
"rep ; movsl\n\t"
|
||||
"pop %%es"
|
||||
::"c" (n),"D" ((long) to),"S" ((long) from)
|
||||
:"cx","di","si");
|
||||
}
|
||||
|
||||
extern inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
|
||||
{
|
||||
__asm__("cld\n\t"
|
||||
"testb $1,%%cl\n\t"
|
||||
"je 1f\n\t"
|
||||
"fs ; movsb\n"
|
||||
"1:\ttestb $2,%%cl\n\t"
|
||||
"je 2f\n\t"
|
||||
"fs ; movsw\n"
|
||||
"2:\tshrl $2,%%ecx\n\t"
|
||||
"rep ; fs ; movsl"
|
||||
::"c" (n),"D" ((long) to),"S" ((long) from)
|
||||
:"cx","di","si");
|
||||
}
|
||||
|
||||
/*
|
||||
* Someone who knows GNU asm better than I should double check the followig.
|
||||
* It seems to work, but I don't know if I'm doing something subtly wrong.
|
||||
* --- TYT, 11/24/91
|
||||
* [ nothing wrong here, Linus: I just changed the ax to be any reg ]
|
||||
*/
|
||||
|
||||
extern inline unsigned long get_fs()
|
||||
{
|
||||
unsigned short _v;
|
||||
__asm__("mov %%fs,%0":"=r" (_v):);
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern inline unsigned long get_ds()
|
||||
{
|
||||
unsigned short _v;
|
||||
__asm__("mov %%ds,%0":"=r" (_v):);
|
||||
return _v;
|
||||
}
|
||||
|
||||
extern inline void set_fs(unsigned long val)
|
||||
{
|
||||
__asm__ __volatile__("mov %0,%%fs"::"r" ((unsigned short) val));
|
||||
}
|
||||
|
||||
72
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/system.h
Normal file
72
Linux-0.98/Yggdrasil-0.98.3/usr/include/asm/system.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#define move_to_user_mode() \
|
||||
__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
|
||||
"pushl $0x17\n\t" \
|
||||
"pushl %%eax\n\t" \
|
||||
"pushfl\n\t" \
|
||||
"pushl $0x0f\n\t" \
|
||||
"pushl $1f\n\t" \
|
||||
"iret\n" \
|
||||
"1:\tmovl $0x17,%%eax\n\t" \
|
||||
"mov %%ax,%%ds\n\t" \
|
||||
"mov %%ax,%%es\n\t" \
|
||||
"mov %%ax,%%fs\n\t" \
|
||||
"mov %%ax,%%gs" \
|
||||
:::"ax")
|
||||
|
||||
#define sti() __asm__ __volatile__ ("sti"::)
|
||||
#define cli() __asm__ __volatile__ ("cli"::)
|
||||
#define nop() __asm__ __volatile__ ("nop"::)
|
||||
|
||||
#define save_flags(x) \
|
||||
__asm__ __volatile__("pushfl ; popl %0":"=r" (x))
|
||||
|
||||
#define restore_flags(x) \
|
||||
__asm__ __volatile__("pushl %0 ; popfl"::"r" (x))
|
||||
|
||||
#define iret() __asm__ __volatile__ ("iret"::)
|
||||
|
||||
#define _set_gate(gate_addr,type,dpl,addr) \
|
||||
__asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
|
||||
"movw %0,%%dx\n\t" \
|
||||
"movl %%eax,%1\n\t" \
|
||||
"movl %%edx,%2" \
|
||||
:: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
|
||||
"m" (*((char *) (gate_addr))), \
|
||||
"m" (*(4+(char *) (gate_addr))), \
|
||||
"d" ((char *) (addr)),"a" (0x00080000) \
|
||||
:"ax","dx")
|
||||
|
||||
#define set_intr_gate(n,addr) \
|
||||
_set_gate(&idt[n],14,0,addr)
|
||||
|
||||
#define set_trap_gate(n,addr) \
|
||||
_set_gate(&idt[n],15,0,addr)
|
||||
|
||||
#define set_system_gate(n,addr) \
|
||||
_set_gate(&idt[n],15,3,addr)
|
||||
|
||||
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
|
||||
*(gate_addr) = ((base) & 0xff000000) | \
|
||||
(((base) & 0x00ff0000)>>16) | \
|
||||
((limit) & 0xf0000) | \
|
||||
((dpl)<<13) | \
|
||||
(0x00408000) | \
|
||||
((type)<<8); \
|
||||
*((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \
|
||||
((limit) & 0x0ffff); }
|
||||
|
||||
#define _set_tssldt_desc(n,addr,limit,type) \
|
||||
__asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
|
||||
"movw %%ax,%2\n\t" \
|
||||
"rorl $16,%%eax\n\t" \
|
||||
"movb %%al,%3\n\t" \
|
||||
"movb $" type ",%4\n\t" \
|
||||
"movb $0x00,%5\n\t" \
|
||||
"movb %%ah,%6\n\t" \
|
||||
"rorl $16,%%eax" \
|
||||
::"a" (addr+0xc0000000), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
|
||||
"m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
|
||||
)
|
||||
|
||||
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),231,"0x89")
|
||||
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),23,"0x82")
|
||||
Reference in New Issue
Block a user