master
ZCH 4 years ago
parent 5cf7f7cd6d
commit 1145a3ab45

12
.gitignore vendored

@ -1,6 +1,6 @@
# ---> CraftCMS # ---> CraftCMS
# Craft 2 Storage (https://craftcms.com/support/craft-storage-gitignore) # Craft 2 Storage (https://craftcms.com/support/craft-storage-gitignore)
# not necessary for Craft 3 (https://github.com/craftcms/craft/issues/26) # not necessary for Craft 3 (https://github.com/craftcms/craft/issues/26)
/craft/storage/* /craft/storage/*
!/craft/storage/rebrand !/craft/storage/rebrand

@ -1,35 +1,35 @@
GCC RUNTIME LIBRARY EXCEPTION GCC RUNTIME LIBRARY EXCEPTION
Version 3.1, 31 March 2009 Version 3.1, 31 March 2009
General information: http://www.gnu.org/licenses/gcc-exception.html General information: http://www.gnu.org/licenses/gcc-exception.html
Copyright (C) 2009 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2009 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception.
When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception.
0. Definitions. 0. Definitions.
A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library.
"GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. "GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF.
"GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. "GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC.
"Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. "Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation.
The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors.
A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process.
1. Grant of Additional Permission. 1. Grant of Additional Permission.
You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules.
2. No Weakening of GCC Copyleft. 2. No Weakening of GCC Copyleft.
The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC.

@ -1,21 +0,0 @@
# 使用3号内核进行调式
#### 从命令行创建一个新的仓库
```bash
touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git
git push -u origin master
```
#### 从命令行推送已经创建的仓库
```bash
git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git
git push -u origin master
```

@ -1,21 +1,21 @@
# 使用3号内核进行调式 # 使用3号内核进行调式
#### 从命令行创建一个新的仓库 #### 从命令行创建一个新的仓库
```bash ```bash
touch README.md touch README.md
git init git init
git add README.md git add README.md
git commit -m "first commit" git commit -m "first commit"
git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git
git push -u origin master git push -u origin master
``` ```
#### 从命令行推送已经创建的仓库 #### 从命令行推送已经创建的仓库
```bash ```bash
git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git git remote add origin https://bdgit.educoder.net/p7px8vou9/system_call_expand.git
git push -u origin master git push -u origin master
``` ```

@ -1,5 +1,5 @@
target remote localhost:1234 target remote localhost:1234
handle SIGSEGV nostop noprint ignore handle SIGSEGV nostop noprint ignore
b main b main
display current->pid display current->pid
c c

@ -1,6 +1,6 @@
revision history: revision history:
版本0: 这是oldlinux.org网站上的linux-0.11-lab.rar中的版本。可能是赵博士在原始0.11版本的基础上修改而成。我做了如下改动: 版本0: 这是oldlinux.org网站上的linux-0.11-lab.rar中的版本。可能是赵博士在原始0.11版本的基础上修改而成。我做了如下改动:
a) 对一些Makefile做了修改生成调试信息 a) 对一些Makefile做了修改生成调试信息
b) 将其移植到ubuntu和debian下主要修改的地方用 "by wyj"标注。 b) 将其移植到ubuntu和debian下主要修改的地方用 "by wyj"标注。

@ -1,2 +1,2 @@
---- Partition table Matches (1 in 1 files) ---- ---- Partition table Matches (1 in 1 files) ----
Hd.c (kernel\blk_drv): printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":""); Hd.c (kernel\blk_drv): printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");

@ -1,125 +1,125 @@
# #
# if you want the ram-disk device, define this to be the # if you want the ram-disk device, define this to be the
# size in blocks. # size in blocks.
# #
RAMDISK = #-DRAMDISK=512 RAMDISK = #-DRAMDISK=512
AS86 =as86 -0 -a AS86 =as86 -0 -a
LD86 =ld86 -0 LD86 =ld86 -0
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32 -Map=System.map.2 -N LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32 -Map=System.map.2 -N
CC =gcc -march=i386 $(RAMDISK) CC =gcc -march=i386 $(RAMDISK)
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -fno-stack-protector -mcld CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -fno-stack-protector -mcld
CPP =cpp -nostdinc -Iinclude CPP =cpp -nostdinc -Iinclude
# #
# ROOT_DEV specifies the default root-device when making the image. # ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the # This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of /dev/hd6 is used by 'build'. # default of /dev/hd6 is used by 'build'.
# #
ROOT_DEV= ROOT_DEV=
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
MATH =kernel/math/math.a MATH =kernel/math/math.a
LIBS =lib/lib.a LIBS =lib/lib.a
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-nostdinc -Iinclude -S -o $*.s $< -nostdinc -Iinclude -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-nostdinc -Iinclude -c -o $*.o $< -nostdinc -Iinclude -c -o $*.o $<
all: Image all: Image
Image: boot/bootsect boot/setup tools/system tools/build Image: boot/bootsect boot/setup tools/system tools/build
cp -f tools/system system.tmp cp -f tools/system system.tmp
strip system.tmp strip system.tmp
tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
rm -f system.tmp rm -f system.tmp
sync sync
disk: Image disk: Image
dd bs=8192 if=Image of=/dev/PS0 dd bs=8192 if=Image of=/dev/PS0
tools/build: tools/build.c tools/build: tools/build.c
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-o tools/build tools/build.c -o tools/build tools/build.c
boot/head.o: boot/head.s boot/head.o: boot/head.s
tools/system: boot/head.o init/main.o \ tools/system: boot/head.o init/main.o \
$(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS) $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \ $(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \ $(ARCHIVES) \
$(DRIVERS) \ $(DRIVERS) \
$(MATH) \ $(MATH) \
$(LIBS) \ $(LIBS) \
-o tools/system -o tools/system
nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw]\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort >System.map nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw]\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort >System.map
kernel/math/math.a: FORCE kernel/math/math.a: FORCE
(cd kernel/math; make) (cd kernel/math; make)
kernel/blk_drv/blk_drv.a: FORCE kernel/blk_drv/blk_drv.a: FORCE
(cd kernel/blk_drv; make) (cd kernel/blk_drv; make)
kernel/chr_drv/chr_drv.a: FORCE kernel/chr_drv/chr_drv.a: FORCE
(cd kernel/chr_drv; make) (cd kernel/chr_drv; make)
kernel/kernel.o: FORCE kernel/kernel.o: FORCE
(cd kernel; make) (cd kernel; make)
mm/mm.o: FORCE mm/mm.o: FORCE
(cd mm; make) (cd mm; make)
fs/fs.o: FORCE fs/fs.o: FORCE
(cd fs; make) (cd fs; make)
lib/lib.a: FORCE lib/lib.a: FORCE
(cd lib; make) (cd lib; make)
FORCE: FORCE:
boot/setup: boot/setup.s boot/setup: boot/setup.s
$(AS86) -o boot/setup.o boot/setup.s $(AS86) -o boot/setup.o boot/setup.s
$(LD86) -s -o boot/setup boot/setup.o $(LD86) -s -o boot/setup boot/setup.o
boot/bootsect: boot/bootsect.s boot/bootsect: boot/bootsect.s
$(AS86) -o boot/bootsect.o boot/bootsect.s $(AS86) -o boot/bootsect.o boot/bootsect.s
$(LD86) -s -o boot/bootsect boot/bootsect.o $(LD86) -s -o boot/bootsect boot/bootsect.o
tmp.s: boot/bootsect.s tools/system tmp.s: boot/bootsect.s tools/system
(echo -n "SYSSIZE = (";ls -l tools/system | grep system \ (echo -n "SYSSIZE = (";ls -l tools/system | grep system \
| cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s | cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
cat boot/bootsect.s >> tmp.s cat boot/bootsect.s >> tmp.s
clean: clean:
rm -f Image System.map tmp_make core System.map.2 rm -f Image System.map tmp_make core System.map.2
rm -f boot/bootsect boot/setup rm -f boot/bootsect boot/setup
rm -f init/*.o tools/system tools/build boot/*.o rm -f init/*.o tools/system tools/build boot/*.o
(cd mm;make clean) (cd mm;make clean)
(cd fs;make clean) (cd fs;make clean)
(cd kernel;make clean) (cd kernel;make clean)
(cd lib;make clean) (cd lib;make clean)
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
(cd fs; make dep) (cd fs; make dep)
(cd kernel; make dep) (cd kernel; make dep)
(cd mm; make dep) (cd mm; make dep)
### Dependencies: ### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \ init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/times.h include/sys/utsname.h \ include/sys/types.h include/sys/times.h include/sys/utsname.h \
include/utime.h include/time.h include/linux/tty.h include/termios.h \ include/utime.h include/time.h include/linux/tty.h include/termios.h \
include/linux/sched.h include/linux/head.h include/linux/fs.h \ include/linux/sched.h include/linux/head.h include/linux/fs.h \
include/linux/mm.h include/signal.h include/asm/system.h include/asm/io.h \ include/linux/mm.h include/signal.h include/asm/system.h include/asm/io.h \
include/stddef.h include/stdarg.h include/fcntl.h include/stddef.h include/stdarg.h include/fcntl.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,260 +1,260 @@
! !
! SYS_SIZE is the number of clicks (16 bytes) to be loaded. ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! versions of linux ! versions of linux
! !
SYSSIZE = 0x3000 SYSSIZE = 0x3000
! !
! bootsect.s (C) 1991 Linus Torvalds ! bootsect.s (C) 1991 Linus Torvalds
! !
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there. ! iself out of the way to address 0x90000, and jumps there.
! !
! It then loads 'setup' directly after itself (0x90200), and the system ! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts. ! at 0x10000, using BIOS interrupts.
! !
! NOTE! currently system is at most 8*65536 bytes long. This should be no ! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB ! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the ! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix ! buffer cache as in minix
! !
! The loader has been made as simple as possible, and continuos ! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It ! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole sectors at a time whenever possible. ! loads pretty fast by getting whole sectors at a time whenever possible.
.globl begtext, begdata, begbss, endtext, enddata, endbss .globl begtext, begdata, begbss, endtext, enddata, endbss
.text .text
begtext: begtext:
.data .data
begdata: begdata:
.bss .bss
begbss: begbss:
.text .text
SETUPLEN = 4 ! nr of setup-sectors SETUPLEN = 4 ! nr of setup-sectors
BOOTSEG = 0x07c0 ! original address of boot-sector BOOTSEG = 0x07c0 ! original address of boot-sector
INITSEG = 0x9000 ! we move boot here - out of the way INITSEG = 0x9000 ! we move boot here - out of the way
SETUPSEG = 0x9020 ! setup starts here SETUPSEG = 0x9020 ! setup starts here
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV: 0x000 - same type of floppy as boot. ! ROOT_DEV: 0x000 - same type of floppy as boot.
! 0x301 - first partition on first drive etc ! 0x301 - first partition on first drive etc
ROOT_DEV = 0x306 ROOT_DEV = 0x306
entry start entry start
start: start:
mov ax,#BOOTSEG mov ax,#BOOTSEG
mov ds,ax mov ds,ax
mov ax,#INITSEG mov ax,#INITSEG
mov es,ax mov es,ax
mov cx,#256 mov cx,#256
sub si,si sub si,si
sub di,di sub di,di
rep rep
movw movw
jmpi go,INITSEG jmpi go,INITSEG
go: mov ax,cs go: mov ax,cs
mov ds,ax mov ds,ax
mov es,ax mov es,ax
! put stack at 0x9ff00. ! put stack at 0x9ff00.
mov ss,ax mov ss,ax
mov sp,#0xFF00 ! arbitrary value >>512 mov sp,#0xFF00 ! arbitrary value >>512
! load the setup-sectors directly after the bootblock. ! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up. ! Note that 'es' is already set up.
load_setup: load_setup:
mov dx,#0x0000 ! drive 0, head 0 mov dx,#0x0000 ! drive 0, head 0
mov cx,#0x0002 ! sector 2, track 0 mov cx,#0x0002 ! sector 2, track 0
mov bx,#0x0200 ! address = 512, in INITSEG mov bx,#0x0200 ! address = 512, in INITSEG
mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
int 0x13 ! read it int 0x13 ! read it
jnc ok_load_setup ! ok - continue jnc ok_load_setup ! ok - continue
mov dx,#0x0000 mov dx,#0x0000
mov ax,#0x0000 ! reset the diskette mov ax,#0x0000 ! reset the diskette
int 0x13 int 0x13
j load_setup j load_setup
ok_load_setup: ok_load_setup:
! Get disk drive parameters, specifically nr of sectors/track ! Get disk drive parameters, specifically nr of sectors/track
mov dl,#0x00 mov dl,#0x00
mov ax,#0x0800 ! AH=8 is get drive parameters mov ax,#0x0800 ! AH=8 is get drive parameters
int 0x13 int 0x13
mov ch,#0x00 mov ch,#0x00
seg cs seg cs
mov sectors,cx mov sectors,cx
mov ax,#INITSEG mov ax,#INITSEG
mov es,ax mov es,ax
! Print some inane message ! Print some inane message
mov ah,#0x03 ! read cursor pos mov ah,#0x03 ! read cursor pos
xor bh,bh xor bh,bh
int 0x10 int 0x10
mov cx,#24 mov cx,#24
mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1 mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor mov ax,#0x1301 ! write string, move cursor
int 0x10 int 0x10
! ok, we've written the message, now ! ok, we've written the message, now
! we want to load the system (at 0x10000) ! we want to load the system (at 0x10000)
mov ax,#SYSSEG mov ax,#SYSSEG
mov es,ax ! segment of 0x010000 mov es,ax ! segment of 0x010000
call read_it call read_it
call kill_motor call kill_motor
! After that we check which root-device to use. If the device is ! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used. ! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently. ! on the number of sectors that the BIOS reports currently.
seg cs seg cs
mov ax,root_dev mov ax,root_dev
cmp ax,#0 cmp ax,#0
jne root_defined jne root_defined
seg cs seg cs
mov bx,sectors mov bx,sectors
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
cmp bx,#15 cmp bx,#15
je root_defined je root_defined
mov ax,#0x021c ! /dev/PS0 - 1.44Mb mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18 cmp bx,#18
je root_defined je root_defined
undef_root: undef_root:
jmp undef_root jmp undef_root
root_defined: root_defined:
seg cs seg cs
mov root_dev,ax mov root_dev,ax
! after that (everyting loaded), we jump to ! after that (everyting loaded), we jump to
! the setup-routine loaded directly after ! the setup-routine loaded directly after
! the bootblock: ! the bootblock:
jmpi 0,SETUPSEG jmpi 0,SETUPSEG
! This routine loads the system at address 0x10000, making sure ! This routine loads the system at address 0x10000, making sure
! no 64kB boundaries are crossed. We try to load it as fast as ! no 64kB boundaries are crossed. We try to load it as fast as
! possible, loading whole tracks whenever we can. ! possible, loading whole tracks whenever we can.
! !
! in: es - starting address segment (normally 0x1000) ! in: es - starting address segment (normally 0x1000)
! !
sread: .word 1+SETUPLEN ! sectors read of current track sread: .word 1+SETUPLEN ! sectors read of current track
head: .word 0 ! current head head: .word 0 ! current head
track: .word 0 ! current track track: .word 0 ! current track
read_it: read_it:
mov ax,es mov ax,es
test ax,#0x0fff test ax,#0x0fff
die: jne die ! es must be at 64kB boundary die: jne die ! es must be at 64kB boundary
xor bx,bx ! bx is starting address within segment xor bx,bx ! bx is starting address within segment
rp_read: rp_read:
mov ax,es mov ax,es
cmp ax,#ENDSEG ! have we loaded all yet? cmp ax,#ENDSEG ! have we loaded all yet?
jb ok1_read jb ok1_read
ret ret
ok1_read: ok1_read:
seg cs seg cs
mov ax,sectors mov ax,sectors
sub ax,sread sub ax,sread
mov cx,ax mov cx,ax
shl cx,#9 shl cx,#9
add cx,bx add cx,bx
jnc ok2_read jnc ok2_read
je ok2_read je ok2_read
xor ax,ax xor ax,ax
sub ax,bx sub ax,bx
shr ax,#9 shr ax,#9
ok2_read: ok2_read:
call read_track call read_track
mov cx,ax mov cx,ax
add ax,sread add ax,sread
seg cs seg cs
cmp ax,sectors cmp ax,sectors
jne ok3_read jne ok3_read
mov ax,#1 mov ax,#1
sub ax,head sub ax,head
jne ok4_read jne ok4_read
inc track inc track
ok4_read: ok4_read:
mov head,ax mov head,ax
xor ax,ax xor ax,ax
ok3_read: ok3_read:
mov sread,ax mov sread,ax
shl cx,#9 shl cx,#9
add bx,cx add bx,cx
jnc rp_read jnc rp_read
mov ax,es mov ax,es
add ax,#0x1000 add ax,#0x1000
mov es,ax mov es,ax
xor bx,bx xor bx,bx
jmp rp_read jmp rp_read
read_track: read_track:
push ax push ax
push bx push bx
push cx push cx
push dx push dx
mov dx,track mov dx,track
mov cx,sread mov cx,sread
inc cx inc cx
mov ch,dl mov ch,dl
mov dx,head mov dx,head
mov dh,dl mov dh,dl
mov dl,#0 mov dl,#0
and dx,#0x0100 and dx,#0x0100
mov ah,#2 mov ah,#2
int 0x13 int 0x13
jc bad_rt jc bad_rt
pop dx pop dx
pop cx pop cx
pop bx pop bx
pop ax pop ax
ret ret
bad_rt: mov ax,#0 bad_rt: mov ax,#0
mov dx,#0 mov dx,#0
int 0x13 int 0x13
pop dx pop dx
pop cx pop cx
pop bx pop bx
pop ax pop ax
jmp read_track jmp read_track
/* /*
* This procedure turns off the floppy drive motor, so * This procedure turns off the floppy drive motor, so
* that we enter the kernel in a known state, and * that we enter the kernel in a known state, and
* don't have to worry about it later. * don't have to worry about it later.
*/ */
kill_motor: kill_motor:
push dx push dx
mov dx,#0x3f2 mov dx,#0x3f2
mov al,#0 mov al,#0
outb outb
pop dx pop dx
ret ret
sectors: sectors:
.word 0 .word 0
msg1: msg1:
.byte 13,10 .byte 13,10
.ascii "Loading system ..." .ascii "Loading system ..."
.byte 13,10,13,10 .byte 13,10,13,10
.org 508 .org 508
root_dev: root_dev:
.word ROOT_DEV .word ROOT_DEV
boot_flag: boot_flag:
.word 0xAA55 .word 0xAA55
.text .text
endtext: endtext:
.data .data
enddata: enddata:
.bss .bss
endbss: endbss:

@ -1,240 +1,240 @@
/* /*
* linux/boot/head.s * linux/boot/head.s
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* head.s contains the 32-bit startup code. * head.s contains the 32-bit startup code.
* *
* NOTE!!! Startup happens at absolute address 0x00000000, which is also where * NOTE!!! Startup happens at absolute address 0x00000000, which is also where
* the page directory will exist. The startup code will be overwritten by * the page directory will exist. The startup code will be overwritten by
* the page directory. * the page directory.
*/ */
.text .text
.globl idt,gdt,pg_dir,tmp_floppy_area .globl idt,gdt,pg_dir,tmp_floppy_area
pg_dir: pg_dir:
.globl startup_32 .globl startup_32
startup_32: startup_32:
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
mov %ax,%fs mov %ax,%fs
mov %ax,%gs mov %ax,%gs
lss stack_start,%esp lss stack_start,%esp
call setup_idt call setup_idt
call setup_gdt call setup_gdt
movl $0x10,%eax # reload all the segment registers movl $0x10,%eax # reload all the segment registers
mov %ax,%ds # after changing gdt. CS was already mov %ax,%ds # after changing gdt. CS was already
mov %ax,%es # reloaded in 'setup_gdt' mov %ax,%es # reloaded in 'setup_gdt'
mov %ax,%fs mov %ax,%fs
mov %ax,%gs mov %ax,%gs
lss stack_start,%esp lss stack_start,%esp
xorl %eax,%eax xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled 1: incl %eax # check that A20 really IS enabled
movl %eax,0x000000 # loop forever if it isn't movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000 cmpl %eax,0x100000
je 1b je 1b
/* /*
* NOTE! 486 should set bit 16, to check for write-protect in supervisor * NOTE! 486 should set bit 16, to check for write-protect in supervisor
* mode. Then it would be unnecessary with the "verify_area()"-calls. * mode. Then it would be unnecessary with the "verify_area()"-calls.
* 486 users probably want to set the NE (#5) bit also, so as to use * 486 users probably want to set the NE (#5) bit also, so as to use
* int 16 for math errors. * int 16 for math errors.
*/ */
movl %cr0,%eax # check math chip movl %cr0,%eax # check math chip
andl $0x80000011,%eax # Save PG,PE,ET andl $0x80000011,%eax # Save PG,PE,ET
/* "orl $0x10020,%eax" here for 486 might be good */ /* "orl $0x10020,%eax" here for 486 might be good */
orl $2,%eax # set MP orl $2,%eax # set MP
movl %eax,%cr0 movl %eax,%cr0
call check_x87 call check_x87
jmp after_page_tables jmp after_page_tables
/* /*
* We depend on ET to be correct. This checks for 287/387. * We depend on ET to be correct. This checks for 287/387.
*/ */
check_x87: check_x87:
fninit fninit
fstsw %ax fstsw %ax
cmpb $0,%al cmpb $0,%al
je 1f /* no coprocessor: have to set bits */ je 1f /* no coprocessor: have to set bits */
movl %cr0,%eax movl %cr0,%eax
xorl $6,%eax /* reset MP, set EM */ xorl $6,%eax /* reset MP, set EM */
movl %eax,%cr0 movl %eax,%cr0
ret ret
.align 4 .align 4
1: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ 1: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
ret ret
/* /*
* setup_idt * setup_idt
* *
* sets up a idt with 256 entries pointing to * sets up a idt with 256 entries pointing to
* ignore_int, interrupt gates. It then loads * ignore_int, interrupt gates. It then loads
* idt. Everything that wants to install itself * idt. Everything that wants to install itself
* in the idt-table may do so themselves. Interrupts * in the idt-table may do so themselves. Interrupts
* are enabled elsewhere, when we can be relatively * are enabled elsewhere, when we can be relatively
* sure everything is ok. This routine will be over- * sure everything is ok. This routine will be over-
* written by the page tables. * written by the page tables.
*/ */
setup_idt: setup_idt:
lea ignore_int,%edx lea ignore_int,%edx
movl $0x00080000,%eax movl $0x00080000,%eax
movw %dx,%ax /* selector = 0x0008 = cs */ movw %dx,%ax /* selector = 0x0008 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea idt,%edi lea idt,%edi
mov $256,%ecx mov $256,%ecx
rp_sidt: rp_sidt:
movl %eax,(%edi) movl %eax,(%edi)
movl %edx,4(%edi) movl %edx,4(%edi)
addl $8,%edi addl $8,%edi
dec %ecx dec %ecx
jne rp_sidt jne rp_sidt
lidt idt_descr lidt idt_descr
ret ret
/* /*
* setup_gdt * setup_gdt
* *
* This routines sets up a new gdt and loads it. * This routines sets up a new gdt and loads it.
* Only two entries are currently built, the same * Only two entries are currently built, the same
* ones that were built in init.s. The routine * ones that were built in init.s. The routine
* is VERY complicated at two whole lines, so this * is VERY complicated at two whole lines, so this
* rather long comment is certainly needed :-). * rather long comment is certainly needed :-).
* This routine will beoverwritten by the page tables. * This routine will beoverwritten by the page tables.
*/ */
setup_gdt: setup_gdt:
lgdt gdt_descr lgdt gdt_descr
ret ret
/* /*
* I put the kernel page tables right after the page directory, * I put the kernel page tables right after the page directory,
* using 4 of them to span 16 Mb of physical memory. People with * using 4 of them to span 16 Mb of physical memory. People with
* more than 16MB will have to expand this. * more than 16MB will have to expand this.
*/ */
.org 0x1000 .org 0x1000
pg0: pg0:
.org 0x2000 .org 0x2000
pg1: pg1:
.org 0x3000 .org 0x3000
pg2: pg2:
.org 0x4000 .org 0x4000
pg3: pg3:
.org 0x5000 .org 0x5000
/* /*
* tmp_floppy_area is used by the floppy-driver when DMA cannot * tmp_floppy_area is used by the floppy-driver when DMA cannot
* reach to a buffer-block. It needs to be aligned, so that it isn't * reach to a buffer-block. It needs to be aligned, so that it isn't
* on a 64kB border. * on a 64kB border.
*/ */
tmp_floppy_area: tmp_floppy_area:
.fill 1024,1,0 .fill 1024,1,0
after_page_tables: after_page_tables:
pushl $0 # These are the parameters to main :-) pushl $0 # These are the parameters to main :-)
pushl $0 pushl $0
pushl $0 pushl $0
pushl $L6 # return address for main, if it decides to. pushl $L6 # return address for main, if it decides to.
pushl $main pushl $main
jmp setup_paging jmp setup_paging
L6: L6:
jmp L6 # main should never return here, but jmp L6 # main should never return here, but
# just in case, we know what happens. # just in case, we know what happens.
/* This is the default interrupt "handler" :-) */ /* This is the default interrupt "handler" :-) */
int_msg: int_msg:
.asciz "Unknown interrupt\n\r" .asciz "Unknown interrupt\n\r"
.align 4 .align 4
ignore_int: ignore_int:
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
push %ds push %ds
push %es push %es
push %fs push %fs
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
mov %ax,%fs mov %ax,%fs
pushl $int_msg pushl $int_msg
call printk call printk
popl %eax popl %eax
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
iret iret
/* /*
* Setup_paging * Setup_paging
* *
* This routine sets up paging by setting the page bit * This routine sets up paging by setting the page bit
* in cr0. The page tables are set up, identity-mapping * in cr0. The page tables are set up, identity-mapping
* the first 16MB. The pager assumes that no illegal * the first 16MB. The pager assumes that no illegal
* addresses are produced (ie >4Mb on a 4Mb machine). * addresses are produced (ie >4Mb on a 4Mb machine).
* *
* NOTE! Although all physical memory should be identity * NOTE! Although all physical memory should be identity
* mapped by this routine, only the kernel page functions * mapped by this routine, only the kernel page functions
* use the >1Mb addresses directly. All "normal" functions * use the >1Mb addresses directly. All "normal" functions
* use just the lower 1Mb, or the local data space, which * use just the lower 1Mb, or the local data space, which
* will be mapped to some other place - mm keeps track of * will be mapped to some other place - mm keeps track of
* that. * that.
* *
* For those with more memory than 16 Mb - tough luck. I've * For those with more memory than 16 Mb - tough luck. I've
* not got it, why should you :-) The source is here. Change * not got it, why should you :-) The source is here. Change
* it. (Seriously - it shouldn't be too difficult. Mostly * it. (Seriously - it shouldn't be too difficult. Mostly
* change some constants etc. I left it at 16Mb, as my machine * change some constants etc. I left it at 16Mb, as my machine
* even cannot be extended past that (ok, but it was cheap :-) * even cannot be extended past that (ok, but it was cheap :-)
* I've tried to show which constants to change by having * I've tried to show which constants to change by having
* some kind of marker at them (search for "16Mb"), but I * some kind of marker at them (search for "16Mb"), but I
* won't guarantee that's all :-( ) * won't guarantee that's all :-( )
*/ */
.align 4 .align 4
setup_paging: setup_paging:
movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */ movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */
xorl %eax,%eax xorl %eax,%eax
xorl %edi,%edi /* pg_dir is at 0x000 */ xorl %edi,%edi /* pg_dir is at 0x000 */
cld;rep;stosl cld;rep;stosl
movl $pg0+7,pg_dir /* set present bit/user r/w */ movl $pg0+7,pg_dir /* set present bit/user r/w */
movl $pg1+7,pg_dir+4 /* --------- " " --------- */ movl $pg1+7,pg_dir+4 /* --------- " " --------- */
movl $pg2+7,pg_dir+8 /* --------- " " --------- */ movl $pg2+7,pg_dir+8 /* --------- " " --------- */
movl $pg3+7,pg_dir+12 /* --------- " " --------- */ movl $pg3+7,pg_dir+12 /* --------- " " --------- */
movl $pg3+4092,%edi movl $pg3+4092,%edi
movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */ movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */
std std
1: stosl /* fill pages backwards - more efficient :-) */ 1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax subl $0x1000,%eax
jge 1b jge 1b
xorl %eax,%eax /* pg_dir is at 0x0000 */ xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3 - page directory start */ movl %eax,%cr3 /* cr3 - page directory start */
movl %cr0,%eax movl %cr0,%eax
orl $0x80000000,%eax orl $0x80000000,%eax
movl %eax,%cr0 /* set paging (PG) bit */ movl %eax,%cr0 /* set paging (PG) bit */
cld /* by wyj */ cld /* by wyj */
ret /* this also flushes prefetch-queue */ ret /* this also flushes prefetch-queue */
.align 4 .align 4
.word 0 .word 0
idt_descr: idt_descr:
.word 256*8-1 # idt contains 256 entries .word 256*8-1 # idt contains 256 entries
.long idt .long idt
.align 4 .align 4
.word 0 .word 0
gdt_descr: gdt_descr:
.word 256*8-1 # so does gdt (not that that's any .word 256*8-1 # so does gdt (not that that's any
.long gdt # magic number, but it works for me :^) .long gdt # magic number, but it works for me :^)
.align 8 .align 8
idt: .fill 256,8,0 # idt is uninitialized idt: .fill 256,8,0 # idt is uninitialized
gdt: .quad 0x0000000000000000 /* NULL descriptor */ gdt: .quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00c09a0000000fff /* 16Mb */ .quad 0x00c09a0000000fff /* 16Mb */
.quad 0x00c0920000000fff /* 16Mb */ .quad 0x00c0920000000fff /* 16Mb */
.quad 0x0000000000000000 /* TEMPORARY - don't use */ .quad 0x0000000000000000 /* TEMPORARY - don't use */
.fill 252,8,0 /* space for LDT's and TSS's etc */ .fill 252,8,0 /* space for LDT's and TSS's etc */

@ -1,231 +1,231 @@
! !
! setup.s (C) 1991 Linus Torvalds ! setup.s (C) 1991 Linus Torvalds
! !
! setup.s is responsible for getting the system data from the BIOS, ! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory. ! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock. ! both setup.s and system has been loaded by the bootblock.
! !
! This code asks the bios for memory/disk/other parameters, and ! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode ! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten ! system to read them from there before the area is overwritten
! for buffer-blocks. ! for buffer-blocks.
! !
! NOTE! These had better be the same as in bootsect.s! ! NOTE! These had better be the same as in bootsect.s!
INITSEG = 0x9000 ! we move boot here - out of the way INITSEG = 0x9000 ! we move boot here - out of the way
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
SETUPSEG = 0x9020 ! this is the current segment SETUPSEG = 0x9020 ! this is the current segment
.globl begtext, begdata, begbss, endtext, enddata, endbss .globl begtext, begdata, begbss, endtext, enddata, endbss
.text .text
begtext: begtext:
.data .data
begdata: begdata:
.bss .bss
begbss: begbss:
.text .text
entry start entry start
start: start:
! ok, the read went well so we get current cursor position and save it for ! ok, the read went well so we get current cursor position and save it for
! posterity. ! posterity.
mov ax,#INITSEG ! this is done in bootsect already, but... mov ax,#INITSEG ! this is done in bootsect already, but...
mov ds,ax mov ds,ax
mov ah,#0x03 ! read cursor pos mov ah,#0x03 ! read cursor pos
xor bh,bh xor bh,bh
int 0x10 ! save it in known place, con_init fetches int 0x10 ! save it in known place, con_init fetches
mov [0],dx ! it from 0x90000. mov [0],dx ! it from 0x90000.
! Get memory size (extended mem, kB) ! Get memory size (extended mem, kB)
mov ah,#0x88 mov ah,#0x88
int 0x15 int 0x15
mov [2],ax mov [2],ax
! Get video-card data: ! Get video-card data:
mov ah,#0x0f mov ah,#0x0f
int 0x10 int 0x10
mov [4],bx ! bh = display page mov [4],bx ! bh = display page
mov [6],ax ! al = video mode, ah = window width mov [6],ax ! al = video mode, ah = window width
! check for EGA/VGA and some config parameters ! check for EGA/VGA and some config parameters
mov ah,#0x12 mov ah,#0x12
mov bl,#0x10 mov bl,#0x10
int 0x10 int 0x10
mov [8],ax mov [8],ax
mov [10],bx mov [10],bx
mov [12],cx mov [12],cx
! Get hd0 data ! Get hd0 data
mov ax,#0x0000 mov ax,#0x0000
mov ds,ax mov ds,ax
lds si,[4*0x41] lds si,[4*0x41]
mov ax,#INITSEG mov ax,#INITSEG
mov es,ax mov es,ax
mov di,#0x0080 mov di,#0x0080
mov cx,#0x10 mov cx,#0x10
rep rep
movsb movsb
! Get hd1 data ! Get hd1 data
mov ax,#0x0000 mov ax,#0x0000
mov ds,ax mov ds,ax
lds si,[4*0x46] lds si,[4*0x46]
mov ax,#INITSEG mov ax,#INITSEG
mov es,ax mov es,ax
mov di,#0x0090 mov di,#0x0090
mov cx,#0x10 mov cx,#0x10
rep rep
movsb movsb
! Check that there IS a hd1 :-) ! Check that there IS a hd1 :-)
mov ax,#0x01500 mov ax,#0x01500
mov dl,#0x81 mov dl,#0x81
int 0x13 int 0x13
jc no_disk1 jc no_disk1
cmp ah,#3 cmp ah,#3
je is_disk1 je is_disk1
no_disk1: no_disk1:
mov ax,#INITSEG mov ax,#INITSEG
mov es,ax mov es,ax
mov di,#0x0090 mov di,#0x0090
mov cx,#0x10 mov cx,#0x10
mov ax,#0x00 mov ax,#0x00
rep rep
stosb stosb
is_disk1: is_disk1:
! now we want to move to protected mode ... ! now we want to move to protected mode ...
cli ! no interrupts allowed ! cli ! no interrupts allowed !
! first we move the system to it's rightful place ! first we move the system to it's rightful place
mov ax,#0x0000 mov ax,#0x0000
cld ! 'direction'=0, movs moves forward cld ! 'direction'=0, movs moves forward
do_move: do_move:
mov es,ax ! destination segment mov es,ax ! destination segment
add ax,#0x1000 add ax,#0x1000
cmp ax,#0x9000 cmp ax,#0x9000
jz end_move jz end_move
mov ds,ax ! source segment mov ds,ax ! source segment
sub di,di sub di,di
sub si,si sub si,si
mov cx,#0x8000 mov cx,#0x8000
rep rep
movsw movsw
jmp do_move jmp do_move
! then we load the segment descriptors ! then we load the segment descriptors
end_move: end_move:
mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-) mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
mov ds,ax mov ds,ax
lidt idt_48 ! load idt with 0,0 lidt idt_48 ! load idt with 0,0
lgdt gdt_48 ! load gdt with whatever appropriate lgdt gdt_48 ! load gdt with whatever appropriate
! that was painless, now we enable A20 ! that was painless, now we enable A20
call empty_8042 call empty_8042
mov al,#0xD1 ! command write mov al,#0xD1 ! command write
out #0x64,al out #0x64,al
call empty_8042 call empty_8042
mov al,#0xDF ! A20 on mov al,#0xDF ! A20 on
out #0x60,al out #0x60,al
call empty_8042 call empty_8042
! well, that went ok, I hope. Now we have to reprogram the interrupts :-( ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
! we put them right after the intel-reserved hardware interrupts, at ! we put them right after the intel-reserved hardware interrupts, at
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
! messed this up with the original PC, and they haven't been able to ! messed this up with the original PC, and they haven't been able to
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
! which is used for the internal hardware interrupts as well. We just ! which is used for the internal hardware interrupts as well. We just
! have to reprogram the 8259's, and it isn't fun. ! have to reprogram the 8259's, and it isn't fun.
mov al,#0x11 ! initialization sequence mov al,#0x11 ! initialization sequence
out #0x20,al ! send it to 8259A-1 out #0x20,al ! send it to 8259A-1
.word 0x00eb,0x00eb ! jmp $+2, jmp $+2 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2
out #0xA0,al ! and to 8259A-2 out #0xA0,al ! and to 8259A-2
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0x20 ! start of hardware int's (0x20) mov al,#0x20 ! start of hardware int's (0x20)
out #0x21,al out #0x21,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0x28 ! start of hardware int's 2 (0x28) mov al,#0x28 ! start of hardware int's 2 (0x28)
out #0xA1,al out #0xA1,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0x04 ! 8259-1 is master mov al,#0x04 ! 8259-1 is master
out #0x21,al out #0x21,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0x02 ! 8259-2 is slave mov al,#0x02 ! 8259-2 is slave
out #0xA1,al out #0xA1,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0x01 ! 8086 mode for both mov al,#0x01 ! 8086 mode for both
out #0x21,al out #0x21,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
out #0xA1,al out #0xA1,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
mov al,#0xFF ! mask off all interrupts for now mov al,#0xFF ! mask off all interrupts for now
out #0x21,al out #0x21,al
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
out #0xA1,al out #0xA1,al
! well, that certainly wasn't fun :-(. Hopefully it works, and we don't ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
! need no steenking BIOS anyway (except for the initial loading :-). ! need no steenking BIOS anyway (except for the initial loading :-).
! The BIOS-routine wants lots of unnecessary data, and it's less ! The BIOS-routine wants lots of unnecessary data, and it's less
! "interesting" anyway. This is how REAL programmers do it. ! "interesting" anyway. This is how REAL programmers do it.
! !
! Well, now's the time to actually move into protected mode. To make ! Well, now's the time to actually move into protected mode. To make
! things as simple as possible, we do no register set-up or anything, ! things as simple as possible, we do no register set-up or anything,
! we let the gnu-compiled 32-bit programs do that. We just jump to ! we let the gnu-compiled 32-bit programs do that. We just jump to
! absolute address 0x00000, in 32-bit protected mode. ! absolute address 0x00000, in 32-bit protected mode.
mov ax,#0x0001 ! protected mode (PE) bit mov ax,#0x0001 ! protected mode (PE) bit
lmsw ax ! This is it! lmsw ax ! This is it!
jmpi 0,8 ! jmp offset 0 of segment 8 (cs) jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
! This routine checks that the keyboard command queue is empty ! This routine checks that the keyboard command queue is empty
! No timeout is used - if this hangs there is something wrong with ! No timeout is used - if this hangs there is something wrong with
! the machine, and we probably couldn't proceed anyway. ! the machine, and we probably couldn't proceed anyway.
empty_8042: empty_8042:
.word 0x00eb,0x00eb .word 0x00eb,0x00eb
in al,#0x64 ! 8042 status port in al,#0x64 ! 8042 status port
test al,#2 ! is input buffer full? test al,#2 ! is input buffer full?
jnz empty_8042 ! yes - loop jnz empty_8042 ! yes - loop
ret ret
gdt: gdt:
.word 0,0,0,0 ! dummy .word 0,0,0,0 ! dummy
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0 .word 0x0000 ! base address=0
.word 0x9A00 ! code read/exec .word 0x9A00 ! code read/exec
.word 0x00C0 ! granularity=4096, 386 .word 0x00C0 ! granularity=4096, 386
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0 .word 0x0000 ! base address=0
.word 0x9200 ! data read/write .word 0x9200 ! data read/write
.word 0x00C0 ! granularity=4096, 386 .word 0x00C0 ! granularity=4096, 386
idt_48: idt_48:
.word 0 ! idt limit=0 .word 0 ! idt limit=0
.word 0,0 ! idt base=0L .word 0,0 ! idt base=0L
gdt_48: gdt_48:
.word 0x800 ! gdt limit=2048, 256 GDT entries .word 0x800 ! gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ! gdt base = 0X9xxxx .word 512+gdt,0x9 ! gdt base = 0X9xxxx
.text .text
endtext: endtext:
.data .data
enddata: enddata:
.bss .bss
endbss: endbss:

@ -1,101 +1,101 @@
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-s -x LDFLAGS =-s -x
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \
-finline-functions -nostdinc -fno-stack-protector -I../include -finline-functions -nostdinc -fno-stack-protector -I../include
CPP =gcc -E -nostdinc -I../include CPP =gcc -E -nostdinc -I../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \ OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \ block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \
bitmap.o fcntl.o ioctl.o truncate.o select.o bitmap.o fcntl.o ioctl.o truncate.o select.o
fs.o: $(OBJS) fs.o: $(OBJS)
$(LD) -r -o fs.o $(OBJS) $(LD) -r -o fs.o $(OBJS)
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
### Dependencies: ### Dependencies:
bitmap.o : bitmap.c ../include/string.h ../include/linux/sched.h \ bitmap.o : bitmap.c ../include/string.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h
block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \ block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/system.h ../include/asm/segment.h ../include/asm/system.h
buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h \ buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/linux/mm.h ../include/signal.h \ ../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/system.h ../include/asm/io.h ../include/linux/kernel.h ../include/asm/system.h ../include/asm/io.h
char_dev.o : char_dev.c ../include/errno.h ../include/sys/types.h \ char_dev.o : char_dev.c ../include/errno.h ../include/sys/types.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/io.h ../include/asm/segment.h ../include/asm/io.h
exec.o : exec.c ../include/errno.h ../include/string.h \ exec.o : exec.c ../include/errno.h ../include/string.h \
../include/sys/stat.h ../include/sys/types.h ../include/a.out.h \ ../include/sys/stat.h ../include/sys/types.h ../include/a.out.h \
../include/linux/fs.h ../include/linux/sched.h ../include/linux/head.h \ ../include/linux/fs.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/segment.h
fcntl.o : fcntl.c ../include/string.h ../include/errno.h \ fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/linux/mm.h ../include/signal.h \ ../include/sys/types.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h ../include/fcntl.h \ ../include/linux/kernel.h ../include/asm/segment.h ../include/fcntl.h \
../include/sys/stat.h ../include/sys/stat.h
file_dev.o : file_dev.c ../include/errno.h ../include/fcntl.h \ file_dev.o : file_dev.c ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \ ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \ ../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h ../include/linux/kernel.h ../include/asm/segment.h
file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h
inode.o : inode.c ../include/string.h ../include/sys/stat.h \ inode.o : inode.c ../include/string.h ../include/sys/stat.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \ ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \ ../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/system.h ../include/linux/kernel.h ../include/asm/system.h
ioctl.o : ioctl.c ../include/string.h ../include/errno.h \ ioctl.o : ioctl.c ../include/string.h ../include/errno.h \
../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \ ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/signal.h ../include/signal.h
namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \ namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \ ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h \ ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h \
../include/string.h ../include/fcntl.h ../include/errno.h \ ../include/string.h ../include/fcntl.h ../include/errno.h \
../include/const.h ../include/sys/stat.h ../include/const.h ../include/sys/stat.h
open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \ open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/utime.h ../include/sys/stat.h \ ../include/sys/types.h ../include/utime.h ../include/sys/stat.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h ../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h
pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \ pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/asm/segment.h ../include/linux/mm.h ../include/asm/segment.h
read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \ read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \
../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \ ../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/signal.h ../include/asm/segment.h ../include/signal.h ../include/asm/segment.h
stat.o : stat.c ../include/errno.h ../include/sys/stat.h \ stat.o : stat.c ../include/errno.h ../include/sys/stat.h \
../include/sys/types.h ../include/linux/fs.h ../include/linux/sched.h \ ../include/sys/types.h ../include/linux/fs.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/mm.h ../include/signal.h \ ../include/linux/head.h ../include/linux/mm.h ../include/signal.h \
../include/linux/kernel.h ../include/asm/segment.h ../include/linux/kernel.h ../include/asm/segment.h
super.o : super.c ../include/linux/config.h ../include/linux/sched.h \ super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/system.h ../include/errno.h ../include/sys/stat.h ../include/asm/system.h ../include/errno.h ../include/sys/stat.h
truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \ truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \ ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/sys/stat.h ../include/signal.h ../include/sys/stat.h

@ -1,168 +1,168 @@
/* /*
* linux/fs/bitmap.c * linux/fs/bitmap.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* bitmap.c contains the code that handles the inode and block bitmaps */ /* bitmap.c contains the code that handles the inode and block bitmaps */
#include <string.h> #include <string.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#define clear_block(addr) \ #define clear_block(addr) \
__asm__ __volatile__ ("cld\n\t" \ __asm__ __volatile__ ("cld\n\t" \
"rep\n\t" \ "rep\n\t" \
"stosl" \ "stosl" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr))) ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)))
#define set_bit(nr,addr) ({\ #define set_bit(nr,addr) ({\
register int res __asm__("ax"); \ register int res __asm__("ax"); \
__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \ __asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ "=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;}) res;})
#define clear_bit(nr,addr) ({\ #define clear_bit(nr,addr) ({\
register int res __asm__("ax"); \ register int res __asm__("ax"); \
__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \ __asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ "=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;}) res;})
#define find_first_zero(addr) ({ \ #define find_first_zero(addr) ({ \
int __res; \ int __res; \
__asm__ __volatile__ ("cld\n" \ __asm__ __volatile__ ("cld\n" \
"1:\tlodsl\n\t" \ "1:\tlodsl\n\t" \
"notl %%eax\n\t" \ "notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \ "bsfl %%eax,%%edx\n\t" \
"je 2f\n\t" \ "je 2f\n\t" \
"addl %%edx,%%ecx\n\t" \ "addl %%edx,%%ecx\n\t" \
"jmp 3f\n" \ "jmp 3f\n" \
"2:\taddl $32,%%ecx\n\t" \ "2:\taddl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \ "cmpl $8192,%%ecx\n\t" \
"jl 1b\n" \ "jl 1b\n" \
"3:" \ "3:" \
:"=c" (__res):"c" (0),"S" (addr)); \ :"=c" (__res):"c" (0),"S" (addr)); \
__res;}) __res;})
void free_block(int dev, int block) void free_block(int dev, int block)
{ {
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device"); panic("trying to free block on nonexistent device");
if (block < sb->s_firstdatazone || block >= sb->s_nzones) if (block < sb->s_firstdatazone || block >= sb->s_nzones)
panic("trying to free block not in datazone"); panic("trying to free block not in datazone");
bh = get_hash_table(dev,block); bh = get_hash_table(dev,block);
if (bh) { if (bh) {
if (bh->b_count != 1) { if (bh->b_count != 1) {
printk("trying to free block (%04x:%d), count=%d\n", printk("trying to free block (%04x:%d), count=%d\n",
dev,block,bh->b_count); dev,block,bh->b_count);
return; return;
} }
bh->b_dirt=0; bh->b_dirt=0;
bh->b_uptodate=0; bh->b_uptodate=0;
brelse(bh); brelse(bh);
} }
block -= sb->s_firstdatazone - 1 ; block -= sb->s_firstdatazone - 1 ;
if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) { if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1); printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
panic("free_block: bit already cleared"); panic("free_block: bit already cleared");
} }
sb->s_zmap[block/8192]->b_dirt = 1; sb->s_zmap[block/8192]->b_dirt = 1;
} }
int new_block(int dev) int new_block(int dev)
{ {
struct buffer_head * bh; struct buffer_head * bh;
struct super_block * sb; struct super_block * sb;
int i,j; int i,j;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("trying to get new block from nonexistant device"); panic("trying to get new block from nonexistant device");
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if (bh=sb->s_zmap[i]) if (bh=sb->s_zmap[i])
if ((j=find_first_zero(bh->b_data))<8192) if ((j=find_first_zero(bh->b_data))<8192)
break; break;
if (i>=8 || !bh || j>=8192) if (i>=8 || !bh || j>=8192)
return 0; return 0;
if (set_bit(j,bh->b_data)) if (set_bit(j,bh->b_data))
panic("new_block: bit already set"); panic("new_block: bit already set");
bh->b_dirt = 1; bh->b_dirt = 1;
j += i*8192 + sb->s_firstdatazone-1; j += i*8192 + sb->s_firstdatazone-1;
if (j >= sb->s_nzones) if (j >= sb->s_nzones)
return 0; return 0;
if (!(bh=getblk(dev,j))) if (!(bh=getblk(dev,j)))
panic("new_block: cannot get block"); panic("new_block: cannot get block");
if (bh->b_count != 1) if (bh->b_count != 1)
panic("new block: count is != 1"); panic("new block: count is != 1");
clear_block(bh->b_data); clear_block(bh->b_data);
bh->b_uptodate = 1; bh->b_uptodate = 1;
bh->b_dirt = 1; bh->b_dirt = 1;
brelse(bh); brelse(bh);
return j; return j;
} }
void free_inode(struct m_inode * inode) void free_inode(struct m_inode * inode)
{ {
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
if (!inode) if (!inode)
return; return;
if (!inode->i_dev) { if (!inode->i_dev) {
memset(inode,0,sizeof(*inode)); memset(inode,0,sizeof(*inode));
return; return;
} }
if (inode->i_count>1) { if (inode->i_count>1) {
printk("trying to free inode with count=%d\n",inode->i_count); printk("trying to free inode with count=%d\n",inode->i_count);
panic("free_inode"); panic("free_inode");
} }
if (inode->i_nlinks) if (inode->i_nlinks)
panic("trying to free inode with links"); panic("trying to free inode with links");
if (!(sb = get_super(inode->i_dev))) if (!(sb = get_super(inode->i_dev)))
panic("trying to free inode on nonexistent device"); panic("trying to free inode on nonexistent device");
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes) if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
panic("trying to free inode 0 or nonexistant inode"); panic("trying to free inode 0 or nonexistant inode");
if (!(bh=sb->s_imap[inode->i_num>>13])) if (!(bh=sb->s_imap[inode->i_num>>13]))
panic("nonexistent imap in superblock"); panic("nonexistent imap in superblock");
if (clear_bit(inode->i_num&8191,bh->b_data)) if (clear_bit(inode->i_num&8191,bh->b_data))
printk("free_inode: bit already cleared.\n\r"); printk("free_inode: bit already cleared.\n\r");
bh->b_dirt = 1; bh->b_dirt = 1;
memset(inode,0,sizeof(*inode)); memset(inode,0,sizeof(*inode));
} }
struct m_inode * new_inode(int dev) struct m_inode * new_inode(int dev)
{ {
struct m_inode * inode; struct m_inode * inode;
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
int i,j; int i,j;
if (!(inode=get_empty_inode())) if (!(inode=get_empty_inode()))
return NULL; return NULL;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("new_inode with unknown device"); panic("new_inode with unknown device");
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if (bh=sb->s_imap[i]) if (bh=sb->s_imap[i])
if ((j=find_first_zero(bh->b_data))<8192) if ((j=find_first_zero(bh->b_data))<8192)
break; break;
if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) { if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {
iput(inode); iput(inode);
return NULL; return NULL;
} }
if (set_bit(j,bh->b_data)) if (set_bit(j,bh->b_data))
panic("new_inode: bit already set"); panic("new_inode: bit already set");
bh->b_dirt = 1; bh->b_dirt = 1;
inode->i_count=1; inode->i_count=1;
inode->i_nlinks=1; inode->i_nlinks=1;
inode->i_dev=dev; inode->i_dev=dev;
inode->i_uid=current->euid; inode->i_uid=current->euid;
inode->i_gid=current->egid; inode->i_gid=current->egid;
inode->i_dirt=1; inode->i_dirt=1;
inode->i_num = j + i*8192; inode->i_num = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
return inode; return inode;
} }

@ -1,73 +1,73 @@
/* /*
* linux/fs/block_dev.c * linux/fs/block_dev.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
int block_write(int dev, long * pos, char * buf, int count) int block_write(int dev, long * pos, char * buf, int count)
{ {
int block = *pos >> BLOCK_SIZE_BITS; int block = *pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1); int offset = *pos & (BLOCK_SIZE-1);
int chars; int chars;
int written = 0; int written = 0;
struct buffer_head * bh; struct buffer_head * bh;
register char * p; register char * p;
while (count>0) { while (count>0) {
chars = BLOCK_SIZE - offset; chars = BLOCK_SIZE - offset;
if (chars > count) if (chars > count)
chars=count; chars=count;
if (chars == BLOCK_SIZE) if (chars == BLOCK_SIZE)
bh = getblk(dev,block); bh = getblk(dev,block);
else else
bh = breada(dev,block,block+1,block+2,-1); bh = breada(dev,block,block+1,block+2,-1);
block++; block++;
if (!bh) if (!bh)
return written?written:-EIO; return written?written:-EIO;
p = offset + bh->b_data; p = offset + bh->b_data;
offset = 0; offset = 0;
*pos += chars; *pos += chars;
written += chars; written += chars;
count -= chars; count -= chars;
while (chars-->0) while (chars-->0)
*(p++) = get_fs_byte(buf++); *(p++) = get_fs_byte(buf++);
bh->b_dirt = 1; bh->b_dirt = 1;
brelse(bh); brelse(bh);
} }
return written; return written;
} }
int block_read(int dev, unsigned long * pos, char * buf, int count) int block_read(int dev, unsigned long * pos, char * buf, int count)
{ {
int block = *pos >> BLOCK_SIZE_BITS; int block = *pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1); int offset = *pos & (BLOCK_SIZE-1);
int chars; int chars;
int read = 0; int read = 0;
struct buffer_head * bh; struct buffer_head * bh;
register char * p; register char * p;
while (count>0) { while (count>0) {
chars = BLOCK_SIZE-offset; chars = BLOCK_SIZE-offset;
if (chars > count) if (chars > count)
chars = count; chars = count;
if (!(bh = breada(dev,block,block+1,block+2,-1))) if (!(bh = breada(dev,block,block+1,block+2,-1)))
return read?read:-EIO; return read?read:-EIO;
block++; block++;
p = offset + bh->b_data; p = offset + bh->b_data;
offset = 0; offset = 0;
*pos += chars; *pos += chars;
read += chars; read += chars;
count -= chars; count -= chars;
while (chars-->0) while (chars-->0)
put_fs_byte(*(p++),buf++); put_fs_byte(*(p++),buf++);
brelse(bh); brelse(bh);
} }
return read; return read;
} }

@ -1,384 +1,384 @@
/* /*
* linux/fs/buffer.c * linux/fs/buffer.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 'buffer.c' implements the buffer-cache functions. Race-conditions have * 'buffer.c' implements the buffer-cache functions. Race-conditions have
* been avoided by NEVER letting a interrupt change a buffer (except for the * been avoided by NEVER letting a interrupt change a buffer (except for the
* data, of course), but instead letting the caller do it. NOTE! As interrupts * data, of course), but instead letting the caller do it. NOTE! As interrupts
* can wake up a caller, some cli-sti sequences are needed to check for * can wake up a caller, some cli-sti sequences are needed to check for
* sleep-on-calls. These should be extremely quick, though (I hope). * sleep-on-calls. These should be extremely quick, though (I hope).
*/ */
/* /*
* NOTE! There is one discordant note here: checking floppies for * NOTE! There is one discordant note here: checking floppies for
* disk change. This is where it fits best, I think, as it should * disk change. This is where it fits best, I think, as it should
* invalidate changed floppy-disk-caches. * invalidate changed floppy-disk-caches.
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
extern void put_super(int dev); extern void put_super(int dev);
extern void invalidate_inodes(int dev); extern void invalidate_inodes(int dev);
extern int end; extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end; struct buffer_head * start_buffer = (struct buffer_head *) &end;
struct buffer_head * hash_table[NR_HASH]; struct buffer_head * hash_table[NR_HASH];
static struct buffer_head * free_list; static struct buffer_head * free_list;
static struct task_struct * buffer_wait = NULL; static struct task_struct * buffer_wait = NULL;
int NR_BUFFERS = 0; int NR_BUFFERS = 0;
static inline void wait_on_buffer(struct buffer_head * bh) static inline void wait_on_buffer(struct buffer_head * bh)
{ {
cli(); cli();
while (bh->b_lock) while (bh->b_lock)
sleep_on(&bh->b_wait); sleep_on(&bh->b_wait);
sti(); sti();
} }
int sys_sync(void) int sys_sync(void)
{ {
int i; int i;
struct buffer_head * bh; struct buffer_head * bh;
sync_inodes(); /* write out inodes into buffers */ sync_inodes(); /* write out inodes into buffers */
bh = start_buffer; bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) { for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dirt) if (bh->b_dirt)
ll_rw_block(WRITE,bh); ll_rw_block(WRITE,bh);
} }
return 0; return 0;
} }
int sync_dev(int dev) int sync_dev(int dev)
{ {
int i; int i;
struct buffer_head * bh; struct buffer_head * bh;
bh = start_buffer; bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) { for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev) if (bh->b_dev != dev)
continue; continue;
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt) if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh); ll_rw_block(WRITE,bh);
} }
sync_inodes(); sync_inodes();
bh = start_buffer; bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) { for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev) if (bh->b_dev != dev)
continue; continue;
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt) if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh); ll_rw_block(WRITE,bh);
} }
return 0; return 0;
} }
void inline invalidate_buffers(int dev) void inline invalidate_buffers(int dev)
{ {
int i; int i;
struct buffer_head * bh; struct buffer_head * bh;
bh = start_buffer; bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) { for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev) if (bh->b_dev != dev)
continue; continue;
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dev == dev) if (bh->b_dev == dev)
bh->b_uptodate = bh->b_dirt = 0; bh->b_uptodate = bh->b_dirt = 0;
} }
} }
/* /*
* This routine checks whether a floppy has been changed, and * This routine checks whether a floppy has been changed, and
* invalidates all buffer-cache-entries in that case. This * invalidates all buffer-cache-entries in that case. This
* is a relatively slow routine, so we have to try to minimize using * is a relatively slow routine, so we have to try to minimize using
* it. Thus it is called only upon a 'mount' or 'open'. This * it. Thus it is called only upon a 'mount' or 'open'. This
* is the best way of combining speed and utility, I think. * is the best way of combining speed and utility, I think.
* People changing diskettes in the middle of an operation deserve * People changing diskettes in the middle of an operation deserve
* to loose :-) * to loose :-)
* *
* NOTE! Although currently this is only for floppies, the idea is * NOTE! Although currently this is only for floppies, the idea is
* that any additional removable block-device will use this routine, * that any additional removable block-device will use this routine,
* and that mount/open needn't know that floppies/whatever are * and that mount/open needn't know that floppies/whatever are
* special. * special.
*/ */
void check_disk_change(int dev) void check_disk_change(int dev)
{ {
int i; int i;
if (MAJOR(dev) != 2) if (MAJOR(dev) != 2)
return; return;
if (!floppy_change(dev & 0x03)) if (!floppy_change(dev & 0x03))
return; return;
for (i=0 ; i<NR_SUPER ; i++) for (i=0 ; i<NR_SUPER ; i++)
if (super_block[i].s_dev == dev) if (super_block[i].s_dev == dev)
put_super(super_block[i].s_dev); put_super(super_block[i].s_dev);
invalidate_inodes(dev); invalidate_inodes(dev);
invalidate_buffers(dev); invalidate_buffers(dev);
} }
#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH) #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
#define hash(dev,block) hash_table[_hashfn(dev,block)] #define hash(dev,block) hash_table[_hashfn(dev,block)]
static inline void remove_from_queues(struct buffer_head * bh) static inline void remove_from_queues(struct buffer_head * bh)
{ {
/* remove from hash-queue */ /* remove from hash-queue */
if (bh->b_next) if (bh->b_next)
bh->b_next->b_prev = bh->b_prev; bh->b_next->b_prev = bh->b_prev;
if (bh->b_prev) if (bh->b_prev)
bh->b_prev->b_next = bh->b_next; bh->b_prev->b_next = bh->b_next;
if (hash(bh->b_dev,bh->b_blocknr) == bh) if (hash(bh->b_dev,bh->b_blocknr) == bh)
hash(bh->b_dev,bh->b_blocknr) = bh->b_next; hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
/* remove from free list */ /* remove from free list */
if (!(bh->b_prev_free) || !(bh->b_next_free)) if (!(bh->b_prev_free) || !(bh->b_next_free))
panic("Free block list corrupted"); panic("Free block list corrupted");
bh->b_prev_free->b_next_free = bh->b_next_free; bh->b_prev_free->b_next_free = bh->b_next_free;
bh->b_next_free->b_prev_free = bh->b_prev_free; bh->b_next_free->b_prev_free = bh->b_prev_free;
if (free_list == bh) if (free_list == bh)
free_list = bh->b_next_free; free_list = bh->b_next_free;
} }
static inline void insert_into_queues(struct buffer_head * bh) static inline void insert_into_queues(struct buffer_head * bh)
{ {
/* put at end of free list */ /* put at end of free list */
bh->b_next_free = free_list; bh->b_next_free = free_list;
bh->b_prev_free = free_list->b_prev_free; bh->b_prev_free = free_list->b_prev_free;
free_list->b_prev_free->b_next_free = bh; free_list->b_prev_free->b_next_free = bh;
free_list->b_prev_free = bh; free_list->b_prev_free = bh;
/* put the buffer in new hash-queue if it has a device */ /* put the buffer in new hash-queue if it has a device */
bh->b_prev = NULL; bh->b_prev = NULL;
bh->b_next = NULL; bh->b_next = NULL;
if (!bh->b_dev) if (!bh->b_dev)
return; return;
bh->b_next = hash(bh->b_dev,bh->b_blocknr); bh->b_next = hash(bh->b_dev,bh->b_blocknr);
hash(bh->b_dev,bh->b_blocknr) = bh; hash(bh->b_dev,bh->b_blocknr) = bh;
bh->b_next->b_prev = bh; bh->b_next->b_prev = bh;
} }
static struct buffer_head * find_buffer(int dev, int block) static struct buffer_head * find_buffer(int dev, int block)
{ {
struct buffer_head * tmp; struct buffer_head * tmp;
for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next) for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
if (tmp->b_dev==dev && tmp->b_blocknr==block) if (tmp->b_dev==dev && tmp->b_blocknr==block)
return tmp; return tmp;
return NULL; return NULL;
} }
/* /*
* Why like this, I hear you say... The reason is race-conditions. * Why like this, I hear you say... The reason is race-conditions.
* As we don't lock buffers (unless we are readint them, that is), * As we don't lock buffers (unless we are readint them, that is),
* something might happen to it while we sleep (ie a read-error * something might happen to it while we sleep (ie a read-error
* will force it bad). This shouldn't really happen currently, but * will force it bad). This shouldn't really happen currently, but
* the code is ready. * the code is ready.
*/ */
struct buffer_head * get_hash_table(int dev, int block) struct buffer_head * get_hash_table(int dev, int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
for (;;) { for (;;) {
if (!(bh=find_buffer(dev,block))) if (!(bh=find_buffer(dev,block)))
return NULL; return NULL;
bh->b_count++; bh->b_count++;
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_blocknr == block) if (bh->b_dev == dev && bh->b_blocknr == block)
return bh; return bh;
bh->b_count--; bh->b_count--;
} }
} }
/* /*
* Ok, this is getblk, and it isn't very clear, again to hinder * Ok, this is getblk, and it isn't very clear, again to hinder
* race-conditions. Most of the code is seldom used, (ie repeating), * race-conditions. Most of the code is seldom used, (ie repeating),
* so it should be much more efficient than it looks. * so it should be much more efficient than it looks.
* *
* The algoritm is changed: hopefully better, and an elusive bug removed. * The algoritm is changed: hopefully better, and an elusive bug removed.
*/ */
#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock) #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
struct buffer_head * getblk(int dev,int block) struct buffer_head * getblk(int dev,int block)
{ {
struct buffer_head * tmp, * bh; struct buffer_head * tmp, * bh;
repeat: repeat:
if (bh = get_hash_table(dev,block)) if (bh = get_hash_table(dev,block))
return bh; return bh;
tmp = free_list; tmp = free_list;
do { do {
if (tmp->b_count) if (tmp->b_count)
continue; continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) { if (!bh || BADNESS(tmp)<BADNESS(bh)) {
bh = tmp; bh = tmp;
if (!BADNESS(tmp)) if (!BADNESS(tmp))
break; break;
} }
/* and repeat until we find something good */ /* and repeat until we find something good */
} while ((tmp = tmp->b_next_free) != free_list); } while ((tmp = tmp->b_next_free) != free_list);
if (!bh) { if (!bh) {
sleep_on(&buffer_wait); sleep_on(&buffer_wait);
goto repeat; goto repeat;
} }
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_count) if (bh->b_count)
goto repeat; goto repeat;
while (bh->b_dirt) { while (bh->b_dirt) {
sync_dev(bh->b_dev); sync_dev(bh->b_dev);
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_count) if (bh->b_count)
goto repeat; goto repeat;
} }
/* NOTE!! While we slept waiting for this block, somebody else might */ /* NOTE!! While we slept waiting for this block, somebody else might */
/* already have added "this" block to the cache. check it */ /* already have added "this" block to the cache. check it */
if (find_buffer(dev,block)) if (find_buffer(dev,block))
goto repeat; goto repeat;
/* OK, FINALLY we know that this buffer is the only one of it's kind, */ /* OK, FINALLY we know that this buffer is the only one of it's kind, */
/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */ /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
bh->b_count=1; bh->b_count=1;
bh->b_dirt=0; bh->b_dirt=0;
bh->b_uptodate=0; bh->b_uptodate=0;
remove_from_queues(bh); remove_from_queues(bh);
bh->b_dev=dev; bh->b_dev=dev;
bh->b_blocknr=block; bh->b_blocknr=block;
insert_into_queues(bh); insert_into_queues(bh);
return bh; return bh;
} }
void brelse(struct buffer_head * buf) void brelse(struct buffer_head * buf)
{ {
if (!buf) if (!buf)
return; return;
wait_on_buffer(buf); wait_on_buffer(buf);
if (!(buf->b_count--)) if (!(buf->b_count--))
panic("Trying to free free buffer"); panic("Trying to free free buffer");
wake_up(&buffer_wait); wake_up(&buffer_wait);
} }
/* /*
* bread() reads a specified block and returns the buffer that contains * bread() reads a specified block and returns the buffer that contains
* it. It returns NULL if the block was unreadable. * it. It returns NULL if the block was unreadable.
*/ */
struct buffer_head * bread(int dev,int block) struct buffer_head * bread(int dev,int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
if (!(bh=getblk(dev,block))) if (!(bh=getblk(dev,block)))
panic("bread: getblk returned NULL\n"); panic("bread: getblk returned NULL\n");
if (bh->b_uptodate) if (bh->b_uptodate)
return bh; return bh;
ll_rw_block(READ,bh); ll_rw_block(READ,bh);
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_uptodate) if (bh->b_uptodate)
return bh; return bh;
brelse(bh); brelse(bh);
return NULL; return NULL;
} }
#define COPYBLK(from,to) \ #define COPYBLK(from,to) \
__asm__("cld\n\t" \ __asm__("cld\n\t" \
"rep\n\t" \ "rep\n\t" \
"movsl\n\t" \ "movsl\n\t" \
::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \ ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
) )
/* /*
* bread_page reads four buffers into memory at the desired address. It's * bread_page reads four buffers into memory at the desired address. It's
* a function of its own, as there is some speed to be got by reading them * a function of its own, as there is some speed to be got by reading them
* all at the same time, not waiting for one to be read, and then another * all at the same time, not waiting for one to be read, and then another
* etc. * etc.
*/ */
void bread_page(unsigned long address,int dev,int b[4]) void bread_page(unsigned long address,int dev,int b[4])
{ {
struct buffer_head * bh[4]; struct buffer_head * bh[4];
int i; int i;
for (i=0 ; i<4 ; i++) for (i=0 ; i<4 ; i++)
if (b[i]) { if (b[i]) {
if (bh[i] = getblk(dev,b[i])) if (bh[i] = getblk(dev,b[i]))
if (!bh[i]->b_uptodate) if (!bh[i]->b_uptodate)
ll_rw_block(READ,bh[i]); ll_rw_block(READ,bh[i]);
} else } else
bh[i] = NULL; bh[i] = NULL;
for (i=0 ; i<4 ; i++,address += BLOCK_SIZE) for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
if (bh[i]) { if (bh[i]) {
wait_on_buffer(bh[i]); wait_on_buffer(bh[i]);
if (bh[i]->b_uptodate) if (bh[i]->b_uptodate)
COPYBLK((unsigned long) bh[i]->b_data,address); COPYBLK((unsigned long) bh[i]->b_data,address);
brelse(bh[i]); brelse(bh[i]);
} }
} }
/* /*
* Ok, breada can be used as bread, but additionally to mark other * Ok, breada can be used as bread, but additionally to mark other
* blocks for reading as well. End the argument list with a negative * blocks for reading as well. End the argument list with a negative
* number. * number.
*/ */
struct buffer_head * breada(int dev,int first, ...) struct buffer_head * breada(int dev,int first, ...)
{ {
va_list args; va_list args;
struct buffer_head * bh, *tmp; struct buffer_head * bh, *tmp;
va_start(args,first); va_start(args,first);
if (!(bh=getblk(dev,first))) if (!(bh=getblk(dev,first)))
panic("bread: getblk returned NULL\n"); panic("bread: getblk returned NULL\n");
if (!bh->b_uptodate) if (!bh->b_uptodate)
ll_rw_block(READ,bh); ll_rw_block(READ,bh);
while ((first=va_arg(args,int))>=0) { while ((first=va_arg(args,int))>=0) {
tmp=getblk(dev,first); tmp=getblk(dev,first);
if (tmp) { if (tmp) {
if (!tmp->b_uptodate) if (!tmp->b_uptodate)
ll_rw_block(READA,bh); ll_rw_block(READA,bh);
tmp->b_count--; tmp->b_count--;
} }
} }
va_end(args); va_end(args);
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_uptodate) if (bh->b_uptodate)
return bh; return bh;
brelse(bh); brelse(bh);
return (NULL); return (NULL);
} }
void buffer_init(long buffer_end) void buffer_init(long buffer_end)
{ {
struct buffer_head * h = start_buffer; struct buffer_head * h = start_buffer;
void * b; void * b;
int i; int i;
if (buffer_end == 1<<20) if (buffer_end == 1<<20)
b = (void *) (640*1024); b = (void *) (640*1024);
else else
b = (void *) buffer_end; b = (void *) buffer_end;
while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) { while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
h->b_dev = 0; h->b_dev = 0;
h->b_dirt = 0; h->b_dirt = 0;
h->b_count = 0; h->b_count = 0;
h->b_lock = 0; h->b_lock = 0;
h->b_uptodate = 0; h->b_uptodate = 0;
h->b_wait = NULL; h->b_wait = NULL;
h->b_next = NULL; h->b_next = NULL;
h->b_prev = NULL; h->b_prev = NULL;
h->b_data = (char *) b; h->b_data = (char *) b;
h->b_prev_free = h-1; h->b_prev_free = h-1;
h->b_next_free = h+1; h->b_next_free = h+1;
h++; h++;
NR_BUFFERS++; NR_BUFFERS++;
if (b == (void *) 0x100000) if (b == (void *) 0x100000)
b = (void *) 0xA0000; b = (void *) 0xA0000;
} }
h--; h--;
free_list = start_buffer; free_list = start_buffer;
free_list->b_prev_free = h; free_list->b_prev_free = h;
h->b_next_free = free_list; h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++) for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL; hash_table[i]=NULL;
} }

@ -1,104 +1,104 @@
/* /*
* linux/fs/char_dev.c * linux/fs/char_dev.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h> #include <asm/io.h>
extern int tty_read(unsigned minor,char * buf,int count); extern int tty_read(unsigned minor,char * buf,int count);
extern int tty_write(unsigned minor,char * buf,int count); extern int tty_write(unsigned minor,char * buf,int count);
typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos); typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos);
static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos) static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos)
{ {
return ((rw==READ)?tty_read(minor,buf,count): return ((rw==READ)?tty_read(minor,buf,count):
tty_write(minor,buf,count)); tty_write(minor,buf,count));
} }
static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos) static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos)
{ {
if (current->tty<0) if (current->tty<0)
return -EPERM; return -EPERM;
return rw_ttyx(rw,current->tty,buf,count,pos); return rw_ttyx(rw,current->tty,buf,count,pos);
} }
static int rw_ram(int rw,char * buf, int count, off_t *pos) static int rw_ram(int rw,char * buf, int count, off_t *pos)
{ {
return -EIO; return -EIO;
} }
static int rw_mem(int rw,char * buf, int count, off_t * pos) static int rw_mem(int rw,char * buf, int count, off_t * pos)
{ {
return -EIO; return -EIO;
} }
static int rw_kmem(int rw,char * buf, int count, off_t * pos) static int rw_kmem(int rw,char * buf, int count, off_t * pos)
{ {
return -EIO; return -EIO;
} }
static int rw_port(int rw,char * buf, int count, off_t * pos) static int rw_port(int rw,char * buf, int count, off_t * pos)
{ {
int i=*pos; int i=*pos;
while (count-->0 && i<65536) { while (count-->0 && i<65536) {
if (rw==READ) if (rw==READ)
put_fs_byte(inb(i),buf++); put_fs_byte(inb(i),buf++);
else else
outb(get_fs_byte(buf++),i); outb(get_fs_byte(buf++),i);
i++; i++;
} }
i -= *pos; i -= *pos;
*pos += i; *pos += i;
return i; return i;
} }
static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos) static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos)
{ {
switch(minor) { switch(minor) {
case 0: case 0:
return rw_ram(rw,buf,count,pos); return rw_ram(rw,buf,count,pos);
case 1: case 1:
return rw_mem(rw,buf,count,pos); return rw_mem(rw,buf,count,pos);
case 2: case 2:
return rw_kmem(rw,buf,count,pos); return rw_kmem(rw,buf,count,pos);
case 3: case 3:
return (rw==READ)?0:count; /* rw_null */ return (rw==READ)?0:count; /* rw_null */
case 4: case 4:
return rw_port(rw,buf,count,pos); return rw_port(rw,buf,count,pos);
default: default:
return -EIO; return -EIO;
} }
} }
#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr))) #define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
static crw_ptr crw_table[]={ static crw_ptr crw_table[]={
NULL, /* nodev */ NULL, /* nodev */
rw_memory, /* /dev/mem etc */ rw_memory, /* /dev/mem etc */
NULL, /* /dev/fd */ NULL, /* /dev/fd */
NULL, /* /dev/hd */ NULL, /* /dev/hd */
rw_ttyx, /* /dev/ttyx */ rw_ttyx, /* /dev/ttyx */
rw_tty, /* /dev/tty */ rw_tty, /* /dev/tty */
NULL, /* /dev/lp */ NULL, /* /dev/lp */
NULL}; /* unnamed pipes */ NULL}; /* unnamed pipes */
int rw_char(int rw,int dev, char * buf, int count, off_t * pos) int rw_char(int rw,int dev, char * buf, int count, off_t * pos)
{ {
crw_ptr call_addr; crw_ptr call_addr;
if (MAJOR(dev)>=NRDEVS) if (MAJOR(dev)>=NRDEVS)
return -ENODEV; return -ENODEV;
if (!(call_addr=crw_table[MAJOR(dev)])) if (!(call_addr=crw_table[MAJOR(dev)]))
return -ENODEV; return -ENODEV;
return call_addr(rw,MINOR(dev),buf,count,pos); return call_addr(rw,MINOR(dev),buf,count,pos);
} }

@ -1,359 +1,359 @@
/* /*
* linux/fs/exec.c * linux/fs/exec.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* #!-checking implemented by tytso. * #!-checking implemented by tytso.
*/ */
/* /*
* Demand-loading implemented 01.12.91 - no need to read anything but * Demand-loading implemented 01.12.91 - no need to read anything but
* the header into memory. The inode of the executable is put into * the header into memory. The inode of the executable is put into
* "current->executable", and page faults do the actual loading. Clean. * "current->executable", and page faults do the actual loading. Clean.
* *
* Once more I can proudly say that linux stood up to being changed: it * Once more I can proudly say that linux stood up to being changed: it
* was less than 2 hours work to get demand-loading completely implemented. * was less than 2 hours work to get demand-loading completely implemented.
*/ */
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <a.out.h> #include <a.out.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/segment.h> #include <asm/segment.h>
extern int sys_exit(int exit_code); extern int sys_exit(int exit_code);
extern int sys_close(int fd); extern int sys_close(int fd);
/* /*
* MAX_ARG_PAGES defines the number of pages allocated for arguments * MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives * and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB ! * a maximum env+arg of 128kB !
*/ */
#define MAX_ARG_PAGES 32 #define MAX_ARG_PAGES 32
int sys_uselib() int sys_uselib()
{ {
return -ENOSYS; return -ENOSYS;
} }
/* /*
* create_tables() parses the env- and arg-strings in new user * create_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their * memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value. * addresses on the "stack", returning the new stack pointer value.
*/ */
static unsigned long * create_tables(char * p,int argc,int envc) static unsigned long * create_tables(char * p,int argc,int envc)
{ {
unsigned long *argv,*envp; unsigned long *argv,*envp;
unsigned long * sp; unsigned long * sp;
sp = (unsigned long *) (0xfffffffc & (unsigned long) p); sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
sp -= envc+1; sp -= envc+1;
envp = sp; envp = sp;
sp -= argc+1; sp -= argc+1;
argv = sp; argv = sp;
put_fs_long((unsigned long)envp,--sp); put_fs_long((unsigned long)envp,--sp);
put_fs_long((unsigned long)argv,--sp); put_fs_long((unsigned long)argv,--sp);
put_fs_long((unsigned long)argc,--sp); put_fs_long((unsigned long)argc,--sp);
while (argc-->0) { while (argc-->0) {
put_fs_long((unsigned long) p,argv++); put_fs_long((unsigned long) p,argv++);
while (get_fs_byte(p++)) /* nothing */ ; while (get_fs_byte(p++)) /* nothing */ ;
} }
put_fs_long(0,argv); put_fs_long(0,argv);
while (envc-->0) { while (envc-->0) {
put_fs_long((unsigned long) p,envp++); put_fs_long((unsigned long) p,envp++);
while (get_fs_byte(p++)) /* nothing */ ; while (get_fs_byte(p++)) /* nothing */ ;
} }
put_fs_long(0,envp); put_fs_long(0,envp);
return sp; return sp;
} }
/* /*
* count() counts the number of arguments/envelopes * count() counts the number of arguments/envelopes
*/ */
static int count(char ** argv) static int count(char ** argv)
{ {
int i=0; int i=0;
char ** tmp; char ** tmp;
if (tmp = argv) if (tmp = argv)
while (get_fs_long((unsigned long *) (tmp++))) while (get_fs_long((unsigned long *) (tmp++)))
i++; i++;
return i; return i;
} }
/* /*
* 'copy_string()' copies argument/envelope strings from user * 'copy_string()' copies argument/envelope strings from user
* memory to free pages in kernel mem. These are in a format ready * memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory. * to be put directly into the top of new user memory.
* *
* Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
* whether the string and the string array are from user or kernel segments: * whether the string and the string array are from user or kernel segments:
* *
* from_kmem argv * argv ** * from_kmem argv * argv **
* 0 user space user space * 0 user space user space
* 1 kernel space user space * 1 kernel space user space
* 2 kernel space kernel space * 2 kernel space kernel space
* *
* We do this by playing games with the fs segment register. Since it * We do this by playing games with the fs segment register. Since it
* it is expensive to load a segment register, we try to avoid calling * it is expensive to load a segment register, we try to avoid calling
* set_fs() unless we absolutely have to. * set_fs() unless we absolutely have to.
*/ */
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
unsigned long p, int from_kmem) unsigned long p, int from_kmem)
{ {
char *tmp, *pag; char *tmp, *pag;
int len, offset = 0; int len, offset = 0;
unsigned long old_fs, new_fs; unsigned long old_fs, new_fs;
if (!p) if (!p)
return 0; /* bullet-proofing */ return 0; /* bullet-proofing */
new_fs = get_ds(); new_fs = get_ds();
old_fs = get_fs(); old_fs = get_fs();
if (from_kmem==2) if (from_kmem==2)
set_fs(new_fs); set_fs(new_fs);
while (argc-- > 0) { while (argc-- > 0) {
if (from_kmem == 1) if (from_kmem == 1)
set_fs(new_fs); set_fs(new_fs);
if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc))) if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
panic("argc is wrong"); panic("argc is wrong");
if (from_kmem == 1) if (from_kmem == 1)
set_fs(old_fs); set_fs(old_fs);
len=0; /* remember zero-padding */ len=0; /* remember zero-padding */
do { do {
len++; len++;
} while (get_fs_byte(tmp++)); } while (get_fs_byte(tmp++));
if (p-len < 0) { /* this shouldn't happen - 128kB */ if (p-len < 0) { /* this shouldn't happen - 128kB */
set_fs(old_fs); set_fs(old_fs);
return 0; return 0;
} }
while (len) { while (len) {
--p; --tmp; --len; --p; --tmp; --len;
if (--offset < 0) { if (--offset < 0) {
offset = p % PAGE_SIZE; offset = p % PAGE_SIZE;
if (from_kmem==2) if (from_kmem==2)
set_fs(old_fs); set_fs(old_fs);
if (!(pag = (char *) page[p/PAGE_SIZE]) && if (!(pag = (char *) page[p/PAGE_SIZE]) &&
!(pag = (char *) (page[p/PAGE_SIZE] = !(pag = (char *) (page[p/PAGE_SIZE] =
(unsigned long *) get_free_page()))) (unsigned long *) get_free_page())))
return 0; return 0;
if (from_kmem==2) if (from_kmem==2)
set_fs(new_fs); set_fs(new_fs);
} }
*(pag + offset) = get_fs_byte(tmp); *(pag + offset) = get_fs_byte(tmp);
} }
} }
if (from_kmem==2) if (from_kmem==2)
set_fs(old_fs); set_fs(old_fs);
return p; return p;
} }
static unsigned long change_ldt(unsigned long text_size,unsigned long * page) static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
{ {
unsigned long code_limit,data_limit,code_base,data_base; unsigned long code_limit,data_limit,code_base,data_base;
int i; int i;
code_limit = text_size+PAGE_SIZE -1; code_limit = text_size+PAGE_SIZE -1;
code_limit &= 0xFFFFF000; code_limit &= 0xFFFFF000;
data_limit = 0x4000000; data_limit = 0x4000000;
code_base = get_base(current->ldt[1]); code_base = get_base(current->ldt[1]);
data_base = code_base; data_base = code_base;
set_base(current->ldt[1],code_base); set_base(current->ldt[1],code_base);
set_limit(current->ldt[1],code_limit); set_limit(current->ldt[1],code_limit);
set_base(current->ldt[2],data_base); set_base(current->ldt[2],data_base);
set_limit(current->ldt[2],data_limit); set_limit(current->ldt[2],data_limit);
/* make sure fs points to the NEW data segment */ /* make sure fs points to the NEW data segment */
__asm__("pushl $0x17\n\tpop %%fs"::); __asm__("pushl $0x17\n\tpop %%fs"::);
data_base += data_limit; data_base += data_limit;
for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) { for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
data_base -= PAGE_SIZE; data_base -= PAGE_SIZE;
if (page[i]) if (page[i])
put_page(page[i],data_base); put_page(page[i],data_base);
} }
return data_limit; return data_limit;
} }
/* /*
* 'do_execve()' executes a new program. * 'do_execve()' executes a new program.
*/ */
int do_execve(unsigned long * eip,long tmp,char * filename, int do_execve(unsigned long * eip,long tmp,char * filename,
char ** argv, char ** envp) char ** argv, char ** envp)
{ {
struct m_inode * inode; struct m_inode * inode;
struct buffer_head * bh; struct buffer_head * bh;
struct exec ex; struct exec ex;
unsigned long page[MAX_ARG_PAGES]; unsigned long page[MAX_ARG_PAGES];
int i,argc,envc; int i,argc,envc;
int e_uid, e_gid; int e_uid, e_gid;
int retval; int retval;
int sh_bang = 0; int sh_bang = 0;
unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4; unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
if ((0xffff & eip[1]) != 0x000f) if ((0xffff & eip[1]) != 0x000f)
panic("execve called from supervisor mode"); panic("execve called from supervisor mode");
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
page[i]=0; page[i]=0;
if (!(inode=namei(filename))) /* get executables inode */ if (!(inode=namei(filename))) /* get executables inode */
return -ENOENT; return -ENOENT;
argc = count(argv); argc = count(argv);
envc = count(envp); envc = count(envp);
restart_interp: restart_interp:
if (!S_ISREG(inode->i_mode)) { /* must be regular file */ if (!S_ISREG(inode->i_mode)) { /* must be regular file */
retval = -EACCES; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
i = inode->i_mode; i = inode->i_mode;
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid; e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid; e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
if (current->euid == inode->i_uid) if (current->euid == inode->i_uid)
i >>= 6; i >>= 6;
else if (current->egid == inode->i_gid) else if (current->egid == inode->i_gid)
i >>= 3; i >>= 3;
if (!(i & 1) && if (!(i & 1) &&
!((inode->i_mode & 0111) && suser())) { !((inode->i_mode & 0111) && suser())) {
retval = -ENOEXEC; retval = -ENOEXEC;
goto exec_error2; goto exec_error2;
} }
if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) { if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
retval = -EACCES; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
ex = *((struct exec *) bh->b_data); /* read exec-header */ ex = *((struct exec *) bh->b_data); /* read exec-header */
if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) { if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
/* /*
* This section does the #! interpretation. * This section does the #! interpretation.
* Sorta complicated, but hopefully it will work. -TYT * Sorta complicated, but hopefully it will work. -TYT
*/ */
char buf[1023], *cp, *interp, *i_name, *i_arg; char buf[1023], *cp, *interp, *i_name, *i_arg;
unsigned long old_fs; unsigned long old_fs;
strncpy(buf, bh->b_data+2, 1022); strncpy(buf, bh->b_data+2, 1022);
brelse(bh); brelse(bh);
iput(inode); iput(inode);
buf[1022] = '\0'; buf[1022] = '\0';
if (cp = strchr(buf, '\n')) { if (cp = strchr(buf, '\n')) {
*cp = '\0'; *cp = '\0';
for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++); for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
} }
if (!cp || *cp == '\0') { if (!cp || *cp == '\0') {
retval = -ENOEXEC; /* No interpreter name found */ retval = -ENOEXEC; /* No interpreter name found */
goto exec_error1; goto exec_error1;
} }
interp = i_name = cp; interp = i_name = cp;
i_arg = 0; i_arg = 0;
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) { for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
if (*cp == '/') if (*cp == '/')
i_name = cp+1; i_name = cp+1;
} }
if (*cp) { if (*cp) {
*cp++ = '\0'; *cp++ = '\0';
i_arg = cp; i_arg = cp;
} }
/* /*
* OK, we've parsed out the interpreter name and * OK, we've parsed out the interpreter name and
* (optional) argument. * (optional) argument.
*/ */
if (sh_bang++ == 0) { if (sh_bang++ == 0) {
p = copy_strings(envc, envp, page, p, 0); p = copy_strings(envc, envp, page, p, 0);
p = copy_strings(--argc, argv+1, page, p, 0); p = copy_strings(--argc, argv+1, page, p, 0);
} }
/* /*
* Splice in (1) the interpreter's name for argv[0] * Splice in (1) the interpreter's name for argv[0]
* (2) (optional) argument to interpreter * (2) (optional) argument to interpreter
* (3) filename of shell script * (3) filename of shell script
* *
* This is done in reverse order, because of how the * This is done in reverse order, because of how the
* user environment and arguments are stored. * user environment and arguments are stored.
*/ */
p = copy_strings(1, &filename, page, p, 1); p = copy_strings(1, &filename, page, p, 1);
argc++; argc++;
if (i_arg) { if (i_arg) {
p = copy_strings(1, &i_arg, page, p, 2); p = copy_strings(1, &i_arg, page, p, 2);
argc++; argc++;
} }
p = copy_strings(1, &i_name, page, p, 2); p = copy_strings(1, &i_name, page, p, 2);
argc++; argc++;
if (!p) { if (!p) {
retval = -ENOMEM; retval = -ENOMEM;
goto exec_error1; goto exec_error1;
} }
/* /*
* OK, now restart the process with the interpreter's inode. * OK, now restart the process with the interpreter's inode.
*/ */
old_fs = get_fs(); old_fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
if (!(inode=namei(interp))) { /* get executables inode */ if (!(inode=namei(interp))) { /* get executables inode */
set_fs(old_fs); set_fs(old_fs);
retval = -ENOENT; retval = -ENOENT;
goto exec_error1; goto exec_error1;
} }
set_fs(old_fs); set_fs(old_fs);
goto restart_interp; goto restart_interp;
} }
brelse(bh); brelse(bh);
if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize || if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
ex.a_text+ex.a_data+ex.a_bss>0x3000000 || ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) { inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
retval = -ENOEXEC; retval = -ENOEXEC;
goto exec_error2; goto exec_error2;
} }
if (N_TXTOFF(ex) != BLOCK_SIZE) { if (N_TXTOFF(ex) != BLOCK_SIZE) {
printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename); printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
retval = -ENOEXEC; retval = -ENOEXEC;
goto exec_error2; goto exec_error2;
} }
if (!sh_bang) { if (!sh_bang) {
p = copy_strings(envc,envp,page,p,0); p = copy_strings(envc,envp,page,p,0);
p = copy_strings(argc,argv,page,p,0); p = copy_strings(argc,argv,page,p,0);
if (!p) { if (!p) {
retval = -ENOMEM; retval = -ENOMEM;
goto exec_error2; goto exec_error2;
} }
} }
/* OK, This is the point of no return */ /* OK, This is the point of no return */
if (current->executable) if (current->executable)
iput(current->executable); iput(current->executable);
current->executable = inode; current->executable = inode;
for (i=0 ; i<32 ; i++) for (i=0 ; i<32 ; i++)
current->sigaction[i].sa_handler = NULL; current->sigaction[i].sa_handler = NULL;
for (i=0 ; i<NR_OPEN ; i++) for (i=0 ; i<NR_OPEN ; i++)
if ((current->close_on_exec>>i)&1) if ((current->close_on_exec>>i)&1)
sys_close(i); sys_close(i);
current->close_on_exec = 0; current->close_on_exec = 0;
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
if (last_task_used_math == current) if (last_task_used_math == current)
last_task_used_math = NULL; last_task_used_math = NULL;
current->used_math = 0; current->used_math = 0;
p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE; p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,argc,envc); p = (unsigned long) create_tables((char *)p,argc,envc);
current->brk = ex.a_bss + current->brk = ex.a_bss +
(current->end_data = ex.a_data + (current->end_data = ex.a_data +
(current->end_code = ex.a_text)); (current->end_code = ex.a_text));
current->start_stack = p & 0xfffff000; current->start_stack = p & 0xfffff000;
current->euid = e_uid; current->euid = e_uid;
current->egid = e_gid; current->egid = e_gid;
i = ex.a_text+ex.a_data; i = ex.a_text+ex.a_data;
while (i&0xfff) while (i&0xfff)
put_fs_byte(0,(char *) (i++)); put_fs_byte(0,(char *) (i++));
eip[0] = ex.a_entry; /* eip, magic happens :-) */ eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */ eip[3] = p; /* stack pointer */
return 0; return 0;
exec_error2: exec_error2:
iput(inode); iput(inode);
exec_error1: exec_error1:
for (i=0 ; i<MAX_ARG_PAGES ; i++) for (i=0 ; i<MAX_ARG_PAGES ; i++)
free_page(page[i]); free_page(page[i]);
return(retval); return(retval);
} }

@ -1,75 +1,75 @@
/* /*
* linux/fs/fcntl.c * linux/fs/fcntl.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
extern int sys_close(int fd); extern int sys_close(int fd);
static int dupfd(unsigned int fd, unsigned int arg) static int dupfd(unsigned int fd, unsigned int arg)
{ {
if (fd >= NR_OPEN || !current->filp[fd]) if (fd >= NR_OPEN || !current->filp[fd])
return -EBADF; return -EBADF;
if (arg >= NR_OPEN) if (arg >= NR_OPEN)
return -EINVAL; return -EINVAL;
while (arg < NR_OPEN) while (arg < NR_OPEN)
if (current->filp[arg]) if (current->filp[arg])
arg++; arg++;
else else
break; break;
if (arg >= NR_OPEN) if (arg >= NR_OPEN)
return -EMFILE; return -EMFILE;
current->close_on_exec &= ~(1<<arg); current->close_on_exec &= ~(1<<arg);
(current->filp[arg] = current->filp[fd])->f_count++; (current->filp[arg] = current->filp[fd])->f_count++;
return arg; return arg;
} }
int sys_dup2(unsigned int oldfd, unsigned int newfd) int sys_dup2(unsigned int oldfd, unsigned int newfd)
{ {
sys_close(newfd); sys_close(newfd);
return dupfd(oldfd,newfd); return dupfd(oldfd,newfd);
} }
int sys_dup(unsigned int fildes) int sys_dup(unsigned int fildes)
{ {
return dupfd(fildes,0); return dupfd(fildes,0);
} }
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp; struct file * filp;
if (fd >= NR_OPEN || !(filp = current->filp[fd])) if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF; return -EBADF;
switch (cmd) { switch (cmd) {
case F_DUPFD: case F_DUPFD:
return dupfd(fd,arg); return dupfd(fd,arg);
case F_GETFD: case F_GETFD:
return (current->close_on_exec>>fd)&1; return (current->close_on_exec>>fd)&1;
case F_SETFD: case F_SETFD:
if (arg&1) if (arg&1)
current->close_on_exec |= (1<<fd); current->close_on_exec |= (1<<fd);
else else
current->close_on_exec &= ~(1<<fd); current->close_on_exec &= ~(1<<fd);
return 0; return 0;
case F_GETFL: case F_GETFL:
return filp->f_flags; return filp->f_flags;
case F_SETFL: case F_SETFL:
filp->f_flags &= ~(O_APPEND | O_NONBLOCK); filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
return 0; return 0;
case F_GETLK: case F_SETLK: case F_SETLKW: case F_GETLK: case F_SETLK: case F_SETLKW:
return -1; return -1;
default: default:
return -1; return -1;
} }
} }

@ -1,90 +1,90 @@
/* /*
* linux/fs/file_dev.c * linux/fs/file_dev.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b))
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
{ {
int left,chars,nr; int left,chars,nr;
struct buffer_head * bh; struct buffer_head * bh;
if ((left=count)<=0) if ((left=count)<=0)
return 0; return 0;
while (left) { while (left) {
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) { if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
if (!(bh=bread(inode->i_dev,nr))) if (!(bh=bread(inode->i_dev,nr)))
break; break;
} else } else
bh = NULL; bh = NULL;
nr = filp->f_pos % BLOCK_SIZE; nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left ); chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars; filp->f_pos += chars;
left -= chars; left -= chars;
if (bh) { if (bh) {
char * p = nr + bh->b_data; char * p = nr + bh->b_data;
while (chars-->0) while (chars-->0)
put_fs_byte(*(p++),buf++); put_fs_byte(*(p++),buf++);
brelse(bh); brelse(bh);
} else { } else {
while (chars-->0) while (chars-->0)
put_fs_byte(0,buf++); put_fs_byte(0,buf++);
} }
} }
inode->i_atime = CURRENT_TIME; inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR; return (count-left)?(count-left):-ERROR;
} }
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
{ {
off_t pos; off_t pos;
int block,c; int block,c;
struct buffer_head * bh; struct buffer_head * bh;
char * p; char * p;
int i=0; int i=0;
/* /*
* ok, append may not work when many processes are writing at the same time * ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway. * but so what. That way leads to madness anyway.
*/ */
if (filp->f_flags & O_APPEND) if (filp->f_flags & O_APPEND)
pos = inode->i_size; pos = inode->i_size;
else else
pos = filp->f_pos; pos = filp->f_pos;
while (i<count) { while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE))) if (!(block = create_block(inode,pos/BLOCK_SIZE)))
break; break;
if (!(bh=bread(inode->i_dev,block))) if (!(bh=bread(inode->i_dev,block)))
break; break;
c = pos % BLOCK_SIZE; c = pos % BLOCK_SIZE;
p = c + bh->b_data; p = c + bh->b_data;
bh->b_dirt = 1; bh->b_dirt = 1;
c = BLOCK_SIZE-c; c = BLOCK_SIZE-c;
if (c > count-i) c = count-i; if (c > count-i) c = count-i;
pos += c; pos += c;
if (pos > inode->i_size) { if (pos > inode->i_size) {
inode->i_size = pos; inode->i_size = pos;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
i += c; i += c;
while (c-->0) while (c-->0)
*(p++) = get_fs_byte(buf++); *(p++) = get_fs_byte(buf++);
brelse(bh); brelse(bh);
} }
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) { if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos; filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
} }
return (i?i:-1); return (i?i:-1);
} }

@ -1,9 +1,9 @@
/* /*
* linux/fs/file_table.c * linux/fs/file_table.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <linux/fs.h> #include <linux/fs.h>
struct file file_table[NR_FILE]; struct file file_table[NR_FILE];

@ -1,340 +1,340 @@
/* /*
* linux/fs/inode.c * linux/fs/inode.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/system.h> #include <asm/system.h>
struct m_inode inode_table[NR_INODE]={{0,},}; struct m_inode inode_table[NR_INODE]={{0,},};
static void read_inode(struct m_inode * inode); static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode); static void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode) static inline void wait_on_inode(struct m_inode * inode)
{ {
cli(); cli();
while (inode->i_lock) while (inode->i_lock)
sleep_on(&inode->i_wait); sleep_on(&inode->i_wait);
sti(); sti();
} }
static inline void lock_inode(struct m_inode * inode) static inline void lock_inode(struct m_inode * inode)
{ {
cli(); cli();
while (inode->i_lock) while (inode->i_lock)
sleep_on(&inode->i_wait); sleep_on(&inode->i_wait);
inode->i_lock=1; inode->i_lock=1;
sti(); sti();
} }
static inline void unlock_inode(struct m_inode * inode) static inline void unlock_inode(struct m_inode * inode)
{ {
inode->i_lock=0; inode->i_lock=0;
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
} }
void invalidate_inodes(int dev) void invalidate_inodes(int dev)
{ {
int i; int i;
struct m_inode * inode; struct m_inode * inode;
inode = 0+inode_table; inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) { for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode); wait_on_inode(inode);
if (inode->i_dev == dev) { if (inode->i_dev == dev) {
if (inode->i_count) if (inode->i_count)
printk("inode in use on removed disk\n\r"); printk("inode in use on removed disk\n\r");
inode->i_dev = inode->i_dirt = 0; inode->i_dev = inode->i_dirt = 0;
} }
} }
} }
void sync_inodes(void) void sync_inodes(void)
{ {
int i; int i;
struct m_inode * inode; struct m_inode * inode;
inode = 0+inode_table; inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) { for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode); wait_on_inode(inode);
if (inode->i_dirt && !inode->i_pipe) if (inode->i_dirt && !inode->i_pipe)
write_inode(inode); write_inode(inode);
} }
} }
static int _bmap(struct m_inode * inode,int block,int create) static int _bmap(struct m_inode * inode,int block,int create)
{ {
struct buffer_head * bh; struct buffer_head * bh;
int i; int i;
if (block<0) if (block<0)
panic("_bmap: block<0"); panic("_bmap: block<0");
if (block >= 7+512+512*512) if (block >= 7+512+512*512)
panic("_bmap: block>big"); panic("_bmap: block>big");
if (block<7) { if (block<7) {
if (create && !inode->i_zone[block]) if (create && !inode->i_zone[block])
if (inode->i_zone[block]=new_block(inode->i_dev)) { if (inode->i_zone[block]=new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME; inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1; inode->i_dirt=1;
} }
return inode->i_zone[block]; return inode->i_zone[block];
} }
block -= 7; block -= 7;
if (block<512) { if (block<512) {
if (create && !inode->i_zone[7]) if (create && !inode->i_zone[7])
if (inode->i_zone[7]=new_block(inode->i_dev)) { if (inode->i_zone[7]=new_block(inode->i_dev)) {
inode->i_dirt=1; inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME; inode->i_ctime=CURRENT_TIME;
} }
if (!inode->i_zone[7]) if (!inode->i_zone[7])
return 0; return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[7]))) if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
return 0; return 0;
i = ((unsigned short *) (bh->b_data))[block]; i = ((unsigned short *) (bh->b_data))[block];
if (create && !i) if (create && !i)
if (i=new_block(inode->i_dev)) { if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block]=i; ((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1; bh->b_dirt=1;
} }
brelse(bh); brelse(bh);
return i; return i;
} }
block -= 512; block -= 512;
if (create && !inode->i_zone[8]) if (create && !inode->i_zone[8])
if (inode->i_zone[8]=new_block(inode->i_dev)) { if (inode->i_zone[8]=new_block(inode->i_dev)) {
inode->i_dirt=1; inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME; inode->i_ctime=CURRENT_TIME;
} }
if (!inode->i_zone[8]) if (!inode->i_zone[8])
return 0; return 0;
if (!(bh=bread(inode->i_dev,inode->i_zone[8]))) if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
return 0; return 0;
i = ((unsigned short *)bh->b_data)[block>>9]; i = ((unsigned short *)bh->b_data)[block>>9];
if (create && !i) if (create && !i)
if (i=new_block(inode->i_dev)) { if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9]=i; ((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1; bh->b_dirt=1;
} }
brelse(bh); brelse(bh);
if (!i) if (!i)
return 0; return 0;
if (!(bh=bread(inode->i_dev,i))) if (!(bh=bread(inode->i_dev,i)))
return 0; return 0;
i = ((unsigned short *)bh->b_data)[block&511]; i = ((unsigned short *)bh->b_data)[block&511];
if (create && !i) if (create && !i)
if (i=new_block(inode->i_dev)) { if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511]=i; ((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1; bh->b_dirt=1;
} }
brelse(bh); brelse(bh);
return i; return i;
} }
int bmap(struct m_inode * inode,int block) int bmap(struct m_inode * inode,int block)
{ {
return _bmap(inode,block,0); return _bmap(inode,block,0);
} }
int create_block(struct m_inode * inode, int block) int create_block(struct m_inode * inode, int block)
{ {
return _bmap(inode,block,1); return _bmap(inode,block,1);
} }
void iput(struct m_inode * inode) void iput(struct m_inode * inode)
{ {
if (!inode) if (!inode)
return; return;
wait_on_inode(inode); wait_on_inode(inode);
if (!inode->i_count) if (!inode->i_count)
panic("iput: trying to free free inode"); panic("iput: trying to free free inode");
if (inode->i_pipe) { if (inode->i_pipe) {
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
if (--inode->i_count) if (--inode->i_count)
return; return;
free_page(inode->i_size); free_page(inode->i_size);
inode->i_count=0; inode->i_count=0;
inode->i_dirt=0; inode->i_dirt=0;
inode->i_pipe=0; inode->i_pipe=0;
return; return;
} }
if (!inode->i_dev) { if (!inode->i_dev) {
inode->i_count--; inode->i_count--;
return; return;
} }
if (S_ISBLK(inode->i_mode)) { if (S_ISBLK(inode->i_mode)) {
sync_dev(inode->i_zone[0]); sync_dev(inode->i_zone[0]);
wait_on_inode(inode); wait_on_inode(inode);
} }
repeat: repeat:
if (inode->i_count>1) { if (inode->i_count>1) {
inode->i_count--; inode->i_count--;
return; return;
} }
if (!inode->i_nlinks) { if (!inode->i_nlinks) {
truncate(inode); truncate(inode);
free_inode(inode); free_inode(inode);
return; return;
} }
if (inode->i_dirt) { if (inode->i_dirt) {
write_inode(inode); /* we can sleep - so do again */ write_inode(inode); /* we can sleep - so do again */
wait_on_inode(inode); wait_on_inode(inode);
goto repeat; goto repeat;
} }
inode->i_count--; inode->i_count--;
return; return;
} }
struct m_inode * get_empty_inode(void) struct m_inode * get_empty_inode(void)
{ {
struct m_inode * inode; struct m_inode * inode;
static struct m_inode * last_inode = inode_table; static struct m_inode * last_inode = inode_table;
int i; int i;
do { do {
inode = NULL; inode = NULL;
for (i = NR_INODE; i ; i--) { for (i = NR_INODE; i ; i--) {
if (++last_inode >= inode_table + NR_INODE) if (++last_inode >= inode_table + NR_INODE)
last_inode = inode_table; last_inode = inode_table;
if (!last_inode->i_count) { if (!last_inode->i_count) {
inode = last_inode; inode = last_inode;
if (!inode->i_dirt && !inode->i_lock) if (!inode->i_dirt && !inode->i_lock)
break; break;
} }
} }
if (!inode) { if (!inode) {
for (i=0 ; i<NR_INODE ; i++) for (i=0 ; i<NR_INODE ; i++)
printk("%04x: %6d\t",inode_table[i].i_dev, printk("%04x: %6d\t",inode_table[i].i_dev,
inode_table[i].i_num); inode_table[i].i_num);
panic("No free inodes in mem"); panic("No free inodes in mem");
} }
wait_on_inode(inode); wait_on_inode(inode);
while (inode->i_dirt) { while (inode->i_dirt) {
write_inode(inode); write_inode(inode);
wait_on_inode(inode); wait_on_inode(inode);
} }
} while (inode->i_count); } while (inode->i_count);
memset(inode,0,sizeof(*inode)); memset(inode,0,sizeof(*inode));
inode->i_count = 1; inode->i_count = 1;
return inode; return inode;
} }
struct m_inode * get_pipe_inode(void) struct m_inode * get_pipe_inode(void)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode = get_empty_inode())) if (!(inode = get_empty_inode()))
return NULL; return NULL;
if (!(inode->i_size=get_free_page())) { if (!(inode->i_size=get_free_page())) {
inode->i_count = 0; inode->i_count = 0;
return NULL; return NULL;
} }
inode->i_count = 2; /* sum of readers/writers */ inode->i_count = 2; /* sum of readers/writers */
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
inode->i_pipe = 1; inode->i_pipe = 1;
return inode; return inode;
} }
struct m_inode * iget(int dev,int nr) struct m_inode * iget(int dev,int nr)
{ {
struct m_inode * inode, * empty; struct m_inode * inode, * empty;
if (!dev) if (!dev)
panic("iget with dev==0"); panic("iget with dev==0");
empty = get_empty_inode(); empty = get_empty_inode();
inode = inode_table; inode = inode_table;
while (inode < NR_INODE+inode_table) { while (inode < NR_INODE+inode_table) {
if (inode->i_dev != dev || inode->i_num != nr) { if (inode->i_dev != dev || inode->i_num != nr) {
inode++; inode++;
continue; continue;
} }
wait_on_inode(inode); wait_on_inode(inode);
if (inode->i_dev != dev || inode->i_num != nr) { if (inode->i_dev != dev || inode->i_num != nr) {
inode = inode_table; inode = inode_table;
continue; continue;
} }
inode->i_count++; inode->i_count++;
if (inode->i_mount) { if (inode->i_mount) {
int i; int i;
for (i = 0 ; i<NR_SUPER ; i++) for (i = 0 ; i<NR_SUPER ; i++)
if (super_block[i].s_imount==inode) if (super_block[i].s_imount==inode)
break; break;
if (i >= NR_SUPER) { if (i >= NR_SUPER) {
printk("Mounted inode hasn't got sb\n"); printk("Mounted inode hasn't got sb\n");
if (empty) if (empty)
iput(empty); iput(empty);
return inode; return inode;
} }
iput(inode); iput(inode);
dev = super_block[i].s_dev; dev = super_block[i].s_dev;
nr = ROOT_INO; nr = ROOT_INO;
inode = inode_table; inode = inode_table;
continue; continue;
} }
if (empty) if (empty)
iput(empty); iput(empty);
return inode; return inode;
} }
if (!empty) if (!empty)
return (NULL); return (NULL);
inode=empty; inode=empty;
inode->i_dev = dev; inode->i_dev = dev;
inode->i_num = nr; inode->i_num = nr;
read_inode(inode); read_inode(inode);
return inode; return inode;
} }
static void read_inode(struct m_inode * inode) static void read_inode(struct m_inode * inode)
{ {
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
int block; int block;
lock_inode(inode); lock_inode(inode);
if (!(sb=get_super(inode->i_dev))) if (!(sb=get_super(inode->i_dev)))
panic("trying to read inode without dev"); panic("trying to read inode without dev");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK; (inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block))) if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block"); panic("unable to read i-node block");
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
*(struct d_inode *)inode = *(struct d_inode *)inode =
((struct d_inode *)bh->b_data) ((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK]; [(inode->i_num-1)%INODES_PER_BLOCK];
brelse(bh); brelse(bh);
unlock_inode(inode); unlock_inode(inode);
} }
static void write_inode(struct m_inode * inode) static void write_inode(struct m_inode * inode)
{ {
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
int block; int block;
lock_inode(inode); lock_inode(inode);
if (!inode->i_dirt || !inode->i_dev) { if (!inode->i_dirt || !inode->i_dev) {
unlock_inode(inode); unlock_inode(inode);
return; return;
} }
if (!(sb=get_super(inode->i_dev))) if (!(sb=get_super(inode->i_dev)))
panic("trying to write inode without device"); panic("trying to write inode without device");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK; (inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block))) if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block"); panic("unable to read i-node block");
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
((struct d_inode *)bh->b_data) ((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK] = [(inode->i_num-1)%INODES_PER_BLOCK] =
*(struct d_inode *)inode; *(struct d_inode *)inode;
bh->b_dirt=1; bh->b_dirt=1;
inode->i_dirt=0; inode->i_dirt=0;
brelse(bh); brelse(bh);
unlock_inode(inode); unlock_inode(inode);
} }

@ -1,46 +1,46 @@
/* /*
* linux/fs/ioctl.c * linux/fs/ioctl.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/sched.h> #include <linux/sched.h>
extern int tty_ioctl(int dev, int cmd, int arg); extern int tty_ioctl(int dev, int cmd, int arg);
typedef int (*ioctl_ptr)(int dev,int cmd,int arg); typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr))) #define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
static ioctl_ptr ioctl_table[]={ static ioctl_ptr ioctl_table[]={
NULL, /* nodev */ NULL, /* nodev */
NULL, /* /dev/mem */ NULL, /* /dev/mem */
NULL, /* /dev/fd */ NULL, /* /dev/fd */
NULL, /* /dev/hd */ NULL, /* /dev/hd */
tty_ioctl, /* /dev/ttyx */ tty_ioctl, /* /dev/ttyx */
tty_ioctl, /* /dev/tty */ tty_ioctl, /* /dev/tty */
NULL, /* /dev/lp */ NULL, /* /dev/lp */
NULL}; /* named pipes */ NULL}; /* named pipes */
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp; struct file * filp;
int dev,mode; int dev,mode;
if (fd >= NR_OPEN || !(filp = current->filp[fd])) if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF; return -EBADF;
mode=filp->f_inode->i_mode; mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode)) if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL; return -EINVAL;
dev = filp->f_inode->i_zone[0]; dev = filp->f_inode->i_zone[0];
if (MAJOR(dev) >= NRDEVS) if (MAJOR(dev) >= NRDEVS)
return -ENODEV; return -ENODEV;
if (!ioctl_table[MAJOR(dev)]) if (!ioctl_table[MAJOR(dev)])
return -ENOTTY; return -ENOTTY;
return ioctl_table[MAJOR(dev)](dev,cmd,arg); return ioctl_table[MAJOR(dev)](dev,cmd,arg);
} }

File diff suppressed because it is too large Load Diff

@ -1,208 +1,208 @@
/* /*
* linux/fs/open.c * linux/fs/open.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <utime.h> #include <utime.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
int sys_ustat(int dev, struct ustat * ubuf) int sys_ustat(int dev, struct ustat * ubuf)
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_utime(char * filename, struct utimbuf * times) int sys_utime(char * filename, struct utimbuf * times)
{ {
struct m_inode * inode; struct m_inode * inode;
long actime,modtime; long actime,modtime;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
if (times) { if (times) {
actime = get_fs_long((unsigned long *) &times->actime); actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime); modtime = get_fs_long((unsigned long *) &times->modtime);
} else } else
actime = modtime = CURRENT_TIME; actime = modtime = CURRENT_TIME;
inode->i_atime = actime; inode->i_atime = actime;
inode->i_mtime = modtime; inode->i_mtime = modtime;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
return 0; return 0;
} }
/* /*
* XXX should we use the real or effective uid? BSD uses the real uid, * XXX should we use the real or effective uid? BSD uses the real uid,
* so as to make this call useful to setuid programs. * so as to make this call useful to setuid programs.
*/ */
int sys_access(const char * filename,int mode) int sys_access(const char * filename,int mode)
{ {
struct m_inode * inode; struct m_inode * inode;
int res, i_mode; int res, i_mode;
mode &= 0007; mode &= 0007;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -EACCES; return -EACCES;
i_mode = res = inode->i_mode & 0777; i_mode = res = inode->i_mode & 0777;
iput(inode); iput(inode);
if (current->uid == inode->i_uid) if (current->uid == inode->i_uid)
res >>= 6; res >>= 6;
else if (current->gid == inode->i_gid) else if (current->gid == inode->i_gid)
res >>= 6; res >>= 6;
if ((res & 0007 & mode) == mode) if ((res & 0007 & mode) == mode)
return 0; return 0;
/* /*
* XXX we are doing this test last because we really should be * XXX we are doing this test last because we really should be
* swapping the effective with the real user id (temporarily), * swapping the effective with the real user id (temporarily),
* and then calling suser() routine. If we do call the * and then calling suser() routine. If we do call the
* suser() routine, it needs to be called last. * suser() routine, it needs to be called last.
*/ */
if ((!current->uid) && if ((!current->uid) &&
(!(mode & 1) || (i_mode & 0111))) (!(mode & 1) || (i_mode & 0111)))
return 0; return 0;
return -EACCES; return -EACCES;
} }
int sys_chdir(const char * filename) int sys_chdir(const char * filename)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode = namei(filename))) if (!(inode = namei(filename)))
return -ENOENT; return -ENOENT;
if (!S_ISDIR(inode->i_mode)) { if (!S_ISDIR(inode->i_mode)) {
iput(inode); iput(inode);
return -ENOTDIR; return -ENOTDIR;
} }
iput(current->pwd); iput(current->pwd);
current->pwd = inode; current->pwd = inode;
return (0); return (0);
} }
int sys_chroot(const char * filename) int sys_chroot(const char * filename)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
if (!S_ISDIR(inode->i_mode)) { if (!S_ISDIR(inode->i_mode)) {
iput(inode); iput(inode);
return -ENOTDIR; return -ENOTDIR;
} }
iput(current->root); iput(current->root);
current->root = inode; current->root = inode;
return (0); return (0);
} }
int sys_chmod(const char * filename,int mode) int sys_chmod(const char * filename,int mode)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
if ((current->euid != inode->i_uid) && !suser()) { if ((current->euid != inode->i_uid) && !suser()) {
iput(inode); iput(inode);
return -EACCES; return -EACCES;
} }
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777); inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
return 0; return 0;
} }
int sys_chown(const char * filename,int uid,int gid) int sys_chown(const char * filename,int uid,int gid)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
if (!suser()) { if (!suser()) {
iput(inode); iput(inode);
return -EACCES; return -EACCES;
} }
inode->i_uid=uid; inode->i_uid=uid;
inode->i_gid=gid; inode->i_gid=gid;
inode->i_dirt=1; inode->i_dirt=1;
iput(inode); iput(inode);
return 0; return 0;
} }
int sys_open(const char * filename,int flag,int mode) int sys_open(const char * filename,int flag,int mode)
{ {
struct m_inode * inode; struct m_inode * inode;
struct file * f; struct file * f;
int i,fd; int i,fd;
mode &= 0777 & ~current->umask; mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++) for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd]) if (!current->filp[fd])
break; break;
if (fd>=NR_OPEN) if (fd>=NR_OPEN)
return -EINVAL; return -EINVAL;
current->close_on_exec &= ~(1<<fd); current->close_on_exec &= ~(1<<fd);
f=0+file_table; f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++) for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break; if (!f->f_count) break;
if (i>=NR_FILE) if (i>=NR_FILE)
return -EINVAL; return -EINVAL;
(current->filp[fd]=f)->f_count++; (current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) { if ((i=open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL; current->filp[fd]=NULL;
f->f_count=0; f->f_count=0;
return i; return i;
} }
/* ttys are somewhat special (ttyxx major==4, tty major==5) */ /* ttys are somewhat special (ttyxx major==4, tty major==5) */
if (S_ISCHR(inode->i_mode)) if (S_ISCHR(inode->i_mode))
if (MAJOR(inode->i_zone[0])==4) { if (MAJOR(inode->i_zone[0])==4) {
if (current->leader && current->tty<0) { if (current->leader && current->tty<0) {
current->tty = MINOR(inode->i_zone[0]); current->tty = MINOR(inode->i_zone[0]);
tty_table[current->tty].pgrp = current->pgrp; tty_table[current->tty].pgrp = current->pgrp;
} }
} else if (MAJOR(inode->i_zone[0])==5) } else if (MAJOR(inode->i_zone[0])==5)
if (current->tty<0) { if (current->tty<0) {
iput(inode); iput(inode);
current->filp[fd]=NULL; current->filp[fd]=NULL;
f->f_count=0; f->f_count=0;
return -EPERM; return -EPERM;
} }
/* Likewise with block-devices: check for floppy_change */ /* Likewise with block-devices: check for floppy_change */
if (S_ISBLK(inode->i_mode)) if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_zone[0]); check_disk_change(inode->i_zone[0]);
f->f_mode = inode->i_mode; f->f_mode = inode->i_mode;
f->f_flags = flag; f->f_flags = flag;
f->f_count = 1; f->f_count = 1;
f->f_inode = inode; f->f_inode = inode;
f->f_pos = 0; f->f_pos = 0;
return (fd); return (fd);
} }
int sys_creat(const char * pathname, int mode) int sys_creat(const char * pathname, int mode)
{ {
return sys_open(pathname, O_CREAT | O_TRUNC, mode); return sys_open(pathname, O_CREAT | O_TRUNC, mode);
} }
int sys_close(unsigned int fd) int sys_close(unsigned int fd)
{ {
struct file * filp; struct file * filp;
if (fd >= NR_OPEN) if (fd >= NR_OPEN)
return -EINVAL; return -EINVAL;
current->close_on_exec &= ~(1<<fd); current->close_on_exec &= ~(1<<fd);
if (!(filp = current->filp[fd])) if (!(filp = current->filp[fd]))
return -EINVAL; return -EINVAL;
current->filp[fd] = NULL; current->filp[fd] = NULL;
if (filp->f_count == 0) if (filp->f_count == 0)
panic("Close: file count is 0"); panic("Close: file count is 0");
if (--filp->f_count) if (--filp->f_count)
return (0); return (0);
iput(filp->f_inode); iput(filp->f_inode);
return (0); return (0);
} }

@ -1,111 +1,111 @@
/* /*
* linux/fs/pipe.c * linux/fs/pipe.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <signal.h> #include <signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> /* for get_free_page */ #include <linux/mm.h> /* for get_free_page */
#include <asm/segment.h> #include <asm/segment.h>
int read_pipe(struct m_inode * inode, char * buf, int count) int read_pipe(struct m_inode * inode, char * buf, int count)
{ {
int chars, size, read = 0; int chars, size, read = 0;
while (count>0) { while (count>0) {
while (!(size=PIPE_SIZE(*inode))) { while (!(size=PIPE_SIZE(*inode))) {
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
if (inode->i_count != 2) /* are there any writers? */ if (inode->i_count != 2) /* are there any writers? */
return read; return read;
sleep_on(&inode->i_wait); sleep_on(&inode->i_wait);
} }
chars = PAGE_SIZE-PIPE_TAIL(*inode); chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count) if (chars > count)
chars = count; chars = count;
if (chars > size) if (chars > size)
chars = size; chars = size;
count -= chars; count -= chars;
read += chars; read += chars;
size = PIPE_TAIL(*inode); size = PIPE_TAIL(*inode);
PIPE_TAIL(*inode) += chars; PIPE_TAIL(*inode) += chars;
PIPE_TAIL(*inode) &= (PAGE_SIZE-1); PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
while (chars-->0) while (chars-->0)
put_fs_byte(((char *)inode->i_size)[size++],buf++); put_fs_byte(((char *)inode->i_size)[size++],buf++);
} }
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
return read; return read;
} }
int write_pipe(struct m_inode * inode, char * buf, int count) int write_pipe(struct m_inode * inode, char * buf, int count)
{ {
int chars, size, written = 0; int chars, size, written = 0;
while (count>0) { while (count>0) {
while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) { while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
if (inode->i_count != 2) { /* no readers */ if (inode->i_count != 2) { /* no readers */
current->signal |= (1<<(SIGPIPE-1)); current->signal |= (1<<(SIGPIPE-1));
return written?written:-1; return written?written:-1;
} }
sleep_on(&inode->i_wait); sleep_on(&inode->i_wait);
} }
chars = PAGE_SIZE-PIPE_HEAD(*inode); chars = PAGE_SIZE-PIPE_HEAD(*inode);
if (chars > count) if (chars > count)
chars = count; chars = count;
if (chars > size) if (chars > size)
chars = size; chars = size;
count -= chars; count -= chars;
written += chars; written += chars;
size = PIPE_HEAD(*inode); size = PIPE_HEAD(*inode);
PIPE_HEAD(*inode) += chars; PIPE_HEAD(*inode) += chars;
PIPE_HEAD(*inode) &= (PAGE_SIZE-1); PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
while (chars-->0) while (chars-->0)
((char *)inode->i_size)[size++]=get_fs_byte(buf++); ((char *)inode->i_size)[size++]=get_fs_byte(buf++);
} }
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
return written; return written;
} }
int sys_pipe(unsigned long * fildes) int sys_pipe(unsigned long * fildes)
{ {
struct m_inode * inode; struct m_inode * inode;
struct file * f[2]; struct file * f[2];
int fd[2]; int fd[2];
int i,j; int i,j;
j=0; j=0;
for(i=0;j<2 && i<NR_FILE;i++) for(i=0;j<2 && i<NR_FILE;i++)
if (!file_table[i].f_count) if (!file_table[i].f_count)
(f[j++]=i+file_table)->f_count++; (f[j++]=i+file_table)->f_count++;
if (j==1) if (j==1)
f[0]->f_count=0; f[0]->f_count=0;
if (j<2) if (j<2)
return -1; return -1;
j=0; j=0;
for(i=0;j<2 && i<NR_OPEN;i++) for(i=0;j<2 && i<NR_OPEN;i++)
if (!current->filp[i]) { if (!current->filp[i]) {
current->filp[ fd[j]=i ] = f[j]; current->filp[ fd[j]=i ] = f[j];
j++; j++;
} }
if (j==1) if (j==1)
current->filp[fd[0]]=NULL; current->filp[fd[0]]=NULL;
if (j<2) { if (j<2) {
f[0]->f_count=f[1]->f_count=0; f[0]->f_count=f[1]->f_count=0;
return -1; return -1;
} }
if (!(inode=get_pipe_inode())) { if (!(inode=get_pipe_inode())) {
current->filp[fd[0]] = current->filp[fd[0]] =
current->filp[fd[1]] = NULL; current->filp[fd[1]] = NULL;
f[0]->f_count = f[1]->f_count = 0; f[0]->f_count = f[1]->f_count = 0;
return -1; return -1;
} }
f[0]->f_inode = f[1]->f_inode = inode; f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0; f[0]->f_pos = f[1]->f_pos = 0;
f[0]->f_mode = 1; /* read */ f[0]->f_mode = 1; /* read */
f[1]->f_mode = 2; /* write */ f[1]->f_mode = 2; /* write */
put_fs_long(fd[0],0+fildes); put_fs_long(fd[0],0+fildes);
put_fs_long(fd[1],1+fildes); put_fs_long(fd[1],1+fildes);
return 0; return 0;
} }

@ -1,103 +1,103 @@
/* /*
* linux/fs/read_write.c * linux/fs/read_write.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/segment.h> #include <asm/segment.h>
extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);
extern int read_pipe(struct m_inode * inode, char * buf, int count); extern int read_pipe(struct m_inode * inode, char * buf, int count);
extern int write_pipe(struct m_inode * inode, char * buf, int count); extern int write_pipe(struct m_inode * inode, char * buf, int count);
extern int block_read(int dev, off_t * pos, char * buf, int count); extern int block_read(int dev, off_t * pos, char * buf, int count);
extern int block_write(int dev, off_t * pos, char * buf, int count); extern int block_write(int dev, off_t * pos, char * buf, int count);
extern int file_read(struct m_inode * inode, struct file * filp, extern int file_read(struct m_inode * inode, struct file * filp,
char * buf, int count); char * buf, int count);
extern int file_write(struct m_inode * inode, struct file * filp, extern int file_write(struct m_inode * inode, struct file * filp,
char * buf, int count); char * buf, int count);
int sys_lseek(unsigned int fd,off_t offset, int origin) int sys_lseek(unsigned int fd,off_t offset, int origin)
{ {
struct file * file; struct file * file;
int tmp; int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode) if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
|| !IS_SEEKABLE(MAJOR(file->f_inode->i_dev))) || !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
return -EBADF; return -EBADF;
if (file->f_inode->i_pipe) if (file->f_inode->i_pipe)
return -ESPIPE; return -ESPIPE;
switch (origin) { switch (origin) {
case 0: case 0:
if (offset<0) return -EINVAL; if (offset<0) return -EINVAL;
file->f_pos=offset; file->f_pos=offset;
break; break;
case 1: case 1:
if (file->f_pos+offset<0) return -EINVAL; if (file->f_pos+offset<0) return -EINVAL;
file->f_pos += offset; file->f_pos += offset;
break; break;
case 2: case 2:
if ((tmp=file->f_inode->i_size+offset) < 0) if ((tmp=file->f_inode->i_size+offset) < 0)
return -EINVAL; return -EINVAL;
file->f_pos = tmp; file->f_pos = tmp;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
return file->f_pos; return file->f_pos;
} }
int sys_read(unsigned int fd,char * buf,int count) int sys_read(unsigned int fd,char * buf,int count)
{ {
struct file * file; struct file * file;
struct m_inode * inode; struct m_inode * inode;
if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd])) if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
return -EINVAL; return -EINVAL;
if (!count) if (!count)
return 0; return 0;
verify_area(buf,count); verify_area(buf,count);
inode = file->f_inode; inode = file->f_inode;
if (inode->i_pipe) if (inode->i_pipe)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
if (S_ISCHR(inode->i_mode)) if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos); return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode)) if (S_ISBLK(inode->i_mode))
return block_read(inode->i_zone[0],&file->f_pos,buf,count); return block_read(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) { if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
if (count+file->f_pos > inode->i_size) if (count+file->f_pos > inode->i_size)
count = inode->i_size - file->f_pos; count = inode->i_size - file->f_pos;
if (count<=0) if (count<=0)
return 0; return 0;
return file_read(inode,file,buf,count); return file_read(inode,file,buf,count);
} }
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode); printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL; return -EINVAL;
} }
int sys_write(unsigned int fd,char * buf,int count) int sys_write(unsigned int fd,char * buf,int count)
{ {
struct file * file; struct file * file;
struct m_inode * inode; struct m_inode * inode;
if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd])) if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
return -EINVAL; return -EINVAL;
if (!count) if (!count)
return 0; return 0;
inode=file->f_inode; inode=file->f_inode;
if (inode->i_pipe) if (inode->i_pipe)
return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO; return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
if (S_ISCHR(inode->i_mode)) if (S_ISCHR(inode->i_mode))
return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos); return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode)) if (S_ISBLK(inode->i_mode))
return block_write(inode->i_zone[0],&file->f_pos,buf,count); return block_write(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
return file_write(inode,file,buf,count); return file_write(inode,file,buf,count);
printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode); printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL; return -EINVAL;
} }

@ -1,10 +1,10 @@
/* nothing , only the stub */ /* nothing , only the stub */
/* gohigh */ /* gohigh */
#include <errno.h> #include <errno.h>
int sys_select() int sys_select()
{ {
return -ENOSYS; return -ENOSYS;
} }

@ -1,66 +1,66 @@
/* /*
* linux/fs/stat.c * linux/fs/stat.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
static void cp_stat(struct m_inode * inode, struct stat * statbuf) static void cp_stat(struct m_inode * inode, struct stat * statbuf)
{ {
struct stat tmp; struct stat tmp;
int i; int i;
verify_area(statbuf,sizeof (* statbuf)); verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev; tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num; tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode; tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks; tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid; tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid; tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0]; tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size; tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime; tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime; tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime; tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++) for (i=0 ; i<sizeof (tmp) ; i++)
put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]); put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
} }
int sys_stat(char * filename, struct stat * statbuf) int sys_stat(char * filename, struct stat * statbuf)
{ {
struct m_inode * inode; struct m_inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
cp_stat(inode,statbuf); cp_stat(inode,statbuf);
iput(inode); iput(inode);
return 0; return 0;
} }
int sys_lstat(char * filename, struct stat * statbuf) int sys_lstat(char * filename, struct stat * statbuf)
{ {
return sys_stat(filename, statbuf); return sys_stat(filename, statbuf);
} }
int sys_fstat(unsigned int fd, struct stat * statbuf) int sys_fstat(unsigned int fd, struct stat * statbuf)
{ {
struct file * f; struct file * f;
struct m_inode * inode; struct m_inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode)) if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF; return -EBADF;
cp_stat(inode,statbuf); cp_stat(inode,statbuf);
return 0; return 0;
} }
int sys_readlink() int sys_readlink()
{ {
return -ENOSYS; return -ENOSYS;
} }

@ -1,282 +1,282 @@
/* /*
* linux/fs/super.c * linux/fs/super.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* super.c contains code to handle the super-block tables. * super.c contains code to handle the super-block tables.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
int sync_dev(int dev); int sync_dev(int dev);
void wait_for_keypress(void); void wait_for_keypress(void);
/* set_bit uses setb, as gas doesn't recognize setc */ /* set_bit uses setb, as gas doesn't recognize setc */
#define set_bit(bitnr,addr) ({ \ #define set_bit(bitnr,addr) ({ \
register int __res __asm__("ax"); \ register int __res __asm__("ax"); \
__asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \ __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
__res; }) __res; })
struct super_block super_block[NR_SUPER]; struct super_block super_block[NR_SUPER];
/* this is initialized in init/main.c */ /* this is initialized in init/main.c */
int ROOT_DEV = 0; int ROOT_DEV = 0;
static void lock_super(struct super_block * sb) static void lock_super(struct super_block * sb)
{ {
cli(); cli();
while (sb->s_lock) while (sb->s_lock)
sleep_on(&(sb->s_wait)); sleep_on(&(sb->s_wait));
sb->s_lock = 1; sb->s_lock = 1;
sti(); sti();
} }
static void free_super(struct super_block * sb) static void free_super(struct super_block * sb)
{ {
cli(); cli();
sb->s_lock = 0; sb->s_lock = 0;
wake_up(&(sb->s_wait)); wake_up(&(sb->s_wait));
sti(); sti();
} }
static void wait_on_super(struct super_block * sb) static void wait_on_super(struct super_block * sb)
{ {
cli(); cli();
while (sb->s_lock) while (sb->s_lock)
sleep_on(&(sb->s_wait)); sleep_on(&(sb->s_wait));
sti(); sti();
} }
struct super_block * get_super(int dev) struct super_block * get_super(int dev)
{ {
struct super_block * s; struct super_block * s;
if (!dev) if (!dev)
return NULL; return NULL;
s = 0+super_block; s = 0+super_block;
while (s < NR_SUPER+super_block) while (s < NR_SUPER+super_block)
if (s->s_dev == dev) { if (s->s_dev == dev) {
wait_on_super(s); wait_on_super(s);
if (s->s_dev == dev) if (s->s_dev == dev)
return s; return s;
s = 0+super_block; s = 0+super_block;
} else } else
s++; s++;
return NULL; return NULL;
} }
void put_super(int dev) void put_super(int dev)
{ {
struct super_block * sb; struct super_block * sb;
/* struct m_inode * inode; */ /* struct m_inode * inode; */
int i; int i;
if (dev == ROOT_DEV) { if (dev == ROOT_DEV) {
printk("root diskette changed: prepare for armageddon\n\r"); printk("root diskette changed: prepare for armageddon\n\r");
return; return;
} }
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
return; return;
if (sb->s_imount) { if (sb->s_imount) {
printk("Mounted disk changed - tssk, tssk\n\r"); printk("Mounted disk changed - tssk, tssk\n\r");
return; return;
} }
lock_super(sb); lock_super(sb);
sb->s_dev = 0; sb->s_dev = 0;
for(i=0;i<I_MAP_SLOTS;i++) for(i=0;i<I_MAP_SLOTS;i++)
brelse(sb->s_imap[i]); brelse(sb->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++) for(i=0;i<Z_MAP_SLOTS;i++)
brelse(sb->s_zmap[i]); brelse(sb->s_zmap[i]);
free_super(sb); free_super(sb);
return; return;
} }
static struct super_block * read_super(int dev) static struct super_block * read_super(int dev)
{ {
struct super_block * s; struct super_block * s;
struct buffer_head * bh; struct buffer_head * bh;
int i,block; int i,block;
if (!dev) if (!dev)
return NULL; return NULL;
check_disk_change(dev); check_disk_change(dev);
if (s = get_super(dev)) if (s = get_super(dev))
return s; return s;
for (s = 0+super_block ;; s++) { for (s = 0+super_block ;; s++) {
if (s >= NR_SUPER+super_block) if (s >= NR_SUPER+super_block)
return NULL; return NULL;
if (!s->s_dev) if (!s->s_dev)
break; break;
} }
s->s_dev = dev; s->s_dev = dev;
s->s_isup = NULL; s->s_isup = NULL;
s->s_imount = NULL; s->s_imount = NULL;
s->s_time = 0; s->s_time = 0;
s->s_rd_only = 0; s->s_rd_only = 0;
s->s_dirt = 0; s->s_dirt = 0;
lock_super(s); lock_super(s);
if (!(bh = bread(dev,1))) { if (!(bh = bread(dev,1))) {
s->s_dev=0; s->s_dev=0;
free_super(s); free_super(s);
return NULL; return NULL;
} }
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
*((struct d_super_block *) s) = *((struct d_super_block *) s) =
*((struct d_super_block *) bh->b_data); *((struct d_super_block *) bh->b_data);
brelse(bh); brelse(bh);
if (s->s_magic != SUPER_MAGIC) { if (s->s_magic != SUPER_MAGIC) {
s->s_dev = 0; s->s_dev = 0;
free_super(s); free_super(s);
return NULL; return NULL;
} }
for (i=0;i<I_MAP_SLOTS;i++) for (i=0;i<I_MAP_SLOTS;i++)
s->s_imap[i] = NULL; s->s_imap[i] = NULL;
for (i=0;i<Z_MAP_SLOTS;i++) for (i=0;i<Z_MAP_SLOTS;i++)
s->s_zmap[i] = NULL; s->s_zmap[i] = NULL;
block=2; block=2;
for (i=0 ; i < s->s_imap_blocks ; i++) for (i=0 ; i < s->s_imap_blocks ; i++)
if (s->s_imap[i]=bread(dev,block)) if (s->s_imap[i]=bread(dev,block))
block++; block++;
else else
break; break;
for (i=0 ; i < s->s_zmap_blocks ; i++) for (i=0 ; i < s->s_zmap_blocks ; i++)
if (s->s_zmap[i]=bread(dev,block)) if (s->s_zmap[i]=bread(dev,block))
block++; block++;
else else
break; break;
if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) { if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
for(i=0;i<I_MAP_SLOTS;i++) for(i=0;i<I_MAP_SLOTS;i++)
brelse(s->s_imap[i]); brelse(s->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++) for(i=0;i<Z_MAP_SLOTS;i++)
brelse(s->s_zmap[i]); brelse(s->s_zmap[i]);
s->s_dev=0; s->s_dev=0;
free_super(s); free_super(s);
return NULL; return NULL;
} }
s->s_imap[0]->b_data[0] |= 1; s->s_imap[0]->b_data[0] |= 1;
s->s_zmap[0]->b_data[0] |= 1; s->s_zmap[0]->b_data[0] |= 1;
free_super(s); free_super(s);
return s; return s;
} }
int sys_umount(char * dev_name) int sys_umount(char * dev_name)
{ {
struct m_inode * inode; struct m_inode * inode;
struct super_block * sb; struct super_block * sb;
int dev; int dev;
if (!(inode=namei(dev_name))) if (!(inode=namei(dev_name)))
return -ENOENT; return -ENOENT;
dev = inode->i_zone[0]; dev = inode->i_zone[0];
if (!S_ISBLK(inode->i_mode)) { if (!S_ISBLK(inode->i_mode)) {
iput(inode); iput(inode);
return -ENOTBLK; return -ENOTBLK;
} }
iput(inode); iput(inode);
if (dev==ROOT_DEV) if (dev==ROOT_DEV)
return -EBUSY; return -EBUSY;
if (!(sb=get_super(dev)) || !(sb->s_imount)) if (!(sb=get_super(dev)) || !(sb->s_imount))
return -ENOENT; return -ENOENT;
if (!sb->s_imount->i_mount) if (!sb->s_imount->i_mount)
printk("Mounted inode has i_mount=0\n"); printk("Mounted inode has i_mount=0\n");
for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++) for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
if (inode->i_dev==dev && inode->i_count) if (inode->i_dev==dev && inode->i_count)
return -EBUSY; return -EBUSY;
sb->s_imount->i_mount=0; sb->s_imount->i_mount=0;
iput(sb->s_imount); iput(sb->s_imount);
sb->s_imount = NULL; sb->s_imount = NULL;
iput(sb->s_isup); iput(sb->s_isup);
sb->s_isup = NULL; sb->s_isup = NULL;
put_super(dev); put_super(dev);
sync_dev(dev); sync_dev(dev);
return 0; return 0;
} }
int sys_mount(char * dev_name, char * dir_name, int rw_flag) int sys_mount(char * dev_name, char * dir_name, int rw_flag)
{ {
struct m_inode * dev_i, * dir_i; struct m_inode * dev_i, * dir_i;
struct super_block * sb; struct super_block * sb;
int dev; int dev;
if (!(dev_i=namei(dev_name))) if (!(dev_i=namei(dev_name)))
return -ENOENT; return -ENOENT;
dev = dev_i->i_zone[0]; dev = dev_i->i_zone[0];
if (!S_ISBLK(dev_i->i_mode)) { if (!S_ISBLK(dev_i->i_mode)) {
iput(dev_i); iput(dev_i);
return -EPERM; return -EPERM;
} }
iput(dev_i); iput(dev_i);
if (!(dir_i=namei(dir_name))) if (!(dir_i=namei(dir_name)))
return -ENOENT; return -ENOENT;
if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) { if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
if (!S_ISDIR(dir_i->i_mode)) { if (!S_ISDIR(dir_i->i_mode)) {
iput(dir_i); iput(dir_i);
return -EPERM; return -EPERM;
} }
if (!(sb=read_super(dev))) { if (!(sb=read_super(dev))) {
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
if (sb->s_imount) { if (sb->s_imount) {
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
if (dir_i->i_mount) { if (dir_i->i_mount) {
iput(dir_i); iput(dir_i);
return -EPERM; return -EPERM;
} }
sb->s_imount=dir_i; sb->s_imount=dir_i;
dir_i->i_mount=1; dir_i->i_mount=1;
dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */ dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */
return 0; /* we do that in umount */ return 0; /* we do that in umount */
} }
void mount_root(void) void mount_root(void)
{ {
int i,free; int i,free;
struct super_block * p; struct super_block * p;
struct m_inode * mi; struct m_inode * mi;
if (32 != sizeof (struct d_inode)) if (32 != sizeof (struct d_inode))
panic("bad i-node size"); panic("bad i-node size");
for(i=0;i<NR_FILE;i++) for(i=0;i<NR_FILE;i++)
file_table[i].f_count=0; file_table[i].f_count=0;
if (MAJOR(ROOT_DEV) == 2) { if (MAJOR(ROOT_DEV) == 2) {
printk("Insert root floppy and press ENTER"); printk("Insert root floppy and press ENTER");
wait_for_keypress(); wait_for_keypress();
} }
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) { for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
p->s_dev = 0; p->s_dev = 0;
p->s_lock = 0; p->s_lock = 0;
p->s_wait = NULL; p->s_wait = NULL;
} }
if (!(p=read_super(ROOT_DEV))) if (!(p=read_super(ROOT_DEV)))
panic("Unable to mount root"); panic("Unable to mount root");
if (!(mi=iget(ROOT_DEV,ROOT_INO))) if (!(mi=iget(ROOT_DEV,ROOT_INO)))
panic("Unable to read root i-node"); panic("Unable to read root i-node");
mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */ mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
p->s_isup = p->s_imount = mi; p->s_isup = p->s_imount = mi;
current->pwd = mi; current->pwd = mi;
current->root = mi; current->root = mi;
free=0; free=0;
i=p->s_nzones; i=p->s_nzones;
while (-- i >= 0) while (-- i >= 0)
if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data)) if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
free++; free++;
printk("%d/%d free blocks\n\r",free,p->s_nzones); printk("%d/%d free blocks\n\r",free,p->s_nzones);
free=0; free=0;
i=p->s_ninodes+1; i=p->s_ninodes+1;
while (-- i >= 0) while (-- i >= 0)
if (!set_bit(i&8191,p->s_imap[i>>13]->b_data)) if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
free++; free++;
printk("%d/%d free inodes\n\r",free,p->s_ninodes); printk("%d/%d free inodes\n\r",free,p->s_ninodes);
} }

@ -1,65 +1,65 @@
/* /*
* linux/fs/truncate.c * linux/fs/truncate.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <sys/stat.h> #include <sys/stat.h>
static void free_ind(int dev,int block) static void free_ind(int dev,int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
unsigned short * p; unsigned short * p;
int i; int i;
if (!block) if (!block)
return; return;
if (bh=bread(dev,block)) { if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data; p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++) for (i=0;i<512;i++,p++)
if (*p) if (*p)
free_block(dev,*p); free_block(dev,*p);
brelse(bh); brelse(bh);
} }
free_block(dev,block); free_block(dev,block);
} }
static void free_dind(int dev,int block) static void free_dind(int dev,int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
unsigned short * p; unsigned short * p;
int i; int i;
if (!block) if (!block)
return; return;
if (bh=bread(dev,block)) { if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data; p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++) for (i=0;i<512;i++,p++)
if (*p) if (*p)
free_ind(dev,*p); free_ind(dev,*p);
brelse(bh); brelse(bh);
} }
free_block(dev,block); free_block(dev,block);
} }
void truncate(struct m_inode * inode) void truncate(struct m_inode * inode)
{ {
int i; int i;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
return; return;
for (i=0;i<7;i++) for (i=0;i<7;i++)
if (inode->i_zone[i]) { if (inode->i_zone[i]) {
free_block(inode->i_dev,inode->i_zone[i]); free_block(inode->i_dev,inode->i_zone[i]);
inode->i_zone[i]=0; inode->i_zone[i]=0;
} }
free_ind(inode->i_dev,inode->i_zone[7]); free_ind(inode->i_dev,inode->i_zone[7]);
free_dind(inode->i_dev,inode->i_zone[8]); free_dind(inode->i_dev,inode->i_zone[8]);
inode->i_zone[7] = inode->i_zone[8] = 0; inode->i_zone[7] = inode->i_zone[8] = 0;
inode->i_size = 0; inode->i_size = 0;
inode->i_dirt = 1; inode->i_dirt = 1;
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
} }

@ -1,220 +1,220 @@
#ifndef _A_OUT_H #ifndef _A_OUT_H
#define _A_OUT_H #define _A_OUT_H
#define __GNU_EXEC_MACROS__ #define __GNU_EXEC_MACROS__
struct exec { struct exec {
unsigned long a_magic; /* Use macros N_MAGIC, etc for access */ unsigned long a_magic; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */ unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */ unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */ unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */ unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */ unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */ unsigned a_drsize; /* length of relocation info for data, in bytes */
}; };
#ifndef N_MAGIC #ifndef N_MAGIC
#define N_MAGIC(exec) ((exec).a_magic) #define N_MAGIC(exec) ((exec).a_magic)
#endif #endif
#ifndef OMAGIC #ifndef OMAGIC
/* Code indicating object file or impure executable. */ /* Code indicating object file or impure executable. */
#define OMAGIC 0407 #define OMAGIC 0407
/* Code indicating pure executable. */ /* Code indicating pure executable. */
#define NMAGIC 0410 #define NMAGIC 0410
/* Code indicating demand-paged executable. */ /* Code indicating demand-paged executable. */
#define ZMAGIC 0413 #define ZMAGIC 0413
#endif /* not OMAGIC */ #endif /* not OMAGIC */
#ifndef N_BADMAG #ifndef N_BADMAG
#define N_BADMAG(x) \ #define N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC) && N_MAGIC(x) != ZMAGIC)
#endif #endif
#define _N_BADMAG(x) \ #define _N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC) && N_MAGIC(x) != ZMAGIC)
#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec)) #define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
#ifndef N_TXTOFF #ifndef N_TXTOFF
#define N_TXTOFF(x) \ #define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec)) (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
#endif #endif
#ifndef N_DATOFF #ifndef N_DATOFF
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#endif #endif
#ifndef N_TRELOFF #ifndef N_TRELOFF
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) #define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#endif #endif
#ifndef N_DRELOFF #ifndef N_DRELOFF
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize) #define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
#endif #endif
#ifndef N_SYMOFF #ifndef N_SYMOFF
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize) #define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
#endif #endif
#ifndef N_STROFF #ifndef N_STROFF
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
#endif #endif
/* Address of text segment in memory after it is loaded. */ /* Address of text segment in memory after it is loaded. */
#ifndef N_TXTADDR #ifndef N_TXTADDR
#define N_TXTADDR(x) 0 #define N_TXTADDR(x) 0
#endif #endif
/* Address of data segment in memory after it is loaded. /* Address of data segment in memory after it is loaded.
Note that it is up to you to define SEGMENT_SIZE Note that it is up to you to define SEGMENT_SIZE
on machines not listed here. */ on machines not listed here. */
#if defined(vax) || defined(hp300) || defined(pyr) #if defined(vax) || defined(hp300) || defined(pyr)
#define SEGMENT_SIZE PAGE_SIZE #define SEGMENT_SIZE PAGE_SIZE
#endif #endif
#ifdef hp300 #ifdef hp300
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#endif #endif
#ifdef sony #ifdef sony
#define SEGMENT_SIZE 0x2000 #define SEGMENT_SIZE 0x2000
#endif /* Sony. */ #endif /* Sony. */
#ifdef is68k #ifdef is68k
#define SEGMENT_SIZE 0x20000 #define SEGMENT_SIZE 0x20000
#endif #endif
#if defined(m68k) && defined(PORTAR) #if defined(m68k) && defined(PORTAR)
#define PAGE_SIZE 0x400 #define PAGE_SIZE 0x400
#define SEGMENT_SIZE PAGE_SIZE #define SEGMENT_SIZE PAGE_SIZE
#endif #endif
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#define SEGMENT_SIZE 1024 #define SEGMENT_SIZE 1024
#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) #define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
#ifndef N_DATADDR #ifndef N_DATADDR
#define N_DATADDR(x) \ #define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#endif #endif
/* Address of bss segment in memory after it is loaded. */ /* Address of bss segment in memory after it is loaded. */
#ifndef N_BSSADDR #ifndef N_BSSADDR
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
#endif #endif
#ifndef N_NLIST_DECLARED #ifndef N_NLIST_DECLARED
struct nlist { struct nlist {
union { union {
char *n_name; char *n_name;
struct nlist *n_next; struct nlist *n_next;
long n_strx; long n_strx;
} n_un; } n_un;
unsigned char n_type; unsigned char n_type;
char n_other; char n_other;
short n_desc; short n_desc;
unsigned long n_value; unsigned long n_value;
}; };
#endif #endif
#ifndef N_UNDF #ifndef N_UNDF
#define N_UNDF 0 #define N_UNDF 0
#endif #endif
#ifndef N_ABS #ifndef N_ABS
#define N_ABS 2 #define N_ABS 2
#endif #endif
#ifndef N_TEXT #ifndef N_TEXT
#define N_TEXT 4 #define N_TEXT 4
#endif #endif
#ifndef N_DATA #ifndef N_DATA
#define N_DATA 6 #define N_DATA 6
#endif #endif
#ifndef N_BSS #ifndef N_BSS
#define N_BSS 8 #define N_BSS 8
#endif #endif
#ifndef N_COMM #ifndef N_COMM
#define N_COMM 18 #define N_COMM 18
#endif #endif
#ifndef N_FN #ifndef N_FN
#define N_FN 15 #define N_FN 15
#endif #endif
#ifndef N_EXT #ifndef N_EXT
#define N_EXT 1 #define N_EXT 1
#endif #endif
#ifndef N_TYPE #ifndef N_TYPE
#define N_TYPE 036 #define N_TYPE 036
#endif #endif
#ifndef N_STAB #ifndef N_STAB
#define N_STAB 0340 #define N_STAB 0340
#endif #endif
/* The following type indicates the definition of a symbol as being /* The following type indicates the definition of a symbol as being
an indirect reference to another symbol. The other symbol an indirect reference to another symbol. The other symbol
appears as an undefined reference, immediately following this symbol. appears as an undefined reference, immediately following this symbol.
Indirection is asymmetrical. The other symbol's value will be used Indirection is asymmetrical. The other symbol's value will be used
to satisfy requests for the indirect symbol, but not vice versa. to satisfy requests for the indirect symbol, but not vice versa.
If the other symbol does not have a definition, libraries will If the other symbol does not have a definition, libraries will
be searched to find a definition. */ be searched to find a definition. */
#define N_INDR 0xa #define N_INDR 0xa
/* The following symbols refer to set elements. /* The following symbols refer to set elements.
All the N_SET[ATDB] symbols with the same name form one set. All the N_SET[ATDB] symbols with the same name form one set.
Space is allocated for the set in the text section, and each set Space is allocated for the set in the text section, and each set
element's value is stored into one word of the space. element's value is stored into one word of the space.
The first word of the space is the length of the set (number of elements). The first word of the space is the length of the set (number of elements).
The address of the set is made into an N_SETV symbol The address of the set is made into an N_SETV symbol
whose name is the same as the name of the set. whose name is the same as the name of the set.
This symbol acts like a N_DATA global symbol This symbol acts like a N_DATA global symbol
in that it can satisfy undefined external references. */ in that it can satisfy undefined external references. */
/* These appear as input to LD, in a .o file. */ /* These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /* Absolute set element symbol */ #define N_SETA 0x14 /* Absolute set element symbol */
#define N_SETT 0x16 /* Text set element symbol */ #define N_SETT 0x16 /* Text set element symbol */
#define N_SETD 0x18 /* Data set element symbol */ #define N_SETD 0x18 /* Data set element symbol */
#define N_SETB 0x1A /* Bss set element symbol */ #define N_SETB 0x1A /* Bss set element symbol */
/* This is output from LD. */ /* This is output from LD. */
#define N_SETV 0x1C /* Pointer to set vector in data area. */ #define N_SETV 0x1C /* Pointer to set vector in data area. */
#ifndef N_RELOCATION_INFO_DECLARED #ifndef N_RELOCATION_INFO_DECLARED
/* This structure describes a single relocation to be performed. /* This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures, The text-relocation section of the file is a vector of these structures,
all of which apply to the text section. all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */ Likewise, the data-relocation section applies to the data section. */
struct relocation_info struct relocation_info
{ {
/* Address (within segment) to be relocated. */ /* Address (within segment) to be relocated. */
int r_address; int r_address;
/* The meaning of r_symbolnum depends on r_extern. */ /* The meaning of r_symbolnum depends on r_extern. */
unsigned int r_symbolnum:24; unsigned int r_symbolnum:24;
/* Nonzero means value is a pc-relative offset /* Nonzero means value is a pc-relative offset
and it should be relocated for changes in its own address and it should be relocated for changes in its own address
as well as for changes in the symbol or section specified. */ as well as for changes in the symbol or section specified. */
unsigned int r_pcrel:1; unsigned int r_pcrel:1;
/* Length (as exponent of 2) of the field to be relocated. /* Length (as exponent of 2) of the field to be relocated.
Thus, a value of 2 indicates 1<<2 bytes. */ Thus, a value of 2 indicates 1<<2 bytes. */
unsigned int r_length:2; unsigned int r_length:2;
/* 1 => relocate with value of symbol. /* 1 => relocate with value of symbol.
r_symbolnum is the index of the symbol r_symbolnum is the index of the symbol
in file's the symbol table. in file's the symbol table.
0 => relocate with the address of a segment. 0 => relocate with the address of a segment.
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
(the N_EXT bit may be set also, but signifies nothing). */ (the N_EXT bit may be set also, but signifies nothing). */
unsigned int r_extern:1; unsigned int r_extern:1;
/* Four bits that aren't used, but when writing an object file /* Four bits that aren't used, but when writing an object file
it is desirable to clear them. */ it is desirable to clear them. */
unsigned int r_pad:4; unsigned int r_pad:4;
}; };
#endif /* no N_RELOCATION_INFO_DECLARED. */ #endif /* no N_RELOCATION_INFO_DECLARED. */
#endif /* __A_OUT_GNU_H__ */ #endif /* __A_OUT_GNU_H__ */

@ -1,24 +1,24 @@
#define outb(value,port) \ #define outb(value,port) \
__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))
#define inb(port) ({ \ #define inb(port) ({ \
unsigned char _v; \ unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \ __asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
_v; \ _v; \
}) })
#define outb_p(value,port) \ #define outb_p(value,port) \
__asm__ ("outb %%al,%%dx\n" \ __asm__ ("outb %%al,%%dx\n" \
"\tjmp 1f\n" \ "\tjmp 1f\n" \
"1:\tjmp 1f\n" \ "1:\tjmp 1f\n" \
"1:"::"a" (value),"d" (port)) "1:"::"a" (value),"d" (port))
#define inb_p(port) ({ \ #define inb_p(port) ({ \
unsigned char _v; \ unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al\n" \ __asm__ volatile ("inb %%dx,%%al\n" \
"\tjmp 1f\n" \ "\tjmp 1f\n" \
"1:\tjmp 1f\n" \ "1:\tjmp 1f\n" \
"1:":"=a" (_v):"d" (port)); \ "1:":"=a" (_v):"d" (port)); \
_v; \ _v; \
}) })

@ -1,15 +1,15 @@
/* /*
* NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This * NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
* goes for all kernel functions (ds=es=kernel space, fs=local data, * 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= * 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 * user data space). This is NOT a bug, as any user program that changes
* es deserves to die if it isn't careful. * es deserves to die if it isn't careful.
*/ */
#define memcpy(dest,src,n) ({ \ #define memcpy(dest,src,n) ({ \
void * _res = dest; \ void * _res = dest; \
__asm__ ("cld;rep;movsb" \ __asm__ ("cld;rep;movsb" \
::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \ ::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
); \ ); \
_res; \ _res; \
}) })

@ -1,65 +1,65 @@
static inline unsigned char get_fs_byte(const char * addr) static inline unsigned char get_fs_byte(const char * addr)
{ {
unsigned register char _v; unsigned register char _v;
__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v; return _v;
} }
static inline unsigned short get_fs_word(const unsigned short *addr) static inline unsigned short get_fs_word(const unsigned short *addr)
{ {
unsigned short _v; unsigned short _v;
__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr)); __asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
return _v; return _v;
} }
static inline unsigned long get_fs_long(const unsigned long *addr) static inline unsigned long get_fs_long(const unsigned long *addr)
{ {
unsigned long _v; unsigned long _v;
__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \ __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
return _v; return _v;
} }
static inline void put_fs_byte(char val,char *addr) static inline void put_fs_byte(char val,char *addr)
{ {
__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
} }
static inline void put_fs_word(short val,short * addr) static inline void put_fs_word(short val,short * addr)
{ {
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr)); __asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
} }
static inline void put_fs_long(unsigned long val,unsigned long * addr) static inline void put_fs_long(unsigned long val,unsigned long * addr)
{ {
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr)); __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
} }
/* /*
* Someone who knows GNU asm better than I should double check the followig. * 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. * It seems to work, but I don't know if I'm doing something subtly wrong.
* --- TYT, 11/24/91 * --- TYT, 11/24/91
* [ nothing wrong here, Linus ] * [ nothing wrong here, Linus ]
*/ */
static inline unsigned long get_fs() static inline unsigned long get_fs()
{ {
unsigned short _v; unsigned short _v;
__asm__("mov %%fs,%%ax":"=a" (_v):); __asm__("mov %%fs,%%ax":"=a" (_v):);
return _v; return _v;
} }
static inline unsigned long get_ds() static inline unsigned long get_ds()
{ {
unsigned short _v; unsigned short _v;
__asm__("mov %%ds,%%ax":"=a" (_v):); __asm__("mov %%ds,%%ax":"=a" (_v):);
return _v; return _v;
} }
static inline void set_fs(unsigned long val) static inline void set_fs(unsigned long val)
{ {
__asm__("mov %0,%%fs"::"a" ((unsigned short) val)); __asm__("mov %0,%%fs"::"a" ((unsigned short) val));
} }

@ -1,66 +1,66 @@
#define move_to_user_mode() \ #define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \ __asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \ "pushl $0x17\n\t" \
"pushl %%eax\n\t" \ "pushl %%eax\n\t" \
"pushfl\n\t" \ "pushfl\n\t" \
"pushl $0x0f\n\t" \ "pushl $0x0f\n\t" \
"pushl $1f\n\t" \ "pushl $1f\n\t" \
"iret\n" \ "iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \ "1:\tmovl $0x17,%%eax\n\t" \
"movw %%ax,%%ds\n\t" \ "movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \ "movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \ "movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \ "movw %%ax,%%gs" \
:::"ax") :::"ax")
#define sti() __asm__ ("sti"::) #define sti() __asm__ ("sti"::)
#define cli() __asm__ ("cli"::) #define cli() __asm__ ("cli"::)
#define nop() __asm__ ("nop"::) #define nop() __asm__ ("nop"::)
#define iret() __asm__ ("iret"::) #define iret() __asm__ ("iret"::)
#define _set_gate(gate_addr,type,dpl,addr) \ #define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \ __asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \ "movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \ "movl %%eax,%1\n\t" \
"movl %%edx,%2" \ "movl %%edx,%2" \
: \ : \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \ "o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \ "o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000)) "d" ((char *) (addr)),"a" (0x00080000))
#define set_intr_gate(n,addr) \ #define set_intr_gate(n,addr) \
_set_gate(&idt[n],14,0,addr) _set_gate(&idt[n],14,0,addr)
#define set_trap_gate(n,addr) \ #define set_trap_gate(n,addr) \
_set_gate(&idt[n],15,0,addr) _set_gate(&idt[n],15,0,addr)
#define set_system_gate(n,addr) \ #define set_system_gate(n,addr) \
_set_gate(&idt[n],15,3,addr) _set_gate(&idt[n],15,3,addr)
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\ #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
*(gate_addr) = ((base) & 0xff000000) | \ *(gate_addr) = ((base) & 0xff000000) | \
(((base) & 0x00ff0000)>>16) | \ (((base) & 0x00ff0000)>>16) | \
((limit) & 0xf0000) | \ ((limit) & 0xf0000) | \
((dpl)<<13) | \ ((dpl)<<13) | \
(0x00408000) | \ (0x00408000) | \
((type)<<8); \ ((type)<<8); \
*((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \ *((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \
((limit) & 0x0ffff); } ((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,type) \ #define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \ __asm__ ("movw $104,%1\n\t" \
"movw %%ax,%2\n\t" \ "movw %%ax,%2\n\t" \
"rorl $16,%%eax\n\t" \ "rorl $16,%%eax\n\t" \
"movb %%al,%3\n\t" \ "movb %%al,%3\n\t" \
"movb $" type ",%4\n\t" \ "movb $" type ",%4\n\t" \
"movb $0x00,%5\n\t" \ "movb $0x00,%5\n\t" \
"movb %%ah,%6\n\t" \ "movb %%ah,%6\n\t" \
"rorl $16,%%eax" \ "rorl $16,%%eax" \
::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \ ::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
"m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \ "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
) )
#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89") #define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82") #define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")

@ -1,15 +1,15 @@
#ifndef _CONST_H #ifndef _CONST_H
#define _CONST_H #define _CONST_H
#define BUFFER_END 0x200000 #define BUFFER_END 0x200000
#define I_TYPE 0170000 #define I_TYPE 0170000
#define I_DIRECTORY 0040000 #define I_DIRECTORY 0040000
#define I_REGULAR 0100000 #define I_REGULAR 0100000
#define I_BLOCK_SPECIAL 0060000 #define I_BLOCK_SPECIAL 0060000
#define I_CHAR_SPECIAL 0020000 #define I_CHAR_SPECIAL 0020000
#define I_NAMED_PIPE 0010000 #define I_NAMED_PIPE 0010000
#define I_SET_UID_BIT 0004000 #define I_SET_UID_BIT 0004000
#define I_SET_GID_BIT 0002000 #define I_SET_GID_BIT 0002000
#endif #endif

@ -1,34 +1,34 @@
#ifndef _CTYPE_H #ifndef _CTYPE_H
#define _CTYPE_H #define _CTYPE_H
#define _U 0x01 /* upper */ #define _U 0x01 /* upper */
#define _L 0x02 /* lower */ #define _L 0x02 /* lower */
#define _D 0x04 /* digit */ #define _D 0x04 /* digit */
#define _C 0x08 /* cntrl */ #define _C 0x08 /* cntrl */
#define _P 0x10 /* punct */ #define _P 0x10 /* punct */
#define _S 0x20 /* white space (space/lf/tab) */ #define _S 0x20 /* white space (space/lf/tab) */
#define _X 0x40 /* hex digit */ #define _X 0x40 /* hex digit */
#define _SP 0x80 /* hard space (0x20) */ #define _SP 0x80 /* hard space (0x20) */
extern unsigned char _ctype[]; extern unsigned char _ctype[];
extern char _ctmp; extern char _ctmp;
#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D)) #define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D))
#define isalpha(c) ((_ctype+1)[c]&(_U|_L)) #define isalpha(c) ((_ctype+1)[c]&(_U|_L))
#define iscntrl(c) ((_ctype+1)[c]&(_C)) #define iscntrl(c) ((_ctype+1)[c]&(_C))
#define isdigit(c) ((_ctype+1)[c]&(_D)) #define isdigit(c) ((_ctype+1)[c]&(_D))
#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D)) #define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D))
#define islower(c) ((_ctype+1)[c]&(_L)) #define islower(c) ((_ctype+1)[c]&(_L))
#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP)) #define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP))
#define ispunct(c) ((_ctype+1)[c]&(_P)) #define ispunct(c) ((_ctype+1)[c]&(_P))
#define isspace(c) ((_ctype+1)[c]&(_S)) #define isspace(c) ((_ctype+1)[c]&(_S))
#define isupper(c) ((_ctype+1)[c]&(_U)) #define isupper(c) ((_ctype+1)[c]&(_U))
#define isxdigit(c) ((_ctype+1)[c]&(_D|_X)) #define isxdigit(c) ((_ctype+1)[c]&(_D|_X))
#define isascii(c) (((unsigned) c)<=0x7f) #define isascii(c) (((unsigned) c)<=0x7f)
#define toascii(c) (((unsigned) c)&0x7f) #define toascii(c) (((unsigned) c)&0x7f)
#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp) #define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp)
#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) #define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp)
#endif #endif

@ -1,60 +1,60 @@
#ifndef _ERRNO_H #ifndef _ERRNO_H
#define _ERRNO_H #define _ERRNO_H
/* /*
* ok, as I hadn't got any other source of information about * ok, as I hadn't got any other source of information about
* possible error numbers, I was forced to use the same numbers * possible error numbers, I was forced to use the same numbers
* as minix. * as minix.
* Hopefully these are posix or something. I wouldn't know (and posix * Hopefully these are posix or something. I wouldn't know (and posix
* isn't telling me - they want $$$ for their f***ing standard). * isn't telling me - they want $$$ for their f***ing standard).
* *
* We don't use the _SIGN cludge of minix, so kernel returns must * We don't use the _SIGN cludge of minix, so kernel returns must
* see to the sign by themselves. * see to the sign by themselves.
* *
* NOTE! Remember to change strerror() if you change this file! * NOTE! Remember to change strerror() if you change this file!
*/ */
extern int errno; extern int errno;
#define ERROR 99 #define ERROR 99
#define EPERM 1 #define EPERM 1
#define ENOENT 2 #define ENOENT 2
#define ESRCH 3 #define ESRCH 3
#define EINTR 4 #define EINTR 4
#define EIO 5 #define EIO 5
#define ENXIO 6 #define ENXIO 6
#define E2BIG 7 #define E2BIG 7
#define ENOEXEC 8 #define ENOEXEC 8
#define EBADF 9 #define EBADF 9
#define ECHILD 10 #define ECHILD 10
#define EAGAIN 11 #define EAGAIN 11
#define ENOMEM 12 #define ENOMEM 12
#define EACCES 13 #define EACCES 13
#define EFAULT 14 #define EFAULT 14
#define ENOTBLK 15 #define ENOTBLK 15
#define EBUSY 16 #define EBUSY 16
#define EEXIST 17 #define EEXIST 17
#define EXDEV 18 #define EXDEV 18
#define ENODEV 19 #define ENODEV 19
#define ENOTDIR 20 #define ENOTDIR 20
#define EISDIR 21 #define EISDIR 21
#define EINVAL 22 #define EINVAL 22
#define ENFILE 23 #define ENFILE 23
#define EMFILE 24 #define EMFILE 24
#define ENOTTY 25 #define ENOTTY 25
#define ETXTBSY 26 #define ETXTBSY 26
#define EFBIG 27 #define EFBIG 27
#define ENOSPC 28 #define ENOSPC 28
#define ESPIPE 29 #define ESPIPE 29
#define EROFS 30 #define EROFS 30
#define EMLINK 31 #define EMLINK 31
#define EPIPE 32 #define EPIPE 32
#define EDOM 33 #define EDOM 33
#define ERANGE 34 #define ERANGE 34
#define EDEADLK 35 #define EDEADLK 35
#define ENAMETOOLONG 36 #define ENAMETOOLONG 36
#define ENOLCK 37 #define ENOLCK 37
#define ENOSYS 38 #define ENOSYS 38
#define ENOTEMPTY 39 #define ENOTEMPTY 39
#endif #endif

@ -1,55 +1,55 @@
#ifndef _FCNTL_H #ifndef _FCNTL_H
#define _FCNTL_H #define _FCNTL_H
#include <sys/types.h> #include <sys/types.h>
/* open/fcntl - NOCTTY, NDELAY isn't implemented yet */ /* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
#define O_ACCMODE 00003 #define O_ACCMODE 00003
#define O_RDONLY 00 #define O_RDONLY 00
#define O_WRONLY 01 #define O_WRONLY 01
#define O_RDWR 02 #define O_RDWR 02
#define O_CREAT 00100 /* not fcntl */ #define O_CREAT 00100 /* not fcntl */
#define O_EXCL 00200 /* not fcntl */ #define O_EXCL 00200 /* not fcntl */
#define O_NOCTTY 00400 /* not fcntl */ #define O_NOCTTY 00400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000 #define O_APPEND 02000
#define O_NONBLOCK 04000 /* not fcntl */ #define O_NONBLOCK 04000 /* not fcntl */
#define O_NDELAY O_NONBLOCK #define O_NDELAY O_NONBLOCK
/* Defines for fcntl-commands. Note that currently /* Defines for fcntl-commands. Note that currently
* locking isn't supported, and other things aren't really * locking isn't supported, and other things aren't really
* tested. * tested.
*/ */
#define F_DUPFD 0 /* dup */ #define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */ #define F_GETFD 1 /* get f_flags */
#define F_SETFD 2 /* set f_flags */ #define F_SETFD 2 /* set f_flags */
#define F_GETFL 3 /* more flags (cloexec) */ #define F_GETFL 3 /* more flags (cloexec) */
#define F_SETFL 4 #define F_SETFL 4
#define F_GETLK 5 /* not implemented */ #define F_GETLK 5 /* not implemented */
#define F_SETLK 6 #define F_SETLK 6
#define F_SETLKW 7 #define F_SETLKW 7
/* for F_[GET|SET]FL */ /* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* Ok, these are locking features, and aren't implemented at any /* Ok, these are locking features, and aren't implemented at any
* level. POSIX wants them. * level. POSIX wants them.
*/ */
#define F_RDLCK 0 #define F_RDLCK 0
#define F_WRLCK 1 #define F_WRLCK 1
#define F_UNLCK 2 #define F_UNLCK 2
/* Once again - not implemented, but ... */ /* Once again - not implemented, but ... */
struct flock { struct flock {
short l_type; short l_type;
short l_whence; short l_whence;
off_t l_start; off_t l_start;
off_t l_len; off_t l_len;
pid_t l_pid; pid_t l_pid;
}; };
extern int creat(const char * filename,mode_t mode); extern int creat(const char * filename,mode_t mode);
extern int fcntl(int fildes,int cmd, ...); extern int fcntl(int fildes,int cmd, ...);
extern int open(const char * filename, int flags, ...); extern int open(const char * filename, int flags, ...);
#endif #endif

@ -1,48 +1,48 @@
#ifndef _CONFIG_H #ifndef _CONFIG_H
#define _CONFIG_H #define _CONFIG_H
/* /*
* The root-device is no longer hard-coded. You can change the default * The root-device is no longer hard-coded. You can change the default
* root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s * root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s
*/ */
/* /*
* define your keyboard here - * define your keyboard here -
* KBD_FINNISH for Finnish keyboards * KBD_FINNISH for Finnish keyboards
* KBD_US for US-type * KBD_US for US-type
* KBD_GR for German keyboards * KBD_GR for German keyboards
* KBD_FR for Frech keyboard * KBD_FR for Frech keyboard
*/ */
#define KBD_US #define KBD_US
/*#define KBD_GR */ /*#define KBD_GR */
/*#define KBD_FR */ /*#define KBD_FR */
/*#define KBD_FINNISH */ /*#define KBD_FINNISH */
/* /*
* Normally, Linux can get the drive parameters from the BIOS at * Normally, Linux can get the drive parameters from the BIOS at
* startup, but if this for some unfathomable reason fails, you'd * startup, but if this for some unfathomable reason fails, you'd
* be left stranded. For this case, you can define HD_TYPE, which * be left stranded. For this case, you can define HD_TYPE, which
* contains all necessary info on your harddisk. * contains all necessary info on your harddisk.
* *
* The HD_TYPE macro should look like this: * The HD_TYPE macro should look like this:
* *
* #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl} * #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl}
* *
* In case of two harddisks, the info should be sepatated by * In case of two harddisks, the info should be sepatated by
* commas: * commas:
* *
* #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl } * #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl }
*/ */
/* /*
This is an example, two drives, first is type 2, second is type 3: This is an example, two drives, first is type 2, second is type 3:
#define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 } #define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 }
NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives
with more than 8 heads. with more than 8 heads.
If you want the BIOS to tell what kind of drive you have, just If you want the BIOS to tell what kind of drive you have, just
leave HD_TYPE undefined. This is the normal thing to do. leave HD_TYPE undefined. This is the normal thing to do.
*/ */
#endif #endif

@ -1,71 +1,71 @@
/* /*
* This file contains some defines for the floppy disk controller. * This file contains some defines for the floppy disk controller.
* Various sources. Mostly "IBM Microcomputers: A Programmers * Various sources. Mostly "IBM Microcomputers: A Programmers
* Handbook", Sanches and Canton. * Handbook", Sanches and Canton.
*/ */
#ifndef _FDREG_H #ifndef _FDREG_H
#define _FDREG_H #define _FDREG_H
extern int ticks_to_floppy_on(unsigned int nr); extern int ticks_to_floppy_on(unsigned int nr);
extern void floppy_on(unsigned int nr); extern void floppy_on(unsigned int nr);
extern void floppy_off(unsigned int nr); extern void floppy_off(unsigned int nr);
extern void floppy_select(unsigned int nr); extern void floppy_select(unsigned int nr);
extern void floppy_deselect(unsigned int nr); extern void floppy_deselect(unsigned int nr);
/* Fd controller regs. S&C, about page 340 */ /* Fd controller regs. S&C, about page 340 */
#define FD_STATUS 0x3f4 #define FD_STATUS 0x3f4
#define FD_DATA 0x3f5 #define FD_DATA 0x3f5
#define FD_DOR 0x3f2 /* Digital Output Register */ #define FD_DOR 0x3f2 /* Digital Output Register */
#define FD_DIR 0x3f7 /* Digital Input Register (read) */ #define FD_DIR 0x3f7 /* Digital Input Register (read) */
#define FD_DCR 0x3f7 /* Diskette Control Register (write)*/ #define FD_DCR 0x3f7 /* Diskette Control Register (write)*/
/* Bits of main status register */ /* Bits of main status register */
#define STATUS_BUSYMASK 0x0F /* drive busy mask */ #define STATUS_BUSYMASK 0x0F /* drive busy mask */
#define STATUS_BUSY 0x10 /* FDC busy */ #define STATUS_BUSY 0x10 /* FDC busy */
#define STATUS_DMA 0x20 /* 0- DMA mode */ #define STATUS_DMA 0x20 /* 0- DMA mode */
#define STATUS_DIR 0x40 /* 0- cpu->fdc */ #define STATUS_DIR 0x40 /* 0- cpu->fdc */
#define STATUS_READY 0x80 /* Data reg ready */ #define STATUS_READY 0x80 /* Data reg ready */
/* Bits of FD_ST0 */ /* Bits of FD_ST0 */
#define ST0_DS 0x03 /* drive select mask */ #define ST0_DS 0x03 /* drive select mask */
#define ST0_HA 0x04 /* Head (Address) */ #define ST0_HA 0x04 /* Head (Address) */
#define ST0_NR 0x08 /* Not Ready */ #define ST0_NR 0x08 /* Not Ready */
#define ST0_ECE 0x10 /* Equipment chech error */ #define ST0_ECE 0x10 /* Equipment chech error */
#define ST0_SE 0x20 /* Seek end */ #define ST0_SE 0x20 /* Seek end */
#define ST0_INTR 0xC0 /* Interrupt code mask */ #define ST0_INTR 0xC0 /* Interrupt code mask */
/* Bits of FD_ST1 */ /* Bits of FD_ST1 */
#define ST1_MAM 0x01 /* Missing Address Mark */ #define ST1_MAM 0x01 /* Missing Address Mark */
#define ST1_WP 0x02 /* Write Protect */ #define ST1_WP 0x02 /* Write Protect */
#define ST1_ND 0x04 /* No Data - unreadable */ #define ST1_ND 0x04 /* No Data - unreadable */
#define ST1_OR 0x10 /* OverRun */ #define ST1_OR 0x10 /* OverRun */
#define ST1_CRC 0x20 /* CRC error in data or addr */ #define ST1_CRC 0x20 /* CRC error in data or addr */
#define ST1_EOC 0x80 /* End Of Cylinder */ #define ST1_EOC 0x80 /* End Of Cylinder */
/* Bits of FD_ST2 */ /* Bits of FD_ST2 */
#define ST2_MAM 0x01 /* Missing Addess Mark (again) */ #define ST2_MAM 0x01 /* Missing Addess Mark (again) */
#define ST2_BC 0x02 /* Bad Cylinder */ #define ST2_BC 0x02 /* Bad Cylinder */
#define ST2_SNS 0x04 /* Scan Not Satisfied */ #define ST2_SNS 0x04 /* Scan Not Satisfied */
#define ST2_SEH 0x08 /* Scan Equal Hit */ #define ST2_SEH 0x08 /* Scan Equal Hit */
#define ST2_WC 0x10 /* Wrong Cylinder */ #define ST2_WC 0x10 /* Wrong Cylinder */
#define ST2_CRC 0x20 /* CRC error in data field */ #define ST2_CRC 0x20 /* CRC error in data field */
#define ST2_CM 0x40 /* Control Mark = deleted */ #define ST2_CM 0x40 /* Control Mark = deleted */
/* Bits of FD_ST3 */ /* Bits of FD_ST3 */
#define ST3_HA 0x04 /* Head (Address) */ #define ST3_HA 0x04 /* Head (Address) */
#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */ #define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */
#define ST3_WP 0x40 /* Write Protect */ #define ST3_WP 0x40 /* Write Protect */
/* Values for FD_COMMAND */ /* Values for FD_COMMAND */
#define FD_RECALIBRATE 0x07 /* move to track 0 */ #define FD_RECALIBRATE 0x07 /* move to track 0 */
#define FD_SEEK 0x0F /* seek track */ #define FD_SEEK 0x0F /* seek track */
#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */ #define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */
#define FD_WRITE 0xC5 /* write with MT, MFM */ #define FD_WRITE 0xC5 /* write with MT, MFM */
#define FD_SENSEI 0x08 /* Sense Interrupt Status */ #define FD_SENSEI 0x08 /* Sense Interrupt Status */
#define FD_SPECIFY 0x03 /* specify HUT etc */ #define FD_SPECIFY 0x03 /* specify HUT etc */
/* DMA commands */ /* DMA commands */
#define DMA_READ 0x46 #define DMA_READ 0x46
#define DMA_WRITE 0x4A #define DMA_WRITE 0x4A
#endif #endif

@ -1,202 +1,202 @@
/* /*
* This file has definitions for some important file table * This file has definitions for some important file table
* structures etc. * structures etc.
*/ */
#ifndef _FS_H #ifndef _FS_H
#define _FS_H #define _FS_H
#include <sys/types.h> #include <sys/types.h>
/* devices are as follows: (same as minix, so we can use the minix /* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.) * file system. These are major numbers.)
* *
* 0 - unused (nodev) * 0 - unused (nodev)
* 1 - /dev/mem * 1 - /dev/mem
* 2 - /dev/fd * 2 - /dev/fd
* 3 - /dev/hd * 3 - /dev/hd
* 4 - /dev/ttyx * 4 - /dev/ttyx
* 5 - /dev/tty * 5 - /dev/tty
* 6 - /dev/lp * 6 - /dev/lp
* 7 - unnamed pipes * 7 - unnamed pipes
*/ */
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3) #define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define READ 0 #define READ 0
#define WRITE 1 #define WRITE 1
#define READA 2 /* read-ahead - don't pause */ #define READA 2 /* read-ahead - don't pause */
#define WRITEA 3 /* "write-ahead" - silly, but somewhat useful */ #define WRITEA 3 /* "write-ahead" - silly, but somewhat useful */
void buffer_init(long buffer_end); void buffer_init(long buffer_end);
#define MAJOR(a) (((unsigned)(a))>>8) #define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff) #define MINOR(a) ((a)&0xff)
#define NAME_LEN 14 #define NAME_LEN 14
#define ROOT_INO 1 #define ROOT_INO 1
#define I_MAP_SLOTS 8 #define I_MAP_SLOTS 8
#define Z_MAP_SLOTS 8 #define Z_MAP_SLOTS 8
#define SUPER_MAGIC 0x137F #define SUPER_MAGIC 0x137F
#define NR_OPEN 20 #define NR_OPEN 20
#define NR_INODE 32 #define NR_INODE 32
#define NR_FILE 64 #define NR_FILE 64
#define NR_SUPER 8 #define NR_SUPER 8
#define NR_HASH 307 #define NR_HASH 307
#define NR_BUFFERS nr_buffers #define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024 #define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10 #define BLOCK_SIZE_BITS 10
#ifndef NULL #ifndef NULL
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode))) #define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry))) #define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))
#define PIPE_HEAD(inode) ((inode).i_zone[0]) #define PIPE_HEAD(inode) ((inode).i_zone[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1]) #define PIPE_TAIL(inode) ((inode).i_zone[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1)) #define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode)) #define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1)) #define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#define INC_PIPE(head) \ #define INC_PIPE(head) \
__asm__("incl %0\n\tandl $4095,%0"::"m" (head)) __asm__("incl %0\n\tandl $4095,%0"::"m" (head))
typedef char buffer_block[BLOCK_SIZE]; typedef char buffer_block[BLOCK_SIZE];
struct buffer_head { struct buffer_head {
char * b_data; /* pointer to data block (1024 bytes) */ char * b_data; /* pointer to data block (1024 bytes) */
unsigned long b_blocknr; /* block number */ unsigned long b_blocknr; /* block number */
unsigned short b_dev; /* device (0 = free) */ unsigned short b_dev; /* device (0 = free) */
unsigned char b_uptodate; unsigned char b_uptodate;
unsigned char b_dirt; /* 0-clean,1-dirty */ unsigned char b_dirt; /* 0-clean,1-dirty */
unsigned char b_count; /* users using this block */ unsigned char b_count; /* users using this block */
unsigned char b_lock; /* 0 - ok, 1 -locked */ unsigned char b_lock; /* 0 - ok, 1 -locked */
struct task_struct * b_wait; struct task_struct * b_wait;
struct buffer_head * b_prev; struct buffer_head * b_prev;
struct buffer_head * b_next; struct buffer_head * b_next;
struct buffer_head * b_prev_free; struct buffer_head * b_prev_free;
struct buffer_head * b_next_free; struct buffer_head * b_next_free;
}; };
struct d_inode { struct d_inode {
unsigned short i_mode; unsigned short i_mode;
unsigned short i_uid; unsigned short i_uid;
unsigned long i_size; unsigned long i_size;
unsigned long i_time; unsigned long i_time;
unsigned char i_gid; unsigned char i_gid;
unsigned char i_nlinks; unsigned char i_nlinks;
unsigned short i_zone[9]; unsigned short i_zone[9];
}; };
struct m_inode { struct m_inode {
unsigned short i_mode; unsigned short i_mode;
unsigned short i_uid; unsigned short i_uid;
unsigned long i_size; unsigned long i_size;
unsigned long i_mtime; unsigned long i_mtime;
unsigned char i_gid; unsigned char i_gid;
unsigned char i_nlinks; unsigned char i_nlinks;
unsigned short i_zone[9]; unsigned short i_zone[9];
/* these are in memory also */ /* these are in memory also */
struct task_struct * i_wait; struct task_struct * i_wait;
unsigned long i_atime; unsigned long i_atime;
unsigned long i_ctime; unsigned long i_ctime;
unsigned short i_dev; unsigned short i_dev;
unsigned short i_num; unsigned short i_num;
unsigned short i_count; unsigned short i_count;
unsigned char i_lock; unsigned char i_lock;
unsigned char i_dirt; unsigned char i_dirt;
unsigned char i_pipe; unsigned char i_pipe;
unsigned char i_mount; unsigned char i_mount;
unsigned char i_seek; unsigned char i_seek;
unsigned char i_update; unsigned char i_update;
}; };
struct file { struct file {
unsigned short f_mode; unsigned short f_mode;
unsigned short f_flags; unsigned short f_flags;
unsigned short f_count; unsigned short f_count;
struct m_inode * f_inode; struct m_inode * f_inode;
off_t f_pos; off_t f_pos;
}; };
struct super_block { struct super_block {
unsigned short s_ninodes; unsigned short s_ninodes;
unsigned short s_nzones; unsigned short s_nzones;
unsigned short s_imap_blocks; unsigned short s_imap_blocks;
unsigned short s_zmap_blocks; unsigned short s_zmap_blocks;
unsigned short s_firstdatazone; unsigned short s_firstdatazone;
unsigned short s_log_zone_size; unsigned short s_log_zone_size;
unsigned long s_max_size; unsigned long s_max_size;
unsigned short s_magic; unsigned short s_magic;
/* These are only in memory */ /* These are only in memory */
struct buffer_head * s_imap[8]; struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8]; struct buffer_head * s_zmap[8];
unsigned short s_dev; unsigned short s_dev;
struct m_inode * s_isup; struct m_inode * s_isup;
struct m_inode * s_imount; struct m_inode * s_imount;
unsigned long s_time; unsigned long s_time;
struct task_struct * s_wait; struct task_struct * s_wait;
unsigned char s_lock; unsigned char s_lock;
unsigned char s_rd_only; unsigned char s_rd_only;
unsigned char s_dirt; unsigned char s_dirt;
}; };
struct d_super_block { struct d_super_block {
unsigned short s_ninodes; unsigned short s_ninodes;
unsigned short s_nzones; unsigned short s_nzones;
unsigned short s_imap_blocks; unsigned short s_imap_blocks;
unsigned short s_zmap_blocks; unsigned short s_zmap_blocks;
unsigned short s_firstdatazone; unsigned short s_firstdatazone;
unsigned short s_log_zone_size; unsigned short s_log_zone_size;
unsigned long s_max_size; unsigned long s_max_size;
unsigned short s_magic; unsigned short s_magic;
}; };
struct dir_entry { struct dir_entry {
unsigned short inode; unsigned short inode;
char name[NAME_LEN]; char name[NAME_LEN];
}; };
extern struct m_inode inode_table[NR_INODE]; extern struct m_inode inode_table[NR_INODE];
extern struct file file_table[NR_FILE]; extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER]; extern struct super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer; extern struct buffer_head * start_buffer;
extern int nr_buffers; extern int nr_buffers;
extern void check_disk_change(int dev); extern void check_disk_change(int dev);
extern int floppy_change(unsigned int nr); extern int floppy_change(unsigned int nr);
extern int ticks_to_floppy_on(unsigned int dev); extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev); extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev); extern void floppy_off(unsigned int dev);
extern void truncate(struct m_inode * inode); extern void truncate(struct m_inode * inode);
extern void sync_inodes(void); extern void sync_inodes(void);
extern void wait_on(struct m_inode * inode); extern void wait_on(struct m_inode * inode);
extern int bmap(struct m_inode * inode,int block); extern int bmap(struct m_inode * inode,int block);
extern int create_block(struct m_inode * inode,int block); extern int create_block(struct m_inode * inode,int block);
extern struct m_inode * namei(const char * pathname); extern struct m_inode * namei(const char * pathname);
extern int open_namei(const char * pathname, int flag, int mode, extern int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode); struct m_inode ** res_inode);
extern void iput(struct m_inode * inode); extern void iput(struct m_inode * inode);
extern struct m_inode * iget(int dev,int nr); extern struct m_inode * iget(int dev,int nr);
extern struct m_inode * get_empty_inode(void); extern struct m_inode * get_empty_inode(void);
extern struct m_inode * get_pipe_inode(void); extern struct m_inode * get_pipe_inode(void);
extern struct buffer_head * get_hash_table(int dev, int block); extern struct buffer_head * get_hash_table(int dev, int block);
extern struct buffer_head * getblk(int dev, int block); extern struct buffer_head * getblk(int dev, int block);
extern void ll_rw_block(int rw, struct buffer_head * bh); extern void ll_rw_block(int rw, struct buffer_head * bh);
extern void brelse(struct buffer_head * buf); extern void brelse(struct buffer_head * buf);
extern struct buffer_head * bread(int dev,int block); extern struct buffer_head * bread(int dev,int block);
extern void bread_page(unsigned long addr,int dev,int b[4]); extern void bread_page(unsigned long addr,int dev,int b[4]);
extern struct buffer_head * breada(int dev,int block,...); extern struct buffer_head * breada(int dev,int block,...);
extern int new_block(int dev); extern int new_block(int dev);
extern void free_block(int dev, int block); extern void free_block(int dev, int block);
extern struct m_inode * new_inode(int dev); extern struct m_inode * new_inode(int dev);
extern void free_inode(struct m_inode * inode); extern void free_inode(struct m_inode * inode);
extern int sync_dev(int dev); extern int sync_dev(int dev);
extern struct super_block * get_super(int dev); extern struct super_block * get_super(int dev);
extern int ROOT_DEV; extern int ROOT_DEV;
extern void mount_root(void); extern void mount_root(void);
#endif #endif

@ -1,65 +1,65 @@
/* /*
* This file contains some defines for the AT-hd-controller. * This file contains some defines for the AT-hd-controller.
* Various sources. Check out some definitions (see comments with * Various sources. Check out some definitions (see comments with
* a ques). * a ques).
*/ */
#ifndef _HDREG_H #ifndef _HDREG_H
#define _HDREG_H #define _HDREG_H
/* Hd controller regs. Ref: IBM AT Bios-listing */ /* Hd controller regs. Ref: IBM AT Bios-listing */
#define HD_DATA 0x1f0 /* _CTL when writing */ #define HD_DATA 0x1f0 /* _CTL when writing */
#define HD_ERROR 0x1f1 /* see err-bits */ #define HD_ERROR 0x1f1 /* see err-bits */
#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ #define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
#define HD_SECTOR 0x1f3 /* starting sector */ #define HD_SECTOR 0x1f3 /* starting sector */
#define HD_LCYL 0x1f4 /* starting cylinder */ #define HD_LCYL 0x1f4 /* starting cylinder */
#define HD_HCYL 0x1f5 /* high byte of starting cyl */ #define HD_HCYL 0x1f5 /* high byte of starting cyl */
#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ #define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
#define HD_STATUS 0x1f7 /* see status-bits */ #define HD_STATUS 0x1f7 /* see status-bits */
#define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */ #define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */
#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ #define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
#define HD_CMD 0x3f6 #define HD_CMD 0x3f6
/* Bits of HD_STATUS */ /* Bits of HD_STATUS */
#define ERR_STAT 0x01 #define ERR_STAT 0x01
#define INDEX_STAT 0x02 #define INDEX_STAT 0x02
#define ECC_STAT 0x04 /* Corrected error */ #define ECC_STAT 0x04 /* Corrected error */
#define DRQ_STAT 0x08 #define DRQ_STAT 0x08
#define SEEK_STAT 0x10 #define SEEK_STAT 0x10
#define WRERR_STAT 0x20 #define WRERR_STAT 0x20
#define READY_STAT 0x40 #define READY_STAT 0x40
#define BUSY_STAT 0x80 #define BUSY_STAT 0x80
/* Values for HD_COMMAND */ /* Values for HD_COMMAND */
#define WIN_RESTORE 0x10 #define WIN_RESTORE 0x10
#define WIN_READ 0x20 #define WIN_READ 0x20
#define WIN_WRITE 0x30 #define WIN_WRITE 0x30
#define WIN_VERIFY 0x40 #define WIN_VERIFY 0x40
#define WIN_FORMAT 0x50 #define WIN_FORMAT 0x50
#define WIN_INIT 0x60 #define WIN_INIT 0x60
#define WIN_SEEK 0x70 #define WIN_SEEK 0x70
#define WIN_DIAGNOSE 0x90 #define WIN_DIAGNOSE 0x90
#define WIN_SPECIFY 0x91 #define WIN_SPECIFY 0x91
/* Bits for HD_ERROR */ /* Bits for HD_ERROR */
#define MARK_ERR 0x01 /* Bad address mark ? */ #define MARK_ERR 0x01 /* Bad address mark ? */
#define TRK0_ERR 0x02 /* couldn't find track 0 */ #define TRK0_ERR 0x02 /* couldn't find track 0 */
#define ABRT_ERR 0x04 /* ? */ #define ABRT_ERR 0x04 /* ? */
#define ID_ERR 0x10 /* ? */ #define ID_ERR 0x10 /* ? */
#define ECC_ERR 0x40 /* ? */ #define ECC_ERR 0x40 /* ? */
#define BBD_ERR 0x80 /* ? */ #define BBD_ERR 0x80 /* ? */
struct partition { struct partition {
unsigned char boot_ind; /* 0x80 - active (unused) */ unsigned char boot_ind; /* 0x80 - active (unused) */
unsigned char head; /* ? */ unsigned char head; /* ? */
unsigned char sector; /* ? */ unsigned char sector; /* ? */
unsigned char cyl; /* ? */ unsigned char cyl; /* ? */
unsigned char sys_ind; /* ? */ unsigned char sys_ind; /* ? */
unsigned char end_head; /* ? */ unsigned char end_head; /* ? */
unsigned char end_sector; /* ? */ unsigned char end_sector; /* ? */
unsigned char end_cyl; /* ? */ unsigned char end_cyl; /* ? */
unsigned int start_sect; /* starting sector counting from 0 */ unsigned int start_sect; /* starting sector counting from 0 */
unsigned int nr_sects; /* nr of sectors in partition */ unsigned int nr_sects; /* nr of sectors in partition */
}; };
#endif #endif

@ -1,20 +1,20 @@
#ifndef _HEAD_H #ifndef _HEAD_H
#define _HEAD_H #define _HEAD_H
typedef struct desc_struct { typedef struct desc_struct {
unsigned long a,b; unsigned long a,b;
} desc_table[256]; } desc_table[256];
extern unsigned long pg_dir[1024]; extern unsigned long pg_dir[1024];
extern desc_table idt,gdt; extern desc_table idt,gdt;
#define GDT_NUL 0 #define GDT_NUL 0
#define GDT_CODE 1 #define GDT_CODE 1
#define GDT_DATA 2 #define GDT_DATA 2
#define GDT_TMP 3 #define GDT_TMP 3
#define LDT_NUL 0 #define LDT_NUL 0
#define LDT_CODE 1 #define LDT_CODE 1
#define LDT_DATA 2 #define LDT_DATA 2
#endif #endif

@ -1,22 +1,22 @@
/* /*
* 'kernel.h' contains some often-used function prototypes etc * 'kernel.h' contains some often-used function prototypes etc
*/ */
void verify_area(void * addr,int count); void verify_area(void * addr,int count);
volatile void panic(const char * str); volatile void panic(const char * str);
int printf(const char * fmt, ...); int printf(const char * fmt, ...);
int printk(const char * fmt, ...); int printk(const char * fmt, ...);
int tty_write(unsigned ch,char * buf,int count); int tty_write(unsigned ch,char * buf,int count);
void * malloc(unsigned int size); void * malloc(unsigned int size);
void free_s(void * obj, int size); void free_s(void * obj, int size);
#define free(x) free_s((x), 0) #define free(x) free_s((x), 0)
/* /*
* This is defined as a macro, but at some point this might become a * This is defined as a macro, but at some point this might become a
* real subroutine that sets a flag if it returns true (to do * real subroutine that sets a flag if it returns true (to do
* BSD-style accounting where the process is flagged if it uses root * BSD-style accounting where the process is flagged if it uses root
* privs). The implication of this is that you should do normal * privs). The implication of this is that you should do normal
* permissions checks first, and check suser() last. * permissions checks first, and check suser() last.
*/ */
#define suser() (current->euid == 0) #define suser() (current->euid == 0)

@ -1,10 +1,10 @@
#ifndef _MM_H #ifndef _MM_H
#define _MM_H #define _MM_H
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
extern unsigned long get_free_page(void); extern unsigned long get_free_page(void);
extern unsigned long put_page(unsigned long page,unsigned long address); extern unsigned long put_page(unsigned long page,unsigned long address);
extern void free_page(unsigned long addr); extern void free_page(unsigned long addr);
#endif #endif

@ -1,239 +1,239 @@
#ifndef _SCHED_H #ifndef _SCHED_H
#define _SCHED_H #define _SCHED_H
#define NR_TASKS 64 #define NR_TASKS 64
#define HZ 100 #define HZ 100
#define FIRST_TASK task[0] #define FIRST_TASK task[0]
#define LAST_TASK task[NR_TASKS-1] #define LAST_TASK task[NR_TASKS-1]
#include <linux/head.h> #include <linux/head.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <signal.h> #include <signal.h>
#if (NR_OPEN > 32) #if (NR_OPEN > 32)
#error "Currently the close-on-exec-flags are in one word, max 32 files/proc" #error "Currently the close-on-exec-flags are in one word, max 32 files/proc"
#endif #endif
#define TASK_RUNNING 0 #define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1 #define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2 #define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3 #define TASK_ZOMBIE 3
#define TASK_STOPPED 4 #define TASK_STOPPED 4
#ifndef NULL #ifndef NULL
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
extern int copy_page_tables(unsigned long from, unsigned long to, long size); extern int copy_page_tables(unsigned long from, unsigned long to, long size);
extern int free_page_tables(unsigned long from, unsigned long size); extern int free_page_tables(unsigned long from, unsigned long size);
extern void sched_init(void); extern void sched_init(void);
extern void schedule(void); extern void schedule(void);
extern void trap_init(void); extern void trap_init(void);
extern void panic(const char * str); extern void panic(const char * str);
extern int tty_write(unsigned minor,char * buf,int count); extern int tty_write(unsigned minor,char * buf,int count);
typedef int (*fn_ptr)(); typedef int (*fn_ptr)();
struct i387_struct { struct i387_struct {
long cwd; long cwd;
long swd; long swd;
long twd; long twd;
long fip; long fip;
long fcs; long fcs;
long foo; long foo;
long fos; long fos;
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
}; };
struct tss_struct { struct tss_struct {
long back_link; /* 16 high bits zero */ long back_link; /* 16 high bits zero */
long esp0; long esp0;
long ss0; /* 16 high bits zero */ long ss0; /* 16 high bits zero */
long esp1; long esp1;
long ss1; /* 16 high bits zero */ long ss1; /* 16 high bits zero */
long esp2; long esp2;
long ss2; /* 16 high bits zero */ long ss2; /* 16 high bits zero */
long cr3; long cr3;
long eip; long eip;
long eflags; long eflags;
long eax,ecx,edx,ebx; long eax,ecx,edx,ebx;
long esp; long esp;
long ebp; long ebp;
long esi; long esi;
long edi; long edi;
long es; /* 16 high bits zero */ long es; /* 16 high bits zero */
long cs; /* 16 high bits zero */ long cs; /* 16 high bits zero */
long ss; /* 16 high bits zero */ long ss; /* 16 high bits zero */
long ds; /* 16 high bits zero */ long ds; /* 16 high bits zero */
long fs; /* 16 high bits zero */ long fs; /* 16 high bits zero */
long gs; /* 16 high bits zero */ long gs; /* 16 high bits zero */
long ldt; /* 16 high bits zero */ long ldt; /* 16 high bits zero */
long trace_bitmap; /* bits: trace 0, bitmap 16-31 */ long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
struct i387_struct i387; struct i387_struct i387;
}; };
struct task_struct { struct task_struct {
/* these are hardcoded - don't touch */ /* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */ long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter; long counter;
long priority; long priority;
long signal; long signal;
struct sigaction sigaction[32]; struct sigaction sigaction[32];
long blocked; /* bitmap of masked signals */ long blocked; /* bitmap of masked signals */
/* various fields */ /* various fields */
int exit_code; int exit_code;
unsigned long start_code,end_code,end_data,brk,start_stack; unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,father,pgrp,session,leader; long pid,father,pgrp,session,leader;
unsigned short uid,euid,suid; unsigned short uid,euid,suid;
unsigned short gid,egid,sgid; unsigned short gid,egid,sgid;
long alarm; long alarm;
long utime,stime,cutime,cstime,start_time; long utime,stime,cutime,cstime,start_time;
unsigned short used_math; unsigned short used_math;
/* file system info */ /* file system info */
int tty; /* -1 if no tty, so it must be signed */ int tty; /* -1 if no tty, so it must be signed */
unsigned short umask; unsigned short umask;
struct m_inode * pwd; struct m_inode * pwd;
struct m_inode * root; struct m_inode * root;
struct m_inode * executable; struct m_inode * executable;
unsigned long close_on_exec; unsigned long close_on_exec;
struct file * filp[NR_OPEN]; struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */ /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
struct desc_struct ldt[3]; struct desc_struct ldt[3];
/* tss for this task */ /* tss for this task */
struct tss_struct tss; struct tss_struct tss;
}; };
/* /*
* INIT_TASK is used to set up the first task table, touch at * INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x9ffff (=640kB) * your own risk!. Base=0, limit=0x9ffff (=640kB)
*/ */
#define INIT_TASK \ #define INIT_TASK \
/* state etc */ { 0,15,15, \ /* state etc */ { 0,15,15, \
/* signals */ 0,{{},},0, \ /* signals */ 0,{{},},0, \
/* ec,brk... */ 0,0,0,0,0,0, \ /* ec,brk... */ 0,0,0,0,0,0, \
/* pid etc.. */ 0,-1,0,0,0, \ /* pid etc.. */ 0,-1,0,0,0, \
/* uid etc */ 0,0,0,0,0,0, \ /* uid etc */ 0,0,0,0,0,0, \
/* alarm */ 0,0,0,0,0,0, \ /* alarm */ 0,0,0,0,0,0, \
/* math */ 0, \ /* math */ 0, \
/* fs info */ -1,0022,NULL,NULL,NULL,0, \ /* fs info */ -1,0022,NULL,NULL,NULL,0, \
/* filp */ {NULL,}, \ /* filp */ {NULL,}, \
{ \ { \
{0,0}, \ {0,0}, \
/* ldt */ {0x9f,0xc0fa00}, \ /* ldt */ {0x9f,0xc0fa00}, \
{0x9f,0xc0f200}, \ {0x9f,0xc0f200}, \
}, \ }, \
/*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\ /*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
0,0,0,0,0,0,0,0, \ 0,0,0,0,0,0,0,0, \
0,0,0x17,0x17,0x17,0x17,0x17,0x17, \ 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
_LDT(0),0x80000000, \ _LDT(0),0x80000000, \
{} \ {} \
}, \ }, \
} }
extern struct task_struct *task[NR_TASKS]; extern struct task_struct *task[NR_TASKS];
extern struct task_struct *last_task_used_math; extern struct task_struct *last_task_used_math;
extern struct task_struct *current; extern struct task_struct *current;
extern long volatile jiffies; extern long volatile jiffies;
extern long startup_time; extern long startup_time;
#define CURRENT_TIME (startup_time+jiffies/HZ) #define CURRENT_TIME (startup_time+jiffies/HZ)
extern void add_timer(long jiffies, void (*fn)(void)); extern void add_timer(long jiffies, void (*fn)(void));
extern void sleep_on(struct task_struct ** p); extern void sleep_on(struct task_struct ** p);
extern void interruptible_sleep_on(struct task_struct ** p); extern void interruptible_sleep_on(struct task_struct ** p);
extern void wake_up(struct task_struct ** p); extern void wake_up(struct task_struct ** p);
/* /*
* Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
* 4-TSS0, 5-LDT0, 6-TSS1 etc ... * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
*/ */
#define FIRST_TSS_ENTRY 4 #define FIRST_TSS_ENTRY 4
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1) #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3)) #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n))) #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
#define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n))) #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
#define str(n) \ #define str(n) \
__asm__("str %%ax\n\t" \ __asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \ "subl %2,%%eax\n\t" \
"shrl $4,%%eax" \ "shrl $4,%%eax" \
:"=a" (n) \ :"=a" (n) \
:"a" (0),"i" (FIRST_TSS_ENTRY<<3)) :"a" (0),"i" (FIRST_TSS_ENTRY<<3))
/* /*
* switch_to(n) should switch tasks to task nr n, first * switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing. * checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used * This also clears the TS-flag if the task we switched to has used
* tha math co-processor latest. * tha math co-processor latest.
*/ */
#define switch_to(n) {\ #define switch_to(n) {\
struct {long a,b;} __tmp; \ struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,current\n\t" \ __asm__("cmpl %%ecx,current\n\t" \
"je 1f\n\t" \ "je 1f\n\t" \
"movw %%dx,%1\n\t" \ "movw %%dx,%1\n\t" \
"xchgl %%ecx,current\n\t" \ "xchgl %%ecx,current\n\t" \
"ljmp *%0\n\t" \ "ljmp *%0\n\t" \
"cmpl %%ecx,last_task_used_math\n\t" \ "cmpl %%ecx,last_task_used_math\n\t" \
"jne 1f\n\t" \ "jne 1f\n\t" \
"clts\n" \ "clts\n" \
"1:" \ "1:" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"d" (_TSS(n)),"c" ((long) task[n])); \ "d" (_TSS(n)),"c" ((long) task[n])); \
} }
#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000) #define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
#define _set_base(addr,base) \ #define _set_base(addr,base) \
__asm__ ("push %%edx\n\t" \ __asm__ ("push %%edx\n\t" \
"movw %%dx,%0\n\t" \ "movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \ "rorl $16,%%edx\n\t" \
"movb %%dl,%1\n\t" \ "movb %%dl,%1\n\t" \
"movb %%dh,%2\n\t" \ "movb %%dh,%2\n\t" \
"pop %%edx" \ "pop %%edx" \
::"m" (*((addr)+2)), \ ::"m" (*((addr)+2)), \
"m" (*((addr)+4)), \ "m" (*((addr)+4)), \
"m" (*((addr)+7)), \ "m" (*((addr)+7)), \
"d" (base) \ "d" (base) \
) )
#define _set_limit(addr,limit) \ #define _set_limit(addr,limit) \
__asm__ ("push %%edx\n\t" \ __asm__ ("push %%edx\n\t" \
"movw %%dx,%0\n\t" \ "movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \ "rorl $16,%%edx\n\t" \
"movb %1,%%dh\n\t" \ "movb %1,%%dh\n\t" \
"andb $0xf0,%%dh\n\t" \ "andb $0xf0,%%dh\n\t" \
"orb %%dh,%%dl\n\t" \ "orb %%dh,%%dl\n\t" \
"movb %%dl,%1\n\t" \ "movb %%dl,%1\n\t" \
"pop %%edx" \ "pop %%edx" \
::"m" (*(addr)), \ ::"m" (*(addr)), \
"m" (*((addr)+6)), \ "m" (*((addr)+6)), \
"d" (limit) \ "d" (limit) \
) )
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) ) #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
static inline unsigned long _get_base(char * addr) static inline unsigned long _get_base(char * addr)
{ {
unsigned long __base; unsigned long __base;
__asm__("movb %3,%%dh\n\t" __asm__("movb %3,%%dh\n\t"
"movb %2,%%dl\n\t" "movb %2,%%dl\n\t"
"shll $16,%%edx\n\t" "shll $16,%%edx\n\t"
"movw %1,%%dx" "movw %1,%%dx"
:"=&d" (__base) :"=&d" (__base)
:"m" (*((addr)+2)), :"m" (*((addr)+2)),
"m" (*((addr)+4)), "m" (*((addr)+4)),
"m" (*((addr)+7))); "m" (*((addr)+7)));
return __base; return __base;
} }
#define get_base(ldt) _get_base( ((char *)&(ldt)) ) #define get_base(ldt) _get_base( ((char *)&(ldt)) )
#define get_limit(segment) ({ \ #define get_limit(segment) ({ \
unsigned long __limit; \ unsigned long __limit; \
__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \ __asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
__limit;}) __limit;})
#endif #endif

@ -1,111 +1,111 @@
/* /*
* Why isn't this a .c file? Enquiring minds.... * Why isn't this a .c file? Enquiring minds....
*/ */
extern int sys_setup(); extern int sys_setup();
extern int sys_exit(); extern int sys_exit();
extern int sys_fork(); extern int sys_fork();
extern int sys_read(); extern int sys_read();
extern int sys_write(); extern int sys_write();
extern int sys_open(); extern int sys_open();
extern int sys_close(); extern int sys_close();
extern int sys_waitpid(); extern int sys_waitpid();
extern int sys_creat(); extern int sys_creat();
extern int sys_link(); extern int sys_link();
extern int sys_unlink(); extern int sys_unlink();
extern int sys_execve(); extern int sys_execve();
extern int sys_chdir(); extern int sys_chdir();
extern int sys_time(); extern int sys_time();
extern int sys_mknod(); extern int sys_mknod();
extern int sys_chmod(); extern int sys_chmod();
extern int sys_chown(); extern int sys_chown();
extern int sys_break(); extern int sys_break();
extern int sys_stat(); extern int sys_stat();
extern int sys_lseek(); extern int sys_lseek();
extern int sys_getpid(); extern int sys_getpid();
extern int sys_mount(); extern int sys_mount();
extern int sys_umount(); extern int sys_umount();
extern int sys_setuid(); extern int sys_setuid();
extern int sys_getuid(); extern int sys_getuid();
extern int sys_stime(); extern int sys_stime();
extern int sys_ptrace(); extern int sys_ptrace();
extern int sys_alarm(); extern int sys_alarm();
extern int sys_fstat(); extern int sys_fstat();
extern int sys_pause(); extern int sys_pause();
extern int sys_utime(); extern int sys_utime();
extern int sys_stty(); extern int sys_stty();
extern int sys_gtty(); extern int sys_gtty();
extern int sys_access(); extern int sys_access();
extern int sys_nice(); extern int sys_nice();
extern int sys_ftime(); extern int sys_ftime();
extern int sys_sync(); extern int sys_sync();
extern int sys_kill(); extern int sys_kill();
extern int sys_rename(); extern int sys_rename();
extern int sys_mkdir(); extern int sys_mkdir();
extern int sys_rmdir(); extern int sys_rmdir();
extern int sys_dup(); extern int sys_dup();
extern int sys_pipe(); extern int sys_pipe();
extern int sys_times(); extern int sys_times();
extern int sys_prof(); extern int sys_prof();
extern int sys_brk(); extern int sys_brk();
extern int sys_setgid(); extern int sys_setgid();
extern int sys_getgid(); extern int sys_getgid();
extern int sys_signal(); extern int sys_signal();
extern int sys_geteuid(); extern int sys_geteuid();
extern int sys_getegid(); extern int sys_getegid();
extern int sys_acct(); extern int sys_acct();
extern int sys_phys(); extern int sys_phys();
extern int sys_lock(); extern int sys_lock();
extern int sys_ioctl(); extern int sys_ioctl();
extern int sys_fcntl(); extern int sys_fcntl();
extern int sys_mpx(); extern int sys_mpx();
extern int sys_setpgid(); extern int sys_setpgid();
extern int sys_ulimit(); extern int sys_ulimit();
extern int sys_uname(); extern int sys_uname();
extern int sys_umask(); extern int sys_umask();
extern int sys_chroot(); extern int sys_chroot();
extern int sys_ustat(); extern int sys_ustat();
extern int sys_dup2(); extern int sys_dup2();
extern int sys_getppid(); extern int sys_getppid();
extern int sys_getpgrp(); extern int sys_getpgrp();
extern int sys_setsid(); extern int sys_setsid();
extern int sys_sigaction(); extern int sys_sigaction();
extern int sys_sgetmask(); extern int sys_sgetmask();
extern int sys_ssetmask(); extern int sys_ssetmask();
extern int sys_setreuid(); extern int sys_setreuid();
extern int sys_setregid(); extern int sys_setregid();
extern int sys_sigpending(); extern int sys_sigpending();
extern int sys_sigsuspend(); extern int sys_sigsuspend();
extern int sys_sethostname(); extern int sys_sethostname();
extern int sys_setrlimit(); extern int sys_setrlimit();
extern int sys_getrlimit(); extern int sys_getrlimit();
extern int sys_getrusage(); extern int sys_getrusage();
extern int sys_gettimeofday(); extern int sys_gettimeofday();
extern int sys_settimeofday(); extern int sys_settimeofday();
extern int sys_getgroups(); extern int sys_getgroups();
extern int sys_setgroups(); extern int sys_setgroups();
extern int sys_select(); extern int sys_select();
extern int sys_symlink(); extern int sys_symlink();
extern int sys_lstat(); extern int sys_lstat();
extern int sys_readlink(); extern int sys_readlink();
extern int sys_uselib(); extern int sys_uselib();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod, sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount, sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm, sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access, sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir, sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid, sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys, sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit, sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid, sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask, sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname, sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday, sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink, sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
sys_lstat, sys_readlink, sys_uselib }; sys_lstat, sys_readlink, sys_uselib };
/* So we don't have to do any more manual updating.... */ /* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);

@ -1,77 +1,77 @@
/* /*
* 'tty.h' defines some structures used by tty_io.c and some defines. * 'tty.h' defines some structures used by tty_io.c and some defines.
* *
* NOTE! Don't touch this without checking that nothing in rs_io.s or * NOTE! Don't touch this without checking that nothing in rs_io.s or
* con_io.s breaks. Some constants are hardwired into the system (mainly * con_io.s breaks. Some constants are hardwired into the system (mainly
* offsets into 'tty_queue' * offsets into 'tty_queue'
*/ */
#ifndef _TTY_H #ifndef _TTY_H
#define _TTY_H #define _TTY_H
#include <termios.h> #include <termios.h>
#define TTY_BUF_SIZE 1024 #define TTY_BUF_SIZE 1024
struct tty_queue { struct tty_queue {
unsigned long data; unsigned long data;
unsigned long head; unsigned long head;
unsigned long tail; unsigned long tail;
struct task_struct * proc_list; struct task_struct * proc_list;
char buf[TTY_BUF_SIZE]; char buf[TTY_BUF_SIZE];
}; };
#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1)) #define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1)) #define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a) ((a).head == (a).tail) #define EMPTY(a) ((a).head == (a).tail)
#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1)) #define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))
#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)]) #define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])
#define FULL(a) (!LEFT(a)) #define FULL(a) (!LEFT(a))
#define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1)) #define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))
#define GETCH(queue,c) \ #define GETCH(queue,c) \
(void)({c=(queue).buf[(queue).tail];INC((queue).tail);}) (void)({c=(queue).buf[(queue).tail];INC((queue).tail);})
#define PUTCH(c,queue) \ #define PUTCH(c,queue) \
(void)({(queue).buf[(queue).head]=(c);INC((queue).head);}) (void)({(queue).buf[(queue).head]=(c);INC((queue).head);})
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR]) #define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT]) #define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE]) #define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
#define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL]) #define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL])
#define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF]) #define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])
#define START_CHAR(tty) ((tty)->termios.c_cc[VSTART]) #define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])
#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP]) #define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
#define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP]) #define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP])
struct tty_struct { struct tty_struct {
struct termios termios; struct termios termios;
int pgrp; int pgrp;
int stopped; int stopped;
void (*write)(struct tty_struct * tty); void (*write)(struct tty_struct * tty);
struct tty_queue read_q; struct tty_queue read_q;
struct tty_queue write_q; struct tty_queue write_q;
struct tty_queue secondary; struct tty_queue secondary;
}; };
extern struct tty_struct tty_table[]; extern struct tty_struct tty_table[];
/* intr=^C quit=^| erase=del kill=^U /* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0 eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Z eol=\0 start=^Q stop=^S susp=^Z eol=\0
reprint=^R discard=^U werase=^W lnext=^V reprint=^R discard=^U werase=^W lnext=^V
eol2=\0 eol2=\0
*/ */
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
void rs_init(void); void rs_init(void);
void con_init(void); void con_init(void);
void tty_init(void); void tty_init(void);
int tty_read(unsigned c, char * buf, int n); int tty_read(unsigned c, char * buf, int n);
int tty_write(unsigned c, char * buf, int n); int tty_write(unsigned c, char * buf, int n);
void rs_write(struct tty_struct * tty); void rs_write(struct tty_struct * tty);
void con_write(struct tty_struct * tty); void con_write(struct tty_struct * tty);
void copy_to_cooked(struct tty_struct * tty); void copy_to_cooked(struct tty_struct * tty);
#endif #endif

@ -1,68 +1,68 @@
#ifndef _SIGNAL_H #ifndef _SIGNAL_H
#define _SIGNAL_H #define _SIGNAL_H
#include <sys/types.h> #include <sys/types.h>
typedef int sig_atomic_t; typedef int sig_atomic_t;
typedef unsigned int sigset_t; /* 32 bits */ typedef unsigned int sigset_t; /* 32 bits */
#define _NSIG 32 #define _NSIG 32
#define NSIG _NSIG #define NSIG _NSIG
#define SIGHUP 1 #define SIGHUP 1
#define SIGINT 2 #define SIGINT 2
#define SIGQUIT 3 #define SIGQUIT 3
#define SIGILL 4 #define SIGILL 4
#define SIGTRAP 5 #define SIGTRAP 5
#define SIGABRT 6 #define SIGABRT 6
#define SIGIOT 6 #define SIGIOT 6
#define SIGUNUSED 7 #define SIGUNUSED 7
#define SIGFPE 8 #define SIGFPE 8
#define SIGKILL 9 #define SIGKILL 9
#define SIGUSR1 10 #define SIGUSR1 10
#define SIGSEGV 11 #define SIGSEGV 11
#define SIGUSR2 12 #define SIGUSR2 12
#define SIGPIPE 13 #define SIGPIPE 13
#define SIGALRM 14 #define SIGALRM 14
#define SIGTERM 15 #define SIGTERM 15
#define SIGSTKFLT 16 #define SIGSTKFLT 16
#define SIGCHLD 17 #define SIGCHLD 17
#define SIGCONT 18 #define SIGCONT 18
#define SIGSTOP 19 #define SIGSTOP 19
#define SIGTSTP 20 #define SIGTSTP 20
#define SIGTTIN 21 #define SIGTTIN 21
#define SIGTTOU 22 #define SIGTTOU 22
/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */ /* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
#define SA_NOCLDSTOP 1 #define SA_NOCLDSTOP 1
#define SA_NOMASK 0x40000000 #define SA_NOMASK 0x40000000
#define SA_ONESHOT 0x80000000 #define SA_ONESHOT 0x80000000
#define SIG_BLOCK 0 /* for blocking signals */ #define SIG_BLOCK 0 /* for blocking signals */
#define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */
#define SIG_SETMASK 2 /* for setting the signal mask */ #define SIG_SETMASK 2 /* for setting the signal mask */
#define SIG_DFL ((void (*)(int))0) /* default signal handling */ #define SIG_DFL ((void (*)(int))0) /* default signal handling */
#define SIG_IGN ((void (*)(int))1) /* ignore signal */ #define SIG_IGN ((void (*)(int))1) /* ignore signal */
struct sigaction { struct sigaction {
void (*sa_handler)(int); void (*sa_handler)(int);
sigset_t sa_mask; sigset_t sa_mask;
int sa_flags; int sa_flags;
void (*sa_restorer)(void); void (*sa_restorer)(void);
}; };
void (*signal(int _sig, void (*_func)(int)))(int); void (*signal(int _sig, void (*_func)(int)))(int);
int raise(int sig); int raise(int sig);
int kill(pid_t pid, int sig); int kill(pid_t pid, int sig);
int sigaddset(sigset_t *mask, int signo); int sigaddset(sigset_t *mask, int signo);
int sigdelset(sigset_t *mask, int signo); int sigdelset(sigset_t *mask, int signo);
int sigemptyset(sigset_t *mask); int sigemptyset(sigset_t *mask);
int sigfillset(sigset_t *mask); int sigfillset(sigset_t *mask);
int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */ int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */
int sigpending(sigset_t *set); int sigpending(sigset_t *set);
int sigprocmask(int how, sigset_t *set, sigset_t *oldset); int sigprocmask(int how, sigset_t *set, sigset_t *oldset);
int sigsuspend(sigset_t *sigmask); int sigsuspend(sigset_t *sigmask);
int sigaction(int sig, struct sigaction *act, struct sigaction *oldact); int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
#endif /* _SIGNAL_H */ #endif /* _SIGNAL_H */

@ -1,28 +1,28 @@
#ifndef _STDARG_H #ifndef _STDARG_H
#define _STDARG_H #define _STDARG_H
typedef char *va_list; typedef char *va_list;
/* Amount of space required in an argument list for an arg of type TYPE. /* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */ TYPE may alternatively be an expression whose type is used. */
#define __va_rounded_size(TYPE) \ #define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
#ifndef __sparc__ #ifndef __sparc__
#define va_start(AP, LASTARG) \ #define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else #else
#define va_start(AP, LASTARG) \ #define va_start(AP, LASTARG) \
(__builtin_saveregs (), \ (__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif #endif
void va_end (va_list); /* Defined in gnulib */ void va_end (va_list); /* Defined in gnulib */
#define va_end(AP) #define va_end(AP)
#define va_arg(AP, TYPE) \ #define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \ (AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE)))) *((TYPE *) (AP - __va_rounded_size (TYPE))))
#endif /* _STDARG_H */ #endif /* _STDARG_H */

@ -1,19 +1,19 @@
#ifndef _STDDEF_H #ifndef _STDDEF_H
#define _STDDEF_H #define _STDDEF_H
#ifndef _PTRDIFF_T #ifndef _PTRDIFF_T
#define _PTRDIFF_T #define _PTRDIFF_T
typedef long ptrdiff_t; typedef long ptrdiff_t;
#endif #endif
#ifndef _SIZE_T #ifndef _SIZE_T
#define _SIZE_T #define _SIZE_T
typedef unsigned long size_t; typedef unsigned long size_t;
#endif #endif
#undef NULL #undef NULL
#define NULL ((void *)0) #define NULL ((void *)0)
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif #endif

@ -1,405 +1,405 @@
#ifndef _STRING_H_ #ifndef _STRING_H_
#define _STRING_H_ #define _STRING_H_
#ifndef NULL #ifndef NULL
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#ifndef _SIZE_T #ifndef _SIZE_T
#define _SIZE_T #define _SIZE_T
typedef unsigned int size_t; typedef unsigned int size_t;
#endif #endif
extern char * strerror(int errno); extern char * strerror(int errno);
/* /*
* This string-include defines all string functions as inline * This string-include defines all string functions as inline
* functions. Use gcc. It also assumes ds=es=data space, this should be * functions. Use gcc. It also assumes ds=es=data space, this should be
* normal. Most of the string-functions are rather heavily hand-optimized, * normal. Most of the string-functions are rather heavily hand-optimized,
* see especially strtok,strstr,str[c]spn. They should work, but are not * see especially strtok,strstr,str[c]spn. They should work, but are not
* very easy to understand. Everything is done entirely within the register * very easy to understand. Everything is done entirely within the register
* set, making the functions fast and clean. String instructions have been * set, making the functions fast and clean. String instructions have been
* used through-out, making for "slightly" unclear code :-) * used through-out, making for "slightly" unclear code :-)
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
extern inline char * strcpy(char * dest,const char *src) extern inline char * strcpy(char * dest,const char *src)
{ {
__asm__("cld\n" __asm__("cld\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"stosb\n\t" "stosb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b" "jne 1b"
::"S" (src),"D" (dest)); ::"S" (src),"D" (dest));
return dest; return dest;
} }
extern inline char * strncpy(char * dest,const char *src,int count) extern inline char * strncpy(char * dest,const char *src,int count)
{ {
__asm__("cld\n" __asm__("cld\n"
"1:\tdecl %2\n\t" "1:\tdecl %2\n\t"
"js 2f\n\t" "js 2f\n\t"
"lodsb\n\t" "lodsb\n\t"
"stosb\n\t" "stosb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b\n\t" "jne 1b\n\t"
"rep\n\t" "rep\n\t"
"stosb\n" "stosb\n"
"2:" "2:"
::"S" (src),"D" (dest),"c" (count)); ::"S" (src),"D" (dest),"c" (count));
return dest; return dest;
} }
extern inline char * strcat(char * dest,const char * src) extern inline char * strcat(char * dest,const char * src)
{ {
__asm__("cld\n\t" __asm__("cld\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"decl %1\n" "decl %1\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"stosb\n\t" "stosb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b" "jne 1b"
::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff)); ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff));
return dest; return dest;
} }
extern inline char * strncat(char * dest,const char * src,int count) extern inline char * strncat(char * dest,const char * src,int count)
{ {
__asm__("cld\n\t" __asm__("cld\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"decl %1\n\t" "decl %1\n\t"
"movl %4,%3\n" "movl %4,%3\n"
"1:\tdecl %3\n\t" "1:\tdecl %3\n\t"
"js 2f\n\t" "js 2f\n\t"
"lodsb\n\t" "lodsb\n\t"
"stosb\n\t" "stosb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b\n" "jne 1b\n"
"2:\txorl %2,%2\n\t" "2:\txorl %2,%2\n\t"
"stosb" "stosb"
::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
); );
return dest; return dest;
} }
extern inline int strcmp(const char * cs,const char * ct) extern inline int strcmp(const char * cs,const char * ct)
{ {
register int __res __asm__("ax"); register int __res __asm__("ax");
__asm__("cld\n" __asm__("cld\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"scasb\n\t" "scasb\n\t"
"jne 2f\n\t" "jne 2f\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b\n\t" "jne 1b\n\t"
"xorl %%eax,%%eax\n\t" "xorl %%eax,%%eax\n\t"
"jmp 3f\n" "jmp 3f\n"
"2:\tmovl $1,%%eax\n\t" "2:\tmovl $1,%%eax\n\t"
"jl 3f\n\t" "jl 3f\n\t"
"negl %%eax\n" "negl %%eax\n"
"3:" "3:"
:"=a" (__res):"D" (cs),"S" (ct)); :"=a" (__res):"D" (cs),"S" (ct));
return __res; return __res;
} }
extern inline int strncmp(const char * cs,const char * ct,int count) extern inline int strncmp(const char * cs,const char * ct,int count)
{ {
register int __res __asm__("ax"); register int __res __asm__("ax");
__asm__("cld\n" __asm__("cld\n"
"1:\tdecl %3\n\t" "1:\tdecl %3\n\t"
"js 2f\n\t" "js 2f\n\t"
"lodsb\n\t" "lodsb\n\t"
"scasb\n\t" "scasb\n\t"
"jne 3f\n\t" "jne 3f\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b\n" "jne 1b\n"
"2:\txorl %%eax,%%eax\n\t" "2:\txorl %%eax,%%eax\n\t"
"jmp 4f\n" "jmp 4f\n"
"3:\tmovl $1,%%eax\n\t" "3:\tmovl $1,%%eax\n\t"
"jl 4f\n\t" "jl 4f\n\t"
"negl %%eax\n" "negl %%eax\n"
"4:" "4:"
:"=a" (__res):"D" (cs),"S" (ct),"c" (count)); :"=a" (__res):"D" (cs),"S" (ct),"c" (count));
return __res; return __res;
} }
extern inline char * strchr(const char * s,char c) extern inline char * strchr(const char * s,char c)
{ {
register char * __res __asm__("ax"); register char * __res __asm__("ax");
__asm__("cld\n\t" __asm__("cld\n\t"
"movb %%al,%%ah\n" "movb %%al,%%ah\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t" "cmpb %%ah,%%al\n\t"
"je 2f\n\t" "je 2f\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"jne 1b\n\t" "jne 1b\n\t"
"movl $1,%1\n" "movl $1,%1\n"
"2:\tmovl %1,%0\n\t" "2:\tmovl %1,%0\n\t"
"decl %0" "decl %0"
:"=a" (__res):"S" (s),"0" (c)); :"=a" (__res):"S" (s),"0" (c));
return __res; return __res;
} }
extern inline char * strrchr(const char * s,char c) extern inline char * strrchr(const char * s,char c)
{ {
register char * __res __asm__("dx"); register char * __res __asm__("dx");
__asm__("cld\n\t" __asm__("cld\n\t"
"movb %%al,%%ah\n" "movb %%al,%%ah\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t" "cmpb %%ah,%%al\n\t"
"jne 2f\n\t" "jne 2f\n\t"
"movl %%esi,%0\n\t" "movl %%esi,%0\n\t"
"decl %0\n" "decl %0\n"
"2:\ttestb %%al,%%al\n\t" "2:\ttestb %%al,%%al\n\t"
"jne 1b" "jne 1b"
:"=d" (__res):"0" (0),"S" (s),"a" (c)); :"=d" (__res):"0" (0),"S" (s),"a" (c));
return __res; return __res;
} }
extern inline int strspn(const char * cs, const char * ct) extern inline int strspn(const char * cs, const char * ct)
{ {
register char * __res __asm__("si"); register char * __res __asm__("si");
__asm__("cld\n\t" __asm__("cld\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %%ecx\n\t" "notl %%ecx\n\t"
"decl %%ecx\n\t" "decl %%ecx\n\t"
"movl %%ecx,%%edx\n" "movl %%ecx,%%edx\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"je 2f\n\t" "je 2f\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"je 1b\n" "je 1b\n"
"2:\tdecl %0" "2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
); );
return __res-cs; return __res-cs;
} }
extern inline int strcspn(const char * cs, const char * ct) extern inline int strcspn(const char * cs, const char * ct)
{ {
register char * __res __asm__("si"); register char * __res __asm__("si");
__asm__("cld\n\t" __asm__("cld\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %%ecx\n\t" "notl %%ecx\n\t"
"decl %%ecx\n\t" "decl %%ecx\n\t"
"movl %%ecx,%%edx\n" "movl %%ecx,%%edx\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"je 2f\n\t" "je 2f\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"jne 1b\n" "jne 1b\n"
"2:\tdecl %0" "2:\tdecl %0"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
); );
return __res-cs; return __res-cs;
} }
extern inline char * strpbrk(const char * cs,const char * ct) extern inline char * strpbrk(const char * cs,const char * ct)
{ {
register char * __res __asm__("si"); register char * __res __asm__("si");
__asm__("cld\n\t" __asm__("cld\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %%ecx\n\t" "notl %%ecx\n\t"
"decl %%ecx\n\t" "decl %%ecx\n\t"
"movl %%ecx,%%edx\n" "movl %%ecx,%%edx\n"
"1:\tlodsb\n\t" "1:\tlodsb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"je 2f\n\t" "je 2f\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"jne 1b\n\t" "jne 1b\n\t"
"decl %0\n\t" "decl %0\n\t"
"jmp 3f\n" "jmp 3f\n"
"2:\txorl %0,%0\n" "2:\txorl %0,%0\n"
"3:" "3:"
:"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
); );
return __res; return __res;
} }
extern inline char * strstr(const char * cs,const char * ct) extern inline char * strstr(const char * cs,const char * ct)
{ {
register char * __res __asm__("ax"); register char * __res __asm__("ax");
__asm__("cld\n\t" \ __asm__("cld\n\t" \
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %%ecx\n\t" "notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n" "movl %%ecx,%%edx\n"
"1:\tmovl %4,%%edi\n\t" "1:\tmovl %4,%%edi\n\t"
"movl %%esi,%%eax\n\t" "movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repe\n\t" "repe\n\t"
"cmpsb\n\t" "cmpsb\n\t"
"je 2f\n\t" /* also works for empty string, see above */ "je 2f\n\t" /* also works for empty string, see above */
"xchgl %%eax,%%esi\n\t" "xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t" "incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t" "cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t" "jne 1b\n\t"
"xorl %%eax,%%eax\n\t" "xorl %%eax,%%eax\n\t"
"2:" "2:"
:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
); );
return __res; return __res;
} }
extern inline int strlen(const char * s) extern inline int strlen(const char * s)
{ {
register int __res ; register int __res ;
__asm__("cld\n\t" __asm__("cld\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %0\n\t" "notl %0\n\t"
"decl %0" "decl %0"
:"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff)); :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff));
return __res; return __res;
} }
extern char * ___strtok; extern char * ___strtok;
extern inline char * strtok(char * s,const char * ct) extern inline char * strtok(char * s,const char * ct)
{ {
register char * __res __asm__("si"); register char * __res __asm__("si");
__asm__("testl %1,%1\n\t" __asm__("testl %1,%1\n\t"
"jne 1f\n\t" "jne 1f\n\t"
"testl %0,%0\n\t" "testl %0,%0\n\t"
"je 8f\n\t" "je 8f\n\t"
"movl %0,%1\n" "movl %0,%1\n"
"1:\txorl %0,%0\n\t" "1:\txorl %0,%0\n\t"
"movl $-1,%%ecx\n\t" "movl $-1,%%ecx\n\t"
"xorl %%eax,%%eax\n\t" "xorl %%eax,%%eax\n\t"
"cld\n\t" "cld\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"notl %%ecx\n\t" "notl %%ecx\n\t"
"decl %%ecx\n\t" "decl %%ecx\n\t"
"je 7f\n\t" /* empty delimeter-string */ "je 7f\n\t" /* empty delimeter-string */
"movl %%ecx,%%edx\n" "movl %%ecx,%%edx\n"
"2:\tlodsb\n\t" "2:\tlodsb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"je 7f\n\t" "je 7f\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"je 2b\n\t" "je 2b\n\t"
"decl %1\n\t" "decl %1\n\t"
"cmpb $0,(%1)\n\t" "cmpb $0,(%1)\n\t"
"je 7f\n\t" "je 7f\n\t"
"movl %1,%0\n" "movl %1,%0\n"
"3:\tlodsb\n\t" "3:\tlodsb\n\t"
"testb %%al,%%al\n\t" "testb %%al,%%al\n\t"
"je 5f\n\t" "je 5f\n\t"
"movl %4,%%edi\n\t" "movl %4,%%edi\n\t"
"movl %%edx,%%ecx\n\t" "movl %%edx,%%ecx\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"jne 3b\n\t" "jne 3b\n\t"
"decl %1\n\t" "decl %1\n\t"
"cmpb $0,(%1)\n\t" "cmpb $0,(%1)\n\t"
"je 5f\n\t" "je 5f\n\t"
"movb $0,(%1)\n\t" "movb $0,(%1)\n\t"
"incl %1\n\t" "incl %1\n\t"
"jmp 6f\n" "jmp 6f\n"
"5:\txorl %1,%1\n" "5:\txorl %1,%1\n"
"6:\tcmpb $0,(%0)\n\t" "6:\tcmpb $0,(%0)\n\t"
"jne 7f\n\t" "jne 7f\n\t"
"xorl %0,%0\n" "xorl %0,%0\n"
"7:\ttestl %0,%0\n\t" "7:\ttestl %0,%0\n\t"
"jne 8f\n\t" "jne 8f\n\t"
"movl %0,%1\n" "movl %0,%1\n"
"8:" "8:"
:"=b" (__res),"=S" (___strtok) :"=b" (__res),"=S" (___strtok)
:"0" (___strtok),"1" (s),"g" (ct) :"0" (___strtok),"1" (s),"g" (ct)
); );
return __res; return __res;
} }
extern inline void * memcpy(void * dest,const void * src, int n) extern inline void * memcpy(void * dest,const void * src, int n)
{ {
__asm__("cld\n\t" __asm__("cld\n\t"
"rep\n\t" "rep\n\t"
"movsb" "movsb"
::"c" (n),"S" (src),"D" (dest) ::"c" (n),"S" (src),"D" (dest)
); );
return dest; return dest;
} }
extern inline void * memmove(void * dest,const void * src, int n) extern inline void * memmove(void * dest,const void * src, int n)
{ {
if (dest<src) if (dest<src)
__asm__("cld\n\t" __asm__("cld\n\t"
"rep\n\t" "rep\n\t"
"movsb" "movsb"
::"c" (n),"S" (src),"D" (dest) ::"c" (n),"S" (src),"D" (dest)
); );
else else
__asm__("std\n\t" __asm__("std\n\t"
"rep\n\t" "rep\n\t"
"movsb" "movsb"
::"c" (n),"S" (src+n-1),"D" (dest+n-1) ::"c" (n),"S" (src+n-1),"D" (dest+n-1)
); );
return dest; return dest;
} }
extern inline int memcmp(const void * cs,const void * ct,int count) extern inline int memcmp(const void * cs,const void * ct,int count)
{ {
register int __res __asm__("ax"); register int __res __asm__("ax");
__asm__("cld\n\t" __asm__("cld\n\t"
"repe\n\t" "repe\n\t"
"cmpsb\n\t" "cmpsb\n\t"
"je 1f\n\t" "je 1f\n\t"
"movl $1,%%eax\n\t" "movl $1,%%eax\n\t"
"jl 1f\n\t" "jl 1f\n\t"
"negl %%eax\n" "negl %%eax\n"
"1:" "1:"
:"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count) :"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count)
); );
return __res; return __res;
} }
extern inline void * memchr(const void * cs,char c,int count) extern inline void * memchr(const void * cs,char c,int count)
{ {
register void * __res __asm__("di"); register void * __res __asm__("di");
if (!count) if (!count)
return NULL; return NULL;
__asm__("cld\n\t" __asm__("cld\n\t"
"repne\n\t" "repne\n\t"
"scasb\n\t" "scasb\n\t"
"je 1f\n\t" "je 1f\n\t"
"movl $1,%0\n" "movl $1,%0\n"
"1:\tdecl %0" "1:\tdecl %0"
:"=D" (__res):"a" (c),"D" (cs),"c" (count) :"=D" (__res):"a" (c),"D" (cs),"c" (count)
); );
return __res; return __res;
} }
extern inline void * memset(void * s,char c,int count) extern inline void * memset(void * s,char c,int count)
{ {
__asm__("cld\n\t" __asm__("cld\n\t"
"rep\n\t" "rep\n\t"
"stosb" "stosb"
::"a" (c),"D" (s),"c" (count) ::"a" (c),"D" (s),"c" (count)
); );
return s; return s;
} }
#endif #endif

@ -1,60 +1,60 @@
#ifndef _SYS_STAT_H #ifndef _SYS_STAT_H
#define _SYS_STAT_H #define _SYS_STAT_H
#include <sys/types.h> #include <sys/types.h>
struct stat { struct stat {
dev_t st_dev; dev_t st_dev;
ino_t st_ino; ino_t st_ino;
umode_t st_mode; umode_t st_mode;
nlink_t st_nlink; nlink_t st_nlink;
uid_t st_uid; uid_t st_uid;
gid_t st_gid; gid_t st_gid;
dev_t st_rdev; dev_t st_rdev;
off_t st_size; off_t st_size;
time_t st_atime; time_t st_atime;
time_t st_mtime; time_t st_mtime;
time_t st_ctime; time_t st_ctime;
}; };
#define S_IFMT 00170000 #define S_IFMT 00170000
#define S_IFLNK 0120000 #define S_IFLNK 0120000
#define S_IFREG 0100000 #define S_IFREG 0100000
#define S_IFBLK 0060000 #define S_IFBLK 0060000
#define S_IFDIR 0040000 #define S_IFDIR 0040000
#define S_IFCHR 0020000 #define S_IFCHR 0020000
#define S_IFIFO 0010000 #define S_IFIFO 0010000
#define S_ISUID 0004000 #define S_ISUID 0004000
#define S_ISGID 0002000 #define S_ISGID 0002000
#define S_ISVTX 0001000 #define S_ISVTX 0001000
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_IRWXU 00700 #define S_IRWXU 00700
#define S_IRUSR 00400 #define S_IRUSR 00400
#define S_IWUSR 00200 #define S_IWUSR 00200
#define S_IXUSR 00100 #define S_IXUSR 00100
#define S_IRWXG 00070 #define S_IRWXG 00070
#define S_IRGRP 00040 #define S_IRGRP 00040
#define S_IWGRP 00020 #define S_IWGRP 00020
#define S_IXGRP 00010 #define S_IXGRP 00010
#define S_IRWXO 00007 #define S_IRWXO 00007
#define S_IROTH 00004 #define S_IROTH 00004
#define S_IWOTH 00002 #define S_IWOTH 00002
#define S_IXOTH 00001 #define S_IXOTH 00001
extern int chmod(const char *_path, mode_t mode); extern int chmod(const char *_path, mode_t mode);
extern int fstat(int fildes, struct stat *stat_buf); extern int fstat(int fildes, struct stat *stat_buf);
extern int mkdir(const char *_path, mode_t mode); extern int mkdir(const char *_path, mode_t mode);
extern int mkfifo(const char *_path, mode_t mode); extern int mkfifo(const char *_path, mode_t mode);
extern int stat(const char *filename, struct stat *stat_buf); extern int stat(const char *filename, struct stat *stat_buf);
extern mode_t umask(mode_t mask); extern mode_t umask(mode_t mask);
#endif #endif

@ -1,15 +1,15 @@
#ifndef _TIMES_H #ifndef _TIMES_H
#define _TIMES_H #define _TIMES_H
#include <sys/types.h> #include <sys/types.h>
struct tms { struct tms {
time_t tms_utime; time_t tms_utime;
time_t tms_stime; time_t tms_stime;
time_t tms_cutime; time_t tms_cutime;
time_t tms_cstime; time_t tms_cstime;
}; };
extern time_t times(struct tms * tp); extern time_t times(struct tms * tp);
#endif #endif

@ -1,46 +1,46 @@
#ifndef _SYS_TYPES_H #ifndef _SYS_TYPES_H
#define _SYS_TYPES_H #define _SYS_TYPES_H
#ifndef _SIZE_T #ifndef _SIZE_T
#define _SIZE_T #define _SIZE_T
typedef unsigned int size_t; typedef unsigned int size_t;
#endif #endif
#ifndef _TIME_T #ifndef _TIME_T
#define _TIME_T #define _TIME_T
typedef long time_t; typedef long time_t;
#endif #endif
#ifndef _PTRDIFF_T #ifndef _PTRDIFF_T
#define _PTRDIFF_T #define _PTRDIFF_T
typedef long ptrdiff_t; typedef long ptrdiff_t;
#endif #endif
#ifndef NULL #ifndef NULL
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
typedef int pid_t; typedef int pid_t;
typedef unsigned short uid_t; typedef unsigned short uid_t;
typedef unsigned char gid_t; typedef unsigned char gid_t;
typedef unsigned short dev_t; typedef unsigned short dev_t;
typedef unsigned short ino_t; typedef unsigned short ino_t;
typedef unsigned short mode_t; typedef unsigned short mode_t;
typedef unsigned short umode_t; typedef unsigned short umode_t;
typedef unsigned char nlink_t; typedef unsigned char nlink_t;
typedef int daddr_t; typedef int daddr_t;
typedef long off_t; typedef long off_t;
typedef unsigned char u_char; typedef unsigned char u_char;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef struct { int quot,rem; } div_t; typedef struct { int quot,rem; } div_t;
typedef struct { long quot,rem; } ldiv_t; typedef struct { long quot,rem; } ldiv_t;
struct ustat { struct ustat {
daddr_t f_tfree; daddr_t f_tfree;
ino_t f_tinode; ino_t f_tinode;
char f_fname[6]; char f_fname[6];
char f_fpack[6]; char f_fpack[6];
}; };
#endif #endif

@ -1,16 +1,16 @@
#ifndef _SYS_UTSNAME_H #ifndef _SYS_UTSNAME_H
#define _SYS_UTSNAME_H #define _SYS_UTSNAME_H
#include <sys/types.h> #include <sys/types.h>
struct utsname { struct utsname {
char sysname[9]; char sysname[9];
char nodename[9]; char nodename[9];
char release[9]; char release[9];
char version[9]; char version[9];
char machine[9]; char machine[9];
}; };
extern int uname(struct utsname * utsbuf); extern int uname(struct utsname * utsbuf);
#endif #endif

@ -1,23 +1,23 @@
#ifndef _SYS_WAIT_H #ifndef _SYS_WAIT_H
#define _SYS_WAIT_H #define _SYS_WAIT_H
#include <sys/types.h> #include <sys/types.h>
#define _LOW(v) ( (v) & 0377) #define _LOW(v) ( (v) & 0377)
#define _HIGH(v) ( ((v) >> 8) & 0377) #define _HIGH(v) ( ((v) >> 8) & 0377)
/* options for waitpid, WUNTRACED not supported */ /* options for waitpid, WUNTRACED not supported */
#define WNOHANG 1 #define WNOHANG 1
#define WUNTRACED 2 #define WUNTRACED 2
#define WIFEXITED(s) (!((s)&0xFF) #define WIFEXITED(s) (!((s)&0xFF)
#define WIFSTOPPED(s) (((s)&0xFF)==0x7F) #define WIFSTOPPED(s) (((s)&0xFF)==0x7F)
#define WEXITSTATUS(s) (((s)>>8)&0xFF) #define WEXITSTATUS(s) (((s)>>8)&0xFF)
#define WTERMSIG(s) ((s)&0x7F) #define WTERMSIG(s) ((s)&0x7F)
#define WSTOPSIG(s) (((s)>>8)&0xFF) #define WSTOPSIG(s) (((s)>>8)&0xFF)
#define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF) #define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF)
pid_t wait(int *stat_loc); pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options); pid_t waitpid(pid_t pid, int *stat_loc, int options);
#endif #endif

@ -1,228 +1,228 @@
#ifndef _TERMIOS_H #ifndef _TERMIOS_H
#define _TERMIOS_H #define _TERMIOS_H
#define TTY_BUF_SIZE 1024 #define TTY_BUF_SIZE 1024
/* 0x54 is just a magic number to make these relatively uniqe ('T') */ /* 0x54 is just a magic number to make these relatively uniqe ('T') */
#define TCGETS 0x5401 #define TCGETS 0x5401
#define TCSETS 0x5402 #define TCSETS 0x5402
#define TCSETSW 0x5403 #define TCSETSW 0x5403
#define TCSETSF 0x5404 #define TCSETSF 0x5404
#define TCGETA 0x5405 #define TCGETA 0x5405
#define TCSETA 0x5406 #define TCSETA 0x5406
#define TCSETAW 0x5407 #define TCSETAW 0x5407
#define TCSETAF 0x5408 #define TCSETAF 0x5408
#define TCSBRK 0x5409 #define TCSBRK 0x5409
#define TCXONC 0x540A #define TCXONC 0x540A
#define TCFLSH 0x540B #define TCFLSH 0x540B
#define TIOCEXCL 0x540C #define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D #define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E #define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F #define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410 #define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411 #define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412 #define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413 #define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414 #define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415 #define TIOCMGET 0x5415
#define TIOCMBIS 0x5416 #define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417 #define TIOCMBIC 0x5417
#define TIOCMSET 0x5418 #define TIOCMSET 0x5418
#define TIOCGSOFTCAR 0x5419 #define TIOCGSOFTCAR 0x5419
#define TIOCSSOFTCAR 0x541A #define TIOCSSOFTCAR 0x541A
#define TIOCINQ 0x541B #define TIOCINQ 0x541B
struct winsize { struct winsize {
unsigned short ws_row; unsigned short ws_row;
unsigned short ws_col; unsigned short ws_col;
unsigned short ws_xpixel; unsigned short ws_xpixel;
unsigned short ws_ypixel; unsigned short ws_ypixel;
}; };
#define NCC 8 #define NCC 8
struct termio { struct termio {
unsigned short c_iflag; /* input mode flags */ unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */ unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */ unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */ unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */ unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */ unsigned char c_cc[NCC]; /* control characters */
}; };
#define NCCS 17 #define NCCS 17
struct termios { struct termios {
unsigned long c_iflag; /* input mode flags */ unsigned long c_iflag; /* input mode flags */
unsigned long c_oflag; /* output mode flags */ unsigned long c_oflag; /* output mode flags */
unsigned long c_cflag; /* control mode flags */ unsigned long c_cflag; /* control mode flags */
unsigned long c_lflag; /* local mode flags */ unsigned long c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */ unsigned char c_line; /* line discipline */
unsigned char c_cc[NCCS]; /* control characters */ unsigned char c_cc[NCCS]; /* control characters */
}; };
/* c_cc characters */ /* c_cc characters */
#define VINTR 0 #define VINTR 0
#define VQUIT 1 #define VQUIT 1
#define VERASE 2 #define VERASE 2
#define VKILL 3 #define VKILL 3
#define VEOF 4 #define VEOF 4
#define VTIME 5 #define VTIME 5
#define VMIN 6 #define VMIN 6
#define VSWTC 7 #define VSWTC 7
#define VSTART 8 #define VSTART 8
#define VSTOP 9 #define VSTOP 9
#define VSUSP 10 #define VSUSP 10
#define VEOL 11 #define VEOL 11
#define VREPRINT 12 #define VREPRINT 12
#define VDISCARD 13 #define VDISCARD 13
#define VWERASE 14 #define VWERASE 14
#define VLNEXT 15 #define VLNEXT 15
#define VEOL2 16 #define VEOL2 16
/* c_iflag bits */ /* c_iflag bits */
#define IGNBRK 0000001 #define IGNBRK 0000001
#define BRKINT 0000002 #define BRKINT 0000002
#define IGNPAR 0000004 #define IGNPAR 0000004
#define PARMRK 0000010 #define PARMRK 0000010
#define INPCK 0000020 #define INPCK 0000020
#define ISTRIP 0000040 #define ISTRIP 0000040
#define INLCR 0000100 #define INLCR 0000100
#define IGNCR 0000200 #define IGNCR 0000200
#define ICRNL 0000400 #define ICRNL 0000400
#define IUCLC 0001000 #define IUCLC 0001000
#define IXON 0002000 #define IXON 0002000
#define IXANY 0004000 #define IXANY 0004000
#define IXOFF 0010000 #define IXOFF 0010000
#define IMAXBEL 0020000 #define IMAXBEL 0020000
/* c_oflag bits */ /* c_oflag bits */
#define OPOST 0000001 #define OPOST 0000001
#define OLCUC 0000002 #define OLCUC 0000002
#define ONLCR 0000004 #define ONLCR 0000004
#define OCRNL 0000010 #define OCRNL 0000010
#define ONOCR 0000020 #define ONOCR 0000020
#define ONLRET 0000040 #define ONLRET 0000040
#define OFILL 0000100 #define OFILL 0000100
#define OFDEL 0000200 #define OFDEL 0000200
#define NLDLY 0000400 #define NLDLY 0000400
#define NL0 0000000 #define NL0 0000000
#define NL1 0000400 #define NL1 0000400
#define CRDLY 0003000 #define CRDLY 0003000
#define CR0 0000000 #define CR0 0000000
#define CR1 0001000 #define CR1 0001000
#define CR2 0002000 #define CR2 0002000
#define CR3 0003000 #define CR3 0003000
#define TABDLY 0014000 #define TABDLY 0014000
#define TAB0 0000000 #define TAB0 0000000
#define TAB1 0004000 #define TAB1 0004000
#define TAB2 0010000 #define TAB2 0010000
#define TAB3 0014000 #define TAB3 0014000
#define XTABS 0014000 #define XTABS 0014000
#define BSDLY 0020000 #define BSDLY 0020000
#define BS0 0000000 #define BS0 0000000
#define BS1 0020000 #define BS1 0020000
#define VTDLY 0040000 #define VTDLY 0040000
#define VT0 0000000 #define VT0 0000000
#define VT1 0040000 #define VT1 0040000
#define FFDLY 0040000 #define FFDLY 0040000
#define FF0 0000000 #define FF0 0000000
#define FF1 0040000 #define FF1 0040000
/* c_cflag bit meaning */ /* c_cflag bit meaning */
#define CBAUD 0000017 #define CBAUD 0000017
#define B0 0000000 /* hang up */ #define B0 0000000 /* hang up */
#define B50 0000001 #define B50 0000001
#define B75 0000002 #define B75 0000002
#define B110 0000003 #define B110 0000003
#define B134 0000004 #define B134 0000004
#define B150 0000005 #define B150 0000005
#define B200 0000006 #define B200 0000006
#define B300 0000007 #define B300 0000007
#define B600 0000010 #define B600 0000010
#define B1200 0000011 #define B1200 0000011
#define B1800 0000012 #define B1800 0000012
#define B2400 0000013 #define B2400 0000013
#define B4800 0000014 #define B4800 0000014
#define B9600 0000015 #define B9600 0000015
#define B19200 0000016 #define B19200 0000016
#define B38400 0000017 #define B38400 0000017
#define EXTA B19200 #define EXTA B19200
#define EXTB B38400 #define EXTB B38400
#define CSIZE 0000060 #define CSIZE 0000060
#define CS5 0000000 #define CS5 0000000
#define CS6 0000020 #define CS6 0000020
#define CS7 0000040 #define CS7 0000040
#define CS8 0000060 #define CS8 0000060
#define CSTOPB 0000100 #define CSTOPB 0000100
#define CREAD 0000200 #define CREAD 0000200
#define CPARENB 0000400 #define CPARENB 0000400
#define CPARODD 0001000 #define CPARODD 0001000
#define HUPCL 0002000 #define HUPCL 0002000
#define CLOCAL 0004000 #define CLOCAL 0004000
#define CIBAUD 03600000 /* input baud rate (not used) */ #define CIBAUD 03600000 /* input baud rate (not used) */
#define CRTSCTS 020000000000 /* flow control */ #define CRTSCTS 020000000000 /* flow control */
#define PARENB CPARENB #define PARENB CPARENB
#define PARODD CPARODD #define PARODD CPARODD
/* c_lflag bits */ /* c_lflag bits */
#define ISIG 0000001 #define ISIG 0000001
#define ICANON 0000002 #define ICANON 0000002
#define XCASE 0000004 #define XCASE 0000004
#define ECHO 0000010 #define ECHO 0000010
#define ECHOE 0000020 #define ECHOE 0000020
#define ECHOK 0000040 #define ECHOK 0000040
#define ECHONL 0000100 #define ECHONL 0000100
#define NOFLSH 0000200 #define NOFLSH 0000200
#define TOSTOP 0000400 #define TOSTOP 0000400
#define ECHOCTL 0001000 #define ECHOCTL 0001000
#define ECHOPRT 0002000 #define ECHOPRT 0002000
#define ECHOKE 0004000 #define ECHOKE 0004000
#define FLUSHO 0010000 #define FLUSHO 0010000
#define PENDIN 0040000 #define PENDIN 0040000
#define IEXTEN 0100000 #define IEXTEN 0100000
/* modem lines */ /* modem lines */
#define TIOCM_LE 0x001 #define TIOCM_LE 0x001
#define TIOCM_DTR 0x002 #define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004 #define TIOCM_RTS 0x004
#define TIOCM_ST 0x008 #define TIOCM_ST 0x008
#define TIOCM_SR 0x010 #define TIOCM_SR 0x010
#define TIOCM_CTS 0x020 #define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040 #define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080 #define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100 #define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR #define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG #define TIOCM_RI TIOCM_RNG
/* tcflow() and TCXONC use these */ /* tcflow() and TCXONC use these */
#define TCOOFF 0 #define TCOOFF 0
#define TCOON 1 #define TCOON 1
#define TCIOFF 2 #define TCIOFF 2
#define TCION 3 #define TCION 3
/* tcflush() and TCFLSH use these */ /* tcflush() and TCFLSH use these */
#define TCIFLUSH 0 #define TCIFLUSH 0
#define TCOFLUSH 1 #define TCOFLUSH 1
#define TCIOFLUSH 2 #define TCIOFLUSH 2
/* tcsetattr uses these */ /* tcsetattr uses these */
#define TCSANOW 0 #define TCSANOW 0
#define TCSADRAIN 1 #define TCSADRAIN 1
#define TCSAFLUSH 2 #define TCSAFLUSH 2
typedef int speed_t; typedef int speed_t;
extern speed_t cfgetispeed(struct termios *termios_p); extern speed_t cfgetispeed(struct termios *termios_p);
extern speed_t cfgetospeed(struct termios *termios_p); extern speed_t cfgetospeed(struct termios *termios_p);
extern int cfsetispeed(struct termios *termios_p, speed_t speed); extern int cfsetispeed(struct termios *termios_p, speed_t speed);
extern int cfsetospeed(struct termios *termios_p, speed_t speed); extern int cfsetospeed(struct termios *termios_p, speed_t speed);
extern int tcdrain(int fildes); extern int tcdrain(int fildes);
extern int tcflow(int fildes, int action); extern int tcflow(int fildes, int action);
extern int tcflush(int fildes, int queue_selector); extern int tcflush(int fildes, int queue_selector);
extern int tcgetattr(int fildes, struct termios *termios_p); extern int tcgetattr(int fildes, struct termios *termios_p);
extern int tcsendbreak(int fildes, int duration); extern int tcsendbreak(int fildes, int duration);
extern int tcsetattr(int fildes, int optional_actions, extern int tcsetattr(int fildes, int optional_actions,
struct termios *termios_p); struct termios *termios_p);
#endif #endif

@ -1,42 +1,42 @@
#ifndef _TIME_H #ifndef _TIME_H
#define _TIME_H #define _TIME_H
#ifndef _TIME_T #ifndef _TIME_T
#define _TIME_T #define _TIME_T
typedef long time_t; typedef long time_t;
#endif #endif
#ifndef _SIZE_T #ifndef _SIZE_T
#define _SIZE_T #define _SIZE_T
typedef unsigned int size_t; typedef unsigned int size_t;
#endif #endif
#define CLOCKS_PER_SEC 100 #define CLOCKS_PER_SEC 100
typedef long clock_t; typedef long clock_t;
struct tm { struct tm {
int tm_sec; int tm_sec;
int tm_min; int tm_min;
int tm_hour; int tm_hour;
int tm_mday; int tm_mday;
int tm_mon; int tm_mon;
int tm_year; int tm_year;
int tm_wday; int tm_wday;
int tm_yday; int tm_yday;
int tm_isdst; int tm_isdst;
}; };
clock_t clock(void); clock_t clock(void);
time_t time(time_t * tp); time_t time(time_t * tp);
double difftime(time_t time2, time_t time1); double difftime(time_t time2, time_t time1);
time_t mktime(struct tm * tp); time_t mktime(struct tm * tp);
char * asctime(const struct tm * tp); char * asctime(const struct tm * tp);
char * ctime(const time_t * tp); char * ctime(const time_t * tp);
struct tm * gmtime(const time_t *tp); struct tm * gmtime(const time_t *tp);
struct tm *localtime(const time_t * tp); struct tm *localtime(const time_t * tp);
size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp); size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
void tzset(void); void tzset(void);
#endif #endif

@ -1,269 +1,269 @@
#ifndef _UNISTD_H #ifndef _UNISTD_H
#define _UNISTD_H #define _UNISTD_H
/* ok, this may be a joke, but I'm working on it */ /* ok, this may be a joke, but I'm working on it */
#define _POSIX_VERSION 198808L #define _POSIX_VERSION 198808L
#define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */ #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
#define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */ #define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
#define _POSIX_VDISABLE '\0' /* character to disable things like ^C */ #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
/*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */ /*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
/*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */ /*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
#define STDIN_FILENO 0 #define STDIN_FILENO 0
#define STDOUT_FILENO 1 #define STDOUT_FILENO 1
#define STDERR_FILENO 2 #define STDERR_FILENO 2
#ifndef NULL #ifndef NULL
#define NULL ((void *)0) #define NULL ((void *)0)
#endif #endif
/* access */ /* access */
#define F_OK 0 #define F_OK 0
#define X_OK 1 #define X_OK 1
#define W_OK 2 #define W_OK 2
#define R_OK 4 #define R_OK 4
/* lseek */ /* lseek */
#define SEEK_SET 0 #define SEEK_SET 0
#define SEEK_CUR 1 #define SEEK_CUR 1
#define SEEK_END 2 #define SEEK_END 2
/* _SC stands for System Configuration. We don't use them much */ /* _SC stands for System Configuration. We don't use them much */
#define _SC_ARG_MAX 1 #define _SC_ARG_MAX 1
#define _SC_CHILD_MAX 2 #define _SC_CHILD_MAX 2
#define _SC_CLOCKS_PER_SEC 3 #define _SC_CLOCKS_PER_SEC 3
#define _SC_NGROUPS_MAX 4 #define _SC_NGROUPS_MAX 4
#define _SC_OPEN_MAX 5 #define _SC_OPEN_MAX 5
#define _SC_JOB_CONTROL 6 #define _SC_JOB_CONTROL 6
#define _SC_SAVED_IDS 7 #define _SC_SAVED_IDS 7
#define _SC_VERSION 8 #define _SC_VERSION 8
/* more (possibly) configurable things - now pathnames */ /* more (possibly) configurable things - now pathnames */
#define _PC_LINK_MAX 1 #define _PC_LINK_MAX 1
#define _PC_MAX_CANON 2 #define _PC_MAX_CANON 2
#define _PC_MAX_INPUT 3 #define _PC_MAX_INPUT 3
#define _PC_NAME_MAX 4 #define _PC_NAME_MAX 4
#define _PC_PATH_MAX 5 #define _PC_PATH_MAX 5
#define _PC_PIPE_BUF 6 #define _PC_PIPE_BUF 6
#define _PC_NO_TRUNC 7 #define _PC_NO_TRUNC 7
#define _PC_VDISABLE 8 #define _PC_VDISABLE 8
#define _PC_CHOWN_RESTRICTED 9 #define _PC_CHOWN_RESTRICTED 9
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/times.h> #include <sys/times.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <utime.h> #include <utime.h>
#ifdef __LIBRARY__ #ifdef __LIBRARY__
#define __NR_setup 0 /* used only by init, to get system going */ #define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1 #define __NR_exit 1
#define __NR_fork 2 #define __NR_fork 2
#define __NR_read 3 #define __NR_read 3
#define __NR_write 4 #define __NR_write 4
#define __NR_open 5 #define __NR_open 5
#define __NR_close 6 #define __NR_close 6
#define __NR_waitpid 7 #define __NR_waitpid 7
#define __NR_creat 8 #define __NR_creat 8
#define __NR_link 9 #define __NR_link 9
#define __NR_unlink 10 #define __NR_unlink 10
#define __NR_execve 11 #define __NR_execve 11
#define __NR_chdir 12 #define __NR_chdir 12
#define __NR_time 13 #define __NR_time 13
#define __NR_mknod 14 #define __NR_mknod 14
#define __NR_chmod 15 #define __NR_chmod 15
#define __NR_chown 16 #define __NR_chown 16
#define __NR_break 17 #define __NR_break 17
#define __NR_stat 18 #define __NR_stat 18
#define __NR_lseek 19 #define __NR_lseek 19
#define __NR_getpid 20 #define __NR_getpid 20
#define __NR_mount 21 #define __NR_mount 21
#define __NR_umount 22 #define __NR_umount 22
#define __NR_setuid 23 #define __NR_setuid 23
#define __NR_getuid 24 #define __NR_getuid 24
#define __NR_stime 25 #define __NR_stime 25
#define __NR_ptrace 26 #define __NR_ptrace 26
#define __NR_alarm 27 #define __NR_alarm 27
#define __NR_fstat 28 #define __NR_fstat 28
#define __NR_pause 29 #define __NR_pause 29
#define __NR_utime 30 #define __NR_utime 30
#define __NR_stty 31 #define __NR_stty 31
#define __NR_gtty 32 #define __NR_gtty 32
#define __NR_access 33 #define __NR_access 33
#define __NR_nice 34 #define __NR_nice 34
#define __NR_ftime 35 #define __NR_ftime 35
#define __NR_sync 36 #define __NR_sync 36
#define __NR_kill 37 #define __NR_kill 37
#define __NR_rename 38 #define __NR_rename 38
#define __NR_mkdir 39 #define __NR_mkdir 39
#define __NR_rmdir 40 #define __NR_rmdir 40
#define __NR_dup 41 #define __NR_dup 41
#define __NR_pipe 42 #define __NR_pipe 42
#define __NR_times 43 #define __NR_times 43
#define __NR_prof 44 #define __NR_prof 44
#define __NR_brk 45 #define __NR_brk 45
#define __NR_setgid 46 #define __NR_setgid 46
#define __NR_getgid 47 #define __NR_getgid 47
#define __NR_signal 48 #define __NR_signal 48
#define __NR_geteuid 49 #define __NR_geteuid 49
#define __NR_getegid 50 #define __NR_getegid 50
#define __NR_acct 51 #define __NR_acct 51
#define __NR_phys 52 #define __NR_phys 52
#define __NR_lock 53 #define __NR_lock 53
#define __NR_ioctl 54 #define __NR_ioctl 54
#define __NR_fcntl 55 #define __NR_fcntl 55
#define __NR_mpx 56 #define __NR_mpx 56
#define __NR_setpgid 57 #define __NR_setpgid 57
#define __NR_ulimit 58 #define __NR_ulimit 58
#define __NR_uname 59 #define __NR_uname 59
#define __NR_umask 60 #define __NR_umask 60
#define __NR_chroot 61 #define __NR_chroot 61
#define __NR_ustat 62 #define __NR_ustat 62
#define __NR_dup2 63 #define __NR_dup2 63
#define __NR_getppid 64 #define __NR_getppid 64
#define __NR_getpgrp 65 #define __NR_getpgrp 65
#define __NR_setsid 66 #define __NR_setsid 66
#define __NR_sigaction 67 #define __NR_sigaction 67
#define __NR_sgetmask 68 #define __NR_sgetmask 68
#define __NR_ssetmask 69 #define __NR_ssetmask 69
#define __NR_setreuid 70 #define __NR_setreuid 70
#define __NR_setregid 71 #define __NR_setregid 71
#define __NR_sigsuspend 72 #define __NR_sigsuspend 72
#define __NR_sigpending 73 #define __NR_sigpending 73
#define __NR_sethostname 74 #define __NR_sethostname 74
#define __NR_setrlimit 75 #define __NR_setrlimit 75
#define __NR_getrlimit 76 #define __NR_getrlimit 76
#define __NR_getrusage 77 #define __NR_getrusage 77
#define __NR_gettimeofday 78 #define __NR_gettimeofday 78
#define __NR_settimeofday 79 #define __NR_settimeofday 79
#define __NR_getgroups 80 #define __NR_getgroups 80
#define __NR_setgroups 81 #define __NR_setgroups 81
#define __NR_select 82 #define __NR_select 82
#define __NR_symlink 83 #define __NR_symlink 83
#define __NR_lstat 84 #define __NR_lstat 84
#define __NR_readlink 85 #define __NR_readlink 85
#define __NR_uselib 86 #define __NR_uselib 86
#define _syscall0(type,name) \ #define _syscall0(type,name) \
type name(void) \ type name(void) \
{ \ { \
long __res; \ long __res; \
__asm__ volatile ("int $0x80" \ __asm__ volatile ("int $0x80" \
: "=a" (__res) \ : "=a" (__res) \
: "0" (__NR_##name)); \ : "0" (__NR_##name)); \
if (__res >= 0) \ if (__res >= 0) \
return (type) __res; \ return (type) __res; \
errno = -__res; \ errno = -__res; \
return -1; \ return -1; \
} }
#define _syscall1(type,name,atype,a) \ #define _syscall1(type,name,atype,a) \
type name(atype a) \ type name(atype a) \
{ \ { \
long __res; \ long __res; \
__asm__ volatile ("int $0x80" \ __asm__ volatile ("int $0x80" \
: "=a" (__res) \ : "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a))); \ : "0" (__NR_##name),"b" ((long)(a))); \
if (__res >= 0) \ if (__res >= 0) \
return (type) __res; \ return (type) __res; \
errno = -__res; \ errno = -__res; \
return -1; \ return -1; \
} }
#define _syscall2(type,name,atype,a,btype,b) \ #define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \ type name(atype a,btype b) \
{ \ { \
long __res; \ long __res; \
__asm__ volatile ("int $0x80" \ __asm__ volatile ("int $0x80" \
: "=a" (__res) \ : "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \ : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
if (__res >= 0) \ if (__res >= 0) \
return (type) __res; \ return (type) __res; \
errno = -__res; \ errno = -__res; \
return -1; \ return -1; \
} }
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \ type name(atype a,btype b,ctype c) \
{ \ { \
long __res; \ long __res; \
__asm__ volatile ("int $0x80" \ __asm__ volatile ("int $0x80" \
: "=a" (__res) \ : "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \ : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
if (__res>=0) \ if (__res>=0) \
return (type) __res; \ return (type) __res; \
errno=-__res; \ errno=-__res; \
return -1; \ return -1; \
} }
#endif /* __LIBRARY__ */ #endif /* __LIBRARY__ */
extern int errno; extern int errno;
int access(const char * filename, mode_t mode); int access(const char * filename, mode_t mode);
int acct(const char * filename); int acct(const char * filename);
int alarm(int sec); int alarm(int sec);
int brk(void * end_data_segment); int brk(void * end_data_segment);
void * sbrk(ptrdiff_t increment); void * sbrk(ptrdiff_t increment);
int chdir(const char * filename); int chdir(const char * filename);
int chmod(const char * filename, mode_t mode); int chmod(const char * filename, mode_t mode);
int chown(const char * filename, uid_t owner, gid_t group); int chown(const char * filename, uid_t owner, gid_t group);
int chroot(const char * filename); int chroot(const char * filename);
int close(int fildes); int close(int fildes);
int creat(const char * filename, mode_t mode); int creat(const char * filename, mode_t mode);
int dup(int fildes); int dup(int fildes);
int execve(const char * filename, char ** argv, char ** envp); int execve(const char * filename, char ** argv, char ** envp);
int execv(const char * pathname, char ** argv); int execv(const char * pathname, char ** argv);
int execvp(const char * file, char ** argv); int execvp(const char * file, char ** argv);
int execl(const char * pathname, char * arg0, ...); int execl(const char * pathname, char * arg0, ...);
int execlp(const char * file, char * arg0, ...); int execlp(const char * file, char * arg0, ...);
int execle(const char * pathname, char * arg0, ...); int execle(const char * pathname, char * arg0, ...);
volatile void exit(int status); volatile void exit(int status);
volatile void _exit(int status); volatile void _exit(int status);
int fcntl(int fildes, int cmd, ...); int fcntl(int fildes, int cmd, ...);
int fork(void); int fork(void);
int getpid(void); int getpid(void);
int getuid(void); int getuid(void);
int geteuid(void); int geteuid(void);
int getgid(void); int getgid(void);
int getegid(void); int getegid(void);
int ioctl(int fildes, int cmd, ...); int ioctl(int fildes, int cmd, ...);
int kill(pid_t pid, int signal); int kill(pid_t pid, int signal);
int link(const char * filename1, const char * filename2); int link(const char * filename1, const char * filename2);
int lseek(int fildes, off_t offset, int origin); int lseek(int fildes, off_t offset, int origin);
int mknod(const char * filename, mode_t mode, dev_t dev); int mknod(const char * filename, mode_t mode, dev_t dev);
int mount(const char * specialfile, const char * dir, int rwflag); int mount(const char * specialfile, const char * dir, int rwflag);
int nice(int val); int nice(int val);
int open(const char * filename, int flag, ...); int open(const char * filename, int flag, ...);
int pause(void); int pause(void);
int pipe(int * fildes); int pipe(int * fildes);
int read(int fildes, char * buf, off_t count); int read(int fildes, char * buf, off_t count);
int setpgrp(void); int setpgrp(void);
int setpgid(pid_t pid,pid_t pgid); int setpgid(pid_t pid,pid_t pgid);
int setuid(uid_t uid); int setuid(uid_t uid);
int setgid(gid_t gid); int setgid(gid_t gid);
void (*signal(int sig, void (*fn)(int)))(int); void (*signal(int sig, void (*fn)(int)))(int);
int stat(const char * filename, struct stat * stat_buf); int stat(const char * filename, struct stat * stat_buf);
int fstat(int fildes, struct stat * stat_buf); int fstat(int fildes, struct stat * stat_buf);
int stime(time_t * tptr); int stime(time_t * tptr);
int sync(void); int sync(void);
time_t time(time_t * tloc); time_t time(time_t * tloc);
time_t times(struct tms * tbuf); time_t times(struct tms * tbuf);
int ulimit(int cmd, long limit); int ulimit(int cmd, long limit);
mode_t umask(mode_t mask); mode_t umask(mode_t mask);
int umount(const char * specialfile); int umount(const char * specialfile);
int uname(struct utsname * name); int uname(struct utsname * name);
int unlink(const char * filename); int unlink(const char * filename);
int ustat(dev_t dev, struct ustat * ubuf); int ustat(dev_t dev, struct ustat * ubuf);
int utime(const char * filename, struct utimbuf * times); int utime(const char * filename, struct utimbuf * times);
pid_t waitpid(pid_t pid,int * wait_stat,int options); pid_t waitpid(pid_t pid,int * wait_stat,int options);
pid_t wait(int * wait_stat); pid_t wait(int * wait_stat);
int write(int fildes, const char * buf, off_t count); int write(int fildes, const char * buf, off_t count);
int dup2(int oldfd, int newfd); int dup2(int oldfd, int newfd);
int getppid(void); int getppid(void);
pid_t getpgrp(void); pid_t getpgrp(void);
pid_t setsid(void); pid_t setsid(void);
#define __always_inline inline __attribute__((always_inline)) #define __always_inline inline __attribute__((always_inline))
#endif #endif

@ -1,13 +1,13 @@
#ifndef _UTIME_H #ifndef _UTIME_H
#define _UTIME_H #define _UTIME_H
#include <sys/types.h> /* I know - shouldn't do this, but .. */ #include <sys/types.h> /* I know - shouldn't do this, but .. */
struct utimbuf { struct utimbuf {
time_t actime; time_t actime;
time_t modtime; time_t modtime;
}; };
extern int utime(const char *filename, struct utimbuf *times); extern int utime(const char *filename, struct utimbuf *times);
#endif #endif

@ -1,210 +1,210 @@
/* /*
* linux/init/main.c * linux/init/main.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#define __LIBRARY__ #define __LIBRARY__
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
/* /*
* we need this inline - forking from kernel space will result * we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This * in NO COPY ON WRITE (!!!), until an execve is executed. This
* is no problem, but for the stack. This is handled by not letting * is no problem, but for the stack. This is handled by not letting
* main() use the stack at all after fork(). Thus, no function * main() use the stack at all after fork(). Thus, no function
* calls - which means inline code for fork too, as otherwise we * calls - which means inline code for fork too, as otherwise we
* would use the stack upon exit from 'fork()'. * would use the stack upon exit from 'fork()'.
* *
* Actually only pause and fork are needed inline, so that there * Actually only pause and fork are needed inline, so that there
* won't be any messing with the stack from main(), but we define * won't be any messing with the stack from main(), but we define
* some others too. * some others too.
*/ */
__always_inline _syscall0(int,fork) __always_inline _syscall0(int,fork)
__always_inline _syscall0(int,pause) __always_inline _syscall0(int,pause)
__always_inline _syscall1(int,setup,void *,BIOS) __always_inline _syscall1(int,setup,void *,BIOS)
__always_inline _syscall0(int,sync) __always_inline _syscall0(int,sync)
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/head.h> #include <linux/head.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <stddef.h> #include <stddef.h>
#include <stdarg.h> #include <stdarg.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/fs.h> #include <linux/fs.h>
static char printbuf[1024]; static char printbuf[1024];
extern int vsprintf(); extern int vsprintf();
extern void init(void); extern void init(void);
extern void blk_dev_init(void); extern void blk_dev_init(void);
extern void chr_dev_init(void); extern void chr_dev_init(void);
extern void hd_init(void); extern void hd_init(void);
extern void floppy_init(void); extern void floppy_init(void);
extern void mem_init(long start, long end); extern void mem_init(long start, long end);
extern long rd_init(long mem_start, int length); extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm); extern long kernel_mktime(struct tm * tm);
extern long startup_time; extern long startup_time;
/* /*
* This is set up by the setup-routine at boot-time * This is set up by the setup-routine at boot-time
*/ */
#define EXT_MEM_K (*(unsigned short *)0x90002) #define EXT_MEM_K (*(unsigned short *)0x90002)
#define DRIVE_INFO (*(struct drive_info *)0x90080) #define DRIVE_INFO (*(struct drive_info *)0x90080)
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
/* /*
* Yeah, yeah, it's ugly, but I cannot find how to do this correctly * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
* and this seems to work. I anybody has more info on the real-time * and this seems to work. I anybody has more info on the real-time
* clock I'd be interested. Most of this was trial and error, and some * clock I'd be interested. Most of this was trial and error, and some
* bios-listing reading. Urghh. * bios-listing reading. Urghh.
*/ */
#define CMOS_READ(addr) ({ \ #define CMOS_READ(addr) ({ \
outb_p(0x80|addr,0x70); \ outb_p(0x80|addr,0x70); \
inb_p(0x71); \ inb_p(0x71); \
}) })
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
static void time_init(void) static void time_init(void)
{ {
struct tm time; struct tm time;
do { do {
time.tm_sec = CMOS_READ(0); time.tm_sec = CMOS_READ(0);
time.tm_min = CMOS_READ(2); time.tm_min = CMOS_READ(2);
time.tm_hour = CMOS_READ(4); time.tm_hour = CMOS_READ(4);
time.tm_mday = CMOS_READ(7); time.tm_mday = CMOS_READ(7);
time.tm_mon = CMOS_READ(8); time.tm_mon = CMOS_READ(8);
time.tm_year = CMOS_READ(9); time.tm_year = CMOS_READ(9);
} while (time.tm_sec != CMOS_READ(0)); } while (time.tm_sec != CMOS_READ(0));
BCD_TO_BIN(time.tm_sec); BCD_TO_BIN(time.tm_sec);
BCD_TO_BIN(time.tm_min); BCD_TO_BIN(time.tm_min);
BCD_TO_BIN(time.tm_hour); BCD_TO_BIN(time.tm_hour);
BCD_TO_BIN(time.tm_mday); BCD_TO_BIN(time.tm_mday);
BCD_TO_BIN(time.tm_mon); BCD_TO_BIN(time.tm_mon);
BCD_TO_BIN(time.tm_year); BCD_TO_BIN(time.tm_year);
time.tm_mon--; time.tm_mon--;
startup_time = kernel_mktime(&time); startup_time = kernel_mktime(&time);
} }
static long memory_end = 0; static long memory_end = 0;
static long buffer_memory_end = 0; static long buffer_memory_end = 0;
static long main_memory_start = 0; static long main_memory_start = 0;
struct drive_info { char dummy[32]; } drive_info; struct drive_info { char dummy[32]; } drive_info;
void main(void) /* This really IS void, no error here. */ void main(void) /* This really IS void, no error here. */
{ /* The startup routine assumes (well, ...) this */ { /* The startup routine assumes (well, ...) this */
/* /*
* Interrupts are still disabled. Do necessary setups, then * Interrupts are still disabled. Do necessary setups, then
* enable them * enable them
*/ */
ROOT_DEV = ORIG_ROOT_DEV; ROOT_DEV = ORIG_ROOT_DEV;
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
drive_info = DRIVE_INFO; drive_info = DRIVE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000; memory_end &= 0xfffff000;
if (memory_end > 16*1024*1024) if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024; memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024) if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024; buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024) else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024; buffer_memory_end = 2*1024*1024;
else else
buffer_memory_end = 1*1024*1024; buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end; main_memory_start = buffer_memory_end;
#ifdef RAMDISK #ifdef RAMDISK
main_memory_start += rd_init(main_memory_start, RAMDISK*1024); main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif #endif
mem_init(main_memory_start,memory_end); mem_init(main_memory_start,memory_end);
trap_init(); trap_init();
blk_dev_init(); blk_dev_init();
chr_dev_init(); chr_dev_init();
tty_init(); tty_init();
time_init(); time_init();
sched_init(); sched_init();
buffer_init(buffer_memory_end); buffer_init(buffer_memory_end);
hd_init(); hd_init();
floppy_init(); floppy_init();
sti(); sti();
move_to_user_mode(); move_to_user_mode();
if (!fork()) { /* we count on this going ok */ if (!fork()) { /* we count on this going ok */
init(); init();
} }
/* /*
* NOTE!! For any other task 'pause()' would mean we have to get a * NOTE!! For any other task 'pause()' would mean we have to get a
* signal to awaken, but task0 is the sole exception (see 'schedule()') * signal to awaken, but task0 is the sole exception (see 'schedule()')
* as task 0 gets activated at every idle moment (when no other tasks * as task 0 gets activated at every idle moment (when no other tasks
* can run). For task0 'pause()' just means we go check if some other * can run). For task0 'pause()' just means we go check if some other
* task can run, and if not we return here. * task can run, and if not we return here.
*/ */
for(;;) pause(); for(;;) pause();
} }
static int printf(const char *fmt, ...) static int printf(const char *fmt, ...)
{ {
va_list args; va_list args;
int i; int i;
va_start(args, fmt); va_start(args, fmt);
write(1,printbuf,i=vsprintf(printbuf, fmt, args)); write(1,printbuf,i=vsprintf(printbuf, fmt, args));
va_end(args); va_end(args);
return i; return i;
} }
static char * argv_rc[] = { "/bin/sh", NULL }; static char * argv_rc[] = { "/bin/sh", NULL };
static char * envp_rc[] = { "HOME=/", NULL, NULL }; static char * envp_rc[] = { "HOME=/", NULL, NULL };
static char * argv[] = { "-/bin/sh",NULL }; static char * argv[] = { "-/bin/sh",NULL };
static char * envp[] = { "HOME=/usr/root", NULL, NULL }; static char * envp[] = { "HOME=/usr/root", NULL, NULL };
void init(void) void init(void)
{ {
int pid,i; int pid,i;
setup((void *) &drive_info); setup((void *) &drive_info);
(void) open("/dev/tty0",O_RDWR,0); (void) open("/dev/tty0",O_RDWR,0);
(void) dup(0); (void) dup(0);
(void) dup(0); (void) dup(0);
printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS, printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
NR_BUFFERS*BLOCK_SIZE); NR_BUFFERS*BLOCK_SIZE);
printf("Free mem: %d bytes\n\r",memory_end-main_memory_start); printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
if (!(pid=fork())) { if (!(pid=fork())) {
close(0); close(0);
if (open("/etc/rc",O_RDONLY,0)) if (open("/etc/rc",O_RDONLY,0))
_exit(1); _exit(1);
execve("/bin/sh",argv_rc,envp_rc); execve("/bin/sh",argv_rc,envp_rc);
_exit(2); _exit(2);
} }
if (pid>0) if (pid>0)
while (pid != wait(&i)) while (pid != wait(&i))
/* nothing */; /* nothing */;
while (1) { while (1) {
if ((pid=fork())<0) { if ((pid=fork())<0) {
printf("Fork failed in init\r\n"); printf("Fork failed in init\r\n");
continue; continue;
} }
if (!pid) { if (!pid) {
close(0);close(1);close(2); close(0);close(1);close(2);
setsid(); setsid();
(void) open("/dev/tty0",O_RDWR,0); (void) open("/dev/tty0",O_RDWR,0);
(void) dup(0); (void) dup(0);
(void) dup(0); (void) dup(0);
_exit(execve("/bin/sh",argv,envp)); _exit(execve("/bin/sh",argv,envp));
} }
while (1) while (1)
if (pid == wait(&i)) if (pid == wait(&i))
break; break;
printf("\n\rchild %d died with code %04x\n\r",pid,i); printf("\n\rchild %d died with code %04x\n\r",pid,i);
sync(); sync();
} }
_exit(0); /* NOTE! _exit, not exit() */ _exit(0); /* NOTE! _exit, not exit() */
} }

@ -1,83 +1,83 @@
# #
# Makefile for the FREAX-kernel. # Makefile for the FREAX-kernel.
# #
# Note! Dependencies are done automagically by 'make dep', which also # Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here # removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32 LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fomit-frame-pointer -finline-functions \ CFLAGS =-w -g -fomit-frame-pointer -finline-functions \
-nostdinc -fno-stack-protector -mcld -I../include -nostdinc -fno-stack-protector -mcld -I../include
CPP =gcc -E -nostdinc -I../include CPP =gcc -E -nostdinc -I../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
OBJS = sched.o system_call.o traps.o asm.o fork.o \ OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \ panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o signal.o mktime.o
kernel.o: $(OBJS) kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS) $(LD) -r -o kernel.o $(OBJS)
sync sync
clean: clean:
rm -f core *.o *.a tmp_make keyboard.s rm -f core *.o *.a tmp_make keyboard.s
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
(cd chr_drv; make clean) (cd chr_drv; make clean)
(cd blk_drv; make clean) (cd blk_drv; make clean)
(cd math; make clean) (cd math; make clean)
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
(cd chr_drv; make dep) (cd chr_drv; make dep)
(cd blk_drv; make dep) (cd blk_drv; make dep)
### Dependencies: ### Dependencies:
exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \ exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \ ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \ ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h ../include/asm/segment.h
fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \ fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/segment.h ../include/asm/system.h ../include/asm/segment.h ../include/asm/system.h
mktime.s mktime.o : mktime.c ../include/time.h mktime.s mktime.o : mktime.c ../include/time.h
panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h \ panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/mm.h ../include/signal.h
printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \ printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \
../include/linux/kernel.h ../include/linux/kernel.h
sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \ sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \ ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \ ../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \ ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
../include/asm/segment.h ../include/asm/segment.h
signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h \ signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \ ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \ sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \ ../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
../include/sys/times.h ../include/sys/utsname.h ../include/sys/times.h ../include/sys/utsname.h
traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \ traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \
../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \ ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h ../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h

@ -1,146 +1,146 @@
/* /*
* linux/kernel/asm.s * linux/kernel/asm.s
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* asm.s contains the low-level code for most hardware faults. * asm.s contains the low-level code for most hardware faults.
* page_exception is handled by the mm, so that isn't here. This * page_exception is handled by the mm, so that isn't here. This
* file also handles (hopefully) fpu-exceptions due to TS-bit, as * file also handles (hopefully) fpu-exceptions due to TS-bit, as
* the fpu must be properly saved/resored. This hasn't been tested. * the fpu must be properly saved/resored. This hasn't been tested.
*/ */
.globl divide_error,debug,nmi,int3,overflow,bounds,invalid_op .globl divide_error,debug,nmi,int3,overflow,bounds,invalid_op
.globl double_fault,coprocessor_segment_overrun .globl double_fault,coprocessor_segment_overrun
.globl invalid_TSS,segment_not_present,stack_segment .globl invalid_TSS,segment_not_present,stack_segment
.globl general_protection,coprocessor_error,irq13,reserved .globl general_protection,coprocessor_error,irq13,reserved
divide_error: divide_error:
pushl $do_divide_error pushl $do_divide_error
no_error_code: no_error_code:
xchgl %eax,(%esp) xchgl %eax,(%esp)
pushl %ebx pushl %ebx
pushl %ecx pushl %ecx
pushl %edx pushl %edx
pushl %edi pushl %edi
pushl %esi pushl %esi
pushl %ebp pushl %ebp
push %ds push %ds
push %es push %es
push %fs push %fs
pushl $0 # "error code" pushl $0 # "error code"
lea 44(%esp),%edx lea 44(%esp),%edx
pushl %edx pushl %edx
movl $0x10,%edx movl $0x10,%edx
mov %dx,%ds mov %dx,%ds
mov %dx,%es mov %dx,%es
mov %dx,%fs mov %dx,%fs
call *%eax call *%eax
addl $8,%esp addl $8,%esp
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
popl %ebp popl %ebp
popl %esi popl %esi
popl %edi popl %edi
popl %edx popl %edx
popl %ecx popl %ecx
popl %ebx popl %ebx
popl %eax popl %eax
iret iret
debug: debug:
pushl $do_int3 # _do_debug pushl $do_int3 # _do_debug
jmp no_error_code jmp no_error_code
nmi: nmi:
pushl $do_nmi pushl $do_nmi
jmp no_error_code jmp no_error_code
int3: int3:
pushl $do_int3 pushl $do_int3
jmp no_error_code jmp no_error_code
overflow: overflow:
pushl $do_overflow pushl $do_overflow
jmp no_error_code jmp no_error_code
bounds: bounds:
pushl $do_bounds pushl $do_bounds
jmp no_error_code jmp no_error_code
invalid_op: invalid_op:
pushl $do_invalid_op pushl $do_invalid_op
jmp no_error_code jmp no_error_code
coprocessor_segment_overrun: coprocessor_segment_overrun:
pushl $do_coprocessor_segment_overrun pushl $do_coprocessor_segment_overrun
jmp no_error_code jmp no_error_code
reserved: reserved:
pushl $do_reserved pushl $do_reserved
jmp no_error_code jmp no_error_code
irq13: irq13:
pushl %eax pushl %eax
xorb %al,%al xorb %al,%al
outb %al,$0xF0 outb %al,$0xF0
movb $0x20,%al movb $0x20,%al
outb %al,$0x20 outb %al,$0x20
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: outb %al,$0xA0 1: outb %al,$0xA0
popl %eax popl %eax
jmp coprocessor_error jmp coprocessor_error
double_fault: double_fault:
pushl $do_double_fault pushl $do_double_fault
error_code: error_code:
xchgl %eax,4(%esp) # error code <-> %eax xchgl %eax,4(%esp) # error code <-> %eax
xchgl %ebx,(%esp) # &function <-> %ebx xchgl %ebx,(%esp) # &function <-> %ebx
pushl %ecx pushl %ecx
pushl %edx pushl %edx
pushl %edi pushl %edi
pushl %esi pushl %esi
pushl %ebp pushl %ebp
push %ds push %ds
push %es push %es
push %fs push %fs
pushl %eax # error code pushl %eax # error code
lea 44(%esp),%eax # offset lea 44(%esp),%eax # offset
pushl %eax pushl %eax
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
mov %ax,%fs mov %ax,%fs
call *%ebx call *%ebx
addl $8,%esp addl $8,%esp
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
popl %ebp popl %ebp
popl %esi popl %esi
popl %edi popl %edi
popl %edx popl %edx
popl %ecx popl %ecx
popl %ebx popl %ebx
popl %eax popl %eax
iret iret
invalid_TSS: invalid_TSS:
pushl $do_invalid_TSS pushl $do_invalid_TSS
jmp error_code jmp error_code
segment_not_present: segment_not_present:
pushl $do_segment_not_present pushl $do_segment_not_present
jmp error_code jmp error_code
stack_segment: stack_segment:
pushl $do_stack_segment pushl $do_stack_segment
jmp error_code jmp error_code
general_protection: general_protection:
pushl $do_general_protection pushl $do_general_protection
jmp error_code jmp error_code

@ -1,58 +1,58 @@
# #
# Makefile for the FREAX-kernel block device drivers. # Makefile for the FREAX-kernel block device drivers.
# #
# Note! Dependencies are done automagically by 'make dep', which also # Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here # removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-s -x LDFLAGS =-s -x
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \
-finline-functions -nostdinc -fno-stack-protector -I../../include -finline-functions -nostdinc -fno-stack-protector -I../../include
CPP =gcc -E -nostdinc -I../../include CPP =gcc -E -nostdinc -I../../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o
blk_drv.a: $(OBJS) blk_drv.a: $(OBJS)
$(AR) rcs blk_drv.a $(OBJS) $(AR) rcs blk_drv.a $(OBJS)
sync sync
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
### Dependencies: ### Dependencies:
floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h \ floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \ ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
../../include/signal.h ../../include/linux/kernel.h \ ../../include/signal.h ../../include/linux/kernel.h \
../../include/linux/fdreg.h ../../include/asm/system.h \ ../../include/linux/fdreg.h ../../include/asm/system.h \
../../include/asm/io.h ../../include/asm/segment.h blk.h ../../include/asm/io.h ../../include/asm/segment.h blk.h
hd.s hd.o : hd.c ../../include/linux/config.h ../../include/linux/sched.h \ hd.s hd.o : hd.c ../../include/linux/config.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \ ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \ ../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
../../include/linux/kernel.h ../../include/linux/hdreg.h \ ../../include/linux/kernel.h ../../include/linux/hdreg.h \
../../include/asm/system.h ../../include/asm/io.h \ ../../include/asm/system.h ../../include/asm/io.h \
../../include/asm/segment.h blk.h ../../include/asm/segment.h blk.h
ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \ ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \ ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \ ../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
../../include/linux/kernel.h ../../include/asm/system.h blk.h ../../include/linux/kernel.h ../../include/asm/system.h blk.h

@ -1,140 +1,140 @@
#ifndef _BLK_H #ifndef _BLK_H
#define _BLK_H #define _BLK_H
#define NR_BLK_DEV 7 #define NR_BLK_DEV 7
/* /*
* NR_REQUEST is the number of entries in the request-queue. * NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads * NOTE that writes may use only the low 2/3 of these: reads
* take precedence. * take precedence.
* *
* 32 seems to be a reasonable number: enough to get some benefit * 32 seems to be a reasonable number: enough to get some benefit
* from the elevator-mechanism, but not so much as to lock a lot of * from the elevator-mechanism, but not so much as to lock a lot of
* buffers when they are in the queue. 64 seems to be too many (easily * buffers when they are in the queue. 64 seems to be too many (easily
* long pauses in reading when heavy writing/syncing is going on) * long pauses in reading when heavy writing/syncing is going on)
*/ */
#define NR_REQUEST 32 #define NR_REQUEST 32
/* /*
* Ok, this is an expanded form so that we can use the same * Ok, this is an expanded form so that we can use the same
* request for paging requests when that is implemented. In * request for paging requests when that is implemented. In
* paging, 'bh' is NULL, and 'waiting' is used to wait for * paging, 'bh' is NULL, and 'waiting' is used to wait for
* read/write completion. * read/write completion.
*/ */
struct request { struct request {
int dev; /* -1 if no request */ int dev; /* -1 if no request */
int cmd; /* READ or WRITE */ int cmd; /* READ or WRITE */
int errors; int errors;
unsigned long sector; unsigned long sector;
unsigned long nr_sectors; unsigned long nr_sectors;
char * buffer; char * buffer;
struct task_struct * waiting; struct task_struct * waiting;
struct buffer_head * bh; struct buffer_head * bh;
struct request * next; struct request * next;
}; };
/* /*
* This is used in the elevator algorithm: Note that * This is used in the elevator algorithm: Note that
* reads always go before writes. This is natural: reads * reads always go before writes. This is natural: reads
* are much more time-critical than writes. * are much more time-critical than writes.
*/ */
#define IN_ORDER(s1,s2) \ #define IN_ORDER(s1,s2) \
((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \ ((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \
((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \ ((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
(s1)->sector < (s2)->sector))) (s1)->sector < (s2)->sector)))
struct blk_dev_struct { struct blk_dev_struct {
void (*request_fn)(void); void (*request_fn)(void);
struct request * current_request; struct request * current_request;
}; };
extern struct blk_dev_struct blk_dev[NR_BLK_DEV]; extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
extern struct request request[NR_REQUEST]; extern struct request request[NR_REQUEST];
extern struct task_struct * wait_for_request; extern struct task_struct * wait_for_request;
#ifdef MAJOR_NR #ifdef MAJOR_NR
/* /*
* Add entries as needed. Currently the only block devices * Add entries as needed. Currently the only block devices
* supported are hard-disks and floppies. * supported are hard-disks and floppies.
*/ */
#if (MAJOR_NR == 1) #if (MAJOR_NR == 1)
/* ram disk */ /* ram disk */
#define DEVICE_NAME "ramdisk" #define DEVICE_NAME "ramdisk"
#define DEVICE_REQUEST do_rd_request #define DEVICE_REQUEST do_rd_request
#define DEVICE_NR(device) ((device) & 7) #define DEVICE_NR(device) ((device) & 7)
#define DEVICE_ON(device) #define DEVICE_ON(device)
#define DEVICE_OFF(device) #define DEVICE_OFF(device)
#elif (MAJOR_NR == 2) #elif (MAJOR_NR == 2)
/* floppy */ /* floppy */
#define DEVICE_NAME "floppy" #define DEVICE_NAME "floppy"
#define DEVICE_INTR do_floppy #define DEVICE_INTR do_floppy
#define DEVICE_REQUEST do_fd_request #define DEVICE_REQUEST do_fd_request
#define DEVICE_NR(device) ((device) & 3) #define DEVICE_NR(device) ((device) & 3)
#define DEVICE_ON(device) floppy_on(DEVICE_NR(device)) #define DEVICE_ON(device) floppy_on(DEVICE_NR(device))
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device)) #define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
#elif (MAJOR_NR == 3) #elif (MAJOR_NR == 3)
/* harddisk */ /* harddisk */
#define DEVICE_NAME "harddisk" #define DEVICE_NAME "harddisk"
#define DEVICE_INTR do_hd #define DEVICE_INTR do_hd
#define DEVICE_REQUEST do_hd_request #define DEVICE_REQUEST do_hd_request
#define DEVICE_NR(device) (MINOR(device)/5) #define DEVICE_NR(device) (MINOR(device)/5)
#define DEVICE_ON(device) #define DEVICE_ON(device)
#define DEVICE_OFF(device) #define DEVICE_OFF(device)
#elif (MAJOR_NR > 3) #elif (MAJOR_NR > 3)
/* unknown blk device */ /* unknown blk device */
#error "unknown blk device" #error "unknown blk device"
#endif #endif
#define CURRENT (blk_dev[MAJOR_NR].current_request) #define CURRENT (blk_dev[MAJOR_NR].current_request)
#define CURRENT_DEV DEVICE_NR(CURRENT->dev) #define CURRENT_DEV DEVICE_NR(CURRENT->dev)
#ifdef DEVICE_INTR #ifdef DEVICE_INTR
void (*DEVICE_INTR)(void) = NULL; void (*DEVICE_INTR)(void) = NULL;
#endif #endif
static void (DEVICE_REQUEST)(void); static void (DEVICE_REQUEST)(void);
static inline void unlock_buffer(struct buffer_head * bh) static inline void unlock_buffer(struct buffer_head * bh)
{ {
if (!bh->b_lock) if (!bh->b_lock)
printk(DEVICE_NAME ": free buffer being unlocked\n"); printk(DEVICE_NAME ": free buffer being unlocked\n");
bh->b_lock=0; bh->b_lock=0;
wake_up(&bh->b_wait); wake_up(&bh->b_wait);
} }
static inline void end_request(int uptodate) static inline void end_request(int uptodate)
{ {
DEVICE_OFF(CURRENT->dev); DEVICE_OFF(CURRENT->dev);
if (CURRENT->bh) { if (CURRENT->bh) {
CURRENT->bh->b_uptodate = uptodate; CURRENT->bh->b_uptodate = uptodate;
unlock_buffer(CURRENT->bh); unlock_buffer(CURRENT->bh);
} }
if (!uptodate) { if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r"); printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",CURRENT->dev, printk("dev %04x, block %d\n\r",CURRENT->dev,
CURRENT->bh->b_blocknr); CURRENT->bh->b_blocknr);
} }
wake_up(&CURRENT->waiting); wake_up(&CURRENT->waiting);
wake_up(&wait_for_request); wake_up(&wait_for_request);
CURRENT->dev = -1; CURRENT->dev = -1;
CURRENT = CURRENT->next; CURRENT = CURRENT->next;
} }
#define INIT_REQUEST \ #define INIT_REQUEST \
repeat: \ repeat: \
if (!CURRENT) \ if (!CURRENT) \
return; \ return; \
if (MAJOR(CURRENT->dev) != MAJOR_NR) \ if (MAJOR(CURRENT->dev) != MAJOR_NR) \
panic(DEVICE_NAME ": request list destroyed"); \ panic(DEVICE_NAME ": request list destroyed"); \
if (CURRENT->bh) { \ if (CURRENT->bh) { \
if (!CURRENT->bh->b_lock) \ if (!CURRENT->bh->b_lock) \
panic(DEVICE_NAME ": block not locked"); \ panic(DEVICE_NAME ": block not locked"); \
} }
#endif #endif
#endif #endif

@ -1,463 +1,463 @@
/* /*
* linux/kernel/floppy.c * linux/kernel/floppy.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 02.12.91 - Changed to static variables to indicate need for reset * 02.12.91 - Changed to static variables to indicate need for reset
* and recalibrate. This makes some things easier (output_byte reset * and recalibrate. This makes some things easier (output_byte reset
* checking etc), and means less interrupt jumping in case of errors, * checking etc), and means less interrupt jumping in case of errors,
* so the code is hopefully easier to understand. * so the code is hopefully easier to understand.
*/ */
/* /*
* This file is certainly a mess. I've tried my best to get it working, * This file is certainly a mess. I've tried my best to get it working,
* but I don't like programming floppies, and I have only one anyway. * but I don't like programming floppies, and I have only one anyway.
* Urgel. I should check for more errors, and do more graceful error * Urgel. I should check for more errors, and do more graceful error
* recovery. Seems there are problems with several drives. I've tried to * recovery. Seems there are problems with several drives. I've tried to
* correct them. No promises. * correct them. No promises.
*/ */
/* /*
* As with hd.c, all routines within this file can (and will) be called * As with hd.c, all routines within this file can (and will) be called
* by interrupts, so extreme caution is needed. A hardware interrupt * by interrupts, so extreme caution is needed. A hardware interrupt
* handler may not sleep, or a kernel panic will happen. Thus I cannot * handler may not sleep, or a kernel panic will happen. Thus I cannot
* call "floppy-on" directly, but have to set a special timer interrupt * call "floppy-on" directly, but have to set a special timer interrupt
* etc. * etc.
* *
* Also, I'm not certain this works on more than 1 floppy. Bugs may * Also, I'm not certain this works on more than 1 floppy. Bugs may
* abund. * abund.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/fdreg.h> #include <linux/fdreg.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
#define MAJOR_NR 2 #define MAJOR_NR 2
#include "blk.h" #include "blk.h"
static int recalibrate = 0; static int recalibrate = 0;
static int reset = 0; static int reset = 0;
static int seek = 0; static int seek = 0;
extern unsigned char current_DOR; extern unsigned char current_DOR;
#define immoutb_p(val,port) \ #define immoutb_p(val,port) \
__asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port)) __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
#define TYPE(x) ((x)>>2) #define TYPE(x) ((x)>>2)
#define DRIVE(x) ((x)&0x03) #define DRIVE(x) ((x)&0x03)
/* /*
* Note that MAX_ERRORS=8 doesn't imply that we retry every bad read * Note that MAX_ERRORS=8 doesn't imply that we retry every bad read
* max 8 times - some types of errors increase the errorcount by 2, * max 8 times - some types of errors increase the errorcount by 2,
* so we might actually retry only 5-6 times before giving up. * so we might actually retry only 5-6 times before giving up.
*/ */
#define MAX_ERRORS 8 #define MAX_ERRORS 8
/* /*
* globals used by 'result()' * globals used by 'result()'
*/ */
#define MAX_REPLIES 7 #define MAX_REPLIES 7
static unsigned char reply_buffer[MAX_REPLIES]; static unsigned char reply_buffer[MAX_REPLIES];
#define ST0 (reply_buffer[0]) #define ST0 (reply_buffer[0])
#define ST1 (reply_buffer[1]) #define ST1 (reply_buffer[1])
#define ST2 (reply_buffer[2]) #define ST2 (reply_buffer[2])
#define ST3 (reply_buffer[3]) #define ST3 (reply_buffer[3])
/* /*
* This struct defines the different floppy types. Unlike minix * This struct defines the different floppy types. Unlike minix
* linux doesn't have a "search for right type"-type, as the code * linux doesn't have a "search for right type"-type, as the code
* for that is convoluted and weird. I've got enough problems with * for that is convoluted and weird. I've got enough problems with
* this driver as it is. * this driver as it is.
* *
* The 'stretch' tells if the tracks need to be boubled for some * The 'stretch' tells if the tracks need to be boubled for some
* types (ie 360kB diskette in 1.2MB drive etc). Others should * types (ie 360kB diskette in 1.2MB drive etc). Others should
* be self-explanatory. * be self-explanatory.
*/ */
static struct floppy_struct { static struct floppy_struct {
unsigned int size, sect, head, track, stretch; unsigned int size, sect, head, track, stretch;
unsigned char gap,rate,spec1; unsigned char gap,rate,spec1;
} floppy_type[] = { } floppy_type[] = {
{ 0, 0,0, 0,0,0x00,0x00,0x00 }, /* no testing */ { 0, 0,0, 0,0,0x00,0x00,0x00 }, /* no testing */
{ 720, 9,2,40,0,0x2A,0x02,0xDF }, /* 360kB PC diskettes */ { 720, 9,2,40,0,0x2A,0x02,0xDF }, /* 360kB PC diskettes */
{ 2400,15,2,80,0,0x1B,0x00,0xDF }, /* 1.2 MB AT-diskettes */ { 2400,15,2,80,0,0x1B,0x00,0xDF }, /* 1.2 MB AT-diskettes */
{ 720, 9,2,40,1,0x2A,0x02,0xDF }, /* 360kB in 720kB drive */ { 720, 9,2,40,1,0x2A,0x02,0xDF }, /* 360kB in 720kB drive */
{ 1440, 9,2,80,0,0x2A,0x02,0xDF }, /* 3.5" 720kB diskette */ { 1440, 9,2,80,0,0x2A,0x02,0xDF }, /* 3.5" 720kB diskette */
{ 720, 9,2,40,1,0x23,0x01,0xDF }, /* 360kB in 1.2MB drive */ { 720, 9,2,40,1,0x23,0x01,0xDF }, /* 360kB in 1.2MB drive */
{ 1440, 9,2,80,0,0x23,0x01,0xDF }, /* 720kB in 1.2MB drive */ { 1440, 9,2,80,0,0x23,0x01,0xDF }, /* 720kB in 1.2MB drive */
{ 2880,18,2,80,0,0x1B,0x00,0xCF }, /* 1.44MB diskette */ { 2880,18,2,80,0,0x1B,0x00,0xCF }, /* 1.44MB diskette */
}; };
/* /*
* Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps * Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps
* Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc), * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
* H is head unload time (1=16ms, 2=32ms, etc) * H is head unload time (1=16ms, 2=32ms, etc)
* *
* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc) * Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)
* and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA). * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
*/ */
extern void floppy_interrupt(void); extern void floppy_interrupt(void);
extern char tmp_floppy_area[1024]; extern char tmp_floppy_area[1024];
/* /*
* These are global variables, as that's the easiest way to give * These are global variables, as that's the easiest way to give
* information to interrupts. They are the data used for the current * information to interrupts. They are the data used for the current
* request. * request.
*/ */
static int cur_spec1 = -1; static int cur_spec1 = -1;
static int cur_rate = -1; static int cur_rate = -1;
static struct floppy_struct * floppy = floppy_type; static struct floppy_struct * floppy = floppy_type;
static unsigned char current_drive = 0; static unsigned char current_drive = 0;
static unsigned char sector = 0; static unsigned char sector = 0;
static unsigned char head = 0; static unsigned char head = 0;
static unsigned char track = 0; static unsigned char track = 0;
static unsigned char seek_track = 0; static unsigned char seek_track = 0;
static unsigned char current_track = 255; static unsigned char current_track = 255;
static unsigned char command = 0; static unsigned char command = 0;
unsigned char selected = 0; unsigned char selected = 0;
struct task_struct * wait_on_floppy_select = NULL; struct task_struct * wait_on_floppy_select = NULL;
void floppy_deselect(unsigned int nr) void floppy_deselect(unsigned int nr)
{ {
if (nr != (current_DOR & 3)) if (nr != (current_DOR & 3))
printk("floppy_deselect: drive not selected\n\r"); printk("floppy_deselect: drive not selected\n\r");
selected = 0; selected = 0;
wake_up(&wait_on_floppy_select); wake_up(&wait_on_floppy_select);
} }
/* /*
* floppy-change is never called from an interrupt, so we can relax a bit * floppy-change is never called from an interrupt, so we can relax a bit
* here, sleep etc. Note that floppy-on tries to set current_DOR to point * here, sleep etc. Note that floppy-on tries to set current_DOR to point
* to the desired drive, but it will probably not survive the sleep if * to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop. * several floppies are used at the same time: thus the loop.
*/ */
int floppy_change(unsigned int nr) int floppy_change(unsigned int nr)
{ {
repeat: repeat:
floppy_on(nr); floppy_on(nr);
while ((current_DOR & 3) != nr && selected) while ((current_DOR & 3) != nr && selected)
interruptible_sleep_on(&wait_on_floppy_select); interruptible_sleep_on(&wait_on_floppy_select);
if ((current_DOR & 3) != nr) if ((current_DOR & 3) != nr)
goto repeat; goto repeat;
if (inb(FD_DIR) & 0x80) { if (inb(FD_DIR) & 0x80) {
floppy_off(nr); floppy_off(nr);
return 1; return 1;
} }
floppy_off(nr); floppy_off(nr);
return 0; return 0;
} }
#define copy_buffer(from,to) \ #define copy_buffer(from,to) \
__asm__("cld ; rep ; movsl" \ __asm__("cld ; rep ; movsl" \
::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \ ::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \
) )
static void setup_DMA(void) static void setup_DMA(void)
{ {
long addr = (long) CURRENT->buffer; long addr = (long) CURRENT->buffer;
cli(); cli();
if (addr >= 0x100000) { if (addr >= 0x100000) {
addr = (long) tmp_floppy_area; addr = (long) tmp_floppy_area;
if (command == FD_WRITE) if (command == FD_WRITE)
copy_buffer(CURRENT->buffer,tmp_floppy_area); copy_buffer(CURRENT->buffer,tmp_floppy_area);
} }
/* mask DMA 2 */ /* mask DMA 2 */
immoutb_p(4|2,10); immoutb_p(4|2,10);
/* output command byte. I don't know why, but everyone (minix, */ /* output command byte. I don't know why, but everyone (minix, */
/* sanches & canton) output this twice, first to 12 then to 11 */ /* sanches & canton) output this twice, first to 12 then to 11 */
__asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t" __asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"
"outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:":: "outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::
"a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE))); "a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE)));
/* 8 low bits of addr */ /* 8 low bits of addr */
immoutb_p(addr,4); immoutb_p(addr,4);
addr >>= 8; addr >>= 8;
/* bits 8-15 of addr */ /* bits 8-15 of addr */
immoutb_p(addr,4); immoutb_p(addr,4);
addr >>= 8; addr >>= 8;
/* bits 16-19 of addr */ /* bits 16-19 of addr */
immoutb_p(addr,0x81); immoutb_p(addr,0x81);
/* low 8 bits of count-1 (1024-1=0x3ff) */ /* low 8 bits of count-1 (1024-1=0x3ff) */
immoutb_p(0xff,5); immoutb_p(0xff,5);
/* high 8 bits of count-1 */ /* high 8 bits of count-1 */
immoutb_p(3,5); immoutb_p(3,5);
/* activate DMA 2 */ /* activate DMA 2 */
immoutb_p(0|2,10); immoutb_p(0|2,10);
sti(); sti();
} }
static void output_byte(char byte) static void output_byte(char byte)
{ {
int counter; int counter;
unsigned char status; unsigned char status;
if (reset) if (reset)
return; return;
for(counter = 0 ; counter < 10000 ; counter++) { for(counter = 0 ; counter < 10000 ; counter++) {
status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR); status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
if (status == STATUS_READY) { if (status == STATUS_READY) {
outb(byte,FD_DATA); outb(byte,FD_DATA);
return; return;
} }
} }
reset = 1; reset = 1;
printk("Unable to send byte to FDC\n\r"); printk("Unable to send byte to FDC\n\r");
} }
static int result(void) static int result(void)
{ {
int i = 0, counter, status; int i = 0, counter, status;
if (reset) if (reset)
return -1; return -1;
for (counter = 0 ; counter < 10000 ; counter++) { for (counter = 0 ; counter < 10000 ; counter++) {
status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY); status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
if (status == STATUS_READY) if (status == STATUS_READY)
return i; return i;
if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) { if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
if (i >= MAX_REPLIES) if (i >= MAX_REPLIES)
break; break;
reply_buffer[i++] = inb_p(FD_DATA); reply_buffer[i++] = inb_p(FD_DATA);
} }
} }
reset = 1; reset = 1;
printk("Getstatus times out\n\r"); printk("Getstatus times out\n\r");
return -1; return -1;
} }
static void bad_flp_intr(void) static void bad_flp_intr(void)
{ {
CURRENT->errors++; CURRENT->errors++;
if (CURRENT->errors > MAX_ERRORS) { if (CURRENT->errors > MAX_ERRORS) {
floppy_deselect(current_drive); floppy_deselect(current_drive);
end_request(0); end_request(0);
} }
if (CURRENT->errors > MAX_ERRORS/2) if (CURRENT->errors > MAX_ERRORS/2)
reset = 1; reset = 1;
else else
recalibrate = 1; recalibrate = 1;
} }
/* /*
* Ok, this interrupt is called after a DMA read/write has succeeded, * Ok, this interrupt is called after a DMA read/write has succeeded,
* so we check the results, and copy any buffers. * so we check the results, and copy any buffers.
*/ */
static void rw_interrupt(void) static void rw_interrupt(void)
{ {
if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) { if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {
if (ST1 & 0x02) { if (ST1 & 0x02) {
printk("Drive %d is write protected\n\r",current_drive); printk("Drive %d is write protected\n\r",current_drive);
floppy_deselect(current_drive); floppy_deselect(current_drive);
end_request(0); end_request(0);
} else } else
bad_flp_intr(); bad_flp_intr();
do_fd_request(); do_fd_request();
return; return;
} }
if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000) if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000)
copy_buffer(tmp_floppy_area,CURRENT->buffer); copy_buffer(tmp_floppy_area,CURRENT->buffer);
floppy_deselect(current_drive); floppy_deselect(current_drive);
end_request(1); end_request(1);
do_fd_request(); do_fd_request();
} }
inline void setup_rw_floppy(void) inline void setup_rw_floppy(void)
{ {
setup_DMA(); setup_DMA();
do_floppy = rw_interrupt; do_floppy = rw_interrupt;
output_byte(command); output_byte(command);
output_byte(head<<2 | current_drive); output_byte(head<<2 | current_drive);
output_byte(track); output_byte(track);
output_byte(head); output_byte(head);
output_byte(sector); output_byte(sector);
output_byte(2); /* sector size = 512 */ output_byte(2); /* sector size = 512 */
output_byte(floppy->sect); output_byte(floppy->sect);
output_byte(floppy->gap); output_byte(floppy->gap);
output_byte(0xFF); /* sector size (0xff when n!=0 ?) */ output_byte(0xFF); /* sector size (0xff when n!=0 ?) */
if (reset) if (reset)
do_fd_request(); do_fd_request();
} }
/* /*
* This is the routine called after every seek (or recalibrate) interrupt * This is the routine called after every seek (or recalibrate) interrupt
* from the floppy controller. Note that the "unexpected interrupt" routine * from the floppy controller. Note that the "unexpected interrupt" routine
* also does a recalibrate, but doesn't come here. * also does a recalibrate, but doesn't come here.
*/ */
static void seek_interrupt(void) static void seek_interrupt(void)
{ {
/* sense drive status */ /* sense drive status */
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) { if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
bad_flp_intr(); bad_flp_intr();
do_fd_request(); do_fd_request();
return; return;
} }
current_track = ST1; current_track = ST1;
setup_rw_floppy(); setup_rw_floppy();
} }
/* /*
* This routine is called when everything should be correctly set up * This routine is called when everything should be correctly set up
* for the transfer (ie floppy motor is on and the correct floppy is * for the transfer (ie floppy motor is on and the correct floppy is
* selected). * selected).
*/ */
static void transfer(void) static void transfer(void)
{ {
if (cur_spec1 != floppy->spec1) { if (cur_spec1 != floppy->spec1) {
cur_spec1 = floppy->spec1; cur_spec1 = floppy->spec1;
output_byte(FD_SPECIFY); output_byte(FD_SPECIFY);
output_byte(cur_spec1); /* hut etc */ output_byte(cur_spec1); /* hut etc */
output_byte(6); /* Head load time =6ms, DMA */ output_byte(6); /* Head load time =6ms, DMA */
} }
if (cur_rate != floppy->rate) if (cur_rate != floppy->rate)
outb_p(cur_rate = floppy->rate,FD_DCR); outb_p(cur_rate = floppy->rate,FD_DCR);
if (reset) { if (reset) {
do_fd_request(); do_fd_request();
return; return;
} }
if (!seek) { if (!seek) {
setup_rw_floppy(); setup_rw_floppy();
return; return;
} }
do_floppy = seek_interrupt; do_floppy = seek_interrupt;
if (seek_track) { if (seek_track) {
output_byte(FD_SEEK); output_byte(FD_SEEK);
output_byte(head<<2 | current_drive); output_byte(head<<2 | current_drive);
output_byte(seek_track); output_byte(seek_track);
} else { } else {
output_byte(FD_RECALIBRATE); output_byte(FD_RECALIBRATE);
output_byte(head<<2 | current_drive); output_byte(head<<2 | current_drive);
} }
if (reset) if (reset)
do_fd_request(); do_fd_request();
} }
/* /*
* Special case - used after a unexpected interrupt (or reset) * Special case - used after a unexpected interrupt (or reset)
*/ */
static void recal_interrupt(void) static void recal_interrupt(void)
{ {
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60) if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1; reset = 1;
else else
recalibrate = 0; recalibrate = 0;
do_fd_request(); do_fd_request();
} }
void unexpected_floppy_interrupt(void) void unexpected_floppy_interrupt(void)
{ {
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60) if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1; reset = 1;
else else
recalibrate = 1; recalibrate = 1;
} }
static void recalibrate_floppy(void) static void recalibrate_floppy(void)
{ {
recalibrate = 0; recalibrate = 0;
current_track = 0; current_track = 0;
current_drive = 1; /* by wyj, ?? */ current_drive = 1; /* by wyj, ?? */
do_floppy = recal_interrupt; do_floppy = recal_interrupt;
output_byte(FD_RECALIBRATE); output_byte(FD_RECALIBRATE);
output_byte(head<<2 | current_drive); output_byte(head<<2 | current_drive);
if (reset) if (reset)
do_fd_request(); do_fd_request();
} }
static void reset_interrupt(void) static void reset_interrupt(void)
{ {
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
(void) result(); (void) result();
output_byte(FD_SPECIFY); output_byte(FD_SPECIFY);
output_byte(cur_spec1); /* hut etc */ output_byte(cur_spec1); /* hut etc */
output_byte(6); /* Head load time =6ms, DMA */ output_byte(6); /* Head load time =6ms, DMA */
do_fd_request(); do_fd_request();
} }
/* /*
* reset is done by pulling bit 2 of DOR low for a while. * reset is done by pulling bit 2 of DOR low for a while.
*/ */
static void reset_floppy(void) static void reset_floppy(void)
{ {
int i; int i;
reset = 0; reset = 0;
cur_spec1 = -1; cur_spec1 = -1;
cur_rate = -1; cur_rate = -1;
recalibrate = 1; recalibrate = 1;
printk("Reset-floppy called\n\r"); printk("Reset-floppy called\n\r");
cli(); cli();
do_floppy = reset_interrupt; do_floppy = reset_interrupt;
outb_p(current_DOR & ~0x04,FD_DOR); outb_p(current_DOR & ~0x04,FD_DOR);
for (i=0 ; i<100 ; i++) for (i=0 ; i<100 ; i++)
__asm__("nop"); __asm__("nop");
outb(current_DOR,FD_DOR); outb(current_DOR,FD_DOR);
sti(); sti();
} }
static void floppy_on_interrupt(void) static void floppy_on_interrupt(void)
{ {
/* We cannot do a floppy-select, as that might sleep. We just force it */ /* We cannot do a floppy-select, as that might sleep. We just force it */
selected = 1; selected = 1;
if (current_drive != (current_DOR & 3)) { if (current_drive != (current_DOR & 3)) {
current_DOR &= 0xFC; current_DOR &= 0xFC;
current_DOR |= current_drive; current_DOR |= current_drive;
outb(current_DOR,FD_DOR); outb(current_DOR,FD_DOR);
add_timer(2,&transfer); add_timer(2,&transfer);
} else } else
transfer(); transfer();
} }
void do_fd_request(void) void do_fd_request(void)
{ {
unsigned int block; unsigned int block;
seek = 0; seek = 0;
if (reset) { if (reset) {
reset_floppy(); reset_floppy();
return; return;
} }
if (recalibrate) { if (recalibrate) {
recalibrate_floppy(); recalibrate_floppy();
return; return;
} }
INIT_REQUEST; INIT_REQUEST;
floppy = (MINOR(CURRENT->dev)>>2) + floppy_type; floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
if (current_drive != CURRENT_DEV) if (current_drive != CURRENT_DEV)
seek = 1; seek = 1;
current_drive = CURRENT_DEV; current_drive = CURRENT_DEV;
block = CURRENT->sector; block = CURRENT->sector;
if (block+2 > floppy->size) { if (block+2 > floppy->size) {
end_request(0); end_request(0);
goto repeat; goto repeat;
} }
sector = block % floppy->sect; sector = block % floppy->sect;
block /= floppy->sect; block /= floppy->sect;
head = block % floppy->head; head = block % floppy->head;
track = block / floppy->head; track = block / floppy->head;
seek_track = track << floppy->stretch; seek_track = track << floppy->stretch;
if (seek_track != current_track) if (seek_track != current_track)
seek = 1; seek = 1;
sector++; sector++;
if (CURRENT->cmd == READ) if (CURRENT->cmd == READ)
command = FD_READ; command = FD_READ;
else if (CURRENT->cmd == WRITE) else if (CURRENT->cmd == WRITE)
command = FD_WRITE; command = FD_WRITE;
else else
panic("do_fd_request: unknown command"); panic("do_fd_request: unknown command");
add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt); add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
} }
void floppy_init(void) void floppy_init(void)
{ {
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_trap_gate(0x26,&floppy_interrupt); set_trap_gate(0x26,&floppy_interrupt);
outb(inb_p(0x21)&~0x40,0x21); outb(inb_p(0x21)&~0x40,0x21);
} }

@ -1,351 +1,351 @@
/* /*
* linux/kernel/hd.c * linux/kernel/hd.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* This is the low-level hd interrupt support. It traverses the * This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As * request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not * all the functions are called within interrupts, we may not
* sleep. Special care is recommended. * sleep. Special care is recommended.
* *
* modified by Drew Eckhardt to check nr of hd's from the CMOS. * modified by Drew Eckhardt to check nr of hd's from the CMOS.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
#define MAJOR_NR 3 #define MAJOR_NR 3
#include "blk.h" #include "blk.h"
#define CMOS_READ(addr) ({ \ #define CMOS_READ(addr) ({ \
outb_p(0x80|addr,0x70); \ outb_p(0x80|addr,0x70); \
inb_p(0x71); \ inb_p(0x71); \
}) })
/* Max read/write errors/sector */ /* Max read/write errors/sector */
#define MAX_ERRORS 7 #define MAX_ERRORS 7
#define MAX_HD 2 #define MAX_HD 2
static void recal_intr(void); static void recal_intr(void);
static int recalibrate = 0; /* 1, wen */ static int recalibrate = 0; /* 1, wen */
static int reset = 0; static int reset = 0;
/* /*
* This struct defines the HD's and their types. * This struct defines the HD's and their types.
*/ */
struct hd_i_struct { struct hd_i_struct {
int head,sect,cyl,wpcom,lzone,ctl; int head,sect,cyl,wpcom,lzone,ctl;
}; };
#ifdef HD_TYPE #ifdef HD_TYPE
struct hd_i_struct hd_info[] = { HD_TYPE }; struct hd_i_struct hd_info[] = { HD_TYPE };
#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct))) #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
#else #else
struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
static int NR_HD = 0; static int NR_HD = 0;
#endif #endif
static struct hd_struct { static struct hd_struct {
long start_sect; long start_sect;
long nr_sects; long nr_sects;
} hd[5*MAX_HD]={{0,0},}; } hd[5*MAX_HD]={{0,0},};
#define port_read(port,buf,nr) \ #define port_read(port,buf,nr) \
__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr)) __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr))
#define port_write(port,buf,nr) \ #define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr)) __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr))
extern void hd_interrupt(void); extern void hd_interrupt(void);
extern void rd_load(void); extern void rd_load(void);
/* This may be used only once, enforced by 'static int callable' */ /* This may be used only once, enforced by 'static int callable' */
int sys_setup(void * BIOS) int sys_setup(void * BIOS)
{ {
static int callable = 1; static int callable = 1;
int i,drive; int i,drive;
unsigned char cmos_disks; unsigned char cmos_disks;
struct partition *p; struct partition *p;
struct buffer_head * bh; struct buffer_head * bh;
if (!callable) if (!callable)
return -1; return -1;
callable = 0; callable = 0;
#ifndef HD_TYPE #ifndef HD_TYPE
for (drive=0 ; drive<2 ; drive++) { for (drive=0 ; drive<2 ; drive++) {
hd_info[drive].cyl = *(unsigned short *) BIOS; hd_info[drive].cyl = *(unsigned short *) BIOS;
hd_info[drive].head = *(unsigned char *) (2+BIOS); hd_info[drive].head = *(unsigned char *) (2+BIOS);
hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
hd_info[drive].ctl = *(unsigned char *) (8+BIOS); hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
hd_info[drive].lzone = *(unsigned short *) (12+BIOS); hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
hd_info[drive].sect = *(unsigned char *) (14+BIOS); hd_info[drive].sect = *(unsigned char *) (14+BIOS);
BIOS += 16; BIOS += 16;
} }
if (hd_info[1].cyl) if (hd_info[1].cyl)
NR_HD=2; NR_HD=2;
else else
NR_HD=1; NR_HD=1;
#endif #endif
for (i=0 ; i<NR_HD ; i++) { for (i=0 ; i<NR_HD ; i++) {
hd[i*5].start_sect = 0; hd[i*5].start_sect = 0;
hd[i*5].nr_sects = hd_info[i].head* hd[i*5].nr_sects = hd_info[i].head*
hd_info[i].sect*hd_info[i].cyl; hd_info[i].sect*hd_info[i].cyl;
} }
/* /*
We querry CMOS about hard disks : it could be that We querry CMOS about hard disks : it could be that
we have a SCSI/ESDI/etc controller that is BIOS we have a SCSI/ESDI/etc controller that is BIOS
compatable with ST-506, and thus showing up in our compatable with ST-506, and thus showing up in our
BIOS table, but not register compatable, and therefore BIOS table, but not register compatable, and therefore
not present in CMOS. not present in CMOS.
Furthurmore, we will assume that our ST-506 drives Furthurmore, we will assume that our ST-506 drives
<if any> are the primary drives in the system, and <if any> are the primary drives in the system, and
the ones reflected as drive 1 or 2. the ones reflected as drive 1 or 2.
The first drive is stored in the high nibble of CMOS The first drive is stored in the high nibble of CMOS
byte 0x12, the second in the low nibble. This will be byte 0x12, the second in the low nibble. This will be
either a 4 bit drive type or 0xf indicating use byte 0x19 either a 4 bit drive type or 0xf indicating use byte 0x19
for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
Needless to say, a non-zero value means we have Needless to say, a non-zero value means we have
an AT controller hard disk for that drive. an AT controller hard disk for that drive.
*/ */
if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
if (cmos_disks & 0x0f) if (cmos_disks & 0x0f)
NR_HD = 2; NR_HD = 2;
else else
NR_HD = 1; NR_HD = 1;
else else
NR_HD = 0; NR_HD = 0;
for (i = NR_HD ; i < 2 ; i++) { for (i = NR_HD ; i < 2 ; i++) {
hd[i*5].start_sect = 0; hd[i*5].start_sect = 0;
hd[i*5].nr_sects = 0; hd[i*5].nr_sects = 0;
} }
for (drive=0 ; drive<NR_HD ; drive++) { for (drive=0 ; drive<NR_HD ; drive++) {
if (!(bh = bread(0x300 + drive*5,0))) { if (!(bh = bread(0x300 + drive*5,0))) {
printk("Unable to read partition table of drive %d\n\r", printk("Unable to read partition table of drive %d\n\r",
drive); drive);
panic(""); panic("");
} }
if (bh->b_data[510] != 0x55 || (unsigned char) if (bh->b_data[510] != 0x55 || (unsigned char)
bh->b_data[511] != 0xAA) { bh->b_data[511] != 0xAA) {
printk("Bad partition table on drive %d\n\r",drive); printk("Bad partition table on drive %d\n\r",drive);
panic(""); panic("");
} }
p = 0x1BE + (void *)bh->b_data; p = 0x1BE + (void *)bh->b_data;
for (i=1;i<5;i++,p++) { for (i=1;i<5;i++,p++) {
hd[i+5*drive].start_sect = p->start_sect; hd[i+5*drive].start_sect = p->start_sect;
hd[i+5*drive].nr_sects = p->nr_sects; hd[i+5*drive].nr_sects = p->nr_sects;
} }
brelse(bh); brelse(bh);
} }
if (NR_HD) if (NR_HD)
printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":""); printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
rd_load(); rd_load();
mount_root(); mount_root();
return (0); return (0);
} }
static int controller_ready(void) static int controller_ready(void)
{ {
/* int retries=10000; */ /* int retries=10000; */
int retries=100000; int retries=100000;
/* while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40); */ /* while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40); */
while (--retries && (inb_p(HD_STATUS)&0x80)); while (--retries && (inb_p(HD_STATUS)&0x80));
return (retries); return (retries);
} }
static int win_result(void) static int win_result(void)
{ {
int i=inb_p(HD_STATUS); int i=inb_p(HD_STATUS);
if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)) if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
== (READY_STAT | SEEK_STAT)) == (READY_STAT | SEEK_STAT))
return(0); /* ok */ return(0); /* ok */
if (i&1) i=inb(HD_ERROR); if (i&1) i=inb(HD_ERROR);
return (1); return (1);
} }
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
unsigned int head,unsigned int cyl,unsigned int cmd, unsigned int head,unsigned int cyl,unsigned int cmd,
void (*intr_addr)(void)) void (*intr_addr)(void))
{ {
register int port asm("dx"); register int port asm("dx");
if (drive>1 || head>15) if (drive>1 || head>15)
panic("Trying to write bad sector"); panic("Trying to write bad sector");
if (!controller_ready()) if (!controller_ready())
panic("HD controller not ready"); panic("HD controller not ready");
do_hd = intr_addr; do_hd = intr_addr;
outb_p(hd_info[drive].ctl,HD_CMD); outb_p(hd_info[drive].ctl,HD_CMD);
port=HD_DATA; port=HD_DATA;
outb_p(hd_info[drive].wpcom>>2,++port); outb_p(hd_info[drive].wpcom>>2,++port);
outb_p(nsect,++port); outb_p(nsect,++port);
outb_p(sect,++port); outb_p(sect,++port);
outb_p(cyl,++port); outb_p(cyl,++port);
outb_p(cyl>>8,++port); outb_p(cyl>>8,++port);
outb_p(0xA0|(drive<<4)|head,++port); outb_p(0xA0|(drive<<4)|head,++port);
outb(cmd,++port); outb(cmd,++port);
} }
static int drive_busy(void) static int drive_busy(void)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < 10000; i++) for (i = 0; i < 10000; i++)
if (READY_STAT == (inb_p(HD_STATUS) & (BUSY_STAT|READY_STAT))) if (READY_STAT == (inb_p(HD_STATUS) & (BUSY_STAT|READY_STAT)))
break; break;
i = inb(HD_STATUS); i = inb(HD_STATUS);
i &= BUSY_STAT | READY_STAT | SEEK_STAT; i &= BUSY_STAT | READY_STAT | SEEK_STAT;
if (i == READY_STAT | SEEK_STAT) if (i == READY_STAT | SEEK_STAT)
return(0); return(0);
printk("HD controller times out\n\r"); printk("HD controller times out\n\r");
return(1); return(1);
} }
static void reset_controller(void) static void reset_controller(void)
{ {
int i; int i;
outb(4,HD_CMD); outb(4,HD_CMD);
for(i = 0; i < 100; i++) nop(); for(i = 0; i < 100; i++) nop();
outb(hd_info[0].ctl & 0x0f ,HD_CMD); outb(hd_info[0].ctl & 0x0f ,HD_CMD);
if (drive_busy()) if (drive_busy())
printk("HD-controller still busy\n\r"); printk("HD-controller still busy\n\r");
if ((i = inb(HD_ERROR)) != 1) if ((i = inb(HD_ERROR)) != 1)
printk("HD-controller reset failed: %02x\n\r",i); printk("HD-controller reset failed: %02x\n\r",i);
} }
static void reset_hd(int nr) static void reset_hd(int nr)
{ {
reset_controller(); reset_controller();
hd_out(nr,hd_info[nr].sect,hd_info[nr].sect,hd_info[nr].head-1, hd_out(nr,hd_info[nr].sect,hd_info[nr].sect,hd_info[nr].head-1,
hd_info[nr].cyl,WIN_SPECIFY,&recal_intr); hd_info[nr].cyl,WIN_SPECIFY,&recal_intr);
} }
void unexpected_hd_interrupt(void) void unexpected_hd_interrupt(void)
{ {
printk("Unexpected HD interrupt\n\r"); printk("Unexpected HD interrupt\n\r");
} }
static void bad_rw_intr(void) static void bad_rw_intr(void)
{ {
if (++CURRENT->errors >= MAX_ERRORS) if (++CURRENT->errors >= MAX_ERRORS)
end_request(0); end_request(0);
if (CURRENT->errors > MAX_ERRORS/2) if (CURRENT->errors > MAX_ERRORS/2)
reset = 1; reset = 1;
} }
static void read_intr(void) static void read_intr(void)
{ {
if (win_result()) { if (win_result()) {
bad_rw_intr(); bad_rw_intr();
do_hd_request(); do_hd_request();
return; return;
} }
port_read(HD_DATA,CURRENT->buffer,256); port_read(HD_DATA,CURRENT->buffer,256);
CURRENT->errors = 0; CURRENT->errors = 0;
CURRENT->buffer += 512; CURRENT->buffer += 512;
CURRENT->sector++; CURRENT->sector++;
if (--CURRENT->nr_sectors) { if (--CURRENT->nr_sectors) {
do_hd = &read_intr; do_hd = &read_intr;
return; return;
} }
end_request(1); end_request(1);
do_hd_request(); do_hd_request();
} }
static void write_intr(void) static void write_intr(void)
{ {
if (win_result()) { if (win_result()) {
bad_rw_intr(); bad_rw_intr();
do_hd_request(); do_hd_request();
return; return;
} }
if (--CURRENT->nr_sectors) { if (--CURRENT->nr_sectors) {
CURRENT->sector++; CURRENT->sector++;
CURRENT->buffer += 512; CURRENT->buffer += 512;
do_hd = &write_intr; do_hd = &write_intr;
port_write(HD_DATA,CURRENT->buffer,256); port_write(HD_DATA,CURRENT->buffer,256);
return; return;
} }
end_request(1); end_request(1);
do_hd_request(); do_hd_request();
} }
static void recal_intr(void) static void recal_intr(void)
{ {
if (win_result()) if (win_result())
bad_rw_intr(); bad_rw_intr();
do_hd_request(); do_hd_request();
} }
void do_hd_request(void) void do_hd_request(void)
{ {
int i,r; int i,r;
unsigned int block,dev; unsigned int block,dev;
unsigned int sec,head,cyl; unsigned int sec,head,cyl;
unsigned int nsect; unsigned int nsect;
INIT_REQUEST; INIT_REQUEST;
dev = MINOR(CURRENT->dev); dev = MINOR(CURRENT->dev);
block = CURRENT->sector; block = CURRENT->sector;
if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) { if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
end_request(0); end_request(0);
goto repeat; goto repeat;
} }
block += hd[dev].start_sect; block += hd[dev].start_sect;
dev /= 5; dev /= 5;
__asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0), __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
"r" (hd_info[dev].sect)); "r" (hd_info[dev].sect));
__asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0), __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
"r" (hd_info[dev].head)); "r" (hd_info[dev].head));
sec++; sec++;
nsect = CURRENT->nr_sectors; nsect = CURRENT->nr_sectors;
if (reset) { if (reset) {
reset = 0; reset = 0;
recalibrate = 1; recalibrate = 1;
reset_hd(CURRENT_DEV); reset_hd(CURRENT_DEV);
return; return;
} }
if (recalibrate) { if (recalibrate) {
recalibrate = 0; recalibrate = 0;
hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0, hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
WIN_RESTORE,&recal_intr); WIN_RESTORE,&recal_intr);
return; return;
} }
if (CURRENT->cmd == WRITE) { if (CURRENT->cmd == WRITE) {
hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++) for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
/* nothing */ ; /* nothing */ ;
if (!r) { if (!r) {
bad_rw_intr(); bad_rw_intr();
goto repeat; goto repeat;
} }
port_write(HD_DATA,CURRENT->buffer,256); port_write(HD_DATA,CURRENT->buffer,256);
} else if (CURRENT->cmd == READ) { } else if (CURRENT->cmd == READ) {
hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
} else } else
panic("unknown hd-command"); panic("unknown hd-command");
} }
void hd_init(void) void hd_init(void)
{ {
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_intr_gate(0x2E,&hd_interrupt); set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21); outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1); outb(inb_p(0xA1)&0xbf,0xA1);
} }

@ -1,165 +1,165 @@
/* /*
* linux/kernel/blk_dev/ll_rw.c * linux/kernel/blk_dev/ll_rw.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* This handles all read/write requests to block devices * This handles all read/write requests to block devices
*/ */
#include <errno.h> #include <errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include "blk.h" #include "blk.h"
/* /*
* The request-struct contains all necessary data * The request-struct contains all necessary data
* to load a nr of sectors into memory * to load a nr of sectors into memory
*/ */
struct request request[NR_REQUEST]; struct request request[NR_REQUEST];
/* /*
* used to wait on when there are no free requests * used to wait on when there are no free requests
*/ */
struct task_struct * wait_for_request = NULL; struct task_struct * wait_for_request = NULL;
/* blk_dev_struct is: /* blk_dev_struct is:
* do_request-address * do_request-address
* next-request * next-request
*/ */
struct blk_dev_struct blk_dev[NR_BLK_DEV] = { struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
{ NULL, NULL }, /* no_dev */ { NULL, NULL }, /* no_dev */
{ NULL, NULL }, /* dev mem */ { NULL, NULL }, /* dev mem */
{ NULL, NULL }, /* dev fd */ { NULL, NULL }, /* dev fd */
{ NULL, NULL }, /* dev hd */ { NULL, NULL }, /* dev hd */
{ NULL, NULL }, /* dev ttyx */ { NULL, NULL }, /* dev ttyx */
{ NULL, NULL }, /* dev tty */ { NULL, NULL }, /* dev tty */
{ NULL, NULL } /* dev lp */ { NULL, NULL } /* dev lp */
}; };
static inline void lock_buffer(struct buffer_head * bh) static inline void lock_buffer(struct buffer_head * bh)
{ {
cli(); cli();
while (bh->b_lock) while (bh->b_lock)
sleep_on(&bh->b_wait); sleep_on(&bh->b_wait);
bh->b_lock=1; bh->b_lock=1;
sti(); sti();
} }
static inline void unlock_buffer(struct buffer_head * bh) static inline void unlock_buffer(struct buffer_head * bh)
{ {
if (!bh->b_lock) if (!bh->b_lock)
printk("ll_rw_block.c: buffer not locked\n\r"); printk("ll_rw_block.c: buffer not locked\n\r");
bh->b_lock = 0; bh->b_lock = 0;
wake_up(&bh->b_wait); wake_up(&bh->b_wait);
} }
/* /*
* add-request adds a request to the linked list. * add-request adds a request to the linked list.
* It disables interrupts so that it can muck with the * It disables interrupts so that it can muck with the
* request-lists in peace. * request-lists in peace.
*/ */
static void add_request(struct blk_dev_struct * dev, struct request * req) static void add_request(struct blk_dev_struct * dev, struct request * req)
{ {
struct request * tmp; struct request * tmp;
req->next = NULL; req->next = NULL;
cli(); cli();
if (req->bh) if (req->bh)
req->bh->b_dirt = 0; req->bh->b_dirt = 0;
if (!(tmp = dev->current_request)) { if (!(tmp = dev->current_request)) {
dev->current_request = req; dev->current_request = req;
sti(); sti();
(dev->request_fn)(); (dev->request_fn)();
return; return;
} }
for ( ; tmp->next ; tmp=tmp->next) for ( ; tmp->next ; tmp=tmp->next)
if ((IN_ORDER(tmp,req) || if ((IN_ORDER(tmp,req) ||
!IN_ORDER(tmp,tmp->next)) && !IN_ORDER(tmp,tmp->next)) &&
IN_ORDER(req,tmp->next)) IN_ORDER(req,tmp->next))
break; break;
req->next=tmp->next; req->next=tmp->next;
tmp->next=req; tmp->next=req;
sti(); sti();
} }
static void make_request(int major,int rw, struct buffer_head * bh) static void make_request(int major,int rw, struct buffer_head * bh)
{ {
struct request * req; struct request * req;
int rw_ahead; int rw_ahead;
/* WRITEA/READA is special case - it is not really needed, so if the */ /* WRITEA/READA is special case - it is not really needed, so if the */
/* buffer is locked, we just forget about it, else it's a normal read */ /* buffer is locked, we just forget about it, else it's a normal read */
if (rw_ahead = (rw == READA || rw == WRITEA)) { if (rw_ahead = (rw == READA || rw == WRITEA)) {
if (bh->b_lock) if (bh->b_lock)
return; return;
if (rw == READA) if (rw == READA)
rw = READ; rw = READ;
else else
rw = WRITE; rw = WRITE;
} }
if (rw!=READ && rw!=WRITE) if (rw!=READ && rw!=WRITE)
panic("Bad block dev command, must be R/W/RA/WA"); panic("Bad block dev command, must be R/W/RA/WA");
lock_buffer(bh); lock_buffer(bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) { if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
unlock_buffer(bh); unlock_buffer(bh);
return; return;
} }
repeat: repeat:
/* we don't allow the write-requests to fill up the queue completely: /* we don't allow the write-requests to fill up the queue completely:
* we want some room for reads: they take precedence. The last third * we want some room for reads: they take precedence. The last third
* of the requests are only for reads. * of the requests are only for reads.
*/ */
if (rw == READ) if (rw == READ)
req = request+NR_REQUEST; req = request+NR_REQUEST;
else else
req = request+((NR_REQUEST*2)/3); req = request+((NR_REQUEST*2)/3);
/* find an empty request */ /* find an empty request */
while (--req >= request) while (--req >= request)
if (req->dev<0) if (req->dev<0)
break; break;
/* if none found, sleep on new requests: check for rw_ahead */ /* if none found, sleep on new requests: check for rw_ahead */
if (req < request) { if (req < request) {
if (rw_ahead) { if (rw_ahead) {
unlock_buffer(bh); unlock_buffer(bh);
return; return;
} }
sleep_on(&wait_for_request); sleep_on(&wait_for_request);
goto repeat; goto repeat;
} }
/* fill up the request-info, and add it to the queue */ /* fill up the request-info, and add it to the queue */
req->dev = bh->b_dev; req->dev = bh->b_dev;
req->cmd = rw; req->cmd = rw;
req->errors=0; req->errors=0;
req->sector = bh->b_blocknr<<1; req->sector = bh->b_blocknr<<1;
req->nr_sectors = 2; req->nr_sectors = 2;
req->buffer = bh->b_data; req->buffer = bh->b_data;
req->waiting = NULL; req->waiting = NULL;
req->bh = bh; req->bh = bh;
req->next = NULL; req->next = NULL;
add_request(major+blk_dev,req); add_request(major+blk_dev,req);
} }
void ll_rw_block(int rw, struct buffer_head * bh) void ll_rw_block(int rw, struct buffer_head * bh)
{ {
unsigned int major; unsigned int major;
if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV || if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
!(blk_dev[major].request_fn)) { !(blk_dev[major].request_fn)) {
printk("Trying to read nonexistent block-device\n\r"); printk("Trying to read nonexistent block-device\n\r");
return; return;
} }
make_request(major,rw,bh); make_request(major,rw,bh);
} }
void blk_dev_init(void) void blk_dev_init(void)
{ {
int i; int i;
for (i=0 ; i<NR_REQUEST ; i++) { for (i=0 ; i<NR_REQUEST ; i++) {
request[i].dev = -1; request[i].dev = -1;
request[i].next = NULL; request[i].next = NULL;
} }
} }

@ -1,126 +1,126 @@
/* /*
* linux/kernel/blk_drv/ramdisk.c * linux/kernel/blk_drv/ramdisk.c
* *
* Written by Theodore Ts'o, 12/2/91 * Written by Theodore Ts'o, 12/2/91
*/ */
#include <string.h> #include <string.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/memory.h> #include <asm/memory.h>
#define MAJOR_NR 1 #define MAJOR_NR 1
#include "blk.h" #include "blk.h"
char *rd_start; char *rd_start;
int rd_length = 0; int rd_length = 0;
void do_rd_request(void) void do_rd_request(void)
{ {
int len; int len;
char *addr; char *addr;
INIT_REQUEST; INIT_REQUEST;
addr = rd_start + (CURRENT->sector << 9); addr = rd_start + (CURRENT->sector << 9);
len = CURRENT->nr_sectors << 9; len = CURRENT->nr_sectors << 9;
if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) { if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {
end_request(0); end_request(0);
goto repeat; goto repeat;
} }
if (CURRENT-> cmd == WRITE) { if (CURRENT-> cmd == WRITE) {
(void ) memcpy(addr, (void ) memcpy(addr,
CURRENT->buffer, CURRENT->buffer,
len); len);
} else if (CURRENT->cmd == READ) { } else if (CURRENT->cmd == READ) {
(void) memcpy(CURRENT->buffer, (void) memcpy(CURRENT->buffer,
addr, addr,
len); len);
} else } else
panic("unknown ramdisk-command"); panic("unknown ramdisk-command");
end_request(1); end_request(1);
goto repeat; goto repeat;
} }
/* /*
* Returns amount of memory which needs to be reserved. * Returns amount of memory which needs to be reserved.
*/ */
long rd_init(long mem_start, int length) long rd_init(long mem_start, int length)
{ {
int i; int i;
char *cp; char *cp;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
rd_start = (char *) mem_start; rd_start = (char *) mem_start;
rd_length = length; rd_length = length;
cp = rd_start; cp = rd_start;
for (i=0; i < length; i++) for (i=0; i < length; i++)
*cp++ = '\0'; *cp++ = '\0';
return(length); return(length);
} }
/* /*
* If the root device is the ram disk, try to load it. * If the root device is the ram disk, try to load it.
* In order to do this, the root device is originally set to the * In order to do this, the root device is originally set to the
* floppy, and we later change it to be ram disk. * floppy, and we later change it to be ram disk.
*/ */
void rd_load(void) void rd_load(void)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct super_block s; struct super_block s;
int block = 256; /* Start at block 256 */ int block = 256; /* Start at block 256 */
int i = 1; int i = 1;
int nblocks; int nblocks;
char *cp; /* Move pointer */ char *cp; /* Move pointer */
if (!rd_length) if (!rd_length)
return; return;
printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length, printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length,
(int) rd_start); (int) rd_start);
if (MAJOR(ROOT_DEV) != 2) if (MAJOR(ROOT_DEV) != 2)
return; return;
bh = breada(ROOT_DEV,block+1,block,block+2,-1); bh = breada(ROOT_DEV,block+1,block,block+2,-1);
if (!bh) { if (!bh) {
printk("Disk error while looking for ramdisk!\n"); printk("Disk error while looking for ramdisk!\n");
return; return;
} }
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
*((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data); *((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data);
brelse(bh); brelse(bh);
if (s.s_magic != SUPER_MAGIC) if (s.s_magic != SUPER_MAGIC)
/* No ram disk image present, assume normal floppy boot */ /* No ram disk image present, assume normal floppy boot */
return; return;
nblocks = s.s_nzones << s.s_log_zone_size; nblocks = s.s_nzones << s.s_log_zone_size;
if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
printk("Ram disk image too big! (%d blocks, %d avail)\n", printk("Ram disk image too big! (%d blocks, %d avail)\n",
nblocks, rd_length >> BLOCK_SIZE_BITS); nblocks, rd_length >> BLOCK_SIZE_BITS);
return; return;
} }
printk("Loading %d bytes into ram disk... 0000k", printk("Loading %d bytes into ram disk... 0000k",
nblocks << BLOCK_SIZE_BITS); nblocks << BLOCK_SIZE_BITS);
cp = rd_start; cp = rd_start;
while (nblocks) { while (nblocks) {
if (nblocks > 2) if (nblocks > 2)
bh = breada(ROOT_DEV, block, block+1, block+2, -1); bh = breada(ROOT_DEV, block, block+1, block+2, -1);
else else
bh = bread(ROOT_DEV, block); bh = bread(ROOT_DEV, block);
if (!bh) { if (!bh) {
printk("I/O error on block %d, aborting load\n", printk("I/O error on block %d, aborting load\n",
block); block);
return; return;
} }
(void) memcpy(cp, bh->b_data, BLOCK_SIZE); (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
brelse(bh); brelse(bh);
printk("\010\010\010\010\010%4dk",i); printk("\010\010\010\010\010%4dk",i);
cp += BLOCK_SIZE; cp += BLOCK_SIZE;
block++; block++;
nblocks--; nblocks--;
i++; i++;
} }
printk("\010\010\010\010\010done \n"); printk("\010\010\010\010\010done \n");
ROOT_DEV=0x0101; ROOT_DEV=0x0101;
} }

@ -1,68 +1,68 @@
# #
# Makefile for the FREAX-kernel character device drivers. # Makefile for the FREAX-kernel character device drivers.
# #
# Note! Dependencies are done automagically by 'make dep', which also # Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here # removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-s -x LDFLAGS =-s -x
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \
-finline-functions -nostdinc -fno-stack-protector -I../../include -finline-functions -nostdinc -fno-stack-protector -I../../include
CPP =gcc -E -nostdinc -I../../include CPP =gcc -E -nostdinc -I../../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
OBJS = tty_io.o console.o keyboard.2.o serial.o rs_io.o \ OBJS = tty_io.o console.o keyboard.2.o serial.o rs_io.o \
tty_ioctl.o tty_ioctl.o
chr_drv.a: $(OBJS) chr_drv.a: $(OBJS)
$(AR) rcs chr_drv.a $(OBJS) $(AR) rcs chr_drv.a $(OBJS)
sync sync
keyboard.2.s: keyboard.S ../../include/linux/config.h keyboard.2.s: keyboard.S ../../include/linux/config.h
$(CPP) -traditional keyboard.S -o keyboard.2.s $(CPP) -traditional keyboard.S -o keyboard.2.s
clean: clean:
rm -f core *.o *.a tmp_make keyboard.2.s rm -f core *.o *.a tmp_make keyboard.2.s
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
### Dependencies: ### Dependencies:
console.s console.o : console.c ../../include/linux/sched.h \ console.s console.o : console.c ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \ ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \ ../../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
../../include/linux/tty.h ../../include/termios.h ../../include/asm/io.h \ ../../include/linux/tty.h ../../include/termios.h ../../include/asm/io.h \
../../include/asm/system.h ../../include/asm/system.h
serial.s serial.o : serial.c ../../include/linux/tty.h ../../include/termios.h \ serial.s serial.o : serial.c ../../include/linux/tty.h ../../include/termios.h \
../../include/linux/sched.h ../../include/linux/head.h \ ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \ ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
../../include/signal.h ../../include/asm/system.h ../../include/asm/io.h ../../include/signal.h ../../include/asm/system.h ../../include/asm/io.h
tty_io.s tty_io.o : tty_io.c ../../include/ctype.h ../../include/errno.h \ tty_io.s tty_io.o : tty_io.c ../../include/ctype.h ../../include/errno.h \
../../include/signal.h ../../include/sys/types.h \ ../../include/signal.h ../../include/sys/types.h \
../../include/linux/sched.h ../../include/linux/head.h \ ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/tty.h \ ../../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/tty.h \
../../include/termios.h ../../include/asm/segment.h \ ../../include/termios.h ../../include/asm/segment.h \
../../include/asm/system.h ../../include/asm/system.h
tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h \ tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h \
../../include/linux/sched.h ../../include/linux/head.h \ ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \ ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
../../include/signal.h ../../include/linux/kernel.h \ ../../include/signal.h ../../include/linux/kernel.h \
../../include/linux/tty.h ../../include/asm/io.h \ ../../include/linux/tty.h ../../include/asm/io.h \
../../include/asm/segment.h ../../include/asm/system.h ../../include/asm/segment.h ../../include/asm/system.h

File diff suppressed because it is too large Load Diff

@ -1,466 +1,466 @@
# 1 "keyboard.S" # 1 "keyboard.S"
# 1 "<built-in>" # 1 "<built-in>"
# 1 "<command-line>" # 1 "<command-line>"
# 1 "keyboard.S" # 1 "keyboard.S"
# 1 "../../include/linux/config.h" 1 # 1 "../../include/linux/config.h" 1
# 36 "../../include/linux/config.h" # 36 "../../include/linux/config.h"
# 47 "../../include/linux/config.h" # 47 "../../include/linux/config.h"
# 14 "keyboard.S" 2 # 14 "keyboard.S" 2
.text .text
.globl keyboard_interrupt .globl keyboard_interrupt
size = 1024 size = 1024
head = 4 head = 4
tail = 8 tail = 8
proc_list = 12 proc_list = 12
buf = 16 buf = 16
mode: .byte 0 mode: .byte 0
leds: .byte 2 leds: .byte 2
e0: .byte 0 e0: .byte 0
keyboard_interrupt: keyboard_interrupt:
pushl %eax pushl %eax
pushl %ebx pushl %ebx
pushl %ecx pushl %ecx
pushl %edx pushl %edx
push %ds push %ds
push %es push %es
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
xor %al,%al xor %al,%al
inb $0x60,%al inb $0x60,%al
cmpb $0xe0,%al cmpb $0xe0,%al
je set_e0 je set_e0
cmpb $0xe1,%al cmpb $0xe1,%al
je set_e1 je set_e1
call key_table(,%eax,4) call key_table(,%eax,4)
movb $0,e0 movb $0,e0
e0_e1: inb $0x61,%al e0_e1: inb $0x61,%al
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: orb $0x80,%al 1: orb $0x80,%al
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: outb %al,$0x61 1: outb %al,$0x61
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: andb $0x7F,%al 1: andb $0x7F,%al
outb %al,$0x61 outb %al,$0x61
movb $0x20,%al movb $0x20,%al
outb %al,$0x20 outb %al,$0x20
pushl $0 pushl $0
call do_tty_interrupt call do_tty_interrupt
addl $4,%esp addl $4,%esp
pop %es pop %es
pop %ds pop %ds
popl %edx popl %edx
popl %ecx popl %ecx
popl %ebx popl %ebx
popl %eax popl %eax
iret iret
set_e0: movb $1,e0 set_e0: movb $1,e0
jmp e0_e1 jmp e0_e1
set_e1: movb $2,e0 set_e1: movb $2,e0
jmp e0_e1 jmp e0_e1
put_queue: put_queue:
pushl %ecx pushl %ecx
pushl %edx pushl %edx
movl table_list,%edx # read-queue for console movl table_list,%edx # read-queue for console
movl head(%edx),%ecx movl head(%edx),%ecx
1: movb %al,buf(%edx,%ecx) 1: movb %al,buf(%edx,%ecx)
incl %ecx incl %ecx
andl $size-1,%ecx andl $size-1,%ecx
cmpl tail(%edx),%ecx # buffer full - discard everything cmpl tail(%edx),%ecx # buffer full - discard everything
je 3f je 3f
shrdl $8,%ebx,%eax shrdl $8,%ebx,%eax
je 2f je 2f
shrl $8,%ebx shrl $8,%ebx
jmp 1b jmp 1b
2: movl %ecx,head(%edx) 2: movl %ecx,head(%edx)
movl proc_list(%edx),%ecx movl proc_list(%edx),%ecx
testl %ecx,%ecx testl %ecx,%ecx
je 3f je 3f
movl $0,(%ecx) movl $0,(%ecx)
3: popl %edx 3: popl %edx
popl %ecx popl %ecx
ret ret
ctrl: movb $0x04,%al ctrl: movb $0x04,%al
jmp 1f jmp 1f
alt: movb $0x10,%al alt: movb $0x10,%al
1: cmpb $0,e0 1: cmpb $0,e0
je 2f je 2f
addb %al,%al addb %al,%al
2: orb %al,mode 2: orb %al,mode
ret ret
unctrl: movb $0x04,%al unctrl: movb $0x04,%al
jmp 1f jmp 1f
unalt: movb $0x10,%al unalt: movb $0x10,%al
1: cmpb $0,e0 1: cmpb $0,e0
je 2f je 2f
addb %al,%al addb %al,%al
2: notb %al 2: notb %al
andb %al,mode andb %al,mode
ret ret
lshift: lshift:
orb $0x01,mode orb $0x01,mode
ret ret
unlshift: unlshift:
andb $0xfe,mode andb $0xfe,mode
ret ret
rshift: rshift:
orb $0x02,mode orb $0x02,mode
ret ret
unrshift: unrshift:
andb $0xfd,mode andb $0xfd,mode
ret ret
caps: testb $0x80,mode caps: testb $0x80,mode
jne 1f jne 1f
xorb $4,leds xorb $4,leds
xorb $0x40,mode xorb $0x40,mode
orb $0x80,mode orb $0x80,mode
set_leds: set_leds:
call kb_wait call kb_wait
movb $0xed,%al movb $0xed,%al
outb %al,$0x60 outb %al,$0x60
call kb_wait call kb_wait
movb leds,%al movb leds,%al
outb %al,$0x60 outb %al,$0x60
ret ret
uncaps: andb $0x7f,mode uncaps: andb $0x7f,mode
ret ret
scroll: scroll:
xorb $1,leds xorb $1,leds
jmp set_leds jmp set_leds
num: xorb $2,leds num: xorb $2,leds
jmp set_leds jmp set_leds
cursor: cursor:
subb $0x47,%al subb $0x47,%al
jb 1f jb 1f
cmpb $12,%al cmpb $12,%al
ja 1f ja 1f
jne cur2 jne cur2
testb $0x0c,mode testb $0x0c,mode
je cur2 je cur2
testb $0x30,mode testb $0x30,mode
jne reboot jne reboot
cur2: cmpb $0x01,e0 cur2: cmpb $0x01,e0
je cur je cur
testb $0x02,leds testb $0x02,leds
je cur je cur
testb $0x03,mode testb $0x03,mode
jne cur jne cur
xorl %ebx,%ebx xorl %ebx,%ebx
movb num_table(%eax),%al movb num_table(%eax),%al
jmp put_queue jmp put_queue
1: ret 1: ret
cur: movb cur_table(%eax),%al cur: movb cur_table(%eax),%al
cmpb $'9,%al cmpb $'9,%al
ja ok_cur ja ok_cur
movb $'~,%ah movb $'~,%ah
ok_cur: shll $16,%eax ok_cur: shll $16,%eax
movw $0x5b1b,%ax movw $0x5b1b,%ax
xorl %ebx,%ebx xorl %ebx,%ebx
jmp put_queue jmp put_queue
num_table: num_table:
.ascii "789 456 1230," .ascii "789 456 1230,"
cur_table: cur_table:
.ascii "HA5 DGC YB623" .ascii "HA5 DGC YB623"
func: func:
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
call show_stat call show_stat
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
subb $0x3B,%al subb $0x3B,%al
jb end_func jb end_func
cmpb $9,%al cmpb $9,%al
jbe ok_func jbe ok_func
subb $18,%al subb $18,%al
cmpb $10,%al cmpb $10,%al
jb end_func jb end_func
cmpb $11,%al cmpb $11,%al
ja end_func ja end_func
ok_func: ok_func:
cmpl $4,%ecx cmpl $4,%ecx
jl end_func jl end_func
movl func_table(,%eax,4),%eax movl func_table(,%eax,4),%eax
xorl %ebx,%ebx xorl %ebx,%ebx
jmp put_queue jmp put_queue
end_func: end_func:
ret ret
func_table: func_table:
.long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
.long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
.long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
# 294 "keyboard.S" # 294 "keyboard.S"
key_map: key_map:
.byte 0,27 .byte 0,27
.ascii "1234567890-=" .ascii "1234567890-="
.byte 127,9 .byte 127,9
.ascii "qwertyuiop[]" .ascii "qwertyuiop[]"
.byte 13,0 .byte 13,0
.ascii "asdfghjkl;'" .ascii "asdfghjkl;'"
.byte '`,0 .byte '`,0
.ascii "\\zxcvbnm,./" .ascii "\\zxcvbnm,./"
.byte 0,'*,0,32 /* 36-39 */ .byte 0,'*,0,32 /* 36-39 */
.fill 16,1,0 .fill 16,1,0
.byte '-,0,0,0,'+ .byte '-,0,0,0,'+
.byte 0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0
.byte '< .byte '<
.fill 10,1,0 .fill 10,1,0
shift_map: shift_map:
.byte 0,27 .byte 0,27
.ascii "!@#$%^&*()_+" .ascii "!@#$%^&*()_+"
.byte 127,9 .byte 127,9
.ascii "QWERTYUIOP{}" .ascii "QWERTYUIOP{}"
.byte 13,0 .byte 13,0
.ascii "ASDFGHJKL:\"" .ascii "ASDFGHJKL:\""
.byte '~,0 .byte '~,0
.ascii "|ZXCVBNM<>?" .ascii "|ZXCVBNM<>?"
.byte 0,'*,0,32 /* 36-39 */ .byte 0,'*,0,32 /* 36-39 */
.fill 16,1,0 .fill 16,1,0
.byte '-,0,0,0,'+ .byte '-,0,0,0,'+
.byte 0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0
.byte '> .byte '>
.fill 10,1,0 .fill 10,1,0
alt_map: alt_map:
.byte 0,0 .byte 0,0
.ascii "\0@\0$\0\0{[]}\\\0" .ascii "\0@\0$\0\0{[]}\\\0"
.byte 0,0 .byte 0,0
.byte 0,0,0,0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0,0,0,0
.byte '~,13,0 .byte '~,13,0
.byte 0,0,0,0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0,0,0,0
.byte 0,0 .byte 0,0
.byte 0,0,0,0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0 .byte 0,0,0,0
.fill 16,1,0 .fill 16,1,0
.byte 0,0,0,0,0 .byte 0,0,0,0,0
.byte 0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0
.byte '| .byte '|
.fill 10,1,0 .fill 10,1,0
# 449 "keyboard.S" # 449 "keyboard.S"
do_self: do_self:
lea alt_map,%ebx lea alt_map,%ebx
testb $0x20,mode testb $0x20,mode
jne 1f jne 1f
lea shift_map,%ebx lea shift_map,%ebx
testb $0x03,mode testb $0x03,mode
jne 1f jne 1f
lea key_map,%ebx lea key_map,%ebx
1: movb (%ebx,%eax),%al 1: movb (%ebx,%eax),%al
orb %al,%al orb %al,%al
je none je none
testb $0x4c,mode testb $0x4c,mode
je 2f je 2f
cmpb $'a,%al cmpb $'a,%al
jb 2f jb 2f
cmpb $'},%al cmpb $'},%al
ja 2f ja 2f
subb $32,%al subb $32,%al
2: testb $0x0c,mode 2: testb $0x0c,mode
je 3f je 3f
cmpb $64,%al cmpb $64,%al
jb 3f jb 3f
cmpb $64+32,%al cmpb $64+32,%al
jae 3f jae 3f
subb $64,%al subb $64,%al
3: testb $0x10,mode 3: testb $0x10,mode
je 4f je 4f
orb $0x80,%al orb $0x80,%al
4: andl $0xff,%eax 4: andl $0xff,%eax
xorl %ebx,%ebx xorl %ebx,%ebx
call put_queue call put_queue
none: ret none: ret
minus: cmpb $1,e0 minus: cmpb $1,e0
jne do_self jne do_self
movl $'/,%eax movl $'/,%eax
xorl %ebx,%ebx xorl %ebx,%ebx
jmp put_queue jmp put_queue
key_table: key_table:
.long none,do_self,do_self,do_self .long none,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,ctrl,do_self,do_self .long do_self,ctrl,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,lshift,do_self .long do_self,do_self,lshift,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,do_self,do_self,do_self .long do_self,do_self,do_self,do_self
.long do_self,minus,rshift,do_self .long do_self,minus,rshift,do_self
.long alt,do_self,caps,func .long alt,do_self,caps,func
.long func,func,func,func .long func,func,func,func
.long func,func,func,func .long func,func,func,func
.long func,num,scroll,cursor .long func,num,scroll,cursor
.long cursor,cursor,do_self,cursor .long cursor,cursor,do_self,cursor
.long cursor,cursor,do_self,cursor .long cursor,cursor,do_self,cursor
.long cursor,cursor,cursor,cursor .long cursor,cursor,cursor,cursor
.long none,none,do_self,func .long none,none,do_self,func
.long func,none,none,none .long func,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,unctrl,none,none .long none,unctrl,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,unlshift,none .long none,none,unlshift,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,unrshift,none .long none,none,unrshift,none
.long unalt,none,uncaps,none .long unalt,none,uncaps,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
.long none,none,none,none .long none,none,none,none
kb_wait: kb_wait:
pushl %eax pushl %eax
1: inb $0x64,%al 1: inb $0x64,%al
testb $0x02,%al testb $0x02,%al
jne 1b jne 1b
popl %eax popl %eax
ret ret
reboot: reboot:
call kb_wait call kb_wait
movw $0x1234,0x472 movw $0x1234,0x472
movb $0xfc,%al movb $0xfc,%al
outb %al,$0x64 outb %al,$0x64
die: jmp die die: jmp die

File diff suppressed because it is too large Load Diff

@ -1,147 +1,147 @@
/* /*
* linux/kernel/rs_io.s * linux/kernel/rs_io.s
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* rs_io.s * rs_io.s
* *
* This module implements the rs232 io interrupts. * This module implements the rs232 io interrupts.
*/ */
.text .text
.globl rs1_interrupt,rs2_interrupt .globl rs1_interrupt,rs2_interrupt
size = 1024 /* must be power of two ! size = 1024 /* must be power of two !
and must match the value and must match the value
in tty_io.c!!! */ in tty_io.c!!! */
/* these are the offsets into the read/write buffer structures */ /* these are the offsets into the read/write buffer structures */
rs_addr = 0 rs_addr = 0
head = 4 head = 4
tail = 8 tail = 8
proc_list = 12 proc_list = 12
buf = 16 buf = 16
startup = 256 /* chars left in write queue when we restart it */ startup = 256 /* chars left in write queue when we restart it */
/* /*
* These are the actual interrupt routines. They look where * These are the actual interrupt routines. They look where
* the interrupt is coming from, and take appropriate action. * the interrupt is coming from, and take appropriate action.
*/ */
.align 4 .align 4
rs1_interrupt: rs1_interrupt:
pushl $table_list+8 pushl $table_list+8
jmp rs_int jmp rs_int
.align 4 .align 4
rs2_interrupt: rs2_interrupt:
pushl $table_list+16 pushl $table_list+16
rs_int: rs_int:
pushl %edx pushl %edx
pushl %ecx pushl %ecx
pushl %ebx pushl %ebx
pushl %eax pushl %eax
push %es push %es
push %ds /* as this is an interrupt, we cannot */ push %ds /* as this is an interrupt, we cannot */
pushl $0x10 /* know that bs is ok. Load it */ pushl $0x10 /* know that bs is ok. Load it */
pop %ds pop %ds
pushl $0x10 pushl $0x10
pop %es pop %es
movl 24(%esp),%edx movl 24(%esp),%edx
movl (%edx),%edx movl (%edx),%edx
movl rs_addr(%edx),%edx movl rs_addr(%edx),%edx
addl $2,%edx /* interrupt ident. reg */ addl $2,%edx /* interrupt ident. reg */
rep_int: rep_int:
xorl %eax,%eax xorl %eax,%eax
inb %dx,%al inb %dx,%al
testb $1,%al testb $1,%al
jne end jne end
cmpb $6,%al /* this shouldn't happen, but ... */ cmpb $6,%al /* this shouldn't happen, but ... */
ja end ja end
movl 24(%esp),%ecx movl 24(%esp),%ecx
pushl %edx pushl %edx
subl $2,%edx subl $2,%edx
call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */ call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
popl %edx popl %edx
jmp rep_int jmp rep_int
end: movb $0x20,%al end: movb $0x20,%al
outb %al,$0x20 /* EOI */ outb %al,$0x20 /* EOI */
pop %ds pop %ds
pop %es pop %es
popl %eax popl %eax
popl %ebx popl %ebx
popl %ecx popl %ecx
popl %edx popl %edx
addl $4,%esp # jump over _table_list entry addl $4,%esp # jump over _table_list entry
iret iret
jmp_table: jmp_table:
.long modem_status,write_char,read_char,line_status .long modem_status,write_char,read_char,line_status
.align 4 .align 4
modem_status: modem_status:
addl $6,%edx /* clear intr by reading modem status reg */ addl $6,%edx /* clear intr by reading modem status reg */
inb %dx,%al inb %dx,%al
ret ret
.align 4 .align 4
line_status: line_status:
addl $5,%edx /* clear intr by reading line status reg. */ addl $5,%edx /* clear intr by reading line status reg. */
inb %dx,%al inb %dx,%al
ret ret
.align 4 .align 4
read_char: read_char:
inb %dx,%al inb %dx,%al
movl %ecx,%edx movl %ecx,%edx
subl $table_list,%edx subl $table_list,%edx
shrl $3,%edx shrl $3,%edx
movl (%ecx),%ecx # read-queue movl (%ecx),%ecx # read-queue
movl head(%ecx),%ebx movl head(%ecx),%ebx
movb %al,buf(%ecx,%ebx) movb %al,buf(%ecx,%ebx)
incl %ebx incl %ebx
andl $size-1,%ebx andl $size-1,%ebx
cmpl tail(%ecx),%ebx cmpl tail(%ecx),%ebx
je 1f je 1f
movl %ebx,head(%ecx) movl %ebx,head(%ecx)
1: pushl %edx 1: pushl %edx
call do_tty_interrupt call do_tty_interrupt
addl $4,%esp addl $4,%esp
ret ret
.align 4 .align 4
write_char: write_char:
movl 4(%ecx),%ecx # write-queue movl 4(%ecx),%ecx # write-queue
movl head(%ecx),%ebx movl head(%ecx),%ebx
subl tail(%ecx),%ebx subl tail(%ecx),%ebx
andl $size-1,%ebx # nr chars in queue andl $size-1,%ebx # nr chars in queue
je write_buffer_empty je write_buffer_empty
cmpl $startup,%ebx cmpl $startup,%ebx
ja 1f ja 1f
movl proc_list(%ecx),%ebx # wake up sleeping process movl proc_list(%ecx),%ebx # wake up sleeping process
testl %ebx,%ebx # is there any? testl %ebx,%ebx # is there any?
je 1f je 1f
movl $0,(%ebx) movl $0,(%ebx)
1: movl tail(%ecx),%ebx 1: movl tail(%ecx),%ebx
movb buf(%ecx,%ebx),%al movb buf(%ecx,%ebx),%al
outb %al,%dx outb %al,%dx
incl %ebx incl %ebx
andl $size-1,%ebx andl $size-1,%ebx
movl %ebx,tail(%ecx) movl %ebx,tail(%ecx)
cmpl head(%ecx),%ebx cmpl head(%ecx),%ebx
je write_buffer_empty je write_buffer_empty
ret ret
.align 4 .align 4
write_buffer_empty: write_buffer_empty:
movl proc_list(%ecx),%ebx # wake up sleeping process movl proc_list(%ecx),%ebx # wake up sleeping process
testl %ebx,%ebx # is there any? testl %ebx,%ebx # is there any?
je 1f je 1f
movl $0,(%ebx) movl $0,(%ebx)
1: incl %edx 1: incl %edx
inb %dx,%al inb %dx,%al
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: andb $0xd,%al /* disable transmit interrupt */ 1: andb $0xd,%al /* disable transmit interrupt */
outb %al,%dx outb %al,%dx
ret ret

@ -1,59 +1,59 @@
/* /*
* linux/kernel/serial.c * linux/kernel/serial.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* serial.c * serial.c
* *
* This module implements the rs232 io functions * This module implements the rs232 io functions
* void rs_write(struct tty_struct * queue); * void rs_write(struct tty_struct * queue);
* void rs_init(void); * void rs_init(void);
* and all interrupts pertaining to serial IO. * and all interrupts pertaining to serial IO.
*/ */
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#define WAKEUP_CHARS (TTY_BUF_SIZE/4) #define WAKEUP_CHARS (TTY_BUF_SIZE/4)
extern void rs1_interrupt(void); extern void rs1_interrupt(void);
extern void rs2_interrupt(void); extern void rs2_interrupt(void);
static void init(int port) static void init(int port)
{ {
outb_p(0x80,port+3); /* set DLAB of line control reg */ outb_p(0x80,port+3); /* set DLAB of line control reg */
outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */ outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */
outb_p(0x00,port+1); /* MS of divisor */ outb_p(0x00,port+1); /* MS of divisor */
outb_p(0x03,port+3); /* reset DLAB */ outb_p(0x03,port+3); /* reset DLAB */
outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */ outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */
outb_p(0x0d,port+1); /* enable all intrs but writes */ outb_p(0x0d,port+1); /* enable all intrs but writes */
(void)inb(port); /* read data port to reset things (?) */ (void)inb(port); /* read data port to reset things (?) */
} }
void rs_init(void) void rs_init(void)
{ {
set_intr_gate(0x24,rs1_interrupt); set_intr_gate(0x24,rs1_interrupt);
set_intr_gate(0x23,rs2_interrupt); set_intr_gate(0x23,rs2_interrupt);
init(tty_table[1].read_q.data); init(tty_table[1].read_q.data);
init(tty_table[2].read_q.data); init(tty_table[2].read_q.data);
outb(inb_p(0x21)&0xE7,0x21); outb(inb_p(0x21)&0xE7,0x21);
} }
/* /*
* This routine gets called when tty_write has put something into * This routine gets called when tty_write has put something into
* the write_queue. It must check wheter the queue is empty, and * the write_queue. It must check wheter the queue is empty, and
* set the interrupt register accordingly * set the interrupt register accordingly
* *
* void _rs_write(struct tty_struct * tty); * void _rs_write(struct tty_struct * tty);
*/ */
void rs_write(struct tty_struct * tty) void rs_write(struct tty_struct * tty)
{ {
cli(); cli();
if (!EMPTY(tty->write_q)) if (!EMPTY(tty->write_q))
outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1); outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1);
sti(); sti();
} }

@ -1,349 +1,349 @@
/* /*
* linux/kernel/tty_io.c * linux/kernel/tty_io.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
* or rs-channels. It also implements echoing, cooked mode etc. * or rs-channels. It also implements echoing, cooked mode etc.
* *
* Kill-line thanks to John T Kohl. * Kill-line thanks to John T Kohl.
*/ */
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#define ALRMMASK (1<<(SIGALRM-1)) #define ALRMMASK (1<<(SIGALRM-1))
#define KILLMASK (1<<(SIGKILL-1)) #define KILLMASK (1<<(SIGKILL-1))
#define INTMASK (1<<(SIGINT-1)) #define INTMASK (1<<(SIGINT-1))
#define QUITMASK (1<<(SIGQUIT-1)) #define QUITMASK (1<<(SIGQUIT-1))
#define TSTPMASK (1<<(SIGTSTP-1)) #define TSTPMASK (1<<(SIGTSTP-1))
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f) #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f) #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
#define L_CANON(tty) _L_FLAG((tty),ICANON) #define L_CANON(tty) _L_FLAG((tty),ICANON)
#define L_ISIG(tty) _L_FLAG((tty),ISIG) #define L_ISIG(tty) _L_FLAG((tty),ISIG)
#define L_ECHO(tty) _L_FLAG((tty),ECHO) #define L_ECHO(tty) _L_FLAG((tty),ECHO)
#define L_ECHOE(tty) _L_FLAG((tty),ECHOE) #define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
#define L_ECHOK(tty) _L_FLAG((tty),ECHOK) #define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) #define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
#define I_UCLC(tty) _I_FLAG((tty),IUCLC) #define I_UCLC(tty) _I_FLAG((tty),IUCLC)
#define I_NLCR(tty) _I_FLAG((tty),INLCR) #define I_NLCR(tty) _I_FLAG((tty),INLCR)
#define I_CRNL(tty) _I_FLAG((tty),ICRNL) #define I_CRNL(tty) _I_FLAG((tty),ICRNL)
#define I_NOCR(tty) _I_FLAG((tty),IGNCR) #define I_NOCR(tty) _I_FLAG((tty),IGNCR)
#define O_POST(tty) _O_FLAG((tty),OPOST) #define O_POST(tty) _O_FLAG((tty),OPOST)
#define O_NLCR(tty) _O_FLAG((tty),ONLCR) #define O_NLCR(tty) _O_FLAG((tty),ONLCR)
#define O_CRNL(tty) _O_FLAG((tty),OCRNL) #define O_CRNL(tty) _O_FLAG((tty),OCRNL)
#define O_NLRET(tty) _O_FLAG((tty),ONLRET) #define O_NLRET(tty) _O_FLAG((tty),ONLRET)
#define O_LCUC(tty) _O_FLAG((tty),OLCUC) #define O_LCUC(tty) _O_FLAG((tty),OLCUC)
struct tty_struct tty_table[] = { struct tty_struct tty_table[] = {
{ {
{ICRNL, /* change incoming CR to NL */ {ICRNL, /* change incoming CR to NL */
OPOST|ONLCR, /* change outgoing NL to CRNL */ OPOST|ONLCR, /* change outgoing NL to CRNL */
0, 0,
ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
0, /* console termio */ 0, /* console termio */
INIT_C_CC}, INIT_C_CC},
0, /* initial pgrp */ 0, /* initial pgrp */
0, /* initial stopped */ 0, /* initial stopped */
con_write, con_write,
{0,0,0,0,""}, /* console read-queue */ {0,0,0,0,""}, /* console read-queue */
{0,0,0,0,""}, /* console write-queue */ {0,0,0,0,""}, /* console write-queue */
{0,0,0,0,""} /* console secondary queue */ {0,0,0,0,""} /* console secondary queue */
},{ },{
{0, /* no translation */ {0, /* no translation */
0, /* no translation */ 0, /* no translation */
B2400 | CS8, B2400 | CS8,
0, 0,
0, 0,
INIT_C_CC}, INIT_C_CC},
0, 0,
0, 0,
rs_write, rs_write,
{0x3f8,0,0,0,""}, /* rs 1 */ {0x3f8,0,0,0,""}, /* rs 1 */
{0x3f8,0,0,0,""}, {0x3f8,0,0,0,""},
{0,0,0,0,""} {0,0,0,0,""}
},{ },{
{0, /* no translation */ {0, /* no translation */
0, /* no translation */ 0, /* no translation */
B2400 | CS8, B2400 | CS8,
0, 0,
0, 0,
INIT_C_CC}, INIT_C_CC},
0, 0,
0, 0,
rs_write, rs_write,
{0x2f8,0,0,0,""}, /* rs 2 */ {0x2f8,0,0,0,""}, /* rs 2 */
{0x2f8,0,0,0,""}, {0x2f8,0,0,0,""},
{0,0,0,0,""} {0,0,0,0,""}
} }
}; };
/* /*
* these are the tables used by the machine code handlers. * these are the tables used by the machine code handlers.
* you can implement pseudo-tty's or something by changing * you can implement pseudo-tty's or something by changing
* them. Currently not done. * them. Currently not done.
*/ */
struct tty_queue * table_list[]={ struct tty_queue * table_list[]={
&tty_table[0].read_q, &tty_table[0].write_q, &tty_table[0].read_q, &tty_table[0].write_q,
&tty_table[1].read_q, &tty_table[1].write_q, &tty_table[1].read_q, &tty_table[1].write_q,
&tty_table[2].read_q, &tty_table[2].write_q &tty_table[2].read_q, &tty_table[2].write_q
}; };
void tty_init(void) void tty_init(void)
{ {
rs_init(); rs_init();
con_init(); con_init();
} }
void tty_intr(struct tty_struct * tty, int mask) void tty_intr(struct tty_struct * tty, int mask)
{ {
int i; int i;
if (tty->pgrp <= 0) if (tty->pgrp <= 0)
return; return;
for (i=0;i<NR_TASKS;i++) for (i=0;i<NR_TASKS;i++)
if (task[i] && task[i]->pgrp==tty->pgrp) if (task[i] && task[i]->pgrp==tty->pgrp)
task[i]->signal |= mask; task[i]->signal |= mask;
} }
static void sleep_if_empty(struct tty_queue * queue) static void sleep_if_empty(struct tty_queue * queue)
{ {
cli(); cli();
while (!current->signal && EMPTY(*queue)) while (!current->signal && EMPTY(*queue))
interruptible_sleep_on(&queue->proc_list); interruptible_sleep_on(&queue->proc_list);
sti(); sti();
} }
static void sleep_if_full(struct tty_queue * queue) static void sleep_if_full(struct tty_queue * queue)
{ {
if (!FULL(*queue)) if (!FULL(*queue))
return; return;
cli(); cli();
while (!current->signal && LEFT(*queue)<128) while (!current->signal && LEFT(*queue)<128)
interruptible_sleep_on(&queue->proc_list); interruptible_sleep_on(&queue->proc_list);
sti(); sti();
} }
void wait_for_keypress(void) void wait_for_keypress(void)
{ {
sleep_if_empty(&tty_table[0].secondary); sleep_if_empty(&tty_table[0].secondary);
} }
void copy_to_cooked(struct tty_struct * tty) void copy_to_cooked(struct tty_struct * tty)
{ {
signed char c; signed char c;
while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) { while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
GETCH(tty->read_q,c); GETCH(tty->read_q,c);
if (c==13) if (c==13)
if (I_CRNL(tty)) if (I_CRNL(tty))
c=10; c=10;
else if (I_NOCR(tty)) else if (I_NOCR(tty))
continue; continue;
else ; else ;
else if (c==10 && I_NLCR(tty)) else if (c==10 && I_NLCR(tty))
c=13; c=13;
if (I_UCLC(tty)) if (I_UCLC(tty))
c=tolower(c); c=tolower(c);
if (L_CANON(tty)) { if (L_CANON(tty)) {
if (c==KILL_CHAR(tty)) { if (c==KILL_CHAR(tty)) {
/* deal with killing the input line */ /* deal with killing the input line */
while(!(EMPTY(tty->secondary) || while(!(EMPTY(tty->secondary) ||
(c=LAST(tty->secondary))==10 || (c=LAST(tty->secondary))==10 ||
c==EOF_CHAR(tty))) { c==EOF_CHAR(tty))) {
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (c<32) if (c<32)
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
tty->write(tty); tty->write(tty);
} }
DEC(tty->secondary.head); DEC(tty->secondary.head);
} }
continue; continue;
} }
if (c==ERASE_CHAR(tty)) { if (c==ERASE_CHAR(tty)) {
if (EMPTY(tty->secondary) || if (EMPTY(tty->secondary) ||
(c=LAST(tty->secondary))==10 || (c=LAST(tty->secondary))==10 ||
c==EOF_CHAR(tty)) c==EOF_CHAR(tty))
continue; continue;
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (c<32) if (c<32)
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
tty->write(tty); tty->write(tty);
} }
DEC(tty->secondary.head); DEC(tty->secondary.head);
continue; continue;
} }
if (c==STOP_CHAR(tty)) { if (c==STOP_CHAR(tty)) {
tty->stopped=1; tty->stopped=1;
continue; continue;
} }
if (c==START_CHAR(tty)) { if (c==START_CHAR(tty)) {
tty->stopped=0; tty->stopped=0;
continue; continue;
} }
} }
if (L_ISIG(tty)) { if (L_ISIG(tty)) {
if (c==INTR_CHAR(tty)) { if (c==INTR_CHAR(tty)) {
tty_intr(tty,INTMASK); tty_intr(tty,INTMASK);
continue; continue;
} }
if (c==QUIT_CHAR(tty)) { if (c==QUIT_CHAR(tty)) {
tty_intr(tty,QUITMASK); tty_intr(tty,QUITMASK);
continue; continue;
} }
} }
if (c==10 || c==EOF_CHAR(tty)) if (c==10 || c==EOF_CHAR(tty))
tty->secondary.data++; tty->secondary.data++;
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (c==10) { if (c==10) {
PUTCH(10,tty->write_q); PUTCH(10,tty->write_q);
PUTCH(13,tty->write_q); PUTCH(13,tty->write_q);
} else if (c<32) { } else if (c<32) {
if (L_ECHOCTL(tty)) { if (L_ECHOCTL(tty)) {
PUTCH('^',tty->write_q); PUTCH('^',tty->write_q);
PUTCH(c+64,tty->write_q); PUTCH(c+64,tty->write_q);
} }
} else } else
PUTCH(c,tty->write_q); PUTCH(c,tty->write_q);
tty->write(tty); tty->write(tty);
} }
PUTCH(c,tty->secondary); PUTCH(c,tty->secondary);
} }
wake_up(&tty->secondary.proc_list); wake_up(&tty->secondary.proc_list);
} }
int tty_read(unsigned channel, char * buf, int nr) int tty_read(unsigned channel, char * buf, int nr)
{ {
struct tty_struct * tty; struct tty_struct * tty;
char c, * b=buf; char c, * b=buf;
int minimum,time,flag=0; int minimum,time,flag=0;
long oldalarm; long oldalarm;
if (channel>2 || nr<0) return -1; if (channel>2 || nr<0) return -1;
tty = &tty_table[channel]; tty = &tty_table[channel];
oldalarm = current->alarm; oldalarm = current->alarm;
time = 10L*tty->termios.c_cc[VTIME]; time = 10L*tty->termios.c_cc[VTIME];
minimum = tty->termios.c_cc[VMIN]; minimum = tty->termios.c_cc[VMIN];
if (time && !minimum) { if (time && !minimum) {
minimum=1; minimum=1;
if (flag=(!oldalarm || time+jiffies<oldalarm)) if (flag=(!oldalarm || time+jiffies<oldalarm))
current->alarm = time+jiffies; current->alarm = time+jiffies;
} }
if (minimum>nr) if (minimum>nr)
minimum=nr; minimum=nr;
while (nr>0) { while (nr>0) {
if (flag && (current->signal & ALRMMASK)) { if (flag && (current->signal & ALRMMASK)) {
current->signal &= ~ALRMMASK; current->signal &= ~ALRMMASK;
break; break;
} }
if (current->signal) if (current->signal)
break; break;
if (EMPTY(tty->secondary) || (L_CANON(tty) && if (EMPTY(tty->secondary) || (L_CANON(tty) &&
!tty->secondary.data && LEFT(tty->secondary)>20)) { !tty->secondary.data && LEFT(tty->secondary)>20)) {
sleep_if_empty(&tty->secondary); sleep_if_empty(&tty->secondary);
continue; continue;
} }
do { do {
GETCH(tty->secondary,c); GETCH(tty->secondary,c);
if (c==EOF_CHAR(tty) || c==10) if (c==EOF_CHAR(tty) || c==10)
tty->secondary.data--; tty->secondary.data--;
if (c==EOF_CHAR(tty) && L_CANON(tty)) if (c==EOF_CHAR(tty) && L_CANON(tty))
return (b-buf); return (b-buf);
else { else {
put_fs_byte(c,b++); put_fs_byte(c,b++);
if (!--nr) if (!--nr)
break; break;
} }
} while (nr>0 && !EMPTY(tty->secondary)); } while (nr>0 && !EMPTY(tty->secondary));
if (time && !L_CANON(tty)) if (time && !L_CANON(tty))
if (flag=(!oldalarm || time+jiffies<oldalarm)) if (flag=(!oldalarm || time+jiffies<oldalarm))
current->alarm = time+jiffies; current->alarm = time+jiffies;
else else
current->alarm = oldalarm; current->alarm = oldalarm;
if (L_CANON(tty)) { if (L_CANON(tty)) {
if (b-buf) if (b-buf)
break; break;
} else if (b-buf >= minimum) } else if (b-buf >= minimum)
break; break;
} }
current->alarm = oldalarm; current->alarm = oldalarm;
if (current->signal && !(b-buf)) if (current->signal && !(b-buf))
return -EINTR; return -EINTR;
return (b-buf); return (b-buf);
} }
int tty_write(unsigned channel, char * buf, int nr) int tty_write(unsigned channel, char * buf, int nr)
{ {
static cr_flag=0; static cr_flag=0;
struct tty_struct * tty; struct tty_struct * tty;
char c, *b=buf; char c, *b=buf;
if (channel>2 || nr<0) return -1; if (channel>2 || nr<0) return -1;
tty = channel + tty_table; tty = channel + tty_table;
while (nr>0) { while (nr>0) {
sleep_if_full(&tty->write_q); sleep_if_full(&tty->write_q);
if (current->signal) if (current->signal)
break; break;
while (nr>0 && !FULL(tty->write_q)) { while (nr>0 && !FULL(tty->write_q)) {
c=get_fs_byte(b); c=get_fs_byte(b);
if (O_POST(tty)) { if (O_POST(tty)) {
if (c=='\r' && O_CRNL(tty)) if (c=='\r' && O_CRNL(tty))
c='\n'; c='\n';
else if (c=='\n' && O_NLRET(tty)) else if (c=='\n' && O_NLRET(tty))
c='\r'; c='\r';
if (c=='\n' && !cr_flag && O_NLCR(tty)) { if (c=='\n' && !cr_flag && O_NLCR(tty)) {
cr_flag = 1; cr_flag = 1;
PUTCH(13,tty->write_q); PUTCH(13,tty->write_q);
continue; continue;
} }
if (O_LCUC(tty)) if (O_LCUC(tty))
c=toupper(c); c=toupper(c);
} }
b++; nr--; b++; nr--;
cr_flag = 0; cr_flag = 0;
PUTCH(c,tty->write_q); PUTCH(c,tty->write_q);
} }
tty->write(tty); tty->write(tty);
if (nr>0) if (nr>0)
schedule(); schedule();
} }
return (b-buf); return (b-buf);
} }
/* /*
* Jeh, sometimes I really like the 386. * Jeh, sometimes I really like the 386.
* This routine is called from an interrupt, * This routine is called from an interrupt,
* and there should be absolutely no problem * and there should be absolutely no problem
* with sleeping even in an interrupt (I hope). * with sleeping even in an interrupt (I hope).
* Of course, if somebody proves me wrong, I'll * Of course, if somebody proves me wrong, I'll
* hate intel for all time :-). We'll have to * hate intel for all time :-). We'll have to
* be careful and see to reinstating the interrupt * be careful and see to reinstating the interrupt
* chips before calling this, though. * chips before calling this, though.
* *
* I don't think we sleep here under normal circumstances * I don't think we sleep here under normal circumstances
* anyway, which is good, as the task sleeping might be * anyway, which is good, as the task sleeping might be
* totally innocent. * totally innocent.
*/ */
void do_tty_interrupt(int tty) void do_tty_interrupt(int tty)
{ {
copy_to_cooked(tty_table+tty); copy_to_cooked(tty_table+tty);
} }
void chr_dev_init(void) void chr_dev_init(void)
{ {
} }

@ -1,204 +1,204 @@
/* /*
* linux/kernel/chr_drv/tty_ioctl.c * linux/kernel/chr_drv/tty_ioctl.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <termios.h> #include <termios.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
static unsigned short quotient[] = { static unsigned short quotient[] = {
0, 2304, 1536, 1047, 857, 0, 2304, 1536, 1047, 857,
768, 576, 384, 192, 96, 768, 576, 384, 192, 96,
64, 48, 24, 12, 6, 3 64, 48, 24, 12, 6, 3
}; };
static void change_speed(struct tty_struct * tty) static void change_speed(struct tty_struct * tty)
{ {
unsigned short port,quot; unsigned short port,quot;
if (!(port = tty->read_q.data)) if (!(port = tty->read_q.data))
return; return;
quot = quotient[tty->termios.c_cflag & CBAUD]; quot = quotient[tty->termios.c_cflag & CBAUD];
cli(); cli();
outb_p(0x80,port+3); /* set DLAB */ outb_p(0x80,port+3); /* set DLAB */
outb_p(quot & 0xff,port); /* LS of divisor */ outb_p(quot & 0xff,port); /* LS of divisor */
outb_p(quot >> 8,port+1); /* MS of divisor */ outb_p(quot >> 8,port+1); /* MS of divisor */
outb(0x03,port+3); /* reset DLAB */ outb(0x03,port+3); /* reset DLAB */
sti(); sti();
} }
static void flush(struct tty_queue * queue) static void flush(struct tty_queue * queue)
{ {
cli(); cli();
queue->head = queue->tail; queue->head = queue->tail;
sti(); sti();
} }
static void wait_until_sent(struct tty_struct * tty) static void wait_until_sent(struct tty_struct * tty)
{ {
/* do nothing - not implemented */ /* do nothing - not implemented */
} }
static void send_break(struct tty_struct * tty) static void send_break(struct tty_struct * tty)
{ {
/* do nothing - not implemented */ /* do nothing - not implemented */
} }
static int get_termios(struct tty_struct * tty, struct termios * termios) static int get_termios(struct tty_struct * tty, struct termios * termios)
{ {
int i; int i;
verify_area(termios, sizeof (*termios)); verify_area(termios, sizeof (*termios));
for (i=0 ; i< (sizeof (*termios)) ; i++) for (i=0 ; i< (sizeof (*termios)) ; i++)
put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios ); put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
return 0; return 0;
} }
static int set_termios(struct tty_struct * tty, struct termios * termios) static int set_termios(struct tty_struct * tty, struct termios * termios)
{ {
int i; int i;
for (i=0 ; i< (sizeof (*termios)) ; i++) for (i=0 ; i< (sizeof (*termios)) ; i++)
((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios); ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
change_speed(tty); change_speed(tty);
return 0; return 0;
} }
static int get_termio(struct tty_struct * tty, struct termio * termio) static int get_termio(struct tty_struct * tty, struct termio * termio)
{ {
int i; int i;
struct termio tmp_termio; struct termio tmp_termio;
verify_area(termio, sizeof (*termio)); verify_area(termio, sizeof (*termio));
tmp_termio.c_iflag = tty->termios.c_iflag; tmp_termio.c_iflag = tty->termios.c_iflag;
tmp_termio.c_oflag = tty->termios.c_oflag; tmp_termio.c_oflag = tty->termios.c_oflag;
tmp_termio.c_cflag = tty->termios.c_cflag; tmp_termio.c_cflag = tty->termios.c_cflag;
tmp_termio.c_lflag = tty->termios.c_lflag; tmp_termio.c_lflag = tty->termios.c_lflag;
tmp_termio.c_line = tty->termios.c_line; tmp_termio.c_line = tty->termios.c_line;
for(i=0 ; i < NCC ; i++) for(i=0 ; i < NCC ; i++)
tmp_termio.c_cc[i] = tty->termios.c_cc[i]; tmp_termio.c_cc[i] = tty->termios.c_cc[i];
for (i=0 ; i< (sizeof (*termio)) ; i++) for (i=0 ; i< (sizeof (*termio)) ; i++)
put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio ); put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
return 0; return 0;
} }
/* /*
* This only works as the 386 is low-byt-first * This only works as the 386 is low-byt-first
*/ */
static int set_termio(struct tty_struct * tty, struct termio * termio) static int set_termio(struct tty_struct * tty, struct termio * termio)
{ {
int i; int i;
struct termio tmp_termio; struct termio tmp_termio;
for (i=0 ; i< (sizeof (*termio)) ; i++) for (i=0 ; i< (sizeof (*termio)) ; i++)
((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio); ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
*(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag; *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
*(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag; *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
*(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag; *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
*(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag; *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
tty->termios.c_line = tmp_termio.c_line; tty->termios.c_line = tmp_termio.c_line;
for(i=0 ; i < NCC ; i++) for(i=0 ; i < NCC ; i++)
tty->termios.c_cc[i] = tmp_termio.c_cc[i]; tty->termios.c_cc[i] = tmp_termio.c_cc[i];
change_speed(tty); change_speed(tty);
return 0; return 0;
} }
int tty_ioctl(int dev, int cmd, int arg) int tty_ioctl(int dev, int cmd, int arg)
{ {
struct tty_struct * tty; struct tty_struct * tty;
if (MAJOR(dev) == 5) { if (MAJOR(dev) == 5) {
dev=current->tty; dev=current->tty;
if (dev<0) if (dev<0)
panic("tty_ioctl: dev<0"); panic("tty_ioctl: dev<0");
} else } else
dev=MINOR(dev); dev=MINOR(dev);
tty = dev + tty_table; tty = dev + tty_table;
switch (cmd) { switch (cmd) {
case TCGETS: case TCGETS:
return get_termios(tty,(struct termios *) arg); return get_termios(tty,(struct termios *) arg);
case TCSETSF: case TCSETSF:
flush(&tty->read_q); /* fallthrough */ flush(&tty->read_q); /* fallthrough */
case TCSETSW: case TCSETSW:
wait_until_sent(tty); /* fallthrough */ wait_until_sent(tty); /* fallthrough */
case TCSETS: case TCSETS:
return set_termios(tty,(struct termios *) arg); return set_termios(tty,(struct termios *) arg);
case TCGETA: case TCGETA:
return get_termio(tty,(struct termio *) arg); return get_termio(tty,(struct termio *) arg);
case TCSETAF: case TCSETAF:
flush(&tty->read_q); /* fallthrough */ flush(&tty->read_q); /* fallthrough */
case TCSETAW: case TCSETAW:
wait_until_sent(tty); /* fallthrough */ wait_until_sent(tty); /* fallthrough */
case TCSETA: case TCSETA:
return set_termio(tty,(struct termio *) arg); return set_termio(tty,(struct termio *) arg);
case TCSBRK: case TCSBRK:
if (!arg) { if (!arg) {
wait_until_sent(tty); wait_until_sent(tty);
send_break(tty); send_break(tty);
} }
return 0; return 0;
case TCXONC: case TCXONC:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TCFLSH: case TCFLSH:
if (arg==0) if (arg==0)
flush(&tty->read_q); flush(&tty->read_q);
else if (arg==1) else if (arg==1)
flush(&tty->write_q); flush(&tty->write_q);
else if (arg==2) { else if (arg==2) {
flush(&tty->read_q); flush(&tty->read_q);
flush(&tty->write_q); flush(&tty->write_q);
} else } else
return -EINVAL; return -EINVAL;
return 0; return 0;
case TIOCEXCL: case TIOCEXCL:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCNXCL: case TIOCNXCL:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCSCTTY: case TIOCSCTTY:
return -EINVAL; /* set controlling term NI */ return -EINVAL; /* set controlling term NI */
case TIOCGPGRP: case TIOCGPGRP:
verify_area((void *) arg,4); verify_area((void *) arg,4);
put_fs_long(tty->pgrp,(unsigned long *) arg); put_fs_long(tty->pgrp,(unsigned long *) arg);
return 0; return 0;
case TIOCSPGRP: case TIOCSPGRP:
tty->pgrp=get_fs_long((unsigned long *) arg); tty->pgrp=get_fs_long((unsigned long *) arg);
return 0; return 0;
case TIOCOUTQ: case TIOCOUTQ:
verify_area((void *) arg,4); verify_area((void *) arg,4);
put_fs_long(CHARS(tty->write_q),(unsigned long *) arg); put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
return 0; return 0;
case TIOCINQ: case TIOCINQ:
verify_area((void *) arg,4); verify_area((void *) arg,4);
put_fs_long(CHARS(tty->secondary), put_fs_long(CHARS(tty->secondary),
(unsigned long *) arg); (unsigned long *) arg);
return 0; return 0;
case TIOCSTI: case TIOCSTI:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCGWINSZ: case TIOCGWINSZ:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCSWINSZ: case TIOCSWINSZ:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCMGET: case TIOCMGET:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCMBIS: case TIOCMBIS:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCMBIC: case TIOCMBIC:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCMSET: case TIOCMSET:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCGSOFTCAR: case TIOCGSOFTCAR:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
case TIOCSSOFTCAR: case TIOCSSOFTCAR:
return -EINVAL; /* not implemented */ return -EINVAL; /* not implemented */
default: default:
return -EINVAL; return -EINVAL;
} }
} }

@ -1,197 +1,197 @@
/* /*
* linux/kernel/exit.c * linux/kernel/exit.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <asm/segment.h> #include <asm/segment.h>
int sys_pause(void); int sys_pause(void);
int sys_close(int fd); int sys_close(int fd);
void release(struct task_struct * p) void release(struct task_struct * p)
{ {
int i; int i;
if (!p) if (!p)
return; return;
for (i=1 ; i<NR_TASKS ; i++) for (i=1 ; i<NR_TASKS ; i++)
if (task[i]==p) { if (task[i]==p) {
task[i]=NULL; task[i]=NULL;
free_page((long)p); free_page((long)p);
schedule(); schedule();
return; return;
} }
panic("trying to release non-existent task"); panic("trying to release non-existent task");
} }
static inline int send_sig(long sig,struct task_struct * p,int priv) static inline int send_sig(long sig,struct task_struct * p,int priv)
{ {
if (!p || sig<1 || sig>32) if (!p || sig<1 || sig>32)
return -EINVAL; return -EINVAL;
if (priv || (current->euid==p->euid) || suser()) if (priv || (current->euid==p->euid) || suser())
p->signal |= (1<<(sig-1)); p->signal |= (1<<(sig-1));
else else
return -EPERM; return -EPERM;
return 0; return 0;
} }
static void kill_session(void) static void kill_session(void)
{ {
struct task_struct **p = NR_TASKS + task; struct task_struct **p = NR_TASKS + task;
while (--p > &FIRST_TASK) { while (--p > &FIRST_TASK) {
if (*p && (*p)->session == current->session) if (*p && (*p)->session == current->session)
(*p)->signal |= 1<<(SIGHUP-1); (*p)->signal |= 1<<(SIGHUP-1);
} }
} }
/* /*
* XXX need to check permissions needed to send signals to process * XXX need to check permissions needed to send signals to process
* groups, etc. etc. kill() permissions semantics are tricky! * groups, etc. etc. kill() permissions semantics are tricky!
*/ */
int sys_kill(int pid,int sig) int sys_kill(int pid,int sig)
{ {
struct task_struct **p = NR_TASKS + task; struct task_struct **p = NR_TASKS + task;
int err, retval = 0; int err, retval = 0;
if (!pid) while (--p > &FIRST_TASK) { if (!pid) while (--p > &FIRST_TASK) {
if (*p && (*p)->pgrp == current->pid) if (*p && (*p)->pgrp == current->pid)
if (err=send_sig(sig,*p,1)) if (err=send_sig(sig,*p,1))
retval = err; retval = err;
} else if (pid>0) while (--p > &FIRST_TASK) { } else if (pid>0) while (--p > &FIRST_TASK) {
if (*p && (*p)->pid == pid) if (*p && (*p)->pid == pid)
if (err=send_sig(sig,*p,0)) if (err=send_sig(sig,*p,0))
retval = err; retval = err;
} else if (pid == -1) while (--p > &FIRST_TASK) } else if (pid == -1) while (--p > &FIRST_TASK)
if (err = send_sig(sig,*p,0)) if (err = send_sig(sig,*p,0))
retval = err; retval = err;
else while (--p > &FIRST_TASK) else while (--p > &FIRST_TASK)
if (*p && (*p)->pgrp == -pid) if (*p && (*p)->pgrp == -pid)
if (err = send_sig(sig,*p,0)) if (err = send_sig(sig,*p,0))
retval = err; retval = err;
return retval; return retval;
} }
static void tell_father(int pid) static void tell_father(int pid)
{ {
int i; int i;
if (pid) if (pid)
for (i=0;i<NR_TASKS;i++) { for (i=0;i<NR_TASKS;i++) {
if (!task[i]) if (!task[i])
continue; continue;
if (task[i]->pid != pid) if (task[i]->pid != pid)
continue; continue;
task[i]->signal |= (1<<(SIGCHLD-1)); task[i]->signal |= (1<<(SIGCHLD-1));
return; return;
} }
/* if we don't find any fathers, we just release ourselves */ /* if we don't find any fathers, we just release ourselves */
/* This is not really OK. Must change it to make father 1 */ /* This is not really OK. Must change it to make father 1 */
printk("BAD BAD - no father found\n\r"); printk("BAD BAD - no father found\n\r");
release(current); release(current);
} }
int do_exit(long code) int do_exit(long code)
{ {
int i; int i;
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
for (i=0 ; i<NR_TASKS ; i++) for (i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->father == current->pid) { if (task[i] && task[i]->father == current->pid) {
task[i]->father = 1; task[i]->father = 1;
if (task[i]->state == TASK_ZOMBIE) if (task[i]->state == TASK_ZOMBIE)
/* assumption task[1] is always init */ /* assumption task[1] is always init */
(void) send_sig(SIGCHLD, task[1], 1); (void) send_sig(SIGCHLD, task[1], 1);
} }
for (i=0 ; i<NR_OPEN ; i++) for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i]) if (current->filp[i])
sys_close(i); sys_close(i);
iput(current->pwd); iput(current->pwd);
current->pwd=NULL; current->pwd=NULL;
iput(current->root); iput(current->root);
current->root=NULL; current->root=NULL;
iput(current->executable); iput(current->executable);
current->executable=NULL; current->executable=NULL;
if (current->leader && current->tty >= 0) if (current->leader && current->tty >= 0)
tty_table[current->tty].pgrp = 0; tty_table[current->tty].pgrp = 0;
if (last_task_used_math == current) if (last_task_used_math == current)
last_task_used_math = NULL; last_task_used_math = NULL;
if (current->leader) if (current->leader)
kill_session(); kill_session();
current->state = TASK_ZOMBIE; current->state = TASK_ZOMBIE;
current->exit_code = code; current->exit_code = code;
tell_father(current->father); tell_father(current->father);
schedule(); schedule();
return (-1); /* just to suppress warnings */ return (-1); /* just to suppress warnings */
} }
int sys_exit(int error_code) int sys_exit(int error_code)
{ {
return do_exit((error_code&0xff)<<8); return do_exit((error_code&0xff)<<8);
} }
int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
{ {
int flag, code; int flag, code;
struct task_struct ** p; struct task_struct ** p;
verify_area(stat_addr,4); verify_area(stat_addr,4);
repeat: repeat:
flag=0; flag=0;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
if (!*p || *p == current) if (!*p || *p == current)
continue; continue;
if ((*p)->father != current->pid) if ((*p)->father != current->pid)
continue; continue;
if (pid>0) { if (pid>0) {
if ((*p)->pid != pid) if ((*p)->pid != pid)
continue; continue;
} else if (!pid) { } else if (!pid) {
if ((*p)->pgrp != current->pgrp) if ((*p)->pgrp != current->pgrp)
continue; continue;
} else if (pid != -1) { } else if (pid != -1) {
if ((*p)->pgrp != -pid) if ((*p)->pgrp != -pid)
continue; continue;
} }
switch ((*p)->state) { switch ((*p)->state) {
case TASK_STOPPED: case TASK_STOPPED:
if (!(options & WUNTRACED)) if (!(options & WUNTRACED))
continue; continue;
put_fs_long(0x7f,stat_addr); put_fs_long(0x7f,stat_addr);
return (*p)->pid; return (*p)->pid;
case TASK_ZOMBIE: case TASK_ZOMBIE:
current->cutime += (*p)->utime; current->cutime += (*p)->utime;
current->cstime += (*p)->stime; current->cstime += (*p)->stime;
flag = (*p)->pid; flag = (*p)->pid;
code = (*p)->exit_code; code = (*p)->exit_code;
release(*p); release(*p);
put_fs_long(code,stat_addr); put_fs_long(code,stat_addr);
return flag; return flag;
default: default:
flag=1; flag=1;
continue; continue;
} }
} }
if (flag) { if (flag) {
if (options & WNOHANG) if (options & WNOHANG)
return 0; return 0;
current->state=TASK_INTERRUPTIBLE; current->state=TASK_INTERRUPTIBLE;
schedule(); schedule();
if (!(current->signal &= ~(1<<(SIGCHLD-1)))) if (!(current->signal &= ~(1<<(SIGCHLD-1))))
goto repeat; goto repeat;
else else
return -EINTR; return -EINTR;
} }
return -ECHILD; return -ECHILD;
} }

@ -1,148 +1,148 @@
/* /*
* linux/kernel/fork.c * linux/kernel/fork.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 'fork.c' contains the help-routines for the 'fork' system call * 'fork.c' contains the help-routines for the 'fork' system call
* (see also system_call.s), and some misc functions ('verify_area'). * (see also system_call.s), and some misc functions ('verify_area').
* Fork is rather simple, once you get the hang of it, but the memory * Fork is rather simple, once you get the hang of it, but the memory
* management can be a bitch. See 'mm/mm.c': 'copy_page_tables()' * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
*/ */
#include <errno.h> #include <errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
extern void write_verify(unsigned long address); extern void write_verify(unsigned long address);
long last_pid=0; long last_pid=0;
void verify_area(void * addr,int size) void verify_area(void * addr,int size)
{ {
unsigned long start; unsigned long start;
start = (unsigned long) addr; start = (unsigned long) addr;
size += start & 0xfff; size += start & 0xfff;
start &= 0xfffff000; start &= 0xfffff000;
start += get_base(current->ldt[2]); start += get_base(current->ldt[2]);
while (size>0) { while (size>0) {
size -= 4096; size -= 4096;
write_verify(start); write_verify(start);
start += 4096; start += 4096;
} }
} }
int copy_mem(int nr,struct task_struct * p) int copy_mem(int nr,struct task_struct * p)
{ {
unsigned long old_data_base,new_data_base,data_limit; unsigned long old_data_base,new_data_base,data_limit;
unsigned long old_code_base,new_code_base,code_limit; unsigned long old_code_base,new_code_base,code_limit;
code_limit=get_limit(0x0f); code_limit=get_limit(0x0f);
data_limit=get_limit(0x17); data_limit=get_limit(0x17);
old_code_base = get_base(current->ldt[1]); old_code_base = get_base(current->ldt[1]);
old_data_base = get_base(current->ldt[2]); old_data_base = get_base(current->ldt[2]);
if (old_data_base != old_code_base) if (old_data_base != old_code_base)
panic("We don't support separate I&D"); panic("We don't support separate I&D");
if (data_limit < code_limit) if (data_limit < code_limit)
panic("Bad data_limit"); panic("Bad data_limit");
new_data_base = new_code_base = nr * 0x4000000; new_data_base = new_code_base = nr * 0x4000000;
p->start_code = new_code_base; p->start_code = new_code_base;
set_base(p->ldt[1],new_code_base); set_base(p->ldt[1],new_code_base);
set_base(p->ldt[2],new_data_base); set_base(p->ldt[2],new_data_base);
if (copy_page_tables(old_data_base,new_data_base,data_limit)) { if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit); free_page_tables(new_data_base,data_limit);
return -ENOMEM; return -ENOMEM;
} }
return 0; return 0;
} }
/* /*
* Ok, this is the main fork-routine. It copies the system process * Ok, this is the main fork-routine. It copies the system process
* information (task[nr]) and sets up the necessary registers. It * information (task[nr]) and sets up the necessary registers. It
* also copies the data segment in it's entirety. * also copies the data segment in it's entirety.
*/ */
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none, int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx, long ebx,long ecx,long edx,
long fs,long es,long ds, long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss) long eip,long cs,long eflags,long esp,long ss)
{ {
struct task_struct *p; struct task_struct *p;
int i; int i;
struct file *f; struct file *f;
p = (struct task_struct *) get_free_page(); p = (struct task_struct *) get_free_page();
if (!p) if (!p)
return -EAGAIN; return -EAGAIN;
task[nr] = p; task[nr] = p;
__asm__ volatile ("cld"); /* by wyj */ __asm__ volatile ("cld"); /* by wyj */
*p = *current; /* NOTE! this doesn't copy the supervisor stack */ *p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE; p->state = TASK_UNINTERRUPTIBLE;
p->pid = last_pid; p->pid = last_pid;
p->father = current->pid; p->father = current->pid;
p->counter = p->priority; p->counter = p->priority;
p->signal = 0; p->signal = 0;
p->alarm = 0; p->alarm = 0;
p->leader = 0; /* process leadership doesn't inherit */ p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0; p->utime = p->stime = 0;
p->cutime = p->cstime = 0; p->cutime = p->cstime = 0;
p->start_time = jiffies; p->start_time = jiffies;
p->tss.back_link = 0; p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long) p; p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10; p->tss.ss0 = 0x10;
p->tss.eip = eip; p->tss.eip = eip;
p->tss.eflags = eflags; p->tss.eflags = eflags;
p->tss.eax = 0; p->tss.eax = 0;
p->tss.ecx = ecx; p->tss.ecx = ecx;
p->tss.edx = edx; p->tss.edx = edx;
p->tss.ebx = ebx; p->tss.ebx = ebx;
p->tss.esp = esp; p->tss.esp = esp;
p->tss.ebp = ebp; p->tss.ebp = ebp;
p->tss.esi = esi; p->tss.esi = esi;
p->tss.edi = edi; p->tss.edi = edi;
p->tss.es = es & 0xffff; p->tss.es = es & 0xffff;
p->tss.cs = cs & 0xffff; p->tss.cs = cs & 0xffff;
p->tss.ss = ss & 0xffff; p->tss.ss = ss & 0xffff;
p->tss.ds = ds & 0xffff; p->tss.ds = ds & 0xffff;
p->tss.fs = fs & 0xffff; p->tss.fs = fs & 0xffff;
p->tss.gs = gs & 0xffff; p->tss.gs = gs & 0xffff;
p->tss.ldt = _LDT(nr); p->tss.ldt = _LDT(nr);
p->tss.trace_bitmap = 0x80000000; p->tss.trace_bitmap = 0x80000000;
if (last_task_used_math == current) if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387)); __asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) { if (copy_mem(nr,p)) {
task[nr] = NULL; task[nr] = NULL;
free_page((long) p); free_page((long) p);
return -EAGAIN; return -EAGAIN;
} }
for (i=0; i<NR_OPEN;i++) for (i=0; i<NR_OPEN;i++)
if (f=p->filp[i]) if (f=p->filp[i])
f->f_count++; f->f_count++;
if (current->pwd) if (current->pwd)
current->pwd->i_count++; current->pwd->i_count++;
if (current->root) if (current->root)
current->root->i_count++; current->root->i_count++;
if (current->executable) if (current->executable)
current->executable->i_count++; current->executable->i_count++;
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
p->state = TASK_RUNNING; /* do this last, just in case */ p->state = TASK_RUNNING; /* do this last, just in case */
return last_pid; return last_pid;
} }
int find_empty_process(void) int find_empty_process(void)
{ {
int i; int i;
repeat: repeat:
if ((++last_pid)<0) last_pid=1; if ((++last_pid)<0) last_pid=1;
for(i=0 ; i<NR_TASKS ; i++) for(i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid == last_pid) goto repeat; if (task[i] && task[i]->pid == last_pid) goto repeat;
for(i=1 ; i<NR_TASKS ; i++) for(i=1 ; i<NR_TASKS ; i++)
if (!task[i]) if (!task[i])
return i; return i;
return -EAGAIN; return -EAGAIN;
} }

@ -1,43 +1,43 @@
# #
# Makefile for the FREAX-kernel character device drivers. # Makefile for the FREAX-kernel character device drivers.
# #
# Note! Dependencies are done automagically by 'make dep', which also # Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here # removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-s -x LDFLAGS =-s -x
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \ CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer -mcld \
-nostdinc -fno-stack-protector -I../../include -nostdinc -fno-stack-protector -I../../include
CPP =gcc -E -nostdinc -I../../include CPP =gcc -E -nostdinc -I../../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
OBJS = math_emulate.o OBJS = math_emulate.o
math.a: $(OBJS) math.a: $(OBJS)
$(AR) rcs math.a $(OBJS) $(AR) rcs math.a $(OBJS)
sync sync
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
### Dependencies: ### Dependencies:

@ -1,42 +1,42 @@
/* /*
* linux/kernel/math/math_emulate.c * linux/kernel/math/math_emulate.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* This directory should contain the math-emulation code. * This directory should contain the math-emulation code.
* Currently only results in a signal. * Currently only results in a signal.
*/ */
#include <signal.h> #include <signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
void math_emulate(long edi, long esi, long ebp, long sys_call_ret, void math_emulate(long edi, long esi, long ebp, long sys_call_ret,
long eax,long ebx,long ecx,long edx, long eax,long ebx,long ecx,long edx,
unsigned short fs,unsigned short es,unsigned short ds, unsigned short fs,unsigned short es,unsigned short ds,
unsigned long eip,unsigned short cs,unsigned long eflags, unsigned long eip,unsigned short cs,unsigned long eflags,
unsigned short ss, unsigned long esp) unsigned short ss, unsigned long esp)
{ {
unsigned char first, second; unsigned char first, second;
/* 0x0007 means user code space */ /* 0x0007 means user code space */
if (cs != 0x000F) { if (cs != 0x000F) {
printk("math_emulate: %04x:%08x\n\r",cs,eip); printk("math_emulate: %04x:%08x\n\r",cs,eip);
panic("Math emulation needed in kernel"); panic("Math emulation needed in kernel");
} }
first = get_fs_byte((char *)((*&eip)++)); first = get_fs_byte((char *)((*&eip)++));
second = get_fs_byte((char *)((*&eip)++)); second = get_fs_byte((char *)((*&eip)++));
printk("%04x:%08x %02x %02x\n\r",cs,eip-2,first,second); printk("%04x:%08x %02x %02x\n\r",cs,eip-2,first,second);
current->signal |= 1<<(SIGFPE-1); current->signal |= 1<<(SIGFPE-1);
} }
void math_error(void) void math_error(void)
{ {
__asm__("fnclex"); __asm__("fnclex");
if (last_task_used_math) if (last_task_used_math)
last_task_used_math->signal |= 1<<(SIGFPE-1); last_task_used_math->signal |= 1<<(SIGFPE-1);
} }

@ -1,58 +1,58 @@
/* /*
* linux/kernel/mktime.c * linux/kernel/mktime.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <time.h> #include <time.h>
/* /*
* This isn't the library routine, it is only used in the kernel. * This isn't the library routine, it is only used in the kernel.
* as such, we don't care about years<1970 etc, but assume everything * as such, we don't care about years<1970 etc, but assume everything
* is ok. Similarly, TZ etc is happily ignored. We just do everything * is ok. Similarly, TZ etc is happily ignored. We just do everything
* as easily as possible. Let's find something public for the library * as easily as possible. Let's find something public for the library
* routines (although I think minix times is public). * routines (although I think minix times is public).
*/ */
/* /*
* PS. I hate whoever though up the year 1970 - couldn't they have gotten * PS. I hate whoever though up the year 1970 - couldn't they have gotten
* a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy. * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.
*/ */
#define MINUTE 60 #define MINUTE 60
#define HOUR (60*MINUTE) #define HOUR (60*MINUTE)
#define DAY (24*HOUR) #define DAY (24*HOUR)
#define YEAR (365*DAY) #define YEAR (365*DAY)
/* interestingly, we assume leap-years */ /* interestingly, we assume leap-years */
static int month[12] = { static int month[12] = {
0, 0,
DAY*(31), DAY*(31),
DAY*(31+29), DAY*(31+29),
DAY*(31+29+31), DAY*(31+29+31),
DAY*(31+29+31+30), DAY*(31+29+31+30),
DAY*(31+29+31+30+31), DAY*(31+29+31+30+31),
DAY*(31+29+31+30+31+30), DAY*(31+29+31+30+31+30),
DAY*(31+29+31+30+31+30+31), DAY*(31+29+31+30+31+30+31),
DAY*(31+29+31+30+31+30+31+31), DAY*(31+29+31+30+31+30+31+31),
DAY*(31+29+31+30+31+30+31+31+30), DAY*(31+29+31+30+31+30+31+31+30),
DAY*(31+29+31+30+31+30+31+31+30+31), DAY*(31+29+31+30+31+30+31+31+30+31),
DAY*(31+29+31+30+31+30+31+31+30+31+30) DAY*(31+29+31+30+31+30+31+31+30+31+30)
}; };
long kernel_mktime(struct tm * tm) long kernel_mktime(struct tm * tm)
{ {
long res; long res;
int year; int year;
if (tm->tm_year < 70 ) tm->tm_year += 100; /* gohigh */ if (tm->tm_year < 70 ) tm->tm_year += 100; /* gohigh */
year = tm->tm_year - 70; year = tm->tm_year - 70;
/* magic offsets (y+1) needed to get leapyears right.*/ /* magic offsets (y+1) needed to get leapyears right.*/
res = YEAR*year + DAY*((year+1)/4); res = YEAR*year + DAY*((year+1)/4);
res += month[tm->tm_mon]; res += month[tm->tm_mon];
/* and (y+2) here. If it wasn't a leap-year, we have to adjust */ /* and (y+2) here. If it wasn't a leap-year, we have to adjust */
if (tm->tm_mon>1 && ((year+2)%4)) if (tm->tm_mon>1 && ((year+2)%4))
res -= DAY; res -= DAY;
res += DAY*(tm->tm_mday-1); res += DAY*(tm->tm_mday-1);
res += HOUR*tm->tm_hour; res += HOUR*tm->tm_hour;
res += MINUTE*tm->tm_min; res += MINUTE*tm->tm_min;
res += tm->tm_sec; res += tm->tm_sec;
return res; return res;
} }

@ -1,24 +1,24 @@
/* /*
* linux/kernel/panic.c * linux/kernel/panic.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* This function is used through-out the kernel (includeinh mm and fs) * This function is used through-out the kernel (includeinh mm and fs)
* to indicate a major problem. * to indicate a major problem.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
void sys_sync(void); /* it's really int */ void sys_sync(void); /* it's really int */
volatile void panic(const char * s) volatile void panic(const char * s)
{ {
printk("Kernel panic: %s\n\r",s); printk("Kernel panic: %s\n\r",s);
if (current == task[0]) if (current == task[0])
printk("In swapper task - not syncing\n\r"); printk("In swapper task - not syncing\n\r");
else else
sys_sync(); sys_sync();
for(;;); for(;;);
} }

@ -1,41 +1,41 @@
/* /*
* linux/kernel/printk.c * linux/kernel/printk.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* When in kernel-mode, we cannot use printf, as fs is liable to * When in kernel-mode, we cannot use printf, as fs is liable to
* point to 'interesting' things. Make a printf with fs-saving, and * point to 'interesting' things. Make a printf with fs-saving, and
* all is well. * all is well.
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <linux/kernel.h> #include <linux/kernel.h>
static char buf[1024]; static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args); extern int vsprintf(char * buf, const char * fmt, va_list args);
int printk(const char *fmt, ...) int printk(const char *fmt, ...)
{ {
va_list args; va_list args;
int i; int i;
va_start(args, fmt); va_start(args, fmt);
i=vsprintf(buf,fmt,args); i=vsprintf(buf,fmt,args);
va_end(args); va_end(args);
__asm__("push %%fs\n\t" __asm__("push %%fs\n\t"
"push %%ds\n\t" "push %%ds\n\t"
"pop %%fs\n\t" "pop %%fs\n\t"
"pushl %0\n\t" "pushl %0\n\t"
"pushl $buf\n\t" "pushl $buf\n\t"
"pushl $0\n\t" "pushl $0\n\t"
"call tty_write\n\t" "call tty_write\n\t"
"addl $8,%%esp\n\t" "addl $8,%%esp\n\t"
"popl %0\n\t" "popl %0\n\t"
"pop %%fs" "pop %%fs"
::"r" (i):"ax","cx","dx"); ::"r" (i):"ax","cx","dx");
return i; return i;
} }

@ -1,412 +1,412 @@
/* /*
* linux/kernel/sched.c * linux/kernel/sched.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 'sched.c' is the main kernel file. It contains scheduling primitives * 'sched.c' is the main kernel file. It contains scheduling primitives
* (sleep_on, wakeup, schedule etc) as well as a number of simple system * (sleep_on, wakeup, schedule etc) as well as a number of simple system
* call functions (type getpid(), which just extracts a field from * call functions (type getpid(), which just extracts a field from
* current-task * current-task
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sys.h> #include <linux/sys.h>
#include <linux/fdreg.h> #include <linux/fdreg.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <signal.h> #include <signal.h>
#define _S(nr) (1<<((nr)-1)) #define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
void show_task(int nr,struct task_struct * p) void show_task(int nr,struct task_struct * p)
{ {
int i,j = 4096-sizeof(struct task_struct); int i,j = 4096-sizeof(struct task_struct);
printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state); printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
i=0; i=0;
while (i<j && !((char *)(p+1))[i]) while (i<j && !((char *)(p+1))[i])
i++; i++;
printk("%d (of %d) chars free in kernel stack\n\r",i,j); printk("%d (of %d) chars free in kernel stack\n\r",i,j);
} }
void show_stat(void) void show_stat(void)
{ {
int i; int i;
for (i=0;i<NR_TASKS;i++) for (i=0;i<NR_TASKS;i++)
if (task[i]) if (task[i])
show_task(i,task[i]); show_task(i,task[i]);
} }
#define LATCH (1193180/HZ) #define LATCH (1193180/HZ)
extern void mem_use(void); extern void mem_use(void);
extern int timer_interrupt(void); extern int timer_interrupt(void);
extern int system_call(void); extern int system_call(void);
union task_union { union task_union {
struct task_struct task; struct task_struct task;
char stack[PAGE_SIZE]; char stack[PAGE_SIZE];
}; };
static union task_union init_task = {INIT_TASK,}; static union task_union init_task = {INIT_TASK,};
long volatile jiffies=0; long volatile jiffies=0;
long startup_time=0; long startup_time=0;
struct task_struct *current = &(init_task.task); struct task_struct *current = &(init_task.task);
struct task_struct *last_task_used_math = NULL; struct task_struct *last_task_used_math = NULL;
struct task_struct * task[NR_TASKS] = {&(init_task.task), }; struct task_struct * task[NR_TASKS] = {&(init_task.task), };
long user_stack [ PAGE_SIZE>>2 ] ; long user_stack [ PAGE_SIZE>>2 ] ;
struct { struct {
long * a; long * a;
short b; short b;
} stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 }; } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
/* /*
* 'math_state_restore()' saves the current math information in the * 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task * old math state array, and gets the new ones from the current task
*/ */
void math_state_restore() void math_state_restore()
{ {
if (last_task_used_math == current) if (last_task_used_math == current)
return; return;
__asm__("fwait"); __asm__("fwait");
if (last_task_used_math) { if (last_task_used_math) {
__asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
} }
last_task_used_math=current; last_task_used_math=current;
if (current->used_math) { if (current->used_math) {
__asm__("frstor %0"::"m" (current->tss.i387)); __asm__("frstor %0"::"m" (current->tss.i387));
} else { } else {
__asm__("fninit"::); __asm__("fninit"::);
current->used_math=1; current->used_math=1;
} }
} }
/* /*
* 'schedule()' is the scheduler function. This is GOOD CODE! There * 'schedule()' is the scheduler function. This is GOOD CODE! There
* probably won't be any reason to change this, as it should work well * probably won't be any reason to change this, as it should work well
* in all circumstances (ie gives IO-bound processes good response etc). * in all circumstances (ie gives IO-bound processes good response etc).
* The one thing you might take a look at is the signal-handler code here. * The one thing you might take a look at is the signal-handler code here.
* *
* NOTE!! Task 0 is the 'idle' task, which gets called when no other * NOTE!! Task 0 is the 'idle' task, which gets called when no other
* tasks can run. It can not be killed, and it cannot sleep. The 'state' * tasks can run. It can not be killed, and it cannot sleep. The 'state'
* information in task[0] is never used. * information in task[0] is never used.
*/ */
void schedule(void) void schedule(void)
{ {
int i,next,c; int i,next,c;
struct task_struct ** p; struct task_struct ** p;
/* check alarm, wake up any interruptible tasks that have got a signal */ /* check alarm, wake up any interruptible tasks that have got a signal */
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) { if (*p) {
if ((*p)->alarm && (*p)->alarm < jiffies) { if ((*p)->alarm && (*p)->alarm < jiffies) {
(*p)->signal |= (1<<(SIGALRM-1)); (*p)->signal |= (1<<(SIGALRM-1));
(*p)->alarm = 0; (*p)->alarm = 0;
} }
if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
(*p)->state==TASK_INTERRUPTIBLE) (*p)->state==TASK_INTERRUPTIBLE)
(*p)->state=TASK_RUNNING; (*p)->state=TASK_RUNNING;
} }
/* this is the scheduler proper: */ /* this is the scheduler proper: */
while (1) { while (1) {
c = -1; c = -1;
next = 0; next = 0;
i = NR_TASKS; i = NR_TASKS;
p = &task[NR_TASKS]; p = &task[NR_TASKS];
while (--i) { while (--i) {
if (!*--p) if (!*--p)
continue; continue;
if ((*p)->state == TASK_RUNNING && (*p)->counter > c) if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i; c = (*p)->counter, next = i;
} }
if (c) break; if (c) break;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) if (*p)
(*p)->counter = ((*p)->counter >> 1) + (*p)->counter = ((*p)->counter >> 1) +
(*p)->priority; (*p)->priority;
} }
switch_to(next); switch_to(next);
} }
int sys_pause(void) int sys_pause(void)
{ {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
return 0; return 0;
} }
void sleep_on(struct task_struct **p) void sleep_on(struct task_struct **p)
{ {
struct task_struct *tmp; struct task_struct *tmp;
if (!p) if (!p)
return; return;
if (current == &(init_task.task)) if (current == &(init_task.task))
panic("task[0] trying to sleep"); panic("task[0] trying to sleep");
tmp = *p; tmp = *p;
*p = current; *p = current;
current->state = TASK_UNINTERRUPTIBLE; current->state = TASK_UNINTERRUPTIBLE;
schedule(); schedule();
if (tmp) if (tmp)
tmp->state=0; tmp->state=0;
} }
void interruptible_sleep_on(struct task_struct **p) void interruptible_sleep_on(struct task_struct **p)
{ {
struct task_struct *tmp; struct task_struct *tmp;
if (!p) if (!p)
return; return;
if (current == &(init_task.task)) if (current == &(init_task.task))
panic("task[0] trying to sleep"); panic("task[0] trying to sleep");
tmp=*p; tmp=*p;
*p=current; *p=current;
repeat: current->state = TASK_INTERRUPTIBLE; repeat: current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (*p && *p != current) { if (*p && *p != current) {
(**p).state=0; (**p).state=0;
goto repeat; goto repeat;
} }
*p=NULL; *p=NULL;
if (tmp) if (tmp)
tmp->state=0; tmp->state=0;
} }
void wake_up(struct task_struct **p) void wake_up(struct task_struct **p)
{ {
if (p && *p) { if (p && *p) {
(**p).state=0; (**p).state=0;
*p=NULL; *p=NULL;
} }
} }
/* /*
* OK, here are some floppy things that shouldn't be in the kernel * OK, here are some floppy things that shouldn't be in the kernel
* proper. They are here because the floppy needs a timer, and this * proper. They are here because the floppy needs a timer, and this
* was the easiest way of doing it. * was the easiest way of doing it.
*/ */
static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL}; static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
static int mon_timer[4]={0,0,0,0}; static int mon_timer[4]={0,0,0,0};
static int moff_timer[4]={0,0,0,0}; static int moff_timer[4]={0,0,0,0};
unsigned char current_DOR = 0x0C; unsigned char current_DOR = 0x0C;
int ticks_to_floppy_on(unsigned int nr) int ticks_to_floppy_on(unsigned int nr)
{ {
extern unsigned char selected; extern unsigned char selected;
unsigned char mask = 0x10 << nr; unsigned char mask = 0x10 << nr;
if (nr>3) if (nr>3)
panic("floppy_on: nr>3"); panic("floppy_on: nr>3");
moff_timer[nr]=10000; /* 100 s = very big :-) */ moff_timer[nr]=10000; /* 100 s = very big :-) */
cli(); /* use floppy_off to turn it off */ cli(); /* use floppy_off to turn it off */
mask |= current_DOR; mask |= current_DOR;
if (!selected) { if (!selected) {
mask &= 0xFC; mask &= 0xFC;
mask |= nr; mask |= nr;
} }
if (mask != current_DOR) { if (mask != current_DOR) {
outb(mask,FD_DOR); outb(mask,FD_DOR);
if ((mask ^ current_DOR) & 0xf0) if ((mask ^ current_DOR) & 0xf0)
mon_timer[nr] = HZ/2; mon_timer[nr] = HZ/2;
else if (mon_timer[nr] < 2) else if (mon_timer[nr] < 2)
mon_timer[nr] = 2; mon_timer[nr] = 2;
current_DOR = mask; current_DOR = mask;
} }
sti(); sti();
return mon_timer[nr]; return mon_timer[nr];
} }
void floppy_on(unsigned int nr) void floppy_on(unsigned int nr)
{ {
cli(); cli();
while (ticks_to_floppy_on(nr)) while (ticks_to_floppy_on(nr))
sleep_on(nr+wait_motor); sleep_on(nr+wait_motor);
sti(); sti();
} }
void floppy_off(unsigned int nr) void floppy_off(unsigned int nr)
{ {
moff_timer[nr]=3*HZ; moff_timer[nr]=3*HZ;
} }
void do_floppy_timer(void) void do_floppy_timer(void)
{ {
int i; int i;
unsigned char mask = 0x10; unsigned char mask = 0x10;
for (i=0 ; i<4 ; i++,mask <<= 1) { for (i=0 ; i<4 ; i++,mask <<= 1) {
if (!(mask & current_DOR)) if (!(mask & current_DOR))
continue; continue;
if (mon_timer[i]) { if (mon_timer[i]) {
if (!--mon_timer[i]) if (!--mon_timer[i])
wake_up(i+wait_motor); wake_up(i+wait_motor);
} else if (!moff_timer[i]) { } else if (!moff_timer[i]) {
current_DOR &= ~mask; current_DOR &= ~mask;
outb(current_DOR,FD_DOR); outb(current_DOR,FD_DOR);
} else } else
moff_timer[i]--; moff_timer[i]--;
} }
} }
#define TIME_REQUESTS 64 #define TIME_REQUESTS 64
static struct timer_list { static struct timer_list {
long jiffies; long jiffies;
void (*fn)(); void (*fn)();
struct timer_list * next; struct timer_list * next;
} timer_list[TIME_REQUESTS], * next_timer = NULL; } timer_list[TIME_REQUESTS], * next_timer = NULL;
void add_timer(long jiffies, void (*fn)(void)) void add_timer(long jiffies, void (*fn)(void))
{ {
struct timer_list * p; struct timer_list * p;
if (!fn) if (!fn)
return; return;
cli(); cli();
if (jiffies <= 0) if (jiffies <= 0)
(fn)(); (fn)();
else { else {
for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++) for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
if (!p->fn) if (!p->fn)
break; break;
if (p >= timer_list + TIME_REQUESTS) if (p >= timer_list + TIME_REQUESTS)
panic("No more time requests free"); panic("No more time requests free");
p->fn = fn; p->fn = fn;
p->jiffies = jiffies; p->jiffies = jiffies;
p->next = next_timer; p->next = next_timer;
next_timer = p; next_timer = p;
while (p->next && p->next->jiffies < p->jiffies) { while (p->next && p->next->jiffies < p->jiffies) {
p->jiffies -= p->next->jiffies; p->jiffies -= p->next->jiffies;
fn = p->fn; fn = p->fn;
p->fn = p->next->fn; p->fn = p->next->fn;
p->next->fn = fn; p->next->fn = fn;
jiffies = p->jiffies; jiffies = p->jiffies;
p->jiffies = p->next->jiffies; p->jiffies = p->next->jiffies;
p->next->jiffies = jiffies; p->next->jiffies = jiffies;
p = p->next; p = p->next;
} }
} }
sti(); sti();
} }
void do_timer(long cpl) void do_timer(long cpl)
{ {
extern int beepcount; extern int beepcount;
extern void sysbeepstop(void); extern void sysbeepstop(void);
if (beepcount) if (beepcount)
if (!--beepcount) if (!--beepcount)
sysbeepstop(); sysbeepstop();
if (cpl) if (cpl)
current->utime++; current->utime++;
else else
current->stime++; current->stime++;
if (next_timer) { if (next_timer) {
next_timer->jiffies--; next_timer->jiffies--;
while (next_timer && next_timer->jiffies <= 0) { while (next_timer && next_timer->jiffies <= 0) {
void (*fn)(void); void (*fn)(void);
fn = next_timer->fn; fn = next_timer->fn;
next_timer->fn = NULL; next_timer->fn = NULL;
next_timer = next_timer->next; next_timer = next_timer->next;
(fn)(); (fn)();
} }
} }
if (current_DOR & 0xf0) if (current_DOR & 0xf0)
do_floppy_timer(); do_floppy_timer();
if ((--current->counter)>0) return; if ((--current->counter)>0) return;
current->counter=0; current->counter=0;
if (!cpl) return; if (!cpl) return;
schedule(); schedule();
} }
int sys_alarm(long seconds) int sys_alarm(long seconds)
{ {
int old = current->alarm; int old = current->alarm;
if (old) if (old)
old = (old - jiffies) / HZ; old = (old - jiffies) / HZ;
current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
return (old); return (old);
} }
int sys_getpid(void) int sys_getpid(void)
{ {
return current->pid; return current->pid;
} }
int sys_getppid(void) int sys_getppid(void)
{ {
return current->father; return current->father;
} }
int sys_getuid(void) int sys_getuid(void)
{ {
return current->uid; return current->uid;
} }
int sys_geteuid(void) int sys_geteuid(void)
{ {
return current->euid; return current->euid;
} }
int sys_getgid(void) int sys_getgid(void)
{ {
return current->gid; return current->gid;
} }
int sys_getegid(void) int sys_getegid(void)
{ {
return current->egid; return current->egid;
} }
int sys_nice(long increment) int sys_nice(long increment)
{ {
if (current->priority-increment>0) if (current->priority-increment>0)
current->priority -= increment; current->priority -= increment;
return 0; return 0;
} }
void sched_init(void) void sched_init(void)
{ {
int i; int i;
struct desc_struct * p; struct desc_struct * p;
if (sizeof(struct sigaction) != 16) if (sizeof(struct sigaction) != 16)
panic("Struct sigaction MUST be 16 bytes"); panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
p = gdt+2+FIRST_TSS_ENTRY; p = gdt+2+FIRST_TSS_ENTRY;
for(i=1;i<NR_TASKS;i++) { for(i=1;i<NR_TASKS;i++) {
task[i] = NULL; task[i] = NULL;
p->a=p->b=0; p->a=p->b=0;
p++; p++;
p->a=p->b=0; p->a=p->b=0;
p++; p++;
} }
/* Clear NT, so that we won't have troubles with that later on */ /* Clear NT, so that we won't have troubles with that later on */
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
ltr(0); ltr(0);
lldt(0); lldt(0);
outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */ outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */ outb(LATCH >> 8 , 0x40); /* MSB */
set_intr_gate(0x20,&timer_interrupt); set_intr_gate(0x20,&timer_interrupt);
outb(inb_p(0x21)&~0x01,0x21); outb(inb_p(0x21)&~0x01,0x21);
set_system_gate(0x80,&system_call); set_system_gate(0x80,&system_call);
} }

@ -1,129 +1,129 @@
/* /*
* linux/kernel/signal.c * linux/kernel/signal.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
volatile void do_exit(int error_code); volatile void do_exit(int error_code);
int sys_sgetmask() int sys_sgetmask()
{ {
return current->blocked; return current->blocked;
} }
int sys_ssetmask(int newmask) int sys_ssetmask(int newmask)
{ {
int old=current->blocked; int old=current->blocked;
current->blocked = newmask & ~(1<<(SIGKILL-1)); current->blocked = newmask & ~(1<<(SIGKILL-1));
return old; return old;
} }
int sys_sigpending() int sys_sigpending()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_sigsuspend() int sys_sigsuspend()
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline void save_old(char * from,char * to) static inline void save_old(char * from,char * to)
{ {
int i; int i;
verify_area(to, sizeof(struct sigaction)); verify_area(to, sizeof(struct sigaction));
for (i=0 ; i< sizeof(struct sigaction) ; i++) { for (i=0 ; i< sizeof(struct sigaction) ; i++) {
put_fs_byte(*from,to); put_fs_byte(*from,to);
from++; from++;
to++; to++;
} }
} }
static inline void get_new(char * from,char * to) static inline void get_new(char * from,char * to)
{ {
int i; int i;
for (i=0 ; i< sizeof(struct sigaction) ; i++) for (i=0 ; i< sizeof(struct sigaction) ; i++)
*(to++) = get_fs_byte(from++); *(to++) = get_fs_byte(from++);
} }
int sys_signal(int signum, long handler, long restorer) int sys_signal(int signum, long handler, long restorer)
{ {
struct sigaction tmp; struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL) if (signum<1 || signum>32 || signum==SIGKILL)
return -1; return -1;
tmp.sa_handler = (void (*)(int)) handler; tmp.sa_handler = (void (*)(int)) handler;
tmp.sa_mask = 0; tmp.sa_mask = 0;
tmp.sa_flags = SA_ONESHOT | SA_NOMASK; tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer = (void (*)(void)) restorer; tmp.sa_restorer = (void (*)(void)) restorer;
handler = (long) current->sigaction[signum-1].sa_handler; handler = (long) current->sigaction[signum-1].sa_handler;
current->sigaction[signum-1] = tmp; current->sigaction[signum-1] = tmp;
return handler; return handler;
} }
int sys_sigaction(int signum, const struct sigaction * action, int sys_sigaction(int signum, const struct sigaction * action,
struct sigaction * oldaction) struct sigaction * oldaction)
{ {
struct sigaction tmp; struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL) if (signum<1 || signum>32 || signum==SIGKILL)
return -1; return -1;
tmp = current->sigaction[signum-1]; tmp = current->sigaction[signum-1];
get_new((char *) action, get_new((char *) action,
(char *) (signum-1+current->sigaction)); (char *) (signum-1+current->sigaction));
if (oldaction) if (oldaction)
save_old((char *) &tmp,(char *) oldaction); save_old((char *) &tmp,(char *) oldaction);
if (current->sigaction[signum-1].sa_flags & SA_NOMASK) if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
current->sigaction[signum-1].sa_mask = 0; current->sigaction[signum-1].sa_mask = 0;
else else
current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
return 0; return 0;
} }
void do_signal(long signr,long eax, long ebx, long ecx, long edx, void do_signal(long signr,long eax, long ebx, long ecx, long edx,
long fs, long es, long ds, long fs, long es, long ds,
long eip, long cs, long eflags, long eip, long cs, long eflags,
unsigned long * esp, long ss) unsigned long * esp, long ss)
{ {
unsigned long sa_handler; unsigned long sa_handler;
long old_eip=eip; long old_eip=eip;
struct sigaction * sa = current->sigaction + signr - 1; struct sigaction * sa = current->sigaction + signr - 1;
int longs; int longs;
unsigned long * tmp_esp; unsigned long * tmp_esp;
sa_handler = (unsigned long) sa->sa_handler; sa_handler = (unsigned long) sa->sa_handler;
if (sa_handler==1) if (sa_handler==1)
return; return;
if (!sa_handler) { if (!sa_handler) {
if (signr==SIGCHLD) if (signr==SIGCHLD)
return; return;
else else
do_exit(1<<(signr-1)); do_exit(1<<(signr-1));
} }
if (sa->sa_flags & SA_ONESHOT) if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL; sa->sa_handler = NULL;
*(&eip) = sa_handler; *(&eip) = sa_handler;
longs = (sa->sa_flags & SA_NOMASK)?7:8; longs = (sa->sa_flags & SA_NOMASK)?7:8;
*(&esp) -= longs; *(&esp) -= longs;
verify_area(esp,longs*4); verify_area(esp,longs*4);
tmp_esp=esp; tmp_esp=esp;
put_fs_long((long) sa->sa_restorer,tmp_esp++); put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++); put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK)) if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++); put_fs_long(current->blocked,tmp_esp++);
put_fs_long(eax,tmp_esp++); put_fs_long(eax,tmp_esp++);
put_fs_long(ecx,tmp_esp++); put_fs_long(ecx,tmp_esp++);
put_fs_long(edx,tmp_esp++); put_fs_long(edx,tmp_esp++);
put_fs_long(eflags,tmp_esp++); put_fs_long(eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++); put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask; current->blocked |= sa->sa_mask;
} }

@ -1,292 +1,292 @@
/* /*
* linux/kernel/sys.c * linux/kernel/sys.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <errno.h> #include <errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <sys/times.h> #include <sys/times.h>
#include <sys/utsname.h> #include <sys/utsname.h>
int sys_ftime() int sys_ftime()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_break() int sys_break()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_ptrace() int sys_ptrace()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_stty() int sys_stty()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_gtty() int sys_gtty()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_rename() int sys_rename()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_prof() int sys_prof()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_setregid(int rgid, int egid) int sys_setregid(int rgid, int egid)
{ {
if (rgid>0) { if (rgid>0) {
if ((current->gid == rgid) || if ((current->gid == rgid) ||
suser()) suser())
current->gid = rgid; current->gid = rgid;
else else
return(-EPERM); return(-EPERM);
} }
if (egid>0) { if (egid>0) {
if ((current->gid == egid) || if ((current->gid == egid) ||
(current->egid == egid) || (current->egid == egid) ||
suser()) { suser()) {
current->egid = egid; current->egid = egid;
current->sgid = egid; current->sgid = egid;
} else } else
return(-EPERM); return(-EPERM);
} }
return 0; return 0;
} }
int sys_setgid(int gid) int sys_setgid(int gid)
{ {
/* return(sys_setregid(gid, gid)); */ /* return(sys_setregid(gid, gid)); */
if (suser()) if (suser())
current->gid = current->egid = current->sgid = gid; current->gid = current->egid = current->sgid = gid;
else if ((gid == current->gid) || (gid == current->sgid)) else if ((gid == current->gid) || (gid == current->sgid))
current->egid = gid; current->egid = gid;
else else
return -EPERM; return -EPERM;
return 0; return 0;
} }
int sys_acct() int sys_acct()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_phys() int sys_phys()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_lock() int sys_lock()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_mpx() int sys_mpx()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_ulimit() int sys_ulimit()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_time(long * tloc) int sys_time(long * tloc)
{ {
int i; int i;
i = CURRENT_TIME; i = CURRENT_TIME;
if (tloc) { if (tloc) {
verify_area(tloc,4); verify_area(tloc,4);
put_fs_long(i,(unsigned long *)tloc); put_fs_long(i,(unsigned long *)tloc);
} }
return i; return i;
} }
/* /*
* Unprivileged users may change the real user id to the effective uid * Unprivileged users may change the real user id to the effective uid
* or vice versa. * or vice versa.
*/ */
int sys_setreuid(int ruid, int euid) int sys_setreuid(int ruid, int euid)
{ {
int old_ruid = current->uid; int old_ruid = current->uid;
if (ruid>0) { if (ruid>0) {
if ((current->euid==ruid) || if ((current->euid==ruid) ||
(old_ruid == ruid) || (old_ruid == ruid) ||
suser()) suser())
current->uid = ruid; current->uid = ruid;
else else
return(-EPERM); return(-EPERM);
} }
if (euid>0) { if (euid>0) {
if ((old_ruid == euid) || if ((old_ruid == euid) ||
(current->euid == euid) || (current->euid == euid) ||
suser()) { suser()) {
current->euid = euid; current->euid = euid;
current->suid = euid; current->suid = euid;
} else { } else {
current->uid = old_ruid; current->uid = old_ruid;
return(-EPERM); return(-EPERM);
} }
} }
return 0; return 0;
} }
int sys_setuid(int uid) int sys_setuid(int uid)
{ {
/* return(sys_setreuid(uid, uid)); */ /* return(sys_setreuid(uid, uid)); */
if (suser()) if (suser())
current->uid = current->euid = current->suid = uid; current->uid = current->euid = current->suid = uid;
else if ((uid == current->uid) || (uid == current->suid)) else if ((uid == current->uid) || (uid == current->suid))
current->euid = uid; current->euid = uid;
else else
return -EPERM; return -EPERM;
return(0); return(0);
} }
int sys_stime(long * tptr) int sys_stime(long * tptr)
{ {
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ; startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
return 0; return 0;
} }
int sys_times(struct tms * tbuf) int sys_times(struct tms * tbuf)
{ {
if (tbuf) { if (tbuf) {
verify_area(tbuf,sizeof *tbuf); verify_area(tbuf,sizeof *tbuf);
put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime); put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime); put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime); put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime); put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
} }
return jiffies; return jiffies;
} }
int sys_brk(unsigned long end_data_seg) int sys_brk(unsigned long end_data_seg)
{ {
if (end_data_seg >= current->end_code && if (end_data_seg >= current->end_code &&
end_data_seg < current->start_stack - 16384) end_data_seg < current->start_stack - 16384)
current->brk = end_data_seg; current->brk = end_data_seg;
return current->brk; return current->brk;
} }
/* /*
* This needs some heave checking ... * This needs some heave checking ...
* I just haven't get the stomach for it. I also don't fully * I just haven't get the stomach for it. I also don't fully
* understand sessions/pgrp etc. Let somebody who does explain it. * understand sessions/pgrp etc. Let somebody who does explain it.
*/ */
int sys_setpgid(int pid, int pgid) int sys_setpgid(int pid, int pgid)
{ {
int i; int i;
if (!pid) if (!pid)
pid = current->pid; pid = current->pid;
if (!pgid) if (!pgid)
pgid = current->pid; pgid = current->pid;
for (i=0 ; i<NR_TASKS ; i++) for (i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid==pid) { if (task[i] && task[i]->pid==pid) {
if (task[i]->leader) if (task[i]->leader)
return -EPERM; return -EPERM;
if (task[i]->session != current->session) if (task[i]->session != current->session)
return -EPERM; return -EPERM;
task[i]->pgrp = pgid; task[i]->pgrp = pgid;
return 0; return 0;
} }
return -ESRCH; return -ESRCH;
} }
int sys_getpgrp(void) int sys_getpgrp(void)
{ {
return current->pgrp; return current->pgrp;
} }
int sys_setsid(void) int sys_setsid(void)
{ {
if (current->leader && !suser()) if (current->leader && !suser())
return -EPERM; return -EPERM;
current->leader = 1; current->leader = 1;
current->session = current->pgrp = current->pid; current->session = current->pgrp = current->pid;
current->tty = -1; current->tty = -1;
return current->pgrp; return current->pgrp;
} }
int sys_getgroups() int sys_getgroups()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_setgroups() int sys_setgroups()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_uname(struct utsname * name) int sys_uname(struct utsname * name)
{ {
static struct utsname thisname = { static struct utsname thisname = {
"linux .0","nodename","release ","version ","machine " "linux .0","nodename","release ","version ","machine "
}; };
int i; int i;
if (!name) return -ERROR; if (!name) return -ERROR;
verify_area(name,sizeof *name); verify_area(name,sizeof *name);
for(i=0;i<sizeof *name;i++) for(i=0;i<sizeof *name;i++)
put_fs_byte(((char *) &thisname)[i],i+(char *) name); put_fs_byte(((char *) &thisname)[i],i+(char *) name);
return 0; return 0;
} }
int sys_sethostname() int sys_sethostname()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_getrlimit() int sys_getrlimit()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_setrlimit() int sys_setrlimit()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_getrusage() int sys_getrusage()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_gettimeofday() int sys_gettimeofday()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_settimeofday() int sys_settimeofday()
{ {
return -ENOSYS; return -ENOSYS;
} }
int sys_umask(int mask) int sys_umask(int mask)
{ {
int old = current->umask; int old = current->umask;
current->umask = mask & 0777; current->umask = mask & 0777;
return (old); return (old);
} }

@ -1,285 +1,285 @@
/* /*
* linux/kernel/system_call.s * linux/kernel/system_call.s
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* system_call.s contains the system-call low-level handling routines. * system_call.s contains the system-call low-level handling routines.
* This also contains the timer-interrupt handler, as some of the code is * This also contains the timer-interrupt handler, as some of the code is
* the same. The hd- and flopppy-interrupts are also here. * the same. The hd- and flopppy-interrupts are also here.
* *
* NOTE: This code handles signal-recognition, which happens every time * NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call. Ordinary interrupts * after a timer-interrupt and after each system call. Ordinary interrupts
* don't handle signal-recognition, as that would clutter them up totally * don't handle signal-recognition, as that would clutter them up totally
* unnecessarily. * unnecessarily.
* *
* Stack layout in 'ret_from_system_call': * Stack layout in 'ret_from_system_call':
* *
* 0(%esp) - %eax * 0(%esp) - %eax
* 4(%esp) - %ebx * 4(%esp) - %ebx
* 8(%esp) - %ecx * 8(%esp) - %ecx
* C(%esp) - %edx * C(%esp) - %edx
* 10(%esp) - %fs * 10(%esp) - %fs
* 14(%esp) - %es * 14(%esp) - %es
* 18(%esp) - %ds * 18(%esp) - %ds
* 1C(%esp) - %eip * 1C(%esp) - %eip
* 20(%esp) - %cs * 20(%esp) - %cs
* 24(%esp) - %eflags * 24(%esp) - %eflags
* 28(%esp) - %oldesp * 28(%esp) - %oldesp
* 2C(%esp) - %oldss * 2C(%esp) - %oldss
*/ */
SIG_CHLD = 17 SIG_CHLD = 17
EAX = 0x00 EAX = 0x00
EBX = 0x04 EBX = 0x04
ECX = 0x08 ECX = 0x08
EDX = 0x0C EDX = 0x0C
FS = 0x10 FS = 0x10
ES = 0x14 ES = 0x14
DS = 0x18 DS = 0x18
EIP = 0x1C EIP = 0x1C
CS = 0x20 CS = 0x20
EFLAGS = 0x24 EFLAGS = 0x24
OLDESP = 0x28 OLDESP = 0x28
OLDSS = 0x2C OLDSS = 0x2C
state = 0 # these are offsets into the task-struct. state = 0 # these are offsets into the task-struct.
counter = 4 counter = 4
priority = 8 priority = 8
signal = 12 signal = 12
sigaction = 16 # MUST be 16 (=len of sigaction) sigaction = 16 # MUST be 16 (=len of sigaction)
blocked = (33*16) blocked = (33*16)
# offsets within sigaction # offsets within sigaction
sa_handler = 0 sa_handler = 0
sa_mask = 4 sa_mask = 4
sa_flags = 8 sa_flags = 8
sa_restorer = 12 sa_restorer = 12
nr_system_calls = 86 /* 72 */ nr_system_calls = 86 /* 72 */
/* /*
* Ok, I get parallel printer interrupts while using the floppy for some * Ok, I get parallel printer interrupts while using the floppy for some
* strange reason. Urgel. Now I just ignore them. * strange reason. Urgel. Now I just ignore them.
*/ */
.globl system_call,sys_fork,timer_interrupt,sys_execve .globl system_call,sys_fork,timer_interrupt,sys_execve
.globl hd_interrupt,floppy_interrupt,parallel_interrupt .globl hd_interrupt,floppy_interrupt,parallel_interrupt
.globl device_not_available, coprocessor_error .globl device_not_available, coprocessor_error
.align 4 .align 4
bad_sys_call: bad_sys_call:
movl $-1,%eax movl $-1,%eax
iret iret
.align 4 .align 4
reschedule: reschedule:
pushl $ret_from_sys_call pushl $ret_from_sys_call
jmp schedule jmp schedule
.align 4 .align 4
system_call: system_call:
cmpl $nr_system_calls-1,%eax cmpl $nr_system_calls-1,%eax
ja bad_sys_call ja bad_sys_call
push %ds push %ds
push %es push %es
push %fs push %fs
pushl %edx pushl %edx
pushl %ecx # push %ebx,%ecx,%edx as parameters pushl %ecx # push %ebx,%ecx,%edx as parameters
pushl %ebx # to the system call pushl %ebx # to the system call
movl $0x10,%edx # set up ds,es to kernel space movl $0x10,%edx # set up ds,es to kernel space
mov %dx,%ds mov %dx,%ds
mov %dx,%es mov %dx,%es
movl $0x17,%edx # fs points to local data space movl $0x17,%edx # fs points to local data space
mov %dx,%fs mov %dx,%fs
call sys_call_table(,%eax,4) call sys_call_table(,%eax,4)
pushl %eax pushl %eax
movl current,%eax movl current,%eax
cmpl $0,state(%eax) # state cmpl $0,state(%eax) # state
jne reschedule jne reschedule
cmpl $0,counter(%eax) # counter cmpl $0,counter(%eax) # counter
je reschedule je reschedule
ret_from_sys_call: ret_from_sys_call:
movl current,%eax # task[0] cannot have signals movl current,%eax # task[0] cannot have signals
cmpl task,%eax cmpl task,%eax
je 3f je 3f
cmpw $0x0f,CS(%esp) # was old code segment supervisor ? cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 3f jne 3f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 3f jne 3f
movl signal(%eax),%ebx movl signal(%eax),%ebx
movl blocked(%eax),%ecx movl blocked(%eax),%ecx
notl %ecx notl %ecx
andl %ebx,%ecx andl %ebx,%ecx
bsfl %ecx,%ecx bsfl %ecx,%ecx
je 3f je 3f
btrl %ecx,%ebx btrl %ecx,%ebx
movl %ebx,signal(%eax) movl %ebx,signal(%eax)
incl %ecx incl %ecx
pushl %ecx pushl %ecx
call do_signal call do_signal
popl %eax popl %eax
3: popl %eax 3: popl %eax
popl %ebx popl %ebx
popl %ecx popl %ecx
popl %edx popl %edx
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
iret iret
.align 4 .align 4
coprocessor_error: coprocessor_error:
push %ds push %ds
push %es push %es
push %fs push %fs
pushl %edx pushl %edx
pushl %ecx pushl %ecx
pushl %ebx pushl %ebx
pushl %eax pushl %eax
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
movl $0x17,%eax movl $0x17,%eax
mov %ax,%fs mov %ax,%fs
pushl $ret_from_sys_call pushl $ret_from_sys_call
jmp math_error jmp math_error
.align 2 .align 2
device_not_available: device_not_available:
push %ds push %ds
push %es push %es
push %fs push %fs
pushl %edx pushl %edx
pushl %ecx pushl %ecx
pushl %ebx pushl %ebx
pushl %eax pushl %eax
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
movl $0x17,%eax movl $0x17,%eax
mov %ax,%fs mov %ax,%fs
pushl $ret_from_sys_call pushl $ret_from_sys_call
clts # clear TS so that we can use math clts # clear TS so that we can use math
movl %cr0,%eax movl %cr0,%eax
testl $0x4,%eax # EM (math emulation bit) testl $0x4,%eax # EM (math emulation bit)
je math_state_restore je math_state_restore
pushl %ebp pushl %ebp
pushl %esi pushl %esi
pushl %edi pushl %edi
call math_emulate call math_emulate
popl %edi popl %edi
popl %esi popl %esi
popl %ebp popl %ebp
ret ret
.align 4 .align 4
timer_interrupt: timer_interrupt:
push %ds # save ds,es and put kernel data space push %ds # save ds,es and put kernel data space
push %es # into them. %fs is used by _system_call push %es # into them. %fs is used by _system_call
push %fs push %fs
pushl %edx # we save %eax,%ecx,%edx as gcc doesn't pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
pushl %ecx # save those across function calls. %ebx pushl %ecx # save those across function calls. %ebx
pushl %ebx # is saved as we use that in ret_sys_call pushl %ebx # is saved as we use that in ret_sys_call
pushl %eax pushl %eax
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
movl $0x17,%eax movl $0x17,%eax
mov %ax,%fs mov %ax,%fs
incl jiffies incl jiffies
movb $0x20,%al # EOI to interrupt controller #1 movb $0x20,%al # EOI to interrupt controller #1
outb %al,$0x20 outb %al,$0x20
movl CS(%esp),%eax movl CS(%esp),%eax
andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor) andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
pushl %eax pushl %eax
call do_timer # 'do_timer(long CPL)' does everything from call do_timer # 'do_timer(long CPL)' does everything from
addl $4,%esp # task switching to accounting ... addl $4,%esp # task switching to accounting ...
jmp ret_from_sys_call jmp ret_from_sys_call
.align 4 .align 4
sys_execve: sys_execve:
lea EIP(%esp),%eax lea EIP(%esp),%eax
pushl %eax pushl %eax
call do_execve call do_execve
addl $4,%esp addl $4,%esp
ret ret
.align 4 .align 4
sys_fork: sys_fork:
call find_empty_process call find_empty_process
testl %eax,%eax testl %eax,%eax
js 1f js 1f
push %gs push %gs
pushl %esi pushl %esi
pushl %edi pushl %edi
pushl %ebp pushl %ebp
pushl %eax pushl %eax
call copy_process call copy_process
addl $20,%esp addl $20,%esp
1: ret 1: ret
hd_interrupt: hd_interrupt:
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
push %ds push %ds
push %es push %es
push %fs push %fs
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
movl $0x17,%eax movl $0x17,%eax
mov %ax,%fs mov %ax,%fs
movb $0x20,%al movb $0x20,%al
outb %al,$0xA0 # EOI to interrupt controller #1 outb %al,$0xA0 # EOI to interrupt controller #1
jmp 1f # give port chance to breathe jmp 1f # give port chance to breathe
1: jmp 1f 1: jmp 1f
1: xorl %edx,%edx 1: xorl %edx,%edx
xchgl do_hd,%edx xchgl do_hd,%edx
testl %edx,%edx testl %edx,%edx
jne 1f jne 1f
movl $unexpected_hd_interrupt,%edx movl $unexpected_hd_interrupt,%edx
1: outb %al,$0x20 1: outb %al,$0x20
call *%edx # "interesting" way of handling intr. call *%edx # "interesting" way of handling intr.
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
iret iret
floppy_interrupt: floppy_interrupt:
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
push %ds push %ds
push %es push %es
push %fs push %fs
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
movl $0x17,%eax movl $0x17,%eax
mov %ax,%fs mov %ax,%fs
movb $0x20,%al movb $0x20,%al
outb %al,$0x20 # EOI to interrupt controller #1 outb %al,$0x20 # EOI to interrupt controller #1
xorl %eax,%eax xorl %eax,%eax
xchgl do_floppy,%eax xchgl do_floppy,%eax
testl %eax,%eax testl %eax,%eax
jne 1f jne 1f
movl $unexpected_floppy_interrupt,%eax movl $unexpected_floppy_interrupt,%eax
1: call *%eax # "interesting" way of handling intr. 1: call *%eax # "interesting" way of handling intr.
pop %fs pop %fs
pop %es pop %es
pop %ds pop %ds
popl %edx popl %edx
popl %ecx popl %ecx
popl %eax popl %eax
iret iret
parallel_interrupt: parallel_interrupt:
pushl %eax pushl %eax
movb $0x20,%al movb $0x20,%al
outb %al,$0x20 outb %al,$0x20
popl %eax popl %eax
iret iret

@ -1,208 +1,208 @@
/* /*
* linux/kernel/traps.c * linux/kernel/traps.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* /*
* 'Traps.c' handles hardware traps and faults after we have saved some * 'Traps.c' handles hardware traps and faults after we have saved some
* state in 'asm.s'. Currently mostly a debugging-aid, will be extended * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
* to mainly kill the offending process (probably by giving it a signal, * to mainly kill the offending process (probably by giving it a signal,
* but possibly by killing it outright if necessary). * but possibly by killing it outright if necessary).
*/ */
#include <string.h> #include <string.h>
#include <linux/head.h> #include <linux/head.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h> #include <asm/io.h>
#define get_seg_byte(seg,addr) ({ \ #define get_seg_byte(seg,addr) ({ \
register char __res; \ register char __res; \
__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \ :"=a" (__res):"0" (seg),"m" (*(addr))); \
__res;}) __res;})
#define get_seg_long(seg,addr) ({ \ #define get_seg_long(seg,addr) ({ \
register unsigned long __res; \ register unsigned long __res; \
__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \ :"=a" (__res):"0" (seg),"m" (*(addr))); \
__res;}) __res;})
#define _fs() ({ \ #define _fs() ({ \
register unsigned short __res; \ register unsigned short __res; \
__asm__("mov %%fs,%%ax":"=a" (__res):); \ __asm__("mov %%fs,%%ax":"=a" (__res):); \
__res;}) __res;})
int do_exit(long code); int do_exit(long code);
void page_exception(void); void page_exception(void);
void divide_error(void); void divide_error(void);
void debug(void); void debug(void);
void nmi(void); void nmi(void);
void int3(void); void int3(void);
void overflow(void); void overflow(void);
void bounds(void); void bounds(void);
void invalid_op(void); void invalid_op(void);
void device_not_available(void); void device_not_available(void);
void double_fault(void); void double_fault(void);
void coprocessor_segment_overrun(void); void coprocessor_segment_overrun(void);
void invalid_TSS(void); void invalid_TSS(void);
void segment_not_present(void); void segment_not_present(void);
void stack_segment(void); void stack_segment(void);
void general_protection(void); void general_protection(void);
void page_fault(void); void page_fault(void);
void coprocessor_error(void); void coprocessor_error(void);
void reserved(void); void reserved(void);
void parallel_interrupt(void); void parallel_interrupt(void);
void irq13(void); void irq13(void);
static void die(char * str,long esp_ptr,long nr) static void die(char * str,long esp_ptr,long nr)
{ {
long * esp = (long *) esp_ptr; long * esp = (long *) esp_ptr;
int i; int i;
printk("%s: %04x\n\r",str,nr&0xffff); printk("%s: %04x\n\r",str,nr&0xffff);
printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n", printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
esp[1],esp[0],esp[2],esp[4],esp[3]); esp[1],esp[0],esp[2],esp[4],esp[3]);
printk("fs: %04x\n",_fs()); printk("fs: %04x\n",_fs());
printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17)); printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
if (esp[4] == 0x17) { if (esp[4] == 0x17) {
printk("Stack: "); printk("Stack: ");
for (i=0;i<4;i++) for (i=0;i<4;i++)
printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
printk("\n"); printk("\n");
} }
str(i); str(i);
printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i);
for(i=0;i<10;i++) for(i=0;i<10;i++)
printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
printk("\n\r"); printk("\n\r");
do_exit(11); /* play segment exception */ do_exit(11); /* play segment exception */
} }
void do_double_fault(long esp, long error_code) void do_double_fault(long esp, long error_code)
{ {
die("double fault",esp,error_code); die("double fault",esp,error_code);
} }
void do_general_protection(long esp, long error_code) void do_general_protection(long esp, long error_code)
{ {
die("general protection",esp,error_code); die("general protection",esp,error_code);
} }
void do_divide_error(long esp, long error_code) void do_divide_error(long esp, long error_code)
{ {
die("divide error",esp,error_code); die("divide error",esp,error_code);
} }
void do_int3(long * esp, long error_code, void do_int3(long * esp, long error_code,
long fs,long es,long ds, long fs,long es,long ds,
long ebp,long esi,long edi, long ebp,long esi,long edi,
long edx,long ecx,long ebx,long eax) long edx,long ecx,long ebx,long eax)
{ {
int tr; int tr;
__asm__("str %%ax":"=a" (tr):"0" (0)); __asm__("str %%ax":"=a" (tr):"0" (0));
printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r", printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r",
eax,ebx,ecx,edx); eax,ebx,ecx,edx);
printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r", printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r",
esi,edi,ebp,(long) esp); esi,edi,ebp,(long) esp);
printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r", printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r",
ds,es,fs,tr); ds,es,fs,tr);
printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]); printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]);
} }
void do_nmi(long esp, long error_code) void do_nmi(long esp, long error_code)
{ {
die("nmi",esp,error_code); die("nmi",esp,error_code);
} }
void do_debug(long esp, long error_code) void do_debug(long esp, long error_code)
{ {
die("debug",esp,error_code); die("debug",esp,error_code);
} }
void do_overflow(long esp, long error_code) void do_overflow(long esp, long error_code)
{ {
die("overflow",esp,error_code); die("overflow",esp,error_code);
} }
void do_bounds(long esp, long error_code) void do_bounds(long esp, long error_code)
{ {
die("bounds",esp,error_code); die("bounds",esp,error_code);
} }
void do_invalid_op(long esp, long error_code) void do_invalid_op(long esp, long error_code)
{ {
die("invalid operand",esp,error_code); die("invalid operand",esp,error_code);
} }
void do_device_not_available(long esp, long error_code) void do_device_not_available(long esp, long error_code)
{ {
die("device not available",esp,error_code); die("device not available",esp,error_code);
} }
void do_coprocessor_segment_overrun(long esp, long error_code) void do_coprocessor_segment_overrun(long esp, long error_code)
{ {
die("coprocessor segment overrun",esp,error_code); die("coprocessor segment overrun",esp,error_code);
} }
void do_invalid_TSS(long esp,long error_code) void do_invalid_TSS(long esp,long error_code)
{ {
die("invalid TSS",esp,error_code); die("invalid TSS",esp,error_code);
} }
void do_segment_not_present(long esp,long error_code) void do_segment_not_present(long esp,long error_code)
{ {
die("segment not present",esp,error_code); die("segment not present",esp,error_code);
} }
void do_stack_segment(long esp,long error_code) void do_stack_segment(long esp,long error_code)
{ {
die("stack segment",esp,error_code); die("stack segment",esp,error_code);
} }
void do_coprocessor_error(long esp, long error_code) void do_coprocessor_error(long esp, long error_code)
{ {
if (last_task_used_math != current) if (last_task_used_math != current)
return; return;
die("coprocessor error",esp,error_code); die("coprocessor error",esp,error_code);
} }
void do_reserved(long esp, long error_code) void do_reserved(long esp, long error_code)
{ {
die("reserved (15,17-47) error",esp,error_code); die("reserved (15,17-47) error",esp,error_code);
} }
void trap_init(void) void trap_init(void)
{ {
int i; int i;
set_trap_gate(0,&divide_error); set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug); set_trap_gate(1,&debug);
set_trap_gate(2,&nmi); set_trap_gate(2,&nmi);
set_system_gate(3,&int3); /* int3-5 can be called from all */ set_system_gate(3,&int3); /* int3-5 can be called from all */
set_system_gate(4,&overflow); set_system_gate(4,&overflow);
set_system_gate(5,&bounds); set_system_gate(5,&bounds);
set_trap_gate(6,&invalid_op); set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available); set_trap_gate(7,&device_not_available);
set_trap_gate(8,&double_fault); set_trap_gate(8,&double_fault);
set_trap_gate(9,&coprocessor_segment_overrun); set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS); set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present); set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment); set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection); set_trap_gate(13,&general_protection);
set_trap_gate(14,&page_fault); set_trap_gate(14,&page_fault);
set_trap_gate(15,&reserved); set_trap_gate(15,&reserved);
set_trap_gate(16,&coprocessor_error); set_trap_gate(16,&coprocessor_error);
for (i=17;i<48;i++) for (i=17;i<48;i++)
set_trap_gate(i,&reserved); set_trap_gate(i,&reserved);
set_trap_gate(45,&irq13); set_trap_gate(45,&irq13);
outb_p(inb_p(0x21)&0xfb,0x21); outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xdf,0xA1); outb(inb_p(0xA1)&0xdf,0xA1);
set_trap_gate(39,&parallel_interrupt); set_trap_gate(39,&parallel_interrupt);
} }

@ -1,233 +1,233 @@
/* /*
* linux/kernel/vsprintf.c * linux/kernel/vsprintf.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/* /*
* Wirzenius wrote this portably, Torvalds fucked it up :-) * Wirzenius wrote this portably, Torvalds fucked it up :-)
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
/* we use this so that we can do without the ctype library */ /* we use this so that we can do without the ctype library */
#define is_digit(c) ((c) >= '0' && (c) <= '9') #define is_digit(c) ((c) >= '0' && (c) <= '9')
static int skip_atoi(const char **s) static int skip_atoi(const char **s)
{ {
int i=0; int i=0;
while (is_digit(**s)) while (is_digit(**s))
i = i*10 + *((*s)++) - '0'; i = i*10 + *((*s)++) - '0';
return i; return i;
} }
#define ZEROPAD 1 /* pad with zero */ #define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */ #define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */ #define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */ #define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */ #define LEFT 16 /* left justified */
#define SPECIAL 32 /* 0x */ #define SPECIAL 32 /* 0x */
#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */
#define do_div(n,base) ({ \ #define do_div(n,base) ({ \
int __res; \ int __res; \
__asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
__res; }) __res; })
static char * number(char * str, int num, int base, int size, int precision static char * number(char * str, int num, int base, int size, int precision
,int type) ,int type)
{ {
char c,sign,tmp[36]; char c,sign,tmp[36];
const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i; int i;
if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
if (type&LEFT) type &= ~ZEROPAD; if (type&LEFT) type &= ~ZEROPAD;
if (base<2 || base>36) if (base<2 || base>36)
return 0; return 0;
c = (type & ZEROPAD) ? '0' : ' ' ; c = (type & ZEROPAD) ? '0' : ' ' ;
if (type&SIGN && num<0) { if (type&SIGN && num<0) {
sign='-'; sign='-';
num = -num; num = -num;
} else } else
sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
if (sign) size--; if (sign) size--;
if (type&SPECIAL) if (type&SPECIAL)
if (base==16) size -= 2; if (base==16) size -= 2;
else if (base==8) size--; else if (base==8) size--;
i=0; i=0;
if (num==0) if (num==0)
tmp[i++]='0'; tmp[i++]='0';
else while (num!=0) else while (num!=0)
tmp[i++]=digits[do_div(num,base)]; tmp[i++]=digits[do_div(num,base)];
if (i>precision) precision=i; if (i>precision) precision=i;
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
*str++ = ' '; *str++ = ' ';
if (sign) if (sign)
*str++ = sign; *str++ = sign;
if (type&SPECIAL) if (type&SPECIAL)
if (base==8) if (base==8)
*str++ = '0'; *str++ = '0';
else if (base==16) { else if (base==16) {
*str++ = '0'; *str++ = '0';
*str++ = digits[33]; *str++ = digits[33];
} }
if (!(type&LEFT)) if (!(type&LEFT))
while(size-->0) while(size-->0)
*str++ = c; *str++ = c;
while(i<precision--) while(i<precision--)
*str++ = '0'; *str++ = '0';
while(i-->0) while(i-->0)
*str++ = tmp[i]; *str++ = tmp[i];
while(size-->0) while(size-->0)
*str++ = ' '; *str++ = ' ';
return str; return str;
} }
int vsprintf(char *buf, const char *fmt, va_list args) int vsprintf(char *buf, const char *fmt, va_list args)
{ {
int len; int len;
int i; int i;
char * str; char * str;
char *s; char *s;
int *ip; int *ip;
int flags; /* flags to number() */ int flags; /* flags to number() */
int field_width; /* width of output field */ int field_width; /* width of output field */
int precision; /* min. # of digits for integers; max int precision; /* min. # of digits for integers; max
number of chars for from string */ number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */ int qualifier; /* 'h', 'l', or 'L' for integer fields */
for (str=buf ; *fmt ; ++fmt) { for (str=buf ; *fmt ; ++fmt) {
if (*fmt != '%') { if (*fmt != '%') {
*str++ = *fmt; *str++ = *fmt;
continue; continue;
} }
/* process flags */ /* process flags */
flags = 0; flags = 0;
repeat: repeat:
++fmt; /* this also skips first '%' */ ++fmt; /* this also skips first '%' */
switch (*fmt) { switch (*fmt) {
case '-': flags |= LEFT; goto repeat; case '-': flags |= LEFT; goto repeat;
case '+': flags |= PLUS; goto repeat; case '+': flags |= PLUS; goto repeat;
case ' ': flags |= SPACE; goto repeat; case ' ': flags |= SPACE; goto repeat;
case '#': flags |= SPECIAL; goto repeat; case '#': flags |= SPECIAL; goto repeat;
case '0': flags |= ZEROPAD; goto repeat; case '0': flags |= ZEROPAD; goto repeat;
} }
/* get field width */ /* get field width */
field_width = -1; field_width = -1;
if (is_digit(*fmt)) if (is_digit(*fmt))
field_width = skip_atoi(&fmt); field_width = skip_atoi(&fmt);
else if (*fmt == '*') { else if (*fmt == '*') {
/* it's the next argument */ /* it's the next argument */
field_width = va_arg(args, int); field_width = va_arg(args, int);
if (field_width < 0) { if (field_width < 0) {
field_width = -field_width; field_width = -field_width;
flags |= LEFT; flags |= LEFT;
} }
} }
/* get the precision */ /* get the precision */
precision = -1; precision = -1;
if (*fmt == '.') { if (*fmt == '.') {
++fmt; ++fmt;
if (is_digit(*fmt)) if (is_digit(*fmt))
precision = skip_atoi(&fmt); precision = skip_atoi(&fmt);
else if (*fmt == '*') { else if (*fmt == '*') {
/* it's the next argument */ /* it's the next argument */
precision = va_arg(args, int); precision = va_arg(args, int);
} }
if (precision < 0) if (precision < 0)
precision = 0; precision = 0;
} }
/* get the conversion qualifier */ /* get the conversion qualifier */
qualifier = -1; qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
qualifier = *fmt; qualifier = *fmt;
++fmt; ++fmt;
} }
switch (*fmt) { switch (*fmt) {
case 'c': case 'c':
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
*str++ = ' '; *str++ = ' ';
*str++ = (unsigned char) va_arg(args, int); *str++ = (unsigned char) va_arg(args, int);
while (--field_width > 0) while (--field_width > 0)
*str++ = ' '; *str++ = ' ';
break; break;
case 's': case 's':
s = va_arg(args, char *); s = va_arg(args, char *);
len = strlen(s); len = strlen(s);
if (precision < 0) if (precision < 0)
precision = len; precision = len;
else if (len > precision) else if (len > precision)
len = precision; len = precision;
if (!(flags & LEFT)) if (!(flags & LEFT))
while (len < field_width--) while (len < field_width--)
*str++ = ' '; *str++ = ' ';
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
*str++ = *s++; *str++ = *s++;
while (len < field_width--) while (len < field_width--)
*str++ = ' '; *str++ = ' ';
break; break;
case 'o': case 'o':
str = number(str, va_arg(args, unsigned long), 8, str = number(str, va_arg(args, unsigned long), 8,
field_width, precision, flags); field_width, precision, flags);
break; break;
case 'p': case 'p':
if (field_width == -1) { if (field_width == -1) {
field_width = 8; field_width = 8;
flags |= ZEROPAD; flags |= ZEROPAD;
} }
str = number(str, str = number(str,
(unsigned long) va_arg(args, void *), 16, (unsigned long) va_arg(args, void *), 16,
field_width, precision, flags); field_width, precision, flags);
break; break;
case 'x': case 'x':
flags |= SMALL; flags |= SMALL;
case 'X': case 'X':
str = number(str, va_arg(args, unsigned long), 16, str = number(str, va_arg(args, unsigned long), 16,
field_width, precision, flags); field_width, precision, flags);
break; break;
case 'd': case 'd':
case 'i': case 'i':
flags |= SIGN; flags |= SIGN;
case 'u': case 'u':
str = number(str, va_arg(args, unsigned long), 10, str = number(str, va_arg(args, unsigned long), 10,
field_width, precision, flags); field_width, precision, flags);
break; break;
case 'n': case 'n':
ip = va_arg(args, int *); ip = va_arg(args, int *);
*ip = (str - buf); *ip = (str - buf);
break; break;
default: default:
if (*fmt != '%') if (*fmt != '%')
*str++ = '%'; *str++ = '%';
if (*fmt) if (*fmt)
*str++ = *fmt; *str++ = *fmt;
else else
--fmt; --fmt;
break; break;
} }
} }
*str = '\0'; *str = '\0';
return str-buf; return str-buf;
} }

@ -1,73 +1,73 @@
# #
# Makefile for some libs needed in the kernel. # Makefile for some libs needed in the kernel.
# #
# Note! Dependencies are done automagically by 'make dep', which also # Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here # removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file). # unless it's something special (ie not a .c file).
# #
AR =ar AR =ar
AS =as AS =as
LD =ld LD =ld
LDFLAGS =-s -x LDFLAGS =-s -x
CC =gcc -march=i386 CC =gcc -march=i386
CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer \ CFLAGS =-w -g -fstrength-reduce -fomit-frame-pointer \
-finline-functions -nostdinc -fno-stack-protector -I../include -finline-functions -nostdinc -fno-stack-protector -I../include
CPP =gcc -E -nostdinc -I../include CPP =gcc -E -nostdinc -I../include
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-S -o $*.s $< -S -o $*.s $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
-c -o $*.o $< -c -o $*.o $<
OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \ OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
execve.o wait.o string.o malloc.o execve.o wait.o string.o malloc.o
lib.a: $(OBJS) lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS) $(AR) rcs lib.a $(OBJS)
sync sync
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
$(CPP) -M $$i;done) >> tmp_make $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
### Dependencies: ### Dependencies:
_exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h \ _exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h
close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h \ close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h
ctype.s ctype.o : ctype.c ../include/ctype.h ctype.s ctype.o : ctype.c ../include/ctype.h
dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h \ dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h
errno.s errno.o : errno.c errno.s errno.o : errno.c
execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h \ execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h
malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h \ malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h \
../include/asm/system.h ../include/asm/system.h
open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h \ open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/stdarg.h ../include/utime.h ../include/stdarg.h
setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h \ setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h
string.s string.o : string.c ../include/string.h string.s string.o : string.c ../include/string.h
wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h \ wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/sys/wait.h ../include/utime.h ../include/sys/wait.h
write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h \ write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h \
../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \ ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
../include/utime.h ../include/utime.h

@ -1,13 +1,13 @@
/* /*
* linux/lib/_exit.c * linux/lib/_exit.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#define __LIBRARY__ #define __LIBRARY__
#include <unistd.h> #include <unistd.h>
volatile void _exit(int exit_code) volatile void _exit(int exit_code)
{ {
__asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code)); __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code));
} }

@ -1,10 +1,10 @@
/* /*
* linux/lib/close.c * linux/lib/close.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#define __LIBRARY__ #define __LIBRARY__
#include <unistd.h> #include <unistd.h>
_syscall1(int,close,int,fd) _syscall1(int,close,int,fd)

@ -1,35 +1,35 @@
/* /*
* linux/lib/ctype.c * linux/lib/ctype.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#include <ctype.h> #include <ctype.h>
char _ctmp; char _ctmp;
unsigned char _ctype[] = {0x00, /* EOF */ unsigned char _ctype[] = {0x00, /* EOF */
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */

@ -1,10 +1,10 @@
/* /*
* linux/lib/dup.c * linux/lib/dup.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
#define __LIBRARY__ #define __LIBRARY__
#include <unistd.h> #include <unistd.h>
_syscall1(int,dup,int,fd) _syscall1(int,dup,int,fd)

@ -1,7 +1,7 @@
/* /*
* linux/lib/errno.c * linux/lib/errno.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
int errno; int errno;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save