/* SupportAsm.S, Copyright (c) by Lukas Ruf, lr@lpr.ch, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/Topsy/ia32/SupportAsm.S,v $ Author(s): Lukas Ruf, lr@lpr.ch Affiliation: ETH Zuerich, TIK Version: $Revision: 1.3 $ Creation Date: Last Date of Change: $Date: 2000/06/06 12:03:23 $ by: $Author: ruf $ $Log: SupportAsm.S,v $ Revision 1.3 2000/06/06 12:03:23 ruf SupportAsm.h Revision 1.2 1999/12/13 21:48:38 ruf GNU General Public Licence Update Revision 1.1 1999/05/13 17:05:58 jeker Initial revision */ #include "asm.h" #include "cpu.h" .section .sasm .align 4,0x9090 /* Boolean testAndSet(Boolean *LockVar); * Multiprocessor able version of Topsy-testAndSet(). No Interrupt Disable is * required, as only the location is modified but not copied into a register. */ FRAME(testAndSet) ENTER pushfl pushl %ebx movl $1,%eax movl ARG1,%ebx bts %eax,(%ebx) /* dereference memory location directly */ jc _isalreadyset movl $0x01,%eax /* return true: set was successfull ! */ jmp _endtestandset _isalreadyset: xorl %eax,%eax /* return false: LockVar was already set */ _endtestandset: popl %ebx popfl LEAVE //// // void __mutex(ulong *p32mutex, ulong pmutex); blocking mutual exclusion // __mutex() is completely multiprocessing able. The bus is implicitely locked // by the i386-instruction btr/bts. There is no need of disable interrupts // or block the whole system. // __mutex() and _demutex() set or reset a single bit in p32mutex (=array of 32 bits). // __mutex(): if a bit is already set, block the process without return ad aeternam // as long as there is no setting of the bit. FRAME(__mutex) ENTER pushfl pushl %eax pushl %ebx movl ARG1,%ebx movl ARG2,%eax andl $0x1F,%eax // => eax % 32 // make sure index points to 32first bits only _mutexL1: bts %eax,(%ebx) jc _mutexL1 // block if already set ! popl %ebx popl %eax popfl LEAVE FRAME(__demutex) ENTER pushfl pushl %eax pushl %ebx movl ARG1,%ebx movl ARG2,%eax andl $0x1F,%eax // => eax % 32 // make sure index points to 32first bits only btr %eax,(%ebx) // reset bit p32mutex[pmutex] popl %ebx popl %eax popfl LEAVE //Topsy i386 Lukas Ruf, December 1997 //------------------------------------------------------------------------------ //// // Simple Program to demonstrate working PM_Switch // //// speaker_port = 0x61 pit_control = 0x43 pit_channel_2 = 0x42 pit_freq = 0x1234dd lofreq = 0x0A9 // (PIT_FREQ / 1000) AND 0FFh hifreq = 0x004 // (PIT_FREQ / 1000) AND 0FF00h .extern __wait //// // void beep(void); //// FRAME(__beep) pushl %eax pushl %ecx pushl %edx movl $pit_control,%edx movb $0xb6,%al outb %al,%dx movl $pit_channel_2,%edx movb $lofreq,%al outb %al,%dx movb $hifreq,%al outb %al,%dx movl $speaker_port,%edx //; on inb %dx,%al orb $3,%al outb %al,%dx call __wait movl $speaker_port,%edx inb %dx,%al andb $0xfc,%al outb %al,%dx popl %edx popl %ecx popl %eax ret FRAME(__reboot) jmp _r1 _rspac1: .byte 0,0 _rspac2: .long 0 _r1: cli leal _rspac2,%eax movl $0000,(%eax) // real mode idt base leal _rspac1,%eax movw $1023,(%eax) // real mode idt limit (256x4B) lidt (%eax) movl %cr0,%eax movl $0x80000001,%ebx // switch back to RM, disable paging notl %ebx andl %ebx,%eax movl %eax,%cr0 xorl %eax,%eax movl %eax,%cr3 // reset Page Directory Base Addr. jmp _rflush nop nop _rflush: movl $0x1234,%eax // prepare for Warm Reset movl $0x40,%ebx // do not test RAM movw %bx,%es movl $0x72,%edi stosw ljmp $0xF000,$0xFFF0 FRAME(__outb) ENTER pushl %eax pushl %edx movl 8(%ebp),%eax movl 12(%ebp),%edx outb %al,%dx popl %edx popl %eax LEAVE FRAME(__outw) ENTER pushl %eax pushl %edx movl 8(%ebp),%eax movl 12(%ebp),%edx outw %ax,%dx popl %edx popl %eax LEAVE FRAME(__outl) ENTER pushl %eax pushl %edx movl 8(%ebp),%eax movl 12(%ebp),%edx outl %eax,%dx popl %edx popl %eax LEAVE FRAME(__inb) ENTER pushl %edx xorl %eax,%eax movl 8(%ebp),%edx inb %dx,%al popl %edx LEAVE FRAME(__inw) ENTER pushl %edx xorl %eax,%eax movl 8(%ebp),%edx inw %dx,%ax popl %edx LEAVE FRAME(__inl) ENTER pushl %edx xorl %eax,%eax movl 8(%ebp),%edx inl %dx,%eax popl %edx LEAVE FRAME(__wait) pushl %ecx movl $(64*6000),%ecx _w2: loop _w2 popl %ecx ret