#
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, /dev/xxxx or empty, in which case the
-# default of FLOPPY is used by 'build'.
+# comment this line if you don't want the emulation-code
#
-ROOT_DEV = /dev/hdb1
+MATH_EMULATION = -DKERNEL_MATH_EMULATION
#
# uncomment the correct keyboard:
#
-# The value of KBDFLAGS should be or'ed together from the following
-# bits, depending on which features you want enabled.
-# 0x80 - Off: the Alt key will set bit 7 if pressed together with
-# another key.
-# On: the Alt key will NOT set the high bit; an escape
-# character is prepended instead.
-# The least significant bits control if the following keys are "dead".
-# The key is dead by default if the bit is on.
-# 0x01 - backquote (`)
-# 0x02 - accent acute
-# 0x04 - circumflex (^)
-# 0x08 - tilde (~)
-# 0x10 - dieresis (umlaut)
-
-KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
-# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F
-# KEYBOARD = -DKBD_US -DKBDFLAGS=0
-# KEYBOARD = -DKBD_GR -DKBDFLAGS=0
-# KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x9F
-# KEYBOARD = -DKBD_FR -DKBDFLAGS=0
-# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x9F
-# KEYBOARD = -DKBD_UK -DKBDFLAGS=0
-# KEYBOARD = -DKBD_DK -DKBDFLAGS=0
-# KEYBOARD = -DKBD_DK_LATIN1 -DKBDFLAGS=0x9F
-# KEYBOARD = -DKBD_DVORAK -DKBDFLAGS=0
-# KEYBOARD = -DKBD_SG -DKBDFLAGS=0
-# KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x9F
+
+KEYBOARD = -DKBD_FINNISH
+# KEYBOARD = -DKBD_US
+# KEYBOARD = -DKBD_GR
+# KEYBOARD = -DKBD_FR
+# KEYBOARD = -DKBD_UK
+# KEYBOARD = -DKBD_DK
+
+#
+# uncomment this line if you are using gcc-1.40
+#
+#GCC_OPT = -fcombine-regs -fstrength-reduce
#
-# comment this line if you don't want the emulation-code
+# standard CFLAGS
#
-MATH_EMULATION = -DKERNEL_MATH_EMULATION
+CFLAGS =-Wall -O6 -fomit-frame-pointer $(GCC_OPT)
#
-# standard CFLAGS
+# ROOT_DEV specifies the default root-device when making the image.
+# This can be either FLOPPY, /dev/xxxx or empty, in which case the
+# default of FLOPPY is used by 'build'.
#
-CFLAGS =-Wall -O6 -fomit-frame-pointer
+ROOT_DEV = /dev/hdb1
#
# if you want the ram-disk device, define this to be the
AS =as
LD =ld
-HOSTCC =gcc -static
-CC =gcc -nostdinc -I$(KERNELHDRS)
-MAKE =make
-CPP =$(CC) -E
-AR =ar
-
-ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o
-FILESYSTEMS =fs/minix/minix.o fs/ext/ext.o fs/msdos/msdos.o
-DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \
- kernel/blk_drv/scsi/scsi.a
+#LDFLAGS =-s -x -M
+LDFLAGS = -M
+CC =gcc $(RAMDISK)
+MAKE =make CFLAGS="$(CFLAGS)"
+CPP =cpp -nostdinc -Iinclude
+
+ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o
+FILESYSTEMS =fs/minix/minix.o
+DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
MATH =kernel/math/math.a
LIBS =lib/lib.a
-SUBDIRS =kernel mm fs net lib
-
-KERNELHDRS =/usr/src/linux/include
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -nostdinc -Iinclude -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) -c -o $*.o $<
+ $(CC) $(CFLAGS) \
+ -nostdinc -Iinclude -c -o $*.o $<
all: Version Image
-subdirs: dummy
- for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
-
Version:
@./makever.sh
- @echo \#define UTS_RELEASE \"0.96c.pl2-`cat .version`\" > include/linux/config_rel.h
+ @echo \#define UTS_RELEASE \"0.95c-`cat .version`\" > include/linux/config_rel.h
@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
touch include/linux/config.h
dd bs=8192 if=Image of=/dev/PS0
tools/build: tools/build.c
- $(HOSTCC) $(CFLAGS) \
+ $(CC) -static $(CFLAGS) \
-o tools/build tools/build.c
boot/head.o: boot/head.s
-tools/system: boot/head.o init/main.o subdirs
- $(LD) $(LDFLAGS) -M boot/head.o init/main.o \
- $(ARCHIVES) \
- $(FILESYSTEMS) \
- $(DRIVERS) \
- $(MATH) \
- $(LIBS) \
- -o tools/system > System.map
+tools/system: boot/head.o init/main.o \
+ $(ARCHIVES) $(FILESYSTEMS) $(DRIVERS) $(MATH) $(LIBS)
+ $(LD) $(LDFLAGS) boot/head.o init/main.o \
+ $(ARCHIVES) \
+ $(FILESYSTEMS) \
+ $(DRIVERS) \
+ $(MATH) \
+ $(LIBS) \
+ -o tools/system > System.map
+
+kernel/math/math.a: dummy
+ (cd kernel/math; $(MAKE) MATH_EMULATION="$(MATH_EMULATION)")
+
+kernel/blk_drv/blk_drv.a: dummy
+ (cd kernel/blk_drv; $(MAKE))
+
+kernel/chr_drv/chr_drv.a: dummy
+ (cd kernel/chr_drv; $(MAKE) KEYBOARD="$(KEYBOARD)")
+
+kernel/kernel.o: dummy
+ (cd kernel; $(MAKE))
+
+mm/mm.o: dummy
+ (cd mm; $(MAKE))
+
+fs/fs.o: dummy
+ (cd fs; $(MAKE))
+
+fs/minix/minix.o: dummy
+ (cd fs/minix; $(MAKE))
+
+lib/lib.a: dummy
+ (cd lib; $(MAKE))
boot/setup: boot/setup.s
$(AS86) -o boot/setup.o boot/setup.s
rm -f Image System.map tmp_make core boot/bootsect boot/setup \
boot/bootsect.s boot/setup.s init/main.s
rm -f init/*.o tools/system tools/build boot/*.o
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
+ (cd mm;make clean)
+ (cd fs;make clean)
+ (cd kernel;make clean)
+ (cd lib;make clean)
backup: clean
- cd .. ; tar cf - linux | compress - > backup.Z
+ (cd .. ; tar cf - linux | compress - > backup.Z)
sync
-depend dep:
+dep:
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
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
+ (cd fs; make dep)
+ (cd kernel; make dep)
+ (cd mm; make dep)
+ (cd lib; make dep)
dummy:
### Dependencies:
-init/main.o : init/main.c /usr/src/linux/include/stddef.h /usr/src/linux/include/stdarg.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/asm/io.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/config.h \
- /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
- /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/termios.h /usr/src/linux/include/linux/unistd.h
+init/main.o : init/main.c include/unistd.h include/sys/stat.h include/sys/types.h \
+ include/sys/time.h include/time.h include/sys/times.h include/sys/utsname.h \
+ include/sys/param.h include/sys/resource.h include/utime.h include/linux/sched.h \
+ include/linux/head.h include/linux/fs.h include/sys/dirent.h include/limits.h \
+ include/linux/mm.h include/linux/kernel.h include/signal.h include/linux/tty.h \
+ include/termios.h include/linux/string.h include/asm/system.h include/asm/io.h \
+ include/stddef.h include/stdarg.h include/fcntl.h
mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18
je root_defined
- mov ax,#0x0200 ! /dev/fd0 - autodetect
+undef_root:
+ jmp undef_root
root_defined:
seg cs
mov root_dev,ax
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0xFF ! mask off all interrupts for now
- out #0xA1,al
+ out #0x21,al
.word 0x00eb,0x00eb
- mov al,#0xFB ! mask all irq's but irq2 which
- out #0x21,al ! is cascaded
+ out #0xA1,al
! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
! need no steenking BIOS anyway (except for the initial loading :-).
push ds
push cs
pop ds
-
-! First try and execute a VESA BIOS call
-
- mov ax,#0x4f00 ! AX = VESA BIOS func RETURN SVGA Info
- push cs
- pop es
- lea di,vib ! ES:[DI] -> VESA Information Block Ptr
- int 0x10
-
- cmp ax,#0x004f ! Check result status
- jne novesa ! VESA BIOS not supported or failed
-
-! OK! We got a VESA BIOS, let's figure out what we can do!
-
-! Print out the VESA information from the VIB
-
- lea si,vib ! This should print out VESA
- lodsb
- call prnt1
- lodsb
- call prnt1
- lodsb
- call prnt1
- lodsb
- call prnt1
- call space
-
- mov al,vib+5 ! This is the version of VESA supported
- call dprnt
- mov al,#0x2e
- call prnt1
- mov al,vib+4
- call dprnt
- call space
-
- push ds
- lds si,vib+6 ! This prints out the OEM string
- call prtstr
- call space
- pop ds
-
- mov al,vib+10 ! This prints out the Vesa Capabilities
- call dprnt
- mov al,vib+11
- call dprnt
- mov al,vib+12
- call dprnt
- mov al,vib+13
- call dprnt
-
- push ds ! Finally, go through the list of modes
- lds si,vib+14
-model: lodsw ! Get mode number
- cmp ax,#0xFFFF
- je isvesa
- call addmod ! Check to see if this is a TEXT mode
- jmp model
-
-isvesa: call docr
- pop ds
- lea si,dscvesa
- lea di,movesa
- lea cx,selmod
- jmp cx
-
-novesa: mov ax,#0xc000
+ mov ax,#0xc000
mov es,ax
lea si,msg1
- call prtstr ! Press <RETURN> to see SVGA-modes ...
+ call prtstr
flush: in al,#0x60 ! Flush the keyboard buffer
cmp al,#0x82
jb nokey
mov al,#0x55
xor al,#0xea
cmp al,bh
- je isvideo7
- lea cx,set8x8
- jmp cx
-isvideo7:
+ jne novid7
lea si,dscvideo7
lea di,movideo7
-
-! Upon Entry to SELMOD, SI -> list of Modes, DI -> List of Mode Numbers
-
selmod: push si
- lea si,msg2 ! Numb: Mode: COLSxROWS
+ lea si,msg2
call prtstr
- mov cx,(di) ! This gets Number of Modes in list
+ xor cx,cx
+ mov cl,(di)
pop si
push si
push cx
tbl: pop bx
push bx
- mov ax,bx
- sub ax,cx
- call hprntl ! Print out selection number
- push ax
- call spcing
- pop ax
- push di
- add ax,ax
- add ax,#2
- add di,ax
- mov ax,(di)
- call hprntl ! Print out MODE number
+ mov al,bl
+ sub al,cl
+ call dprnt
call spcing
- pop di
lodsw
xchg al,ah
call dprnt
loop tbl
pop cx
call docr
- lea si,msg3 ! Choose Mode Number
+ lea si,msg3
call prtstr
pop si
add cl,#0x80
nozero: sub al,#0x80
dec al
xor ah,ah
- shl ax,#1
- push ax
add di,ax
inc di
- inc di
- mov ax,(di) ! AX = Mode
- cmp ah,#0
- jne setvesa
- int 0x10 ! Set OLD style mode
-
-retmode:
+ push ax
+ mov al,(di)
+ int 0x10
pop ax
+ shl ax,#1
add si,ax
- lodsw ! Get COLSxROWS
+ lodsw
pop ds
ret
-
-setvesa:
- pop bx
- cmp ah,#0xFF ! Special, mode FF, set 8x8 font
- je set8x8
-
- push bx
- mov bx,ax ! Mode to set
- mov ax,#0x4f02 ! Set VESA mode
- int 0x10
-
- jmp retmode
-
-! If we can't find the adapter in the table, at least set 80x50
-
-set8x8:
+novid7:
mov ax,#0x1112
mov bl,#0
int 0x10 ! use 8x8 font set (50 lines on VGA)
mov ax,#0x5032 ! return 80x50
ret
-! Routine to add mode in ax to VESA selection table
-
-addmod: push cx
- push ds
- push es
- push di
- push bx
- push dx
- push ax
-
- mov cx,ax ! CX = VESA mode number
- push cs
- pop es
- lea di,mib ! ES:[DI] -> Mode Information Block
- mov ax,#0x4f01 ! AX = Get VESA Mode Info
- int 0x10
-
- cmp ax,#0x004f ! If fails, assume it's not a TEXT mode
- jne adfail
-
- push cs
- pop ds ! Make DS contain something reasonable
-
- mov ax,mib ! Get Mode Attributes field
- and al,#0x12 ! Mask Text and Extended bits
- cmp al,#0x02 ! Text and Extended info available?
- jne adfail
-
- call space
-
- mov ax,mib+18 ! Horizontal Resolution
- mov bl,mib+22 ! X Char Size
- div bl
-! HACK: For some reason, my Diamond Stealth card returns 160 cols for its
-! 132 coloumn modes, so don't return any sizes > 132?
- sub al,#132
- jbe orgcol
- sub al,al
-orgcol: add al,#132 ! MIN(cols, 132)
- mov dh,al ! Put num cols in DH
- mov ax,mib+20 ! Vertical Resolution
- mov bl,mib+23 ! Y Char Size
- div bl
- mov dl,al ! Put num rows in DL
-
- mov bx,movesa ! Get current number of video modes
- lea di,movesa
- inc (di) ! This is a NEW mode
- add bx,bx
- add di,bx
- add di,#2
- pop ax ! Get Mode number back
- push ax
- mov (di),ax ! Mode number
- lea di,dscvesa
- add di,bx
- mov (di),dx ! Screen resolution
-
-adfail: pop ax
- pop dx
- pop bx
- pop di
- pop es
- pop ds
- pop cx
-
- ret
-
! Routine that 'tabs' to next col.
spcing: mov al,#0x2e
+ call prnt1
+ mov al,#0x20
call prnt1
-space3: mov al,#0x20
+ mov al,#0x20
call prnt1
-space2: mov al,#0x20
+ mov al,#0x20
call prnt1
-space: mov al,#0x20
+ mov al,#0x20
call prnt1
ret
jmp prtstr
fin: ret
-! Routine to print out HEX values on screen.
-! The value to be printed is in the AX register.
-
-hprntl: xchg ah,al
- call hprnt
- xchg ah,al
- call hprnt
- ret
-
-! Routine to print out HEX values on the screen
-! The valueto be printed is in the AL register. AH is preserved.
-
-hprnt: push ax
- shr al,4
- and al,#0xf
- call hprnt1
- pop ax
- push ax
- and al,#0xf
- call hprnt1
- pop ax
- ret
-
-! Routine to print out one HEX digit on the screen.
-! The value to be printed is in al (0-F)
-
-hprnt1: cmp al,#10
- jl hdec
- add al,#7 ! Convert 10-15 to A-F
-hdec: add al,#0x30 ! Convert to ASCII
- call prnt1 ! print it
- ret
-
! Routine to print a decimal value on screen, the value to be
! printed is put in al (i.e 0-255).
msg1: .ascii "Press <RETURN> to see SVGA-modes available or any other key to continue."
db 0x0d, 0x0a, 0x0a, 0x00
-msg2: .ascii "Numb: Mode: COLSxROWS:"
+msg2: .ascii "Mode: COLSxROWS:"
db 0x0d, 0x0a, 0x0a, 0x00
msg3: .ascii "Choose mode by pressing the corresponding number."
db 0x0d, 0x0a, 0x00
! Manufacturer: Numofmodes: Mode:
-moati: .word 0x02, 0x23, 0x33
-moahead: .word 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
-mocandt: .word 0x02, 0x60, 0x61
-mocirrus: .word 0x04, 0x1f, 0x20, 0x22, 0x31
-moeverex: .word 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
-mogenoa: .word 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
-moparadise: .word 0x02, 0x55, 0x54
-motrident: .word 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
-motseng: .word 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
-movideo7: .word 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
-movesa: .word 0x02, 0x03, 0xFFFF, 254*0
+moati: .byte 0x02, 0x23, 0x33
+moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
+mocandt: .byte 0x02, 0x60, 0x61
+mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31
+moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
+mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
+moparadise: .byte 0x02, 0x55, 0x54
+motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
+motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
+movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
! msb = Cols lsb = Rows:
dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
-dscvesa: .word 0x5019, 0x5032, 254*0
-vib: .word 256*0
-mib: .word 256*0
-
.text
endtext:
.data
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-SUBDIRS =minix ext msdos
+AR =ar
+AS =as
+LD =ld
+CC =gcc -nostdinc -I../include
+CPP =cpp -nostdinc -I../include
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.c.o:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
.s.o:
$(AS) -o $*.o $<
OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
- select.o fifo.o
-
-all: fs.o subdirs
+ select.o
fs.o: $(OBJS)
$(LD) -r -o fs.o $(OBJS)
-subdirs: dummy
- for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
-
clean:
rm -f core *.o *.a tmp_make
- for i in *.c; do rm -f `basename $$i .c`.s;done
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
+ for i in *.c;do rm -f `basename $$i .c`.s;done
+ cd minix; make clean
-depend dep:
+dep:
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
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
-
-dummy:
+ cd minix; make dep
### Dependencies:
-block_dev.o : block_dev.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/asm/system.h
-buffer.o : buffer.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/linux/config.h \
- /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
- /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/asm/io.h
-exec.o : exec.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/ptrace.h \
- /usr/src/linux/include/a.out.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/user.h
-fcntl.o : fcntl.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-fifo.o : fifo.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-file_table.o : file_table.c /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/asm/system.h
-ioctl.o : ioctl.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h
-namei.o : namei.c /usr/src/linux/include/errno.h /usr/src/linux/include/const.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h
-open.o : open.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/utime.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/asm/segment.h
-pipe.o : pipe.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-read_write.o : read_write.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/asm/segment.h
-select.o : select.c /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/const.h \
- /usr/src/linux/include/errno.h
-stat.o : stat.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/asm/segment.h
-super.o : super.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
- /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/errno.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/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
+ ../include/asm/system.h
+buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h ../include/linux/config_rel.h \
+ ../include/linux/config_ver.h ../include/linux/sched.h ../include/linux/head.h \
+ ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/system.h \
+ ../include/asm/io.h
+exec.o : exec.c ../include/signal.h ../include/sys/types.h ../include/errno.h \
+ ../include/linux/string.h ../include/sys/stat.h ../include/a.out.h ../include/linux/fs.h \
+ ../include/sys/dirent.h ../include/limits.h ../include/linux/sched.h ../include/linux/head.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/asm/segment.h
+fcntl.o : fcntl.c ../include/linux/string.h ../include/errno.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/asm/segment.h ../include/fcntl.h ../include/sys/stat.h
+file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+ ../include/limits.h
+inode.o : inode.c ../include/linux/string.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/asm/system.h
+ioctl.o : ioctl.c ../include/linux/string.h ../include/errno.h ../include/sys/stat.h \
+ ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+ ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+ ../include/signal.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+ ../include/sys/resource.h
+namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+ ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+ ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/linux/string.h \
+ ../include/fcntl.h ../include/errno.h ../include/const.h ../include/sys/stat.h
+open.o : open.c ../include/errno.h ../include/fcntl.h ../include/sys/types.h \
+ ../include/utime.h ../include/sys/stat.h ../include/sys/vfs.h ../include/linux/string.h \
+ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/asm/segment.h
+pipe.o : pipe.c ../include/signal.h ../include/sys/types.h ../include/errno.h \
+ ../include/termios.h ../include/fcntl.h ../include/asm/segment.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h
+read_write.o : read_write.c ../include/errno.h ../include/sys/types.h ../include/sys/stat.h \
+ ../include/sys/dirent.h ../include/limits.h ../include/linux/kernel.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/linux/minix_fs.h ../include/asm/segment.h
+select.o : select.c ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
+ ../include/linux/sched.h ../include/linux/head.h ../include/linux/mm.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/linux/string.h ../include/asm/segment.h ../include/asm/system.h ../include/sys/stat.h \
+ ../include/const.h ../include/errno.h
+stat.o : stat.c ../include/errno.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/asm/segment.h
+super.o : super.c ../include/linux/config.h ../include/linux/config_rel.h ../include/linux/config_ver.h \
+ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
+ ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+ ../include/signal.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+ ../include/sys/resource.h ../include/linux/minix_fs.h ../include/asm/system.h \
+ ../include/asm/segment.h ../include/errno.h ../include/sys/stat.h
static struct buffer_head * start_buffer = (struct buffer_head *) &end;
static struct buffer_head * hash_table[NR_HASH];
static struct buffer_head * free_list;
-static struct wait_queue * buffer_wait = NULL;
+static struct task_struct * buffer_wait = NULL;
int NR_BUFFERS = 0;
static inline void wait_on_buffer(struct buffer_head * bh)
struct buffer_head * bh;
bh = free_list;
- for (i = NR_BUFFERS*2 ; i-- > 0 ; bh = bh->b_next_free) {
- if (bh->b_lock)
+ for (i=0 ; i<NR_BUFFERS ; i++,bh = bh->b_next_free) {
+#if 0
+ if (dev && (bh->b_dev != dev))
continue;
- if (!bh->b_dirt)
+#endif
+ wait_on_buffer(bh);
+#if 0
+ if (dev && (bh->b_dev != dev))
continue;
- ll_rw_block(WRITE,bh);
+#endif
+ if (bh->b_dirt)
+ ll_rw_block(WRITE,bh);
}
}
int sys_sync(void)
{
- int i;
-
- for (i=0 ; i<NR_SUPER ; i++)
- if (super_block[i].s_dev
- && super_block[i].s_op
- && super_block[i].s_op->write_super
- && super_block[i].s_dirt)
- super_block[i].s_op->write_super(&super_block[i]);
sync_inodes(); /* write out inodes into buffers */
sync_buffers(0);
return 0;
int sync_dev(int dev)
{
- struct super_block * sb;
-
- if (sb = get_super (dev))
- if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
- sb->s_op->write_super (sb);
sync_buffers(dev);
sync_inodes();
sync_buffers(dev);
if (bh = get_hash_table(dev,block))
return bh;
buffers = NR_BUFFERS;
- for (tmp = free_list ; buffers-- > 0 ; tmp = tmp->b_next_free) {
+ tmp = free_list;
+ do {
+ tmp = tmp->b_next_free;
if (tmp->b_count)
continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) {
if (!BADNESS(tmp))
break;
}
-#if 0
if (tmp->b_dirt)
ll_rw_block(WRITEA,tmp);
-#endif
- }
/* and repeat until we find something good */
+ } while (buffers--);
if (!bh) {
sleep_on(&buffer_wait);
goto repeat;
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
- if (bh->b_dirt) {
- sync_buffers(bh->b_dev);
- goto repeat;
+ while (bh->b_dirt) {
+ sync_dev(bh->b_dev);
+ wait_on_buffer(bh);
+ if (bh->b_count)
+ goto repeat;
}
/* NOTE!! While we slept waiting for this block, somebody else might */
/* already have added "this" block to the cache. check it */
tmp=getblk(dev,first);
if (tmp) {
if (!tmp->b_uptodate)
- ll_rw_block(READA,tmp);
+ ll_rw_block(READA,bh);
tmp->b_count--;
}
}
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
- h->b_reqnext = NULL;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
#include <signal.h>
#include <errno.h>
-#include <sys/ptrace.h>
+#include <linux/string.h>
+#include <sys/stat.h>
#include <a.out.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/segment.h>
-#include <sys/user.h>
extern int sys_exit(int exit_code);
extern int sys_close(int fd);
*/
#define MAX_ARG_PAGES 32
-/*
- * These are the only things you should do on a core-file: use only these
- * macros to write out all the necessary info.
- */
-#define DUMP_WRITE(addr,nr) \
-while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
-
-#define DUMP_SEEK(offset) \
-if (file.f_op->lseek) { \
- if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
- goto close_coredump; \
-} else file.f_pos = (offset)
-
-/*
- * Routine writes a core dump image in the current directory.
- * Currently only a stub-function.
- *
- * Note that setuid/setgid files won't make a core-dump if the uid/gid
- * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
- * field, which also makes sure the core-dumps won't be recursive if the
- * dumping of the process results in another error..
- */
-int core_dump(long signr, struct pt_regs * regs)
-{
- struct inode * inode = NULL;
- struct file file;
- unsigned short fs;
- int has_dumped = 0;
- register int dump_start, dump_size;
- struct user dump;
-
- if (!current->dumpable)
- return 0;
- current->dumpable = 0;
-/* See if we have enough room to write the upage. */
- if(current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE/1024) return 0;
- __asm__("mov %%fs,%0":"=r" (fs));
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode))
- goto end_coredump;
- if (!S_ISREG(inode->i_mode))
- goto end_coredump;
- if (!inode->i_op || !inode->i_op->default_file_ops)
- goto end_coredump;
- file.f_mode = 3;
- file.f_flags = 0;
- file.f_count = 1;
- file.f_inode = inode;
- file.f_pos = 0;
- file.f_reada = 0;
- file.f_op = inode->i_op->default_file_ops;
- if (file.f_op->open)
- if (file.f_op->open(inode,&file))
- goto end_coredump;
- if (!file.f_op->write)
- goto close_coredump;
- has_dumped = 1;
-/* write and seek example: from kernel space */
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- dump.magic = CMAGIC;
- dump.u_tsize = current->end_code / PAGE_SIZE;
- dump.u_dsize = (current->brk - current->end_code) / PAGE_SIZE;
- dump.u_ssize =((current->start_stack +(PAGE_SIZE-1)) / PAGE_SIZE) -
- (regs->esp/ PAGE_SIZE);
-/* If the size of the dump file exceeds the rlimit, then see what would happen
- if we wrote the stack, but not the data area. */
- if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE/1024 >
- current->rlim[RLIMIT_CORE].rlim_cur)
- dump.u_dsize = 0;
-/* Make sure we have enough room to write the stack and data areas. */
- if ((dump.u_ssize+1) * PAGE_SIZE / 1024 >
- current->rlim[RLIMIT_CORE].rlim_cur)
- dump.u_ssize = 0;
- dump.u_comm = 0;
- dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump)));
- dump.signal = signr;
- dump.regs = *regs;
- dump.start_code = 0;
- dump.start_stack = regs->esp & ~(PAGE_SIZE - 1);
-/* Flag indicating the math stuff is valid. */
- if (dump.u_fpvalid = current->used_math) {
- if (last_task_used_math == current)
- __asm__("clts ; fnsave %0"::"m" (dump.i387));
- else
- memcpy(&dump.i387,¤t->tss.i387,sizeof(dump.i387));
- };
- DUMP_WRITE(&dump,sizeof(dump));
- DUMP_SEEK(sizeof(dump));
- /* Dump the task struct. Not be used by gdb, but could be useful */
- DUMP_WRITE(current,sizeof(*current));
-/* Now dump all of the user data. Include malloced stuff as well */
- DUMP_SEEK(PAGE_SIZE);
-/* now we start writing out the user space info */
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
-/* Dump the data area */
- if (dump.u_dsize != 0) {
- dump_start = current->end_code;
- dump_size = current->brk - current->end_code;
- DUMP_WRITE(dump_start,dump_size);
- };
-/* Now prepare to dump the stack area */
- if (dump.u_ssize != 0) {
- dump_start = regs->esp & ~(PAGE_SIZE - 1);
- dump_size = dump.u_ssize * PAGE_SIZE;
- DUMP_WRITE(dump_start,dump_size);
- };
-close_coredump:
- if (file.f_op->release)
- file.f_op->release(inode,&file);
-end_coredump:
- __asm__("mov %0,%%fs"::"r" (fs));
- iput(inode);
- return has_dumped;
-}
-
/*
* Note that a shared library must be both readable and executable due to
* security reasons.
struct inode * inode;
struct buffer_head * bh;
struct exec ex;
- int i;
- struct file * f;
if (get_limit(0x17) != TASK_SIZE)
return -EINVAL;
inode = NULL;
if (!inode)
return -ENOENT;
- if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
+ if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ|MAY_EXEC)) {
iput(inode);
return -EACCES;
}
- if (inode->i_count > 1) { /* check for writers */
- f=0+file_table;
- for (i=0 ; i<NR_FILE ; i++,f++ )
- if (f->f_count && (f->f_mode & 2))
- if (inode == f->f_inode) {
- iput(inode);
- return -ETXTBSY;
- }
- }
- if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
+ if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
iput(inode);
return -EACCES;
}
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
unsigned long p, int from_kmem)
{
- char *tmp, *pag = NULL;
+ char *tmp, *pag;
int len, offset = 0;
unsigned long old_fs, new_fs;
return data_limit;
}
-static void read_omagic(struct inode *inode, int bytes)
-{
- struct buffer_head *bh;
- int n, blkno, blk = 0;
- char *dest = (char *) 0;
-
- while (bytes > 0) {
- if (!(blkno = bmap(inode, blk)))
- sys_exit(-1);
- if (!(bh = bread(inode->i_dev, blkno)))
- sys_exit(-1);
- n = (blk ? BLOCK_SIZE : BLOCK_SIZE - sizeof(struct exec));
- if (bytes < n)
- n = bytes;
-
- memcpy_tofs(dest, (blk ? bh->b_data :
- bh->b_data + sizeof(struct exec)), n);
- brelse(bh);
- ++blk;
- dest += n;
- bytes -= n;
- }
- iput(inode);
- current->executable = NULL;
-}
-
/*
* 'do_execve()' executes a new program.
*
int sh_bang = 0;
unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
int ch;
- struct file * f;
if ((0xffff & eip[1]) != 0x000f)
panic("execve called from supervisor mode");
page[i]=0;
if (!(inode=namei(filename))) /* get executables inode */
return -ENOENT;
- if (inode->i_count > 1) { /* check for writers */
- f=0+file_table;
- for (i=0 ; i<NR_FILE ; i++,f++ )
- if (f->f_count && (f->f_mode & 2))
- if (inode == f->f_inode) {
- retval = -ETXTBSY;
- goto exec_error2;
- }
- }
argc = count(argv);
envc = count(envp);
retval = -EACCES;
goto exec_error2;
}
- if (IS_NOEXEC(inode)) { /* FS mustn't be mounted noexec */
- retval = -EPERM;
- goto exec_error2;
- }
i = inode->i_mode;
- if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
- euid) || ((i & S_ISGID) && inode->i_gid != current->egid)) &&
- !suser()) {
- retval = -EPERM;
- goto exec_error2;
- }
/* make sure we don't let suid, sgid files be ptraced. */
if (current->flags & PF_PTRACED) {
e_uid = current->euid;
retval = -EACCES;
goto exec_error2;
}
- if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
+ if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
retval = -EACCES;
goto exec_error2;
}
goto restart_interp;
}
brelse(bh);
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
- 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 ||
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
retval = -ENOEXEC;
goto exec_error2;
}
- if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
+ if (N_TXTOFF(ex) != BLOCK_SIZE) {
printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
retval = -ENOEXEC;
goto exec_error2;
}
}
/* OK, This is the point of no return */
- current->dumpable = 1;
for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
if (ch == '/')
i = 0;
iput(current->libraries[i].library);
current->libraries[i].library = NULL;
}
- if (e_uid != current->euid || e_gid != current->egid ||
- !permission(inode,MAY_READ))
- current->dumpable = 0;
current->numlibraries = 0;
current->executable = inode;
current->signal = 0;
current->rss = (LIBRARY_OFFSET - p + PAGE_SIZE-1) / PAGE_SIZE;
current->suid = current->euid = e_uid;
current->sgid = current->egid = e_gid;
- if (N_MAGIC(ex) == OMAGIC)
- read_omagic(inode, ex.a_text+ex.a_data);
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
- send_sig(SIGTRAP, current, 0);
+ send_sig(SIGTRAP, current, 0);
return 0;
exec_error2:
iput(inode);
+++ /dev/null
-#
-# Makefile for the linux ext-filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-.c.s:
- $(CC) $(CFLAGS) -S $<
-.c.o:
- $(CC) $(CFLAGS) -c $<
-.s.o:
- $(AS) -o $*.o $<
-
-OBJS= bitmap.o freelists.o truncate.o namei.o inode.o \
- file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
-
-ext.o: $(OBJS)
- $(LD) -r -o ext.o $(OBJS)
-
-clean:
- rm -f core *.o *.a tmp_make
- for i in *.c;do rm -f `basename $$i .c`.s;done
-
-dep:
- sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
- cp tmp_make Makefile
-
-### Dependencies:
-bitmap.o : bitmap.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h
-blkdev.o : blkdev.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h
-chrdev.o : chrdev.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/stat.h
-fifo.o : fifo.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/stat.h
-freelists.o : freelists.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h
-namei.o : namei.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h /usr/src/linux/include/const.h
-symlink.o : symlink.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/stat.h
-truncate.o : truncate.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ext_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h
+++ /dev/null
-/*
- * linux/fs/ext/bitmap.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/bitmap.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-/* bitmap.c contains the code that handles the inode and block bitmaps */
-
-
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-
-#ifdef EXTFS_BITMAP
-
-#define clear_block(addr) \
-__asm__("cld\n\t" \
- "rep\n\t" \
- "stosl" \
- ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
-
-#define set_bit(nr,addr) ({\
-char res; \
-__asm__ __volatile__("btsl %1,%2\n\tsetb %0": \
-"=q" (res):"r" (nr),"m" (*(addr))); \
-res;})
-
-#define clear_bit(nr,addr) ({\
-char res; \
-__asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
-"=q" (res):"r" (nr),"m" (*(addr))); \
-res;})
-
-#define find_first_zero(addr) ({ \
-int __res; \
-__asm__("cld\n" \
- "1:\tlodsl\n\t" \
- "notl %%eax\n\t" \
- "bsfl %%eax,%%edx\n\t" \
- "jne 2f\n\t" \
- "addl $32,%%ecx\n\t" \
- "cmpl $8192,%%ecx\n\t" \
- "jl 1b\n\t" \
- "xorl %%edx,%%edx\n" \
- "2:\taddl %%edx,%%ecx" \
- :"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
-__res;})
-
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
-
-static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
- unsigned numbits)
-{
- unsigned i, j, end, sum = 0;
- struct buffer_head *bh;
-
- for (i=0; (i<numblocks) && numbits; i++) {
- if (!(bh=map[i]))
- return(0);
- if (numbits >= (8*BLOCK_SIZE)) {
- end = BLOCK_SIZE;
- numbits -= 8*BLOCK_SIZE;
- } else {
- int tmp;
- end = numbits >> 3;
- numbits &= 0x7;
- tmp = bh->b_data[end] & ((1<<numbits)-1);
- sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
- numbits = 0;
- }
- for (j=0; j<end; j++)
- sum += nibblemap[bh->b_data[j] & 0xf]
- + nibblemap[(bh->b_data[j]>>4)&0xf];
- }
- return(sum);
-}
-
-int ext_free_block(int dev, int block)
-{
- struct super_block * sb;
- struct buffer_head * bh;
- unsigned int bit,zone;
-
- if (!(sb = get_super(dev)))
- panic("trying to free block on nonexistent device");
- if (block < sb->s_firstdatazone || block >= sb->s_nzones)
- panic("trying to free block not in datazone");
- bh = get_hash_table(dev,block);
- if (bh) {
- if (bh->b_count > 1) {
- brelse(bh);
- return 0;
- }
- bh->b_dirt=0;
- bh->b_uptodate=0;
- if (bh->b_count)
- brelse(bh);
- }
- zone = block - sb->s_firstdatazone + 1;
- bit = zone & 8191;
- zone >>= 13;
- bh = sb->s_zmap[zone];
- if (clear_bit(bit,bh->b_data))
- printk("free_block (%04x:%d): bit already cleared\n",dev,block);
- bh->b_dirt = 1;
- return 1;
-}
-
-int ext_new_block(int dev)
-{
- struct buffer_head * bh;
- struct super_block * sb;
- int i,j;
-
- if (!(sb = get_super(dev)))
- panic("trying to get new block from nonexistant device");
- j = 8192;
- for (i=0 ; i<8 ; i++)
- if (bh=sb->s_zmap[i])
- if ((j=find_first_zero(bh->b_data))<8192)
- break;
- if (i>=8 || !bh || j>=8192)
- return 0;
- if (set_bit(j,bh->b_data))
- panic("new_block: bit already set");
- bh->b_dirt = 1;
- j += i*8192 + sb->s_firstdatazone-1;
- if (j >= sb->s_nzones)
- return 0;
- if (!(bh=getblk(dev,j)))
- panic("new_block: cannot get block");
- if (bh->b_count != 1)
- panic("new block: count is != 1");
- clear_block(bh->b_data);
- bh->b_uptodate = 1;
- bh->b_dirt = 1;
- brelse(bh);
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: allocating block %d\n", j);
-#endif
- return j;
-}
-
-unsigned long ext_count_free_blocks(struct super_block *sb)
-{
- return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
- << sb->s_log_zone_size;
-}
-
-void ext_free_inode(struct inode * inode)
-{
- struct buffer_head * bh;
-
- if (!inode)
- return;
- if (!inode->i_dev) {
- memset(inode,0,sizeof(*inode));
- return;
- }
- if (inode->i_count>1) {
- printk("free_inode: inode has count=%d\n",inode->i_count);
- return;
- }
- if (inode->i_nlink) {
- printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
- return;
- }
- if (!inode->i_sb) {
- printk("free_inode: inode on nonexistent device\n");
- return;
- }
- if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
- printk("free_inode: inode 0 or nonexistent inode\n");
- return;
- }
- if (!(bh=inode->i_sb->s_imap[inode->i_ino>>13])) {
- printk("free_inode: nonexistent imap in superblock\n");
- return;
- }
- if (clear_bit(inode->i_ino&8191,bh->b_data))
- printk("free_inode: bit already cleared.\n\r");
- bh->b_dirt = 1;
- memset(inode,0,sizeof(*inode));
-}
-
-struct inode * ext_new_inode(int dev)
-{
- struct inode * inode;
- struct buffer_head * bh;
- int i,j;
-
- if (!(inode=get_empty_inode()))
- return NULL;
- if (!(inode->i_sb = get_super(dev))) {
- printk("new_inode: unknown device\n");
- iput(inode);
- return NULL;
- }
- inode->i_flags = inode->i_sb->s_flags;
- j = 8192;
- for (i=0 ; i<8 ; i++)
- if (bh=inode->i_sb->s_imap[i])
- if ((j=find_first_zero(bh->b_data))<8192)
- break;
- if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->s_ninodes) {
- iput(inode);
- return NULL;
- }
- if (set_bit(j,bh->b_data)) { /* shouldn't happen */
- printk("new_inode: bit already set");
- iput(inode);
- return NULL;
- }
- bh->b_dirt = 1;
- inode->i_count = 1;
- inode->i_nlink = 1;
- inode->i_dev = dev;
- inode->i_uid = current->euid;
- inode->i_gid = current->egid;
- inode->i_dirt = 1;
- inode->i_ino = j + i*8192;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = NULL;
-#ifdef EXTFS_DEBUG
- printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
-#endif
- return inode;
-}
-
-unsigned long ext_count_free_inodes(struct super_block *sb)
-{
- return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
-}
-
-#endif
+++ /dev/null
-/*
- * linux/fs/ext/blkdev.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/blkdev.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#include <errno.h>
-
-/*
- * Called every time an ext block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations ext_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ext_bmap, /* bmap */
- ext_truncate /* truncate */
-};
+++ /dev/null
-/*
- * linux/fs/ext/chrdev.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/chrdev.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#include <errno.h>
-
-/*
- * Called every time an ext character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations ext_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ext_bmap, /* bmap */
- ext_truncate /* truncate */
-};
-
+++ /dev/null
-/*
- * linux/fs/ext/dir.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/dir.c
- *
- * (C) 1991 Linus Torvalds
- *
- * ext directory handling functions
- */
-
-#include <errno.h>
-
-#include <asm/segment.h>
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static int ext_readdir(struct inode *, struct file *, struct dirent *, int);
-
-static struct file_operations ext_dir_operations = {
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write - bad */
- ext_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open code */
- NULL /* no special release code */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations ext_dir_inode_operations = {
- &ext_dir_operations, /* default directory file-ops */
- ext_create, /* create */
- ext_lookup, /* lookup */
- ext_link, /* link */
- ext_unlink, /* unlink */
- ext_symlink, /* symlink */
- ext_mkdir, /* mkdir */
- ext_rmdir, /* rmdir */
- ext_mknod, /* mknod */
- ext_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ext_bmap, /* bmap */
- ext_truncate /* truncate */
-};
-
-static int ext_readdir(struct inode * inode, struct file * filp,
- struct dirent * dirent, int count)
-{
- unsigned int block,offset,i;
- char c;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- if (!inode || !S_ISDIR(inode->i_mode))
- return -EBADF;
-/* if (filp->f_pos & (sizeof (struct ext_dir_entry) - 1))
- return -EBADF; */
- while (filp->f_pos < inode->i_size) {
- offset = filp->f_pos & 1023;
- block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
- if (!block || !(bh = bread(inode->i_dev,block))) {
- filp->f_pos += 1024-offset;
- continue;
- }
- de = (struct ext_dir_entry *) (offset + bh->b_data);
- while (offset < 1024 && filp->f_pos < inode->i_size) {
- offset += de->rec_len;
- filp->f_pos += de->rec_len;
- if (de->inode) {
- for (i = 0; i < de->name_len; i++)
- if (c = de->name[i])
- put_fs_byte(c,i+dirent->d_name);
- else
- break;
- if (i) {
- put_fs_long(de->inode,&dirent->d_ino);
- put_fs_byte(0,i+dirent->d_name);
- put_fs_word(i,&dirent->d_reclen);
- brelse(bh);
- return i;
- }
- }
-/* de++; */
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- }
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove.
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations ext_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL /* truncate */
-};
+++ /dev/null
-/*
- * linux/fs/ext/file.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/file.c
- *
- * (C) 1991 Linus Torvalds
- *
- * ext regular file handling primitives
- */
-
-#include <errno.h>
-
-#include <sys/dirent.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-
-#define NBUF 16
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-
-static int ext_file_read(struct inode *, struct file *, char *, int);
-static int ext_file_write(struct inode *, struct file *, char *, int);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the ext filesystem.
- */
-static struct file_operations ext_file_operations = {
- NULL, /* lseek - default */
- ext_file_read, /* read */
- ext_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open is needed */
- NULL /* release */
-};
-
-struct inode_operations ext_file_inode_operations = {
- &ext_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ext_bmap, /* bmap */
- ext_truncate /* truncate */
-};
-
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
- cli();
- while (bh->b_lock)
- sleep_on(&bh->b_wait);
- sti();
-}
-
-static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
-{
- int read,left,chars,nr;
- int block, blocks, offset;
- struct buffer_head ** bhb, ** bhe;
- struct buffer_head * buflist[NBUF];
-
- if (!inode) {
- printk("ext_file_read: inode = NULL\n");
- return -EINVAL;
- }
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
- printk("ext_file_read: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
- if (filp->f_pos > inode->i_size)
- left = 0;
- else
- left = inode->i_size - filp->f_pos;
- if (left > count)
- left = count;
- if (left <= 0)
- return 0;
- read = 0;
- block = filp->f_pos >> BLOCK_SIZE_BITS;
- offset = filp->f_pos & (BLOCK_SIZE-1);
- blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
- bhb = bhe = buflist;
- do {
- if (blocks) {
- --blocks;
- if (nr = ext_bmap(inode,block++)) {
- *bhb = getblk(inode->i_dev,nr);
- if (!(*bhb)->b_uptodate)
- ll_rw_block(READ,*bhb);
- } else
- *bhb = NULL;
-
- if (++bhb == &buflist[NBUF])
- bhb = buflist;
-
- if (bhb != bhe)
- continue;
- }
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!(*bhe)->b_uptodate) {
- do {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (bhe != bhb);
- break;
- }
- }
-
- if (left < BLOCK_SIZE - offset)
- chars = left;
- else
- chars = BLOCK_SIZE - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
- brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_fs_byte(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (left > 0);
- if (!read)
- return -EIO;
- if (!IS_RDONLY(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- return read;
-}
-
-static int ext_file_write(struct inode * inode, struct file * filp, char * buf, int count)
-{
- off_t pos;
- int written,block,c;
- struct buffer_head * bh;
- char * p;
-
- if (!inode) {
- printk("ext_file_write: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("ext_file_write: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = filp->f_pos;
- written = 0;
- while (written<count) {
- if (!(block = ext_create_block(inode,pos/BLOCK_SIZE))) {
- if (!written)
- written = -ENOSPC;
- break;
- }
- c = BLOCK_SIZE - (pos % BLOCK_SIZE);
- if (c > count-written)
- c = count-written;
- if (c == BLOCK_SIZE)
- bh = getblk(inode->i_dev, block);
- else
- bh = bread(inode->i_dev,block);
- if (!bh) {
- if (!written)
- written = -EIO;
- break;
- }
- p = (pos % BLOCK_SIZE) + bh->b_data;
- pos += c;
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_dirt = 1;
- }
- written += c;
- memcpy_fromfs(p,buf,c);
- buf += c;
- bh->b_uptodate = 1;
- bh->b_dirt = 1;
- brelse(bh);
- }
- inode->i_mtime = CURRENT_TIME;
- inode->i_ctime = CURRENT_TIME;
- filp->f_pos = pos;
- inode->i_dirt = 1;
- return written;
-}
+++ /dev/null
-/*
- * linux/fs/ext/freelists.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- */
-
-/* freelists.c contains the code that handles the inode and block free lists */
-
-
-/*
-
- The free blocks are managed by a linked list. The super block contains the
- number of the first free block. This block contains 254 numbers of other
- free blocks and the number of the next block in the list.
-
- When an ext fs is mounted, the number of the first free block is stored
- in s->s_zmap[0] and the block header is stored in s->s_zmap[1]. s_zmap[2]
- contains the count of free blocks.
-
- Currently, it is a hack to allow this kind of management with the super_block
- structure.
- Perhaps, in the future, we may have to change the super_block structure to
- include dedicated fields.
-
- The free inodes are also managed by a linked list in a similar way. The
- super block contains the number of the first free inode. This inode contains
- 14 numbers of other free inodes and the number of the next inode in the list.
-
- The number of the first free inode is stored in s->s_imap[0] and the header
- of the block containing the inode is stored in s->s_imap[1]. s_imap[2] contains
- the count of free inodes.
-
-*/
-
-#include <linux/string.h>
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-
-#ifdef EXTFS_FREELIST
-
-#define clear_block(addr) \
-__asm__("cld\n\t" \
- "rep\n\t" \
- "stosl" \
- ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
-
-int ext_free_block(int dev, int block)
-{
- struct super_block * sb;
- struct buffer_head * bh;
- struct ext_free_block * efb;
-
- if (!(sb = get_super(dev)))
- panic("trying to free block on nonexistent device");
- lock_super (sb);
- if (block < sb->s_firstdatazone || block >= sb->s_nzones)
- panic("trying to free block not in datazone");
- bh = get_hash_table(dev,block);
- if (bh) {
- if (bh->b_count > 1) {
- brelse(bh);
- free_super (sb);
- return 0;
- }
- bh->b_dirt=0;
- bh->b_uptodate=0;
- if (bh->b_count)
- brelse(bh);
- }
- if (sb->s_zmap[1])
- efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
- if (!sb->s_zmap[1] || efb->count == 254) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_block: block full, skipping to %d\n", block);
-#endif
- if (sb->s_zmap[1])
- brelse (sb->s_zmap[1]);
- if (!(sb->s_zmap[1] = bread (dev, block)))
- panic ("ext_free_block: unable to read block to free\n");
- efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
- efb->next = (unsigned long) sb->s_zmap[0];
- efb->count = 0;
- sb->s_zmap[0] = (struct buffer_head *) block;
- } else {
- efb->free[efb->count++] = block;
- }
- sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) + 1);
- sb->s_dirt = 1;
- sb->s_zmap[1]->b_dirt = 1;
- free_super (sb);
- return 1;
-}
-
-int ext_new_block(int dev)
-{
- struct buffer_head * bh;
- struct super_block * sb;
- struct ext_free_block * efb;
- int /* i, */ j;
-
- if (!(sb = get_super(dev)))
- panic("trying to get new block from nonexistant device");
- if (!sb->s_zmap[1])
- return 0;
- lock_super (sb);
- efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
- if (efb->count) {
- j = efb->free[--efb->count];
- sb->s_zmap[1]->b_dirt = 1;
- } else {
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: block empty, skipping to %d\n", efb->next);
-#endif
- j = (unsigned long) sb->s_zmap[0];
- sb->s_zmap[0] = (struct buffer_head *) efb->next;
- brelse (sb->s_zmap[1]);
- if (!sb->s_zmap[0]) {
- sb->s_zmap[1] = NULL;
- } else {
- if (!(sb->s_zmap[1] = bread (dev, (unsigned long) sb->s_zmap[0])))
- panic ("ext_new_block: unable to read next free block\n");
- }
- }
- if (j < sb->s_firstdatazone || j > sb->s_nzones) {
- printk ("ext_new_block: blk = %d\n", j);
- panic ("allocating block not in data zone\n");
- }
- sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) - 1);
- sb->s_dirt = 1;
-
- if (!(bh=getblk(dev,j)))
- panic("new_block: cannot get block");
- if (bh->b_count != 1)
- panic("new block: count is != 1");
- clear_block(bh->b_data);
- bh->b_uptodate = 1;
- bh->b_dirt = 1;
- brelse(bh);
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: allocating block %d\n", j);
-#endif
- free_super (sb);
- return j;
-}
-
-unsigned long ext_count_free_blocks(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
- struct buffer_head * bh;
- struct ext_free_block * efb;
- unsigned long count, block;
-
- lock_super (sb);
- if (!sb->s_zmap[1])
- count = 0;
- else {
- efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
- count = efb->count + 1;
- block = efb->next;
- while (block) {
- if (!(bh = bread (sb->s_dev, block))) {
- printk ("ext_count_free: error while reading free blocks list\n");
- block = 0;
- } else {
- efb = (struct ext_free_block *) bh->b_data;
- count += efb->count + 1;
- block = efb->next;
- brelse (bh);
- }
- }
- }
-printk("ext_count_free_blocks: stored = %d, computed = %d\n",
- (unsigned long) sb->s_zmap[2], count);
- free_super (sb);
- return count;
-#else
- return (unsigned long) sb->s_zmap[2];
-#endif
-}
-
-void ext_free_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_free_inode * efi;
- unsigned long block;
-
- if (!inode)
- return;
- if (!inode->i_dev) {
- memset(inode,0,sizeof(*inode));
- return;
- }
- if (inode->i_count>1) {
- printk("free_inode: inode has count=%d\n",inode->i_count);
- return;
- }
- if (inode->i_nlink) {
- printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
- return;
- }
- if (!inode->i_sb) {
- printk("free_inode: inode on nonexistent device\n");
- return;
- }
- lock_super (inode->i_sb);
- if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
- printk("free_inode: inode 0 or nonexistent inode\n");
- free_super (inode->i_sb);
- return;
- }
- if (inode->i_sb->s_imap[1])
- efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
- (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
- if (!inode->i_sb->s_imap[1] || efi->count == 14) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
-#endif
- if (inode->i_sb->s_imap[1])
- brelse (inode->i_sb->s_imap[1]);
- block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
- if (!(bh = bread(inode->i_dev, block)))
- panic("ext_free_inode: unable to read inode block\n");
- efi = ((struct ext_free_inode *) bh->b_data) +
- (inode->i_ino - 1) % EXT_INODES_PER_BLOCK;
- efi->next = (unsigned long) inode->i_sb->s_imap[0];
- efi->count = 0;
- inode->i_sb->s_imap[0] = (struct buffer_head *) inode->i_ino;
- inode->i_sb->s_imap[1] = bh;
- } else {
- efi->free[efi->count++] = inode->i_ino;
- }
- inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) + 1);
- inode->i_sb->s_dirt = 1;
- inode->i_sb->s_imap[1]->b_dirt = 1;
- free_super (inode->i_sb);
- memset(inode,0,sizeof(*inode));
-}
-
-struct inode * ext_new_inode(int dev)
-{
- struct inode * inode;
- struct ext_free_inode * efi;
- unsigned long block;
- int /* i, */ j;
-
- if (!(inode=get_empty_inode()))
- return NULL;
- if (!(inode->i_sb = get_super(dev))) {
- printk("new_inode: unknown device\n");
- iput(inode);
- return NULL;
- }
- inode->i_flags = inode->i_sb->s_flags;
- if (!inode->i_sb->s_imap[1])
- return 0;
- lock_super (inode->i_sb);
- efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
- (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
- if (efi->count) {
- j = efi->free[--efi->count];
- inode->i_sb->s_imap[1]->b_dirt = 1;
- } else {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
-#endif
- j = (unsigned long) inode->i_sb->s_imap[0];
- if (efi->next < 1 || efi->next > inode->i_sb->s_ninodes) {
- printk ("efi->next = %d\n", efi->next);
- panic ("ext_new_inode: bad inode number in free list\n");
- }
- inode->i_sb->s_imap[0] = (struct buffer_head *) efi->next;
- block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
- brelse (inode->i_sb->s_imap[1]);
- if (!inode->i_sb->s_imap[0]) {
- inode->i_sb->s_imap[1] = NULL;
- } else {
- if (!(inode->i_sb->s_imap[1] = bread (dev, block)))
- panic ("ext_new_inode: unable to read next free inode block\n");
- }
- }
- inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) - 1);
- inode->i_sb->s_dirt = 1;
- inode->i_count = 1;
- inode->i_nlink = 1;
- inode->i_dev = dev;
- inode->i_uid = current->euid;
- inode->i_gid = current->egid;
- inode->i_dirt = 1;
- inode->i_ino = j;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = NULL;
-#ifdef EXTFS_DEBUG
-printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
-#endif
- free_super (inode->i_sb);
- return inode;
-}
-
-unsigned long ext_count_free_inodes(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
- struct buffer_head * bh;
- struct ext_free_inode * efi;
- unsigned long count, block, ino;
-
- lock_super (sb);
- if (!sb->s_imap[1])
- count = 0;
- else {
- efi = ((struct ext_free_inode *) sb->s_imap[1]->b_data) +
- ((((unsigned long) sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK);
- count = efi->count + 1;
- ino = efi->next;
- while (ino) {
- if (ino < 1 || ino > sb->s_ninodes) {
- printk ("s_imap[0] = %d, ino = %d\n",
- (int) sb->s_imap[0],ino);
- panic ("ext_count_fre_inodes: bad inode number in free list\n");
- }
- block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
- if (!(bh = bread (sb->s_dev, block))) {
- printk ("ext_count_free_inodes: error while reading free inodes list\n");
- block = 0;
- } else {
- efi = ((struct ext_free_inode *) bh->b_data) +
- ((ino - 1) % EXT_INODES_PER_BLOCK);
- count += efi->count + 1;
- ino = efi->next;
- brelse (bh);
- }
- }
- }
-printk("ext_count_free_inodes: stored = %d, computed = %d\n",
- (unsigned long) sb->s_imap[2], count);
- free_super (sb);
- return count;
-#else
- return (unsigned long) sb->s_imap[2];
-#endif
-}
-
-#endif
+++ /dev/null
-/*
- * linux/fs/ext/inode.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/inode.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-
-int sync_dev(int dev);
-
-void ext_put_inode(struct inode *inode)
-{
- inode->i_size = 0;
- ext_truncate(inode);
- ext_free_inode(inode);
-}
-
-void ext_put_super(struct super_block *sb)
-{
-#ifdef EXTFS_BITMAP
- int i;
-#endif
-
- lock_super(sb);
- sb->s_dev = 0;
-#ifdef EXTFS_BITMAP
- for(i = 0 ; i < EXT_I_MAP_SLOTS ; i++)
- brelse(sb->s_imap[i]);
- for(i = 0 ; i < EXT_Z_MAP_SLOTS ; i++)
- brelse(sb->s_zmap[i]);
-#endif
-#ifdef EXTFS_FREELIST
- if (sb->s_imap[1])
- brelse (sb->s_imap[1]);
- if (sb->s_zmap[1])
- brelse (sb->s_zmap[1]);
-#endif
- free_super(sb);
- return;
-}
-
-static struct super_operations ext_sops = {
- ext_read_inode,
- ext_write_inode,
- ext_put_inode,
- ext_put_super,
- ext_write_super,
- ext_statfs
-};
-
-struct super_block *ext_read_super(struct super_block *s,void *data)
-{
- struct buffer_head *bh;
- struct ext_super_block *es;
- int dev=s->s_dev,block;
-#ifdef EXTFS_BITMAP
- int i;
-#endif
-
- lock_super(s);
- if (!(bh = bread(dev,1))) {
- s->s_dev=0;
- free_super(s);
- printk("bread failed\n");
- return NULL;
- }
-/* *((struct ext_super_block *) s) =
- *((struct ext_super_block *) bh->b_data); */
- es = (struct ext_super_block *) bh->b_data;
- s->s_ninodes = es->s_ninodes;
- s->s_nzones = es->s_nzones;
-#ifdef EXTFS_BITMAP
- s->s_imap_blocks = es->s_imap_blocks;
- s->s_zmap_blocks = es->s_zmap_blocks;
-#endif
- s->s_firstdatazone = es->s_firstdatazone;
- s->s_log_zone_size = es->s_log_zone_size;
- s->s_max_size = es->s_max_size;
- s->s_magic = es->s_magic;
-#ifdef EXTFS_FREELIST
- s->s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock;
- s->s_zmap[2] = (struct buffer_head *) es->s_freeblockscount;
- s->s_imap[0] = (struct buffer_head *) es->s_firstfreeinode;
- s->s_imap[2] = (struct buffer_head *) es->s_freeinodescount;
-#endif
- brelse(bh);
- if (s->s_magic != EXT_SUPER_MAGIC) {
- s->s_dev = 0;
- free_super(s);
- printk("magic match failed\n");
- return NULL;
- }
-#ifdef EXTFS_BITMAP
- for (i=0;i < EXT_I_MAP_SLOTS;i++)
- s->s_imap[i] = NULL;
- for (i=0;i < EXT_Z_MAP_SLOTS;i++)
- s->s_zmap[i] = NULL;
- block=2;
- for (i=0 ; i < s->s_imap_blocks ; i++)
- if (s->s_imap[i]=bread(dev,block))
- block++;
- else
- break;
- for (i=0 ; i < s->s_zmap_blocks ; i++)
- if (s->s_zmap[i]=bread(dev,block))
- block++;
- else
- break;
- if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
- for(i=0;i<EXT_I_MAP_SLOTS;i++)
- brelse(s->s_imap[i]);
- for(i=0;i<EXT_Z_MAP_SLOTS;i++)
- brelse(s->s_zmap[i]);
- s->s_dev=0;
- free_super(s);
- printk("block failed\n");
- return NULL;
- }
- s->s_imap[0]->b_data[0] |= 1;
- s->s_zmap[0]->b_data[0] |= 1;
-#endif
-#ifdef EXTFS_FREELIST
- if (!s->s_zmap[0])
- s->s_zmap[1] = NULL;
- else
- if (!(s->s_zmap[1] = bread (dev, (unsigned long) s->s_zmap[0]))) {
- printk ("ext_read_super: unable to read first free block\n");
- s->s_dev = 0;
- free_super(s);
- return NULL;
- }
- if (!s->s_imap[0])
- s->s_imap[1] = NULL;
- else {
- block = 2 + (((unsigned long) s->s_imap[0]) - 1) / EXT_INODES_PER_BLOCK;
- if (!(s->s_imap[1] = bread (dev, block))) {
- printk ("ext_read_super: unable to read first free inode block\n");
- brelse(s->s_zmap[1]);
- s->s_dev = 0;
- free_super (s);
- return NULL;
- }
- }
-#endif
-
- free_super(s);
- /* set up enough so that it can read an inode */
- s->s_dev = dev;
- s->s_op = &ext_sops;
- if (!(s->s_mounted = iget(dev,EXT_ROOT_INO))) {
- s->s_dev=0;
- printk("get root inode failed\n");
- return NULL;
- }
- return s;
-}
-
-void ext_write_super (struct super_block *sb)
-{
-#ifdef EXTFS_FREELIST
- struct buffer_head * bh;
- struct ext_super_block * es;
-
-#ifdef EXTFS_DEBUG
- printk ("ext_write_super called\n");
-#endif
- if (!(bh = bread (sb->s_dev, 1))) {
- printk ("ext_write_super: bread failed\n");
- return;
- }
- es = (struct ext_super_block *) bh->b_data;
- es->s_firstfreeblock = (unsigned long) sb->s_zmap[0];
- es->s_freeblockscount = (unsigned long) sb->s_zmap[2];
- es->s_firstfreeinode = (unsigned long) sb->s_imap[0];
- es->s_freeinodescount = (unsigned long) sb->s_imap[2];
- bh->b_dirt = 1;
- brelse (bh);
- sb->s_dirt = 0;
-#endif
-}
-
-void ext_statfs (struct super_block *sb, struct statfs *buf)
-{
- long tmp;
-
- put_fs_long(EXT_SUPER_MAGIC, &buf->f_type);
- put_fs_long(1024, &buf->f_bsize);
- put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
- tmp = ext_count_free_blocks(sb);
- put_fs_long(tmp, &buf->f_bfree);
- put_fs_long(tmp, &buf->f_bavail);
- put_fs_long(sb->s_ninodes, &buf->f_files);
- put_fs_long(ext_count_free_inodes(sb), &buf->f_ffree);
- /* Don't know what value to put in buf->f_fsid */
-}
-
-static int _ext_bmap(struct inode * inode,int block,int create)
-{
- struct buffer_head * bh;
- int i;
-
- if (block<0) {
- printk("_ext_bmap: block<0");
- return 0;
- }
- if (block >= 9+256+256*256+256*256*256) {
- printk("_ext_bmap: block>big");
- return 0;
- }
- if (block<9) {
- if (create && !inode->i_data[block])
- if (inode->i_data[block]=ext_new_block(inode->i_dev)) {
- inode->i_ctime=CURRENT_TIME;
- inode->i_dirt=1;
- }
- return inode->i_data[block];
- }
- block -= 9;
- if (block<256) {
- if (create && !inode->i_data[9])
- if (inode->i_data[9]=ext_new_block(inode->i_dev)) {
- inode->i_dirt=1;
- inode->i_ctime=CURRENT_TIME;
- }
- if (!inode->i_data[9])
- return 0;
- if (!(bh = bread(inode->i_dev,inode->i_data[9])))
- return 0;
- i = ((unsigned long *) (bh->b_data))[block];
- if (create && !i)
- if (i=ext_new_block(inode->i_dev)) {
- ((unsigned long *) (bh->b_data))[block]=i;
- bh->b_dirt=1;
- }
- brelse(bh);
- return i;
- }
- block -= 256;
- if (block<256*256) {
- if (create && !inode->i_data[10])
- if (inode->i_data[10]=ext_new_block(inode->i_dev)) {
- inode->i_dirt=1;
- inode->i_ctime=CURRENT_TIME;
- }
- if (!inode->i_data[10])
- return 0;
- if (!(bh=bread(inode->i_dev,inode->i_data[10])))
- return 0;
- i = ((unsigned long *)bh->b_data)[block>>8];
- if (create && !i)
- if (i=ext_new_block(inode->i_dev)) {
- ((unsigned long *) (bh->b_data))[block>>8]=i;
- bh->b_dirt=1;
- }
- brelse(bh);
- if (!i)
- return 0;
- if (!(bh=bread(inode->i_dev,i)))
- return 0;
- i = ((unsigned long *)bh->b_data)[block&255];
- if (create && !i)
- if (i=ext_new_block(inode->i_dev)) {
- ((unsigned long *) (bh->b_data))[block&255]=i;
- bh->b_dirt=1;
- }
- brelse(bh);
- return i;
- }
- printk("ext_bmap: triple indirection not yet implemented\n");
- return 0;
-}
-
-int ext_bmap(struct inode * inode,int block)
-{
- return _ext_bmap(inode,block,0);
-}
-
-int ext_create_block(struct inode * inode, int block)
-{
- return _ext_bmap(inode,block,1);
-}
-
-void ext_read_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_inode * raw_inode;
- int block;
-
-#ifdef EXTFS_BITMAP
- block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
- (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-#endif
-#ifdef EXTFS_FREELIST
- block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-#endif
- if (!(bh=bread(inode->i_dev,block)))
- panic("unable to read i-node block");
- raw_inode = ((struct ext_inode *) bh->b_data) +
- (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
- inode->i_mode = raw_inode->i_mode;
- inode->i_uid = raw_inode->i_uid;
- inode->i_gid = raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
- inode->i_size = raw_inode->i_size;
- inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = raw_inode->i_zone[0];
- else for (block = 0; block < 12; block++)
- inode->i_data[block] = raw_inode->i_zone[block];
- brelse(bh);
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &ext_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &ext_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ext_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &ext_chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &ext_blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &ext_fifo_inode_operations;
- inode->i_size = 0;
- inode->i_pipe = 1;
- PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
- }
-}
-
-void ext_write_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_inode * raw_inode;
- int block;
-
-#ifdef EXTFS_BITMAP
- block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
- (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-#endif
-#ifdef EXTFS_FREELIST
- block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
-#endif
- if (!(bh=bread(inode->i_dev,block)))
- panic("unable to read i-node block");
- raw_inode = ((struct ext_inode *)bh->b_data) +
- (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
- raw_inode->i_mode = inode->i_mode;
- raw_inode->i_uid = inode->i_uid;
- raw_inode->i_gid = inode->i_gid;
- raw_inode->i_nlinks = inode->i_nlink;
- raw_inode->i_size = inode->i_size;
- raw_inode->i_time = inode->i_mtime;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- raw_inode->i_zone[0] = inode->i_rdev;
- else for (block = 0; block < 12; block++)
- raw_inode->i_zone[block] = inode->i_data[block];
- bh->b_dirt=1;
- inode->i_dirt=0;
- brelse(bh);
-}
+++ /dev/null
-/*
- * linux/fs/ext/namei.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/namei.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <asm/segment.h>
-
-#include <errno.h>
-#include <const.h>
-
-/*
- * comment out this line if you want names > EXT_NAME_LEN chars to be
- * truncated. Else they will be disallowed.
- */
-/* #define NO_TRUNCATE */
-
-/*
- * EXT_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a power of 2 and must be greater or equal than 8
- * because a directory entry needs 8 bytes for its fixed part
- * (4 bytes for the inode, 2 bytes for the entry length and 2 bytes
- * for the name length)
- */
-#define EXT_DIR_PAD 8
-
-/*
- *
- * EXT_DIR_MIN_SIZE is the minimal size of a directory entry
- *
- * During allocations, a directory entry is split into 2 ones
- * *ONLY* if the size of the unused part is greater than or
- * equal to EXT_DIR_MIN_SIZE
- */
-#define EXT_DIR_MIN_SIZE 12
-
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use ext_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, ext_match returns 1 for success, 0 for failure.
- */
-static int ext_match(int len,const char * name,struct ext_dir_entry * de)
-{
- register int same __asm__("ax");
-
- if (!de || !de->inode || len > EXT_NAME_LEN)
- return 0;
- /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
- if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
- return 1;
-/* if (len < EXT_NAME_LEN && de->name[len])
- return 0; */
- if (len < EXT_NAME_LEN && len != de->name_len)
- return 0;
- __asm__("cld\n\t"
- "fs ; repe ; cmpsb\n\t"
- "setz %%al"
- :"=a" (same)
- :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
- :"cx","di","si");
- return same;
-}
-
-/*
- * ext_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- *
- * addition for the ext file system : this function returns the previous
- * and next directory entries in the parameters prev_dir and next_dir
- */
-static struct buffer_head * ext_find_entry(struct inode * dir,
- const char * name, int namelen, struct ext_dir_entry ** res_dir,
- struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
-{
-/* int entries; */
- int block /* ,i */;
- long offset;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- *res_dir = NULL;
- if (!dir)
- return NULL;
-#ifdef NO_TRUNCATE
- if (namelen > EXT_NAME_LEN)
- return NULL;
-#else
- if (namelen > EXT_NAME_LEN)
- namelen = EXT_NAME_LEN;
-#endif
-/* entries = dir->i_size / (sizeof (struct ext_dir_entry)); */
- if (!(block = dir->i_data[0]))
- return NULL;
- if (!(bh = bread(dir->i_dev,block)))
- return NULL;
- if (prev_dir)
- *prev_dir = NULL;
- if (next_dir)
- *next_dir = NULL;
-/* i = 0; */
- offset = 0;
- de = (struct ext_dir_entry *) bh->b_data;
- while (offset < dir->i_size) {
- if ((char *)de >= BLOCK_SIZE+bh->b_data) {
- brelse(bh);
- bh = NULL;
- if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) ||
- !(bh = bread(dir->i_dev,block))) {
-/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
-/* offset += BLOCK_SIZE; */
- continue;
- }
- de = (struct ext_dir_entry *) bh->b_data;
- if (prev_dir)
- *prev_dir = NULL;
- }
- if (ext_match(namelen,name,de)) {
- *res_dir = de;
- if (next_dir)
- if (offset + de->rec_len < dir->i_size)
- *next_dir = (struct ext_dir_entry *)
- ((char *) de + de->rec_len);
- else
- *next_dir = NULL;
- return bh;
- }
- offset += de->rec_len;
- if (prev_dir)
- *prev_dir = de;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-/* i++; */
- }
- brelse(bh);
- return NULL;
-}
-
-int ext_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result)
-{
- int ino;
- struct ext_dir_entry * de;
- struct buffer_head * bh;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- if (!(bh = ext_find_entry(dir,name,len,&de,NULL,NULL))) {
- iput(dir);
- return -ENOENT;
- }
- ino = de->inode;
- brelse(bh);
- if (!(*result = iget(dir->i_dev,ino))) {
- iput(dir);
- return -EACCES;
- }
- iput(dir);
- return 0;
-}
-
-/*
- * ext_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as ext_find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * ext_add_entry(struct inode * dir,
- const char * name, int namelen, struct ext_dir_entry ** res_dir)
-{
- int block,i;
- long offset;
- unsigned short rec_len;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * de1;
-
- *res_dir = NULL;
- if (!dir)
- return NULL;
-#ifdef NO_TRUNCATE
- if (namelen > EXT_NAME_LEN)
- return NULL;
-#else
- if (namelen > EXT_NAME_LEN)
- namelen = EXT_NAME_LEN;
-#endif
- if (!namelen)
- return NULL;
- if (!(block = dir->i_data[0]))
- return NULL;
- if (!(bh = bread(dir->i_dev,block)))
- return NULL;
- rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
-/* i = 0; */
- offset = 0;
- de = (struct ext_dir_entry *) bh->b_data;
- while (1) {
- if ((char *)de >= BLOCK_SIZE+bh->b_data && offset < dir->i_size) {
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry: skipping to next block\n");
-#endif
- brelse(bh);
- bh = NULL;
- block = ext_create_block(dir,offset>>BLOCK_SIZE_BITS);
- if (!block)
- return NULL;
- if (!(bh = bread(dir->i_dev,block))) {
-/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
- offset += BLOCK_SIZE;
- continue;
- }
- de = (struct ext_dir_entry *) bh->b_data;
- }
- if (offset >= dir->i_size) {
- /* Check that the directory entry fits in the block */
- if (offset % BLOCK_SIZE == 0
- || (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
- if ((offset % BLOCK_SIZE) != 0) {
- /* If the entry does not fit in the
- block, the remainder of the block
- becomes an unused entry */
- de->inode = 0;
- de->rec_len = BLOCK_SIZE
- - (offset & (BLOCK_SIZE - 1));
- de->name_len = 0;
- offset += de->rec_len;
- dir->i_size += de->rec_len;
- dir->i_dirt = 1;
- dir->i_ctime = CURRENT_TIME;
- bh->b_dirt = 1;
- }
- brelse (bh);
- bh = NULL;
- block = ext_create_block (dir,offset>>BLOCK_SIZE_BITS);
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry : creating next block\n");
-#endif
- if (!block)
- return NULL;
- if (!(bh = bread(dir->i_dev,block)))
- return NULL; /* Other thing to do ??? */
- de = (struct ext_dir_entry *) bh->b_data;
- }
- /* Allocate the entry */
- de->inode=0;
- de->rec_len = rec_len;
-/* dir->i_size = (i+1)*sizeof(struct ext_dir_entry); */
- dir->i_size += de->rec_len;
- dir->i_dirt = 1;
- dir->i_ctime = CURRENT_TIME;
- }
- if (!de->inode && de->rec_len >= rec_len) {
- if (de->rec_len > rec_len
- && de->rec_len - rec_len >= EXT_DIR_MIN_SIZE) {
- /* The found entry is too big : it is split
- into 2 ones :
- - the 1st one will be used to hold the name,
- - the 2nd one is unused */
- de1 = (struct ext_dir_entry *) ((char *) de + rec_len);
- de1->inode = 0;
- de1->rec_len = de->rec_len - rec_len;
- de1->name_len = 0;
- de->rec_len = rec_len;
- }
- dir->i_mtime = CURRENT_TIME;
- de->name_len = namelen;
- for (i=0; i < namelen ; i++)
- de->name[i]=/*(i<namelen)?*/get_fs_byte(name+i)/*:0*/;
- bh->b_dirt = 1;
- *res_dir = de;
- return bh;
- }
- offset += de->rec_len;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- return NULL;
-}
-
-int ext_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- inode = ext_new_inode(dir->i_dev);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &ext_file_inode_operations;
- inode->i_mode = mode;
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- bh->b_dirt = 1;
- brelse(bh);
- iput(dir);
- *result = inode;
- return 0;
-}
-
-int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- if (!dir)
- return -ENOENT;
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- inode = ext_new_inode(dir->i_dev);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_uid = current->euid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &ext_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &ext_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ext_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &ext_chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &ext_blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &ext_fifo_inode_operations;
- inode->i_size = 0;
- inode->i_pipe = 1;
- PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
- }
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = rdev;
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- bh->b_dirt = 1;
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
-{
- struct inode * inode;
- struct buffer_head * bh, *dir_block;
- struct ext_dir_entry * de;
-
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- inode = ext_new_inode(dir->i_dev);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &ext_dir_inode_operations;
- inode->i_size = 2 * 16; /* Each entry is coded on 16 bytes for "." and ".."
- - 4 bytes for the inode number,
- - 2 bytes for the record length
- - 2 bytes for the name length
- - 8 bytes for the name */
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
- if (!(inode->i_data[0] = ext_new_block(inode->i_dev))) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- inode->i_dirt = 1;
- if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -EIO;
- }
- de = (struct ext_dir_entry *) dir_block->b_data;
- de->inode=inode->i_ino;
- de->rec_len=16;
- de->name_len=1;
- strcpy(de->name,".");
-/* de++; */
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- de->inode = dir->i_ino;
- de->rec_len=16;
- de->name_len=2;
- strcpy(de->name,"..");
- inode->i_nlink = 2;
- dir_block->b_dirt = 1;
- brelse(dir_block);
- inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- iput(dir);
- inode->i_nlink=0;
- iput(inode);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- bh->b_dirt = 1;
- dir->i_nlink++;
- dir->i_dirt = 1;
- iput(dir);
- iput(inode);
- brelse(bh);
- return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
- int /* nr, */ block;
-/* int len; */
- unsigned long offset;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * de1;
-
-/* len = inode->i_size / sizeof (struct ext_dir_entry); */
- if (inode->i_size < 2 * 12 || !inode->i_data[0] ||
- !(bh=bread(inode->i_dev,inode->i_data[0]))) {
- printk("warning - bad directory on dev %04x\n",inode->i_dev);
- return 0;
- }
- de = (struct ext_dir_entry *) bh->b_data;
- de1 = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- if (de->inode != inode->i_ino || !de1->inode ||
- strcmp(".",de->name) || strcmp("..",de1->name)) {
- printk("warning - bad directory on dev %04x\n",inode->i_dev);
- return 0;
- }
-/* nr = 2; */
- offset = de->rec_len + de1->rec_len;
- de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
- while (offset < inode->i_size ) {
- if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
- brelse(bh);
- block = ext_bmap(inode, offset >> BLOCK_SIZE_BITS);
- if (!block) {
- offset += BLOCK_SIZE;
- continue;
- }
- if (!(bh=bread(inode->i_dev,block)))
- return 0;
- de = (struct ext_dir_entry *) bh->b_data;
- }
- if (de->inode) {
- brelse(bh);
- return 0;
- }
- offset += de->rec_len;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- return 1;
-}
-
-static inline void ext_merge_entries (struct ext_dir_entry * de,
- struct ext_dir_entry * pde, struct ext_dir_entry * nde)
-{
- if (! nde->inode)
- de->rec_len += nde->rec_len;
- if (! pde->inode)
- pde->rec_len += de->rec_len;
-}
-
-int ext_rmdir(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * pde, * nde;
-
- inode = NULL;
- bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
- retval = -ENOENT;
- if (!bh)
- goto end_rmdir;
- retval = -EPERM;
- if (!(inode = iget(dir->i_dev, de->inode)))
- goto end_rmdir;
- if ((dir->i_mode & S_ISVTX) && current->euid &&
- inode->i_uid != current->euid)
- goto end_rmdir;
- if (inode->i_dev != dir->i_dev)
- goto end_rmdir;
- if (inode == dir) /* we may not delete ".", but "../dir" is ok */
- goto end_rmdir;
- if (!S_ISDIR(inode->i_mode)) {
- retval = -ENOTDIR;
- goto end_rmdir;
- }
- if (!empty_dir(inode)) {
- retval = -ENOTEMPTY;
- goto end_rmdir;
- }
- if (inode->i_count > 1) {
- retval = -EBUSY;
- goto end_rmdir;
- }
- if (inode->i_nlink != 2)
- printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
- de->inode = 0;
- de->name_len = 0;
- ext_merge_entries (de, pde, nde);
- bh->b_dirt = 1;
- inode->i_nlink=0;
- inode->i_dirt=1;
- dir->i_nlink--;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt=1;
- retval = 0;
-end_rmdir:
- iput(dir);
- iput(inode);
- brelse(bh);
- return retval;
-}
-
-int ext_unlink(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * pde, * nde;
-
- retval = -ENOENT;
- inode = NULL;
- bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
- if (!bh)
- goto end_unlink;
- if (!(inode = iget(dir->i_dev, de->inode)))
- goto end_unlink;
- retval = -EPERM;
- if ((dir->i_mode & S_ISVTX) && !suser() &&
- current->euid != inode->i_uid &&
- current->euid != dir->i_uid)
- goto end_unlink;
- if (S_ISDIR(inode->i_mode))
- goto end_unlink;
- if (!inode->i_nlink) {
- printk("Deleting nonexistent file (%04x:%d), %d\n",
- inode->i_dev,inode->i_ino,inode->i_nlink);
- inode->i_nlink=1;
- }
- de->inode = 0;
- de->name_len = 0;
- ext_merge_entries (de, pde, nde);
- bh->b_dirt = 1;
- inode->i_nlink--;
- inode->i_dirt = 1;
- inode->i_ctime = CURRENT_TIME;
- retval = 0;
-end_unlink:
- brelse(bh);
- iput(inode);
- iput(dir);
- return retval;
-}
-
-int ext_symlink(struct inode * dir, const char * name, int len, const char * symname)
-{
- struct ext_dir_entry * de;
- struct inode * inode = NULL;
- struct buffer_head * bh = NULL, * name_block = NULL;
- int i;
- char c;
-
- if (!(inode = ext_new_inode(dir->i_dev))) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_mode = S_IFLNK | 0777;
- inode->i_op = &ext_symlink_inode_operations;
- if (!(inode->i_data[0] = ext_new_block(inode->i_dev))) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- inode->i_dirt = 1;
- if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -EIO;
- }
- i = 0;
- while (i < 1023 && (c=get_fs_byte(symname++)))
- name_block->b_data[i++] = c;
- name_block->b_data[i] = 0;
- name_block->b_dirt = 1;
- brelse(name_block);
- inode->i_size = i;
- inode->i_dirt = 1;
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- bh->b_dirt = 1;
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
-{
- struct ext_dir_entry * de;
- struct buffer_head * bh;
-
- if (S_ISDIR(oldinode->i_mode)) {
- iput(oldinode);
- iput(dir);
- return -EPERM;
- }
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- iput(oldinode);
- return -EEXIST;
- }
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- iput(dir);
- iput(oldinode);
- return -ENOSPC;
- }
- de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
- brelse(bh);
- iput(dir);
- oldinode->i_nlink++;
- oldinode->i_ctime = CURRENT_TIME;
- oldinode->i_dirt = 1;
- iput(oldinode);
- return 0;
-}
-
-static int subdir(struct inode * new, struct inode * old)
-{
- unsigned short fs;
- int ino;
- int result;
-
- __asm__("mov %%fs,%0":"=r" (fs));
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- new->i_count++;
- result = 0;
- for (;;) {
- if (new == old) {
- result = 1;
- break;
- }
- if (new->i_dev != old->i_dev)
- break;
- ino = new->i_ino;
- if (ext_lookup(new,"..",2,&new))
- break;
- if (new->i_ino == ino)
- break;
- }
- iput(new);
- __asm__("mov %0,%%fs"::"r" (fs));
- return result;
-}
-
-#define PARENT_INO(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->inode
-/* (((struct ext_dir_entry *) (buffer))[1].inode) */
-
-#define PARENT_NAME(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->name
-/* (((struct ext_dir_entry *) (buffer))[1].name) */
-
-/*
- * rename uses retrying to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
- * Anybody can rename anything with this: the permission checks are left to the
- * higher-level routines.
- */
-static int do_ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len)
-{
- struct inode * old_inode, * new_inode;
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct ext_dir_entry * old_de, * new_de, * pde, * nde;
- int retval;
-
- goto start_up;
-try_again:
- brelse(old_bh);
- brelse(new_bh);
- brelse(dir_bh);
- iput(old_inode);
- iput(new_inode);
- current->counter = 0;
- schedule();
-start_up:
- old_inode = new_inode = NULL;
- old_bh = new_bh = dir_bh = NULL;
- old_bh = ext_find_entry(old_dir,old_name,old_len,&old_de,&pde,&nde);
- retval = -ENOENT;
- if (!old_bh)
- goto end_rename;
- old_inode = iget(old_dir->i_dev, old_de->inode);
- if (!old_inode)
- goto end_rename;
- if ((old_dir->i_mode & S_ISVTX) &&
- current->euid != old_inode->i_uid &&
- current->euid != old_dir->i_uid && !suser())
- goto end_rename;
- new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
- if (new_bh) {
- new_inode = iget(new_dir->i_dev, new_de->inode);
- if (!new_inode) {
- brelse(new_bh);
- new_bh = NULL;
- }
- }
- if (new_inode == old_inode) {
- retval = 0;
- goto end_rename;
- }
- if (S_ISDIR(new_inode->i_mode)) {
- retval = -EEXIST;
- goto end_rename;
- }
- if (S_ISDIR(old_inode->i_mode)) {
- retval = -EEXIST;
- if (new_bh)
- goto end_rename;
- retval = -EACCES;
- if (!permission(old_inode, MAY_WRITE))
- goto end_rename;
- retval = -EINVAL;
- if (subdir(new_dir, old_inode))
- goto end_rename;
- retval = -EIO;
- if (!old_inode->i_data[0])
- goto end_rename;
- if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0])))
- goto end_rename;
- if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
- goto end_rename;
- }
- if (!new_bh)
- new_bh = ext_add_entry(new_dir,new_name,new_len,&new_de);
- retval = -ENOSPC;
- if (!new_bh)
- goto end_rename;
-/* sanity checking before doing the rename - avoid races */
- if (new_inode && (new_de->inode != new_inode->i_ino))
- goto try_again;
- if (new_de->inode && !new_inode)
- goto try_again;
- if (old_de->inode != old_inode->i_ino)
- goto try_again;
-/* ok, that's it */
- old_de->inode = 0;
- old_de->name_len = 0;
- ext_merge_entries (old_de, pde, nde);
- new_de->inode = old_inode->i_ino;
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_dirt = 1;
- }
- old_bh->b_dirt = 1;
- new_bh->b_dirt = 1;
- if (dir_bh) {
- PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
- old_dir->i_nlink--;
- new_dir->i_nlink++;
- old_dir->i_dirt = 1;
- new_dir->i_dirt = 1;
- }
- retval = 0;
-end_rename:
- brelse(dir_bh);
- brelse(old_bh);
- brelse(new_bh);
- iput(old_inode);
- iput(new_inode);
- iput(old_dir);
- iput(new_dir);
- return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len)
-{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;
- result = do_ext_rename(old_dir, old_name, old_len,
- new_dir, new_name, new_len);
- lock = 0;
- wake_up(&wait);
- return result;
-}
+++ /dev/null
-/*
- * linux/fs/ext/symlink.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/symlink.c
- *
- * (C) 1991 Linus Torvalds
- *
- * ext symlink handling code
- */
-
-#include <errno.h>
-
-#include <asm/segment.h>
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static int ext_readlink(struct inode *, char *, int);
-static struct inode * ext_follow_link(struct inode *, struct inode *);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations ext_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ext_readlink, /* readlink */
- ext_follow_link, /* follow_link */
- NULL, /* bmap */
- NULL /* truncate */
-};
-
-static struct inode * ext_follow_link(struct inode * dir, struct inode * inode)
-{
- unsigned short fs;
- struct buffer_head * bh;
-
- if (!dir) {
- dir = current->root;
- dir->i_count++;
- }
- if (!inode) {
- iput(dir);
- return NULL;
- }
- if (!S_ISLNK(inode->i_mode)) {
- iput(dir);
- return inode;
- }
- __asm__("mov %%fs,%0":"=r" (fs));
- if ((current->link_count > 5) || !inode->i_data[0] ||
- !(bh = bread(inode->i_dev, inode->i_data[0]))) {
- iput(dir);
- iput(inode);
- return NULL;
- }
- iput(inode);
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- current->link_count++;
- inode = _namei(bh->b_data,dir,1);
- current->link_count--;
- __asm__("mov %0,%%fs"::"r" (fs));
- brelse(bh);
- return inode;
-}
-
-static int ext_readlink(struct inode * inode, char * buffer, int buflen)
-{
- struct buffer_head * bh;
- int i;
- char c;
-
- if (!S_ISLNK(inode->i_mode)) {
- iput(inode);
- return -EINVAL;
- }
- if (buflen > 1023)
- buflen = 1023;
- if (inode->i_data[0])
- bh = bread(inode->i_dev, inode->i_data[0]);
- else
- bh = NULL;
- iput(inode);
- if (!bh)
- return 0;
- i = 0;
- while (i<buflen && (c = bh->b_data[i])) {
- i++;
- put_fs_byte(c,buffer++);
- }
- brelse(bh);
- return i;
-}
+++ /dev/null
-/*
- * linux/fs/ext/truncate.c
- *
- * (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/truncate.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#include <errno.h>
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-static int trunc_direct(struct inode * inode)
-{
- int i;
- int result = 0;
-#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 9 ; i++) {
- if (i < DIRECT_BLOCK)
- goto repeat;
- if (!inode->i_data[i])
- continue;
- result = 1;
- if (ext_free_block(inode->i_dev,inode->i_data[i]))
- inode->i_data[i] = 0;
- }
- return result;
-}
-
-static int trunc_indirect(struct inode * inode, int offset, unsigned long * p)
-{
- int i;
- struct buffer_head * bh = NULL;
- unsigned long * ind;
- int result = 0;
-#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
-
- if (*p)
- bh = bread(inode->i_dev,*p);
- if (!bh)
- return 0;
-repeat:
- for (i = INDIRECT_BLOCK ; i < 256 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK)
- goto repeat;
- ind = i+(unsigned long *) bh->b_data;
- if (!*ind)
- continue;
- result = 1;
- if (ext_free_block(inode->i_dev,*ind))
- *ind = 0;
- }
- ind = (unsigned long *) bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(ind++))
- break;
- brelse(bh);
- if (i >= 256) {
- result = 1;
- if (ext_free_block(inode->i_dev,*p))
- *p = 0;
- }
- return result;
-}
-
-static int trunc_dindirect(struct inode * inode)
-{
- int i;
- struct buffer_head * bh = NULL;
- unsigned long * dind;
- int result = 0;
-#define DINDIRECT_BLOCK ((DIRECT_BLOCK-(256+9))>>8)
-
- if (inode->i_data[10])
- bh = bread(inode->i_dev,inode->i_data[10]);
- if (!bh)
- return 0;
-repeat:
- for (i = DINDIRECT_BLOCK ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < DINDIRECT_BLOCK)
- goto repeat;
- dind = i+(unsigned long *) bh->b_data;
- if (!*dind)
- continue;
- result |= trunc_indirect(inode,9+256+(i<<8),dind);
- }
- dind = (unsigned long *) bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(dind++))
- break;
- brelse(bh);
- if (i >= 256) {
- result = 1;
- if (ext_free_block(inode->i_dev,inode->i_data[10]))
- inode->i_data[10] = 0;
- }
- return result;
-}
-
-void ext_truncate(struct inode * inode)
-{
- int flag;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-/* if (inode->i_data[7] & 0xffff0000)
- printk("BAD! ext inode has 16 high bits set\n"); */
- while (1) {
- flag = trunc_direct(inode);
- flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]);
- flag |= trunc_dindirect(inode);
- if (!flag)
- break;
- current->counter = 0;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_dirt = 1;
-}
-
-/*
- * Called when a inode is released. Note that this is different
- * from ext_open: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
- */
-void ext_release(struct inode * inode, struct file * filp)
-{
- printk("ext_release not implemented\n");
-}
* (C) 1991 Linus Torvalds
*/
-#include <errno.h>
-
-#include <asm/segment.h>
-
-#include <linux/stat.h>
-#include <linux/fcntl.h>
#include <linux/string.h>
+#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <asm/segment.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
extern int sys_close(int fd);
int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
- if (oldfd >= NR_OPEN || !current->filp[oldfd])
- return -EBADF;
if (newfd == oldfd)
return newfd;
sys_close(newfd);
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove
- */
-
-#include <errno.h>
-
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-extern struct file_operations read_pipe_fops;
-extern struct file_operations write_pipe_fops;
-extern struct file_operations rdwr_pipe_fops;
-
-static int fifo_open(struct inode * inode,struct file * filp)
-{
- int retval = 0;
- unsigned long page;
-
- switch( filp->f_mode ) {
-
- case 1:
- /*
- * O_RDONLY
- * POSIX.1 says that O_NONBLOCK means return with the FIFO
- * opened, even when there is no process writing the FIFO.
- */
- filp->f_op = &read_pipe_fops;
- PIPE_READERS(*inode)++;
- if (!(filp->f_flags & O_NONBLOCK))
- while (!PIPE_WRITERS(*inode)) {
- if (PIPE_HEAD(*inode) != PIPE_TAIL(*inode))
- break;
- if (current->signal & ~current->blocked) {
- retval = -ERESTARTSYS;
- break;
- }
- interruptible_sleep_on(&PIPE_READ_WAIT(*inode));
- }
- if (retval)
- PIPE_READERS(*inode)--;
- break;
-
- case 2:
- /*
- * O_WRONLY
- * POSIX.1 says that O_NONBLOCK means return -1 with
- * errno=ENXIO when there is no process reading the FIFO.
- */
- if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) {
- retval = -ENXIO;
- break;
- }
- filp->f_op = &write_pipe_fops;
- PIPE_WRITERS(*inode)++;
- while (!PIPE_READERS(*inode)) {
- if (current->signal & ~current->blocked) {
- retval = -ERESTARTSYS;
- break;
- }
- interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
- }
- if (retval)
- PIPE_WRITERS(*inode)--;
- break;
-
- case 3:
- /*
- * O_RDWR
- * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
- * This implementation will NEVER block on a O_RDWR open, since
- * the process can at least talk to itself.
- */
- filp->f_op = &rdwr_pipe_fops;
- PIPE_WRITERS(*inode) += 1;
- PIPE_READERS(*inode) += 1;
- break;
-
- default:
- retval = -EINVAL;
- }
- if (PIPE_WRITERS(*inode))
- wake_up(&PIPE_READ_WAIT(*inode));
- if (PIPE_READERS(*inode))
- wake_up(&PIPE_WRITE_WAIT(*inode));
- if (retval || inode->i_size)
- return retval;
- page = get_free_page();
- if (inode->i_size) {
- free_page(page);
- return 0;
- }
- if (!page)
- return -ENOMEM;
- inode->i_size = page;
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the access mode of the file...
- */
-struct file_operations def_fifo_fops = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- fifo_open, /* will set read or write pipe_fops */
- NULL
-};
*/
#include <linux/string.h>
-#include <linux/stat.h>
+#include <sys/stat.h>
+
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-
#include <asm/system.h>
struct inode inode_table[NR_INODE]={{0,},};
static void write_inode(struct inode * inode)
{
- if (!inode->i_dirt)
- return;
- inode->i_dirt = 0;
lock_inode(inode);
- if (inode->i_dev && inode->i_sb &&
- inode->i_sb->s_op && inode->i_sb->s_op->write_inode)
- inode->i_sb->s_op->write_inode(inode);
+ if (!inode->i_dirt || !inode->i_dev) {
+ unlock_inode(inode);
+ return;
+ }
+ if (inode->i_op && inode->i_op->write_inode)
+ inode->i_op->write_inode(inode);
unlock_inode(inode);
}
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
- if (inode->i_dirt)
+ if (inode->i_dirt && !inode->i_pipe)
write_inode(inode);
}
}
if (!inode)
return;
wait_on_inode(inode);
- if (!inode->i_count) {
- printk("iput: trying to free free inode\n");
- printk("device %04x, inode %d, mode=%07o\n",inode->i_rdev,
- inode->i_ino,inode->i_mode);
- return;
- }
+ if (!inode->i_count)
+ panic("iput: trying to free free inode");
if (inode->i_pipe) {
wake_up(&inode->i_wait);
wake_up(&inode->i_wait2);
+ if (--inode->i_count)
+ return;
+ free_page(inode->i_size);
+ inode->i_count=0;
+ inode->i_dirt=0;
+ inode->i_pipe=0;
+ return;
}
-repeat:
- if (inode->i_count>1) {
+ if (!inode->i_dev) {
inode->i_count--;
return;
}
- if (inode->i_pipe) {
- free_page(inode->i_size);
- inode->i_size = 0;
+ if (S_ISBLK(inode->i_mode)) {
+ sync_dev(inode->i_rdev);
+ wait_on_inode(inode);
}
- if (!inode->i_dev) {
+repeat:
+ if (inode->i_count>1) {
inode->i_count--;
return;
}
if (!inode->i_nlink) {
- if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
- inode->i_sb->s_op->put_inode(inode);
- return;
- }
+ if (inode->i_op && inode->i_op->put_inode)
+ inode->i_op->put_inode(inode);
+ return;
}
if (inode->i_dirt) {
write_inode(inode); /* we can sleep - so do again */
if (!(inode = get_empty_inode()))
return NULL;
- if (!(inode->i_size = get_free_page())) {
+ if (!(inode->i_size=get_free_page())) {
inode->i_count = 0;
return NULL;
}
inode->i_count = 2; /* sum of readers/writers */
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
inode->i_pipe = 1;
return inode;
}
}
inode->i_dev = dev;
inode->i_ino = nr;
- inode->i_flags = inode->i_sb->s_flags;
read_inode(inode);
return inode;
}
* (C) 1991 Linus Torvalds
*/
+#include <linux/string.h>
#include <errno.h>
+#include <sys/stat.h>
-#include <asm/segment.h>
-#include <linux/string.h>
-#include <linux/stat.h>
#include <linux/sched.h>
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
- int block;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
- if (S_ISREG(filp->f_inode->i_mode) && cmd == BMAP_IOCTL &&
- filp->f_inode->i_op->bmap) {
- block = get_fs_long((long *) arg);
- block = filp->f_inode->i_op->bmap(filp->f_inode,block);
- put_fs_long(block,(long *) arg);
- return 0;
- }
if (filp->f_op && filp->f_op->ioctl)
return filp->f_op->ioctl(filp->f_inode, filp, cmd,arg);
return -EINVAL;
#
# Note 2! The CFLAGS definitions are now in the main makefile...
+AR =ar
+AS =as
+LD =ld
+CC =gcc -nostdinc -I../../include
+CPP =cpp -nostdinc -I../../include
+
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.c.o:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
.s.o:
$(AS) -o $*.o $<
-OBJS= bitmap.o truncate.o namei.o inode.o \
- file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+OBJS= minix_op.o bitmap.o truncate.o namei.o inode.o file_dev.o
minix.o: $(OBJS)
$(LD) -r -o minix.o $(OBJS)
dep:
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
### Dependencies:
-bitmap.o : bitmap.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h
-blkdev.o : blkdev.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h
-chrdev.o : chrdev.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/stat.h
-fifo.o : fifo.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/linux/stat.h
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/asm/segment.h
-namei.o : namei.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h /usr/src/linux/include/const.h
-symlink.o : symlink.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/stat.h
-truncate.o : truncate.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h
+bitmap.o : bitmap.c ../../include/linux/string.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/minix_fs.h
+file_dev.o : file_dev.c ../../include/errno.h ../../include/fcntl.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/sys/stat.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/linux/mm.h \
+ ../../include/linux/kernel.h ../../include/signal.h ../../include/sys/param.h \
+ ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h ../../include/linux/minix_fs.h \
+ ../../include/asm/segment.h
+inode.o : inode.c ../../include/linux/string.h ../../include/sys/stat.h ../../include/sys/types.h \
+ ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/asm/system.h
+minix_op.o : minix_op.c ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/minix_fs.h
+namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+ ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/linux/minix_fs.h ../../include/asm/segment.h ../../include/linux/string.h \
+ ../../include/fcntl.h ../../include/errno.h ../../include/const.h ../../include/sys/stat.h
+truncate.o : truncate.c ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/linux/tty.h \
+ ../../include/termios.h ../../include/errno.h ../../include/fcntl.h ../../include/sys/stat.h
/*
- * linux/fs/minix/bitmap.c
+ * linux/fs/bitmap.c
*
* (C) 1991 Linus Torvalds
*/
/* bitmap.c contains the code that handles the inode and block bitmaps */
-
#include <linux/string.h>
+
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;})
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
-
-static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
- unsigned numbits)
-{
- unsigned i, j, end, sum = 0;
- struct buffer_head *bh;
-
- for (i=0; (i<numblocks) && numbits; i++) {
- if (!(bh=map[i]))
- return(0);
- if (numbits >= (8*BLOCK_SIZE)) {
- end = BLOCK_SIZE;
- numbits -= 8*BLOCK_SIZE;
- } else {
- int tmp;
- end = numbits >> 3;
- numbits &= 0x7;
- tmp = bh->b_data[end] & ((1<<numbits)-1);
- sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
- numbits = 0;
- }
- for (j=0; j<end; j++)
- sum += nibblemap[bh->b_data[j] & 0xf]
- + nibblemap[(bh->b_data[j]>>4)&0xf];
- }
- return(sum);
-}
-
int minix_free_block(int dev, int block)
{
struct super_block * sb;
return j;
}
-unsigned long minix_count_free_blocks(struct super_block *sb)
-{
- return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
- << sb->s_log_zone_size;
-}
-
void minix_free_inode(struct inode * inode)
{
struct buffer_head * bh;
iput(inode);
return NULL;
}
- inode->i_flags = inode->i_sb->s_flags;
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=inode->i_sb->s_imap[i])
inode->i_dirt = 1;
inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = NULL;
+ inode->i_op = &minix_inode_operations;
return inode;
}
-
-unsigned long minix_count_free_inodes(struct super_block *sb)
-{
- return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
-}
+++ /dev/null
-/*
- * linux/fs/minix/blkdev.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <errno.h>
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix block special file is opened
- */
-static int blkdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i < MAX_BLKDEV) {
- filp->f_op = blkdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- blkdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations minix_blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- minix_bmap, /* bmap */
- minix_truncate /* truncate */
-};
+++ /dev/null
-/*
- * linux/fs/minix/chrdev.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <errno.h>
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-/*
- * Called every time a minix character special file is opened
- */
-static int chrdev_open(struct inode * inode, struct file * filp)
-{
- int i;
-
- i = MAJOR(inode->i_rdev);
- if (i < MAX_CHRDEV) {
- filp->f_op = chrdev_fops[i];
- if (filp->f_op && filp->f_op->open)
- return filp->f_op->open(inode,filp);
- }
- return 0;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-static struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- chrdev_open, /* open */
- NULL, /* release */
-};
-
-struct inode_operations minix_chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- minix_bmap, /* bmap */
- minix_truncate /* truncate */
-};
-
+++ /dev/null
-/*
- * linux/fs/minix/dir.c
- *
- * (C) 1991 Linus Torvalds
- *
- * minix directory handling functions
- */
-
-#include <errno.h>
-
-#include <asm/segment.h>
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/stat.h>
-
-static int minix_readdir(struct inode *, struct file *, struct dirent *, int);
-
-static struct file_operations minix_dir_operations = {
- NULL, /* lseek - default */
- minix_file_read, /* read */
- NULL, /* write - bad */
- minix_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open code */
- NULL /* no special release code */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations minix_dir_inode_operations = {
- &minix_dir_operations, /* default directory file-ops */
- minix_create, /* create */
- minix_lookup, /* lookup */
- minix_link, /* link */
- minix_unlink, /* unlink */
- minix_symlink, /* symlink */
- minix_mkdir, /* mkdir */
- minix_rmdir, /* rmdir */
- minix_mknod, /* mknod */
- minix_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- minix_bmap, /* bmap */
- minix_truncate /* truncate */
-};
-
-static int minix_readdir(struct inode * inode, struct file * filp,
- struct dirent * dirent, int count)
-{
- unsigned int block,offset,i;
- char c;
- struct buffer_head * bh;
- struct minix_dir_entry * de;
-
- if (!inode || !S_ISDIR(inode->i_mode))
- return -EBADF;
- if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1))
- return -EBADF;
- while (filp->f_pos < inode->i_size) {
- offset = filp->f_pos & 1023;
- block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
- if (!block || !(bh = bread(inode->i_dev,block))) {
- filp->f_pos += 1024-offset;
- continue;
- }
- de = (struct minix_dir_entry *) (offset + bh->b_data);
- while (offset < 1024 && filp->f_pos < inode->i_size) {
- offset += sizeof (struct minix_dir_entry);
- filp->f_pos += sizeof (struct minix_dir_entry);
- if (de->inode) {
- for (i = 0; i < MINIX_NAME_LEN; i++)
- if (c = de->name[i])
- put_fs_byte(c,i+dirent->d_name);
- else
- break;
- if (i) {
- put_fs_long(de->inode,&dirent->d_ino);
- put_fs_byte(0,i+dirent->d_name);
- put_fs_word(i,&dirent->d_reclen);
- brelse(bh);
- return i;
- }
- }
- de++;
- }
- brelse(bh);
- }
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/fifo.c
- *
- * written by Paul H. Hargrove
- */
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-
-extern struct file_operations def_fifo_fops;
-
-struct inode_operations minix_fifo_inode_operations = {
- &def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL /* truncate */
-};
+++ /dev/null
-/*
- * linux/fs/minix/file.c
- *
- * (C) 1991 Linus Torvalds
- *
- * minix regular file handling primitives
- */
-
-#include <errno.h>
-
-#include <sys/dirent.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-
-#define NBUF 16
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-
-int minix_file_read(struct inode *, struct file *, char *, int);
-static int minix_file_write(struct inode *, struct file *, char *, int);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the minix filesystem.
- */
-static struct file_operations minix_file_operations = {
- NULL, /* lseek - default */
- minix_file_read, /* read */
- minix_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open is needed */
- NULL /* release */
-};
-
-struct inode_operations minix_file_inode_operations = {
- &minix_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- minix_bmap, /* bmap */
- minix_truncate /* truncate */
-};
-
-static inline void wait_on_buffer(struct buffer_head * bh)
-{
- cli();
- while (bh->b_lock)
- sleep_on(&bh->b_wait);
- sti();
-}
-
-/*
- * minix_file_read() is also needed by the directory read-routine,
- * so it's not static. NOTE! reading directories directly is a bad idea,
- * but has to be supported for now for compatability reasons with older
- * versions.
- */
-int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
-{
- int read,left,chars,nr;
- int block, blocks, offset;
- struct buffer_head ** bhb, ** bhe;
- struct buffer_head * buflist[NBUF];
-
- if (!inode) {
- printk("minix_file_read: inode = NULL\n");
- return -EINVAL;
- }
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
- printk("minix_file_read: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
- if (filp->f_pos > inode->i_size)
- left = 0;
- else
- left = inode->i_size - filp->f_pos;
- if (left > count)
- left = count;
- if (left <= 0)
- return 0;
- read = 0;
- block = filp->f_pos >> BLOCK_SIZE_BITS;
- offset = filp->f_pos & (BLOCK_SIZE-1);
- blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
- bhb = bhe = buflist;
- do {
- if (blocks) {
- --blocks;
- if (nr = minix_bmap(inode,block++)) {
- *bhb = getblk(inode->i_dev,nr);
- if (!(*bhb)->b_uptodate)
- ll_rw_block(READ,*bhb);
- } else
- *bhb = NULL;
-
- if (++bhb == &buflist[NBUF])
- bhb = buflist;
-
- if (bhb != bhe)
- continue;
- }
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!(*bhe)->b_uptodate) {
- do {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (bhe != bhb);
- break;
- }
- }
-
- if (left < BLOCK_SIZE - offset)
- chars = left;
- else
- chars = BLOCK_SIZE - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
- brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_fs_byte(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (left > 0);
- if (!read)
- return -EIO;
- if (!IS_RDONLY(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- return read;
-}
-
-static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
-{
- off_t pos;
- int written,block,c;
- struct buffer_head * bh;
- char * p;
-
- if (!inode) {
- printk("minix_file_write: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("minix_file_write: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = filp->f_pos;
- written = 0;
- while (written<count) {
- if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
- if (!written)
- written = -ENOSPC;
- break;
- }
- c = BLOCK_SIZE - (pos % BLOCK_SIZE);
- if (c > count-written)
- c = count-written;
- if (c == BLOCK_SIZE)
- bh = getblk(inode->i_dev, block);
- else
- bh = bread(inode->i_dev,block);
- if (!bh) {
- if (!written)
- written = -EIO;
- break;
- }
- p = (pos % BLOCK_SIZE) + bh->b_data;
- pos += c;
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_dirt = 1;
- }
- written += c;
- memcpy_fromfs(p,buf,c);
- buf += c;
- bh->b_uptodate = 1;
- bh->b_dirt = 1;
- brelse(bh);
- }
- inode->i_mtime = CURRENT_TIME;
- inode->i_ctime = CURRENT_TIME;
- filp->f_pos = pos;
- inode->i_dirt = 1;
- return written;
-}
--- /dev/null
+/*
+ * linux/fs/file_dev.c
+ *
+ * (C) 1991 Linus Torvalds
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/dirent.h>
+#include <sys/stat.h>
+
+#include <linux/sched.h>
+#include <linux/minix_fs.h>
+#include <linux/kernel.h>
+#include <asm/segment.h>
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count)
+{
+ unsigned int block,offset,i;
+ char c;
+ struct buffer_head * bh;
+ struct minix_dir_entry * de;
+
+ if (!inode || !S_ISDIR(inode->i_mode))
+ return -EBADF;
+ if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1))
+ return -EBADF;
+ while (filp->f_pos < inode->i_size) {
+ offset = filp->f_pos & 1023;
+ block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
+ if (!block || !(bh = bread(inode->i_dev,block))) {
+ filp->f_pos += 1024-offset;
+ continue;
+ }
+ de = (struct minix_dir_entry *) (offset + bh->b_data);
+ while (offset < 1024 && filp->f_pos < inode->i_size) {
+ offset += sizeof (struct minix_dir_entry);
+ filp->f_pos += sizeof (struct minix_dir_entry);
+ if (de->inode) {
+ for (i = 0; i < MINIX_NAME_LEN; i++)
+ if (c = de->name[i])
+ put_fs_byte(c,i+dirent->d_name);
+ else
+ break;
+ if (i) {
+ put_fs_long(de->inode,&dirent->d_ino);
+ put_fs_byte(0,i+dirent->d_name);
+ put_fs_word(i,&dirent->d_reclen);
+ brelse(bh);
+ return i;
+ }
+ }
+ de++;
+ }
+ brelse(bh);
+ }
+ return 0;
+}
+
+int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
+{
+ int read,left,chars,nr;
+ struct buffer_head * bh;
+
+ if (!inode) {
+ printk("minix_file_read: inode = NULL\n");
+ return -EINVAL;
+ }
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
+ printk("minix_file_read: mode = %07o\n",inode->i_mode);
+ return -EINVAL;
+ }
+ if (filp->f_pos > inode->i_size)
+ left = 0;
+ else
+ left = inode->i_size - filp->f_pos;
+ if (left > count)
+ left = count;
+ read = 0;
+ while (left > 0) {
+ if (nr = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS)) {
+ if (!(bh=bread(inode->i_dev,nr)))
+ return read?read:-EIO;
+ } else
+ bh = NULL;
+ nr = filp->f_pos & (BLOCK_SIZE-1);
+ chars = MIN( BLOCK_SIZE-nr , left );
+ filp->f_pos += chars;
+ left -= chars;
+ read += chars;
+ if (bh) {
+ memcpy_tofs(buf,nr+bh->b_data,chars);
+ buf += chars;
+ brelse(bh);
+ } else {
+ while (chars-->0)
+ put_fs_byte(0,buf++);
+ }
+ }
+ inode->i_atime = CURRENT_TIME;
+ return read;
+}
+
+int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
+{
+ off_t pos;
+ int written,block,c;
+ struct buffer_head * bh;
+ char * p;
+
+ if (!inode) {
+ printk("minix_file_write: inode = NULL\n");
+ return -EINVAL;
+ }
+ if (!S_ISREG(inode->i_mode)) {
+ printk("minix_file_write: mode = %07o\n",inode->i_mode);
+ return -EINVAL;
+ }
+/*
+ * ok, append may not work when many processes are writing at the same time
+ * but so what. That way leads to madness anyway.
+ */
+ if (filp->f_flags & O_APPEND)
+ pos = inode->i_size;
+ else
+ pos = filp->f_pos;
+ written = 0;
+ while (written<count) {
+ if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
+ if (!written)
+ written = -ENOSPC;
+ break;
+ }
+ c = BLOCK_SIZE - (pos % BLOCK_SIZE);
+ if (c > count-written)
+ c = count-written;
+ if (c == BLOCK_SIZE)
+ bh = getblk(inode->i_dev, block);
+ else
+ bh = bread(inode->i_dev,block);
+ if (!bh) {
+ if (!written)
+ written = -EIO;
+ break;
+ }
+ p = (pos % BLOCK_SIZE) + bh->b_data;
+ pos += c;
+ if (pos > inode->i_size) {
+ inode->i_size = pos;
+ inode->i_dirt = 1;
+ }
+ written += c;
+ memcpy_fromfs(p,buf,c);
+ buf += c;
+ bh->b_uptodate = 1;
+ bh->b_dirt = 1;
+ brelse(bh);
+ }
+ inode->i_mtime = CURRENT_TIME;
+ if (!(filp->f_flags & O_APPEND)) {
+ filp->f_pos = pos;
+ inode->i_ctime = CURRENT_TIME;
+ }
+ inode->i_dirt = 1;
+ return written;
+}
*/
#include <linux/string.h>
-#include <linux/stat.h>
+#include <sys/stat.h>
+
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
-#include <asm/segment.h>
int sync_dev(int dev);
-void minix_put_inode(struct inode *inode)
-{
- inode->i_size = 0;
- minix_truncate(inode);
- minix_free_inode(inode);
-}
-
void minix_put_super(struct super_block *sb)
{
int i;
static struct super_operations minix_sops = {
minix_read_inode,
- minix_write_inode,
- minix_put_inode,
- minix_put_super,
- NULL,
- minix_statfs
+ minix_put_super
};
struct super_block *minix_read_super(struct super_block *s,void *data)
{
struct buffer_head *bh;
- struct minix_super_block *ms;
int i,dev=s->s_dev,block;
lock_super(s);
printk("bread failed\n");
return NULL;
}
- ms = (struct minix_super_block *) bh->b_data;
- s->s_ninodes = ms->s_ninodes;
- s->s_nzones = ms->s_nzones;
- s->s_imap_blocks = ms->s_imap_blocks;
- s->s_zmap_blocks = ms->s_zmap_blocks;
- s->s_firstdatazone = ms->s_firstdatazone;
- s->s_log_zone_size = ms->s_log_zone_size;
- s->s_max_size = ms->s_max_size;
- s->s_magic = ms->s_magic;
+ *((struct minix_super_block *) s) =
+ *((struct minix_super_block *) bh->b_data);
brelse(bh);
if (s->s_magic != MINIX_SUPER_MAGIC) {
s->s_dev = 0;
return s;
}
-void minix_statfs (struct super_block *sb, struct statfs *buf)
-{
- long tmp;
-
- put_fs_long(MINIX_SUPER_MAGIC, &buf->f_type);
- put_fs_long(1024, &buf->f_bsize);
- put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
- tmp = minix_count_free_blocks(sb);
- put_fs_long(tmp, &buf->f_bfree);
- put_fs_long(tmp, &buf->f_bavail);
- put_fs_long(sb->s_ninodes, &buf->f_files);
- put_fs_long(minix_count_free_inodes(sb), &buf->f_ffree);
- /* Don't know what value to put in buf->f_fsid */
-}
-
static int _minix_bmap(struct inode * inode,int block,int create)
{
struct buffer_head * bh;
else for (block = 0; block < 9; block++)
inode->i_data[block] = raw_inode->i_zone[block];
brelse(bh);
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &minix_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &minix_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &minix_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &minix_chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &minix_blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &minix_fifo_inode_operations;
- inode->i_size = 0;
- inode->i_pipe = 1;
- PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
- }
+ inode->i_op = &minix_inode_operations;
}
void minix_write_inode(struct inode * inode)
--- /dev/null
+/*
+ * linux/fs/minix/minix_op.c
+ *
+ * structures for the minix super_block/inode/file-operations
+ */
+
+#include <linux/fs.h>
+#include <linux/minix_fs.h>
+
+void minix_put_inode(struct inode *inode)
+{
+ inode->i_size = 0;
+ minix_truncate(inode);
+ minix_free_inode(inode);
+}
+
+/*
+ * These are the low-level inode operations for minix filesystem inodes.
+ */
+struct inode_operations minix_inode_operations = {
+ minix_create,
+ minix_lookup,
+ minix_link,
+ minix_unlink,
+ minix_symlink,
+ minix_mkdir,
+ minix_rmdir,
+ minix_mknod,
+ minix_rename,
+ minix_readlink,
+ minix_open,
+ minix_release,
+ minix_follow_link,
+ minix_bmap,
+ minix_truncate,
+ minix_write_inode,
+ minix_put_inode
+};
+
+/*
+ * We have mostly NULL's here: the current defaults are ok for
+ * the minix filesystem.
+ */
+struct file_operations minix_file_operations = {
+ NULL, /* lseek - default */
+ minix_file_read, /* read */
+ minix_file_write, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* close - default */
+ NULL, /* select - default */
+ NULL /* ioctl - default */
+};
+
+struct file_operations minix_dir_operations = {
+ NULL, /* lseek - default */
+ minix_file_read, /* read */
+ NULL, /* write - bad */
+ minix_readdir, /* readdir */
+ NULL, /* close - default */
+ NULL, /* select - default */
+ NULL /* ioctl - default */
+};
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
#include <asm/segment.h>
+#include <linux/string.h>
+#include <fcntl.h>
#include <errno.h>
#include <const.h>
+#include <sys/stat.h>
/*
* comment out this line if you want names > MINIX_NAME_LEN chars to be
return NULL;
}
+struct inode * minix_follow_link(struct inode * dir, struct inode * inode)
+{
+ unsigned short fs;
+ struct buffer_head * bh;
+
+ if (!dir) {
+ dir = current->root;
+ dir->i_count++;
+ }
+ if (!inode) {
+ iput(dir);
+ return NULL;
+ }
+ if (!S_ISLNK(inode->i_mode)) {
+ iput(dir);
+ return inode;
+ }
+ __asm__("mov %%fs,%0":"=r" (fs));
+ if ((current->link_count > 5) || !inode->i_data[0] ||
+ !(bh = bread(inode->i_dev, inode->i_data[0]))) {
+ iput(dir);
+ iput(inode);
+ return NULL;
+ }
+ iput(inode);
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ current->link_count++;
+ inode = _namei(bh->b_data,dir,1);
+ current->link_count--;
+ __asm__("mov %0,%%fs"::"r" (fs));
+ brelse(bh);
+ return inode;
+}
+
int minix_lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
{
iput(dir);
return -ENOSPC;
}
- inode->i_op = &minix_file_inode_operations;
inode->i_mode = mode;
inode->i_dirt = 1;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
}
inode->i_uid = current->euid;
inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &minix_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &minix_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &minix_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &minix_chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &minix_blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode)) {
- inode->i_op = &minix_fifo_inode_operations;
- inode->i_size = 0;
- inode->i_pipe = 1;
- PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
- }
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = rdev;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
iput(dir);
return -ENOSPC;
}
- inode->i_op = &minix_dir_inode_operations;
inode->i_size = 2 * sizeof (struct minix_dir_entry);
+ inode->i_dirt = 1;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
return -EIO;
}
return -ENOSPC;
}
inode->i_mode = S_IFLNK | 0777;
- inode->i_op = &minix_symlink_inode_operations;
+ inode->i_dirt = 1;
if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
return -EIO;
}
bh = minix_find_entry(dir,name,len,&de);
if (bh) {
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
brelse(bh);
iput(dir);
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
- inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
old_inode = iget(old_dir->i_dev, old_de->inode);
if (!old_inode)
goto end_rename;
- if ((old_dir->i_mode & S_ISVTX) &&
- current->euid != old_inode->i_uid &&
- current->euid != old_dir->i_uid && !suser())
- goto end_rename;
new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
if (new_bh) {
new_inode = iget(new_dir->i_dev, new_de->inode);
retval = 0;
goto end_rename;
}
- if (S_ISDIR(new_inode->i_mode)) {
- retval = -EEXIST;
- goto end_rename;
- }
if (S_ISDIR(old_inode->i_mode)) {
retval = -EEXIST;
if (new_bh)
/* ok, that's it */
old_de->inode = 0;
new_de->inode = old_inode->i_ino;
- if (new_inode) {
+ if (new_inode)
new_inode->i_nlink--;
- new_inode->i_dirt = 1;
- }
old_bh->b_dirt = 1;
new_bh->b_dirt = 1;
if (dir_bh) {
int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len)
{
- static struct wait_queue * wait = NULL;
+ static struct task_struct * wait = NULL;
static int lock = 0;
int result;
wake_up(&wait);
return result;
}
+
+int minix_readlink(struct inode * inode, char * buffer, int buflen)
+{
+ struct buffer_head * bh;
+ int i;
+ char c;
+
+ if (!S_ISLNK(inode->i_mode)) {
+ iput(inode);
+ return -EINVAL;
+ }
+ if (buflen > 1023)
+ buflen = 1023;
+ if (inode->i_data[0])
+ bh = bread(inode->i_dev, inode->i_data[0]);
+ else
+ bh = NULL;
+ iput(inode);
+ if (!bh)
+ return 0;
+ i = 0;
+ while (i<buflen && (c = bh->b_data[i])) {
+ i++;
+ put_fs_byte(c,buffer++);
+ }
+ brelse(bh);
+ return i;
+}
+++ /dev/null
-/*
- * linux/fs/minix/symlink.c
- *
- * (C) 1991 Linus Torvalds
- *
- * minix symlink handling code
- */
-
-#include <errno.h>
-
-#include <asm/segment.h>
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/stat.h>
-
-static int minix_readlink(struct inode *, char *, int);
-static struct inode * minix_follow_link(struct inode *, struct inode *);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations minix_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- minix_readlink, /* readlink */
- minix_follow_link, /* follow_link */
- NULL, /* bmap */
- NULL /* truncate */
-};
-
-static struct inode * minix_follow_link(struct inode * dir, struct inode * inode)
-{
- unsigned short fs;
- struct buffer_head * bh;
-
- if (!dir) {
- dir = current->root;
- dir->i_count++;
- }
- if (!inode) {
- iput(dir);
- return NULL;
- }
- if (!S_ISLNK(inode->i_mode)) {
- iput(dir);
- return inode;
- }
- __asm__("mov %%fs,%0":"=r" (fs));
- if ((current->link_count > 5) || !inode->i_data[0] ||
- !(bh = bread(inode->i_dev, inode->i_data[0]))) {
- iput(dir);
- iput(inode);
- return NULL;
- }
- iput(inode);
- __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- current->link_count++;
- inode = _namei(bh->b_data,dir,1);
- current->link_count--;
- __asm__("mov %0,%%fs"::"r" (fs));
- brelse(bh);
- return inode;
-}
-
-static int minix_readlink(struct inode * inode, char * buffer, int buflen)
-{
- struct buffer_head * bh;
- int i;
- char c;
-
- if (!S_ISLNK(inode->i_mode)) {
- iput(inode);
- return -EINVAL;
- }
- if (buflen > 1023)
- buflen = 1023;
- if (inode->i_data[0])
- bh = bread(inode->i_dev, inode->i_data[0]);
- else
- bh = NULL;
- iput(inode);
- if (!bh)
- return 0;
- i = 0;
- while (i<buflen && (c = bh->b_data[i])) {
- i++;
- put_fs_byte(c,buffer++);
- }
- brelse(bh);
- return i;
-}
* (C) 1991 Linus Torvalds
*/
-#include <errno.h>
-
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/tty.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
/*
* Truncate has the most races in the whole filesystem: coding it is
{
printk("minix_release not implemented\n");
}
+
+static int check_char_dev(struct inode * inode, struct file * filp)
+{
+ struct tty_struct *tty;
+ int min, dev;
+
+ dev = inode->i_rdev;
+ if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
+ if (MAJOR(dev) == 5)
+ min = current->tty;
+ else
+ min = MINOR(dev);
+ if (min < 0)
+ return -1;
+ if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
+ return -1;
+ tty = TTY_TABLE(min);
+ if (!(filp->f_flags & O_NOCTTY) &&
+ current->leader &&
+ current->tty<0 &&
+ tty->session==0) {
+ current->tty = min;
+ tty->session= current->session;
+ tty->pgrp = current->pgrp;
+ }
+ if (IS_A_SERIAL(min))
+ serial_open(min-64);
+ }
+ return 0;
+}
+
+/*
+ * Called every time a minix-file is opened
+ */
+int minix_open(struct inode * inode, struct file * filp)
+{
+ if (S_ISCHR(inode->i_mode)) {
+ if (check_char_dev(inode,filp))
+ return -EAGAIN;
+ } else if (S_ISBLK(inode->i_mode))
+ check_disk_change(inode->i_rdev);
+ else if (S_ISREG(inode->i_mode))
+ filp->f_op = &minix_file_operations;
+ else if (S_ISDIR(inode->i_mode))
+ filp->f_op = &minix_dir_operations;
+ return 0;
+}
+++ /dev/null
-#
-# Makefile for the linux MS-DOS-filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-.c.s:
- $(CC) $(CFLAGS) \
- -S -o $*.s $<
-.c.o:
- $(CC) $(CFLAGS) -c -o $*.o $<
-.s.o:
- $(AS) -o $*.o $<
-
-OBJS= namei.o inode.o file.o dir.o misc.o fat.o
-
-msdos.o: $(OBJS)
- $(LD) -r -o msdos.o $(OBJS)
-
-clean:
- rm -f core *.o *.a tmp_make
- for i in *.c;do rm -f `basename $$i .c`.s;done
-
-dep:
- sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
- cp tmp_make Makefile
-
-### Dependencies:
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
- /usr/src/linux/include/linux/wait.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-fat.o : fat.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/kernel.h
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
- /usr/src/linux/include/linux/wait.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/msdos_fs.h
-inode.o : inode.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
- /usr/src/linux/include/linux/wait.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h
-misc.o : misc.c /usr/src/linux/include/errno.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/msdos_fs.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-namei.o : namei.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/msdos_fs.h
+++ /dev/null
-/*
- * linux/fs/msdos/dir.c
- *
- * Written 1992 by Werner Almesberger
- *
- * MS-DOS directory handling functions
- */
-
-#include <errno.h>
-#include <asm/segment.h>
-#include <linux/stat.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-
-/* for compatibility warnings */
-#include <linux/sched.h>
-
-static int msdos_dummy_read(struct inode *inode,struct file *filp,char *buf,
- int count);
-static int msdos_readdir(struct inode *inode,struct file *filp,
- struct dirent *dirent,int count);
-
-
-static struct file_operations msdos_dir_operations = {
- NULL, /* lseek - default */
- msdos_dummy_read, /* read */
- NULL, /* write - bad */
- msdos_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open code */
- NULL /* no special release code */
-};
-
-struct inode_operations msdos_dir_inode_operations = {
- &msdos_dir_operations, /* default directory file-ops */
- msdos_create, /* create */
- msdos_lookup, /* lookup */
- NULL, /* link */
- msdos_unlink, /* unlink */
- NULL, /* symlink */
- msdos_mkdir, /* mkdir */
- msdos_rmdir, /* rmdir */
- NULL, /* mknod */
- msdos_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- msdos_bmap, /* bmap */
- NULL /* truncate */
-};
-
-
-/* So grep * doesn't complain in the presence of directories. */
-
-static int msdos_dummy_read(struct inode *inode,struct file *filp,char *buf,
- int count)
-{
- static long last_warning = 0;
-
- if (CURRENT_TIME-last_warning >= 10) {
- printk("COMPATIBILITY WARNING: reading a directory\r\n");
- last_warning = CURRENT_TIME;
- }
- return 0;
-}
-
-
-static int msdos_readdir(struct inode *inode,struct file *filp,
- struct dirent *dirent,int count)
-{
- int ino,i,i2,last;
- char c,*walk;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
-
- if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF;
- if (inode->i_ino == MSDOS_ROOT_INO) {
-/* Fake . and .. for the root directory. */
- if (filp->f_pos == 2) filp->f_pos = 0;
- else if (filp->f_pos < 2) {
- walk = filp->f_pos++ ? ".." : ".";
- for (i = 0; *walk; walk++)
- put_fs_byte(*walk,dirent->d_name+i++);
- put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
- put_fs_byte(0,dirent->d_name+i);
- put_fs_word(i,&dirent->d_reclen);
- return i;
- }
- }
- if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
- bh = NULL;
- while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
- if (de->name[0] && ((unsigned char *) (de->name))[0] !=
- DELETED_FLAG && !(de->attr & ATTR_VOLUME)) {
- for (i = last = 0; i < 8; i++) {
- if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
- if (c != ' ') last = i+1;
- put_fs_byte(c,i+dirent->d_name);
- }
- i = last;
- if (de->ext[0] && de->ext[0] != ' ') {
- put_fs_byte('.',i+dirent->d_name);
- i++;
- for (i2 = 0; i2 < 3; i2++) {
- if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
- put_fs_byte(c,i+dirent->d_name);
- i++;
- if (c != ' ') last = i;
- }
- }
- if (i = last) {
- if (!strcmp(de->name,MSDOS_DOT))
- ino = inode->i_ino;
- else if (!strcmp(de->name,MSDOS_DOTDOT))
- ino = msdos_parent_ino(inode,0);
- put_fs_long(ino,&dirent->d_ino);
- put_fs_byte(0,i+dirent->d_name);
- put_fs_word(i,&dirent->d_reclen);
- brelse(bh);
- return i;
- }
- }
- }
- if (bh) brelse(bh);
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/msdos/fat.c
- *
- * Written 1992 by Werner Almesberger
- */
-
-#include <errno.h>
-#include <linux/stat.h>
-#include <linux/msdos_fs.h>
-#include <linux/kernel.h>
-
-
-static struct fat_cache *fat_cache,cache[FAT_CACHE];
-
-
-/* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
- new_value is != -1, that FAT entry is replaced by it. */
-
-int fat_access(struct super_block *sb,int this,int new_value)
-{
- struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
- unsigned char *p_first,*p_last;
- void *data,*data2,*c_data,*c_data2;
- int first,last,next,copy;
-
- if (MSDOS_SB(sb)->fat_bits == 16) first = last = this*2;
- else {
- first = this*3/2;
- last = first+1;
- }
- if (!(bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
- SECTOR_BITS),&data))) {
- printk("bread in fat_access failed\r\n");
- return 0;
- }
- if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
- bh2 = bh;
- data2 = data;
- }
- else {
- if (!(bh2 = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
- >> SECTOR_BITS),&data2))) {
- brelse(bh);
- printk("bread in fat_access failed\r\n");
- return 0;
- }
- }
- if (MSDOS_SB(sb)->fat_bits == 16) {
- next = ((unsigned short *) data)[(first & (SECTOR_SIZE-1))
- >> 1];
- if (next >= 0xfff8) next = -1;
- }
- else {
- p_first = &((unsigned char *) data)[first & (SECTOR_SIZE-1)];
- p_last = &((unsigned char *) data2)[(first+1) &
- (SECTOR_SIZE-1)];
- if (this & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
- else next = (*p_first+(*p_last << 8)) & 0xfff;
- if (next >= 0xff8) next = -1;
- }
- if (new_value != -1) {
- if (MSDOS_SB(sb)->fat_bits == 16)
- ((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >>
- 1] = new_value;
- else {
- if (this & 1) {
- *p_first = (*p_first & 0xf) | (new_value << 4);
- *p_last = new_value >> 4;
- }
- else {
- *p_first = new_value & 0xff;
- *p_last = (*p_last & 0xf0) | (new_value >> 8);
- }
- bh2->b_dirt = 1;
- }
- bh->b_dirt = 1;
- for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
- if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
- fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
- fat_length*copy,&c_data))) break;
- memcpy(c_data,data,SECTOR_SIZE);
- c_bh->b_dirt = 1;
- if (data != data2 || bh != bh2) {
- if (!(c_bh2 = msdos_sread(sb->s_dev,
- MSDOS_SB(sb)->fat_start+(first >>
- SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy
- +1,&c_data2))) {
- brelse(c_bh);
- break;
- }
- memcpy(c_data2,data2,SECTOR_SIZE);
- brelse(c_bh2);
- }
- brelse(c_bh);
- }
- }
- brelse(bh);
- if (data != data2) brelse(bh2);
- return next;
-}
-
-
-void cache_init(void)
-{
- static int initialized = 0;
- int count;
-
- if (initialized) return;
- fat_cache = &cache[0];
- for (count = 0; count < FAT_CACHE; count++) {
- cache[count].device = 0;
- cache[count].next = count == FAT_CACHE-1 ? NULL :
- &cache[count+1];
- }
- initialized = 1;
-}
-
-
-void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
-{
- struct fat_cache *walk;
-
-#ifdef DEBUG
-printk("cache lookup: %d\r\n",*f_clu);
-#endif
- for (walk = fat_cache; walk; walk = walk->next)
- if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
- walk->file_cluster <= cluster && walk->file_cluster >
- *f_clu) {
- *d_clu = walk->disk_cluster;
-#ifdef DEBUG
-printk("cache hit: %d (%d)\r\n",walk->file_cluster,*d_clu);
-#endif
- if ((*f_clu = walk->file_cluster) == cluster) return;
- }
-}
-
-
-#ifdef DEBUG
-static void list_cache(void)
-{
- struct fat_cache *walk;
-
- for (walk = fat_cache; walk; walk = walk->next) {
- if (walk->device) printk("(%d,%d) ",walk->file_cluster,
- walk->disk_cluster);
- else printk("-- ");
- }
- printk("\r\n");
-}
-#endif
-
-
-void cache_add(struct inode *inode,int f_clu,int d_clu)
-{
- struct fat_cache *walk,*last;
-
-#ifdef DEBUG
-printk("cache add: %d (%d)\r\n",f_clu,d_clu);
-#endif
- last = NULL;
- for (walk = fat_cache; walk->next; walk = (last = walk)->next)
- if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
- walk->file_cluster == f_clu) {
- if (walk->disk_cluster != d_clu)
- panic("FAT cache corruption");
- /* update LRU */
- if (last == NULL) return;
- last->next = walk->next;
- walk->next = fat_cache;
- fat_cache = walk;
-#ifdef DEBUG
-list_cache();
-#endif
- return;
- }
- walk->device = inode->i_dev;
- walk->ino = inode->i_ino;
- walk->file_cluster = f_clu;
- walk->disk_cluster = d_clu;
- last->next = NULL;
- walk->next = fat_cache;
- fat_cache = walk;
-#ifdef DEBUG
-list_cache();
-#endif
-}
-
-
-/* Cache invalidation occurs rarely, thus the LRU chain is not updated. It
- fixes itself after a while. */
-
-void cache_inval_inode(struct inode *inode)
-{
- struct fat_cache *walk;
-
- for (walk = fat_cache; walk; walk = walk->next)
- if (walk->device == inode->i_dev && walk->ino == inode->i_ino)
- walk->device = 0;
-}
-
-
-void cache_inval_dev(int device)
-{
- struct fat_cache *walk;
-
- for (walk = fat_cache; walk; walk = walk->next)
- if (walk->device == device) walk->device = 0;
-}
-
-
-int get_cluster(struct inode *inode,int cluster)
-{
- int this,count;
-
- if (!(this = inode->i_data[D_START])) return 0;
- if (!cluster) return this;
- count = 0;
- for (cache_lookup(inode,cluster,&count,&this); count < cluster;
- count++) {
- if ((this = fat_access(inode->i_sb,this,-1)) == -1) return 0;
- if (!this) return 0;
- }
- cache_add(inode,cluster,this);
- return this;
-}
-
-
-int msdos_smap(struct inode *inode,int sector)
-{
- struct msdos_sb_info *sb;
- int cluster,offset;
-
- sb = MSDOS_SB(inode->i_sb);
- if (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
- !inode->i_data[D_START])) {
- if (sector >= sb->dir_entries >> MSDOS_DPS_BITS) return 0;
- return sector+sb->dir_start;
- }
- cluster = sector/sb->cluster_size;
- offset = sector % sb->cluster_size;
- if (!(cluster = get_cluster(inode,cluster))) return 0;
- return (cluster-2)*sb->cluster_size+sb->data_start+offset;
-}
-
-
-/* Free all clusters after the skip'th cluster. Doesn't use the cache,
- because this way we get an additional sanity check. */
-
-int fat_free(struct inode *inode,int skip)
-{
- int this,last;
-
- if (!(this = inode->i_data[D_START])) return 0;
- last = 0;
- while (skip--) {
- last = this;
- if ((this = fat_access(inode->i_sb,this,-1)) == -1)
- return 0;
- if (!this) {
- printk("fat_free: skipped EOF\r\n");
- return -EIO;
- }
- }
- if (last)
- fat_access(inode->i_sb,last,MSDOS_SB(inode->i_sb)->fat_bits ==
- 12 ? 0xff8 : 0xfff8);
- else {
- inode->i_data[D_START] = 0;
- inode->i_dirt = 1;
- }
- while (this != -1)
- if (!(this = fat_access(inode->i_sb,this,0)))
- panic("fat_free: deleting beyond EOF");
- cache_inval_inode(inode);
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/msdos/file.c
- *
- * Written 1992 by Werner Almesberger
- *
- * MS-DOS regular file handling primitives
- */
-
-#include <errno.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-
-
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-
-
-static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
- int count);
-static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
- int count);
-
-
-static struct file_operations msdos_file_operations = {
- NULL, /* lseek - default */
- msdos_file_read, /* read */
- msdos_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* no special open is needed */
- NULL /* release */
-};
-
-struct inode_operations msdos_file_inode_operations = {
- &msdos_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- msdos_bmap, /* bmap */
- msdos_truncate /* truncate */
-};
-
-/* No bmap for MS-DOS FS' that don't align data at kByte boundaries. */
-
-struct inode_operations msdos_file_inode_operations_no_bmap = {
- &msdos_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- msdos_truncate /* truncate */
-};
-
-
-static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
- int count)
-{
- char *start;
- int left,offset,size,sector,cnt;
- char ch;
- struct buffer_head *bh;
- void *data;
-
-/* printk("msdos_file_read\r\n"); */
- if (!inode) {
- printk("msdos_file_read: inode = NULL\r\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("msdos_file_read: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
- if (filp->f_pos >= inode->i_size || count <= 0) return 0;
- start = buf;
- while (left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) {
- if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
- break;
- offset = filp->f_pos & (SECTOR_SIZE-1);
- if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
- filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
- if (inode->i_data[D_BINARY]) {
- memcpy_tofs(buf,data+offset,size);
- buf += size;
- }
- else for (cnt = size; cnt; cnt--) {
- if ((ch = *((char *) data+offset++)) == '\r')
- size--;
- else {
- if (ch != 26) put_fs_byte(ch,buf++);
- else {
- filp->f_pos = inode->i_size;
- brelse(bh);
- return buf-start;
- }
- }
- }
- brelse(bh);
- }
- if (start == buf) return -EIO;
- return buf-start;
-}
-
-
-static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
- int count)
-{
- int sector,offset,size,left,written;
- int error,carry;
- char *start,*to,ch;
- struct buffer_head *bh;
- void *data;
-
- if (!inode) {
- printk("msdos_file_write: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("msdos_file_write: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
- if (count <= 0) return 0;
- error = carry = 0;
- for (start = buf; count || carry; count -= size) {
- while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
- if ((error = msdos_add_cluster(inode)) < 0) break;
- if (error) break;
- offset = filp->f_pos & (SECTOR_SIZE-1);
- size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
- if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
- error = -EIO;
- break;
- }
- if (inode->i_data[D_BINARY]) {
- memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
- buf,written = size);
- buf += size;
- }
- else {
- written = left = SECTOR_SIZE-offset;
- to = data+(filp->f_pos & (SECTOR_SIZE-1));
- if (carry) {
- *to++ = '\n';
- left--;
- carry = 0;
- }
- for (size = 0; size < count && left; size++) {
- if ((ch = get_fs_byte(buf++)) == '\n') {
- *to++ = '\r';
- left--;
- }
- if (!left) carry = 1;
- else {
- *to++ = ch;
- left--;
- }
- }
- written -= left;
- }
- filp->f_pos += written;
- if (filp->f_pos > inode->i_size) {
- inode->i_size = filp->f_pos;
- inode->i_dirt = 1;
- }
- bh->b_dirt = 1;
- brelse(bh);
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_data[D_ATTRS] |= ATTR_ARCH;
- inode->i_dirt = 1;
- return start == buf ? error : buf-start;
-}
-
-
-void msdos_truncate(struct inode *inode)
-{
- int cluster;
-
- if (!S_ISREG(inode->i_mode)) return;
- cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
- (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
- inode->i_data[D_ATTRS] |= ATTR_ARCH;
- inode->i_dirt = 1;
-}
+++ /dev/null
-/*
- * linux/fs/msdos/inode.c
- *
- * Written 1992 by Werner Almesberger
- */
-
-#include <errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/msdos_fs.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/segment.h>
-
-
-void msdos_put_inode(struct inode *inode)
-{
- struct inode *depend;
-
- inode->i_size = 0;
- msdos_truncate(inode);
- depend = (struct inode *) inode->i_data[D_DEPEND];
- memset(inode,0,sizeof(struct inode));
- if (depend) {
- if ((struct inode *) depend->i_data[D_OLD] != inode) {
- printk("Invalid link (0x%X): expected 0x%X, got "
- "0x%X\r\n",(int) depend,(int) inode,
- depend->i_data[D_OLD]);
- panic("That's fatal");
- }
- depend->i_data[D_OLD] = 0;
- iput(depend);
- }
-}
-
-
-void msdos_put_super(struct super_block *sb)
-{
- cache_inval_dev(sb->s_dev);
- lock_super(sb);
- sb->s_dev = 0;
- free_super(sb);
- return;
-}
-
-
-static struct super_operations msdos_sops = {
- msdos_read_inode,
- msdos_write_inode,
- msdos_put_inode,
- msdos_put_super,
- NULL, /* added in 0.96c */
- msdos_statfs
-};
-
-
-static int parse_options(char *options,char *check,char *conversion)
-{
- char *this,*value;
-
- *check = 'n';
- *conversion = 'b';
- if (!options) return 1;
- for (this = strtok(options,","); this; this = strtok(NULL,",")) {
- if (value = strchr(this,'=')) *value++ = 0;
- if (!strcmp(this,"check") && value) {
- if (value[0] && !value[1] && strchr("rns",*value))
- *check = *value;
- else if (!strcmp(value,"releaxed")) *check = 'r';
- else if (!strcmp(value,"normal")) *check = 'n';
- else if (!strcmp(value,"strict")) *check = 's';
- else return 0;
- }
- else if (!strcmp(this,"conv") && value) {
- if (value[0] && !value[1] && strchr("bta",*value))
- *conversion = *value;
- else if (!strcmp(value,"binary")) *conversion = 'b';
- else if (!strcmp(value,"text")) *conversion = 't';
- else if (!strcmp(value,"auto")) *conversion = 'a';
- else return 0;
- }
- else return 0;
- }
- return 1;
-}
-
-
-/* Read the super block of an MS-DOS FS. */
-
-struct super_block *msdos_read_super(struct super_block *s,void *data)
-{
- struct buffer_head *bh;
- struct msdos_boot_sector *b;
- int data_sectors;
- char check,conversion;
-
- if (!parse_options((char *) data,&check,&conversion)) {
- s->s_dev = 0;
- return NULL;
- }
- cache_init();
- lock_super(s);
- bh = bread(s->s_dev,0);
- free_super(s);
- if (bh == NULL) {
- s->s_dev = 0;
- printk("MSDOS bread failed\r\n");
- return NULL;
- }
- b = (struct msdos_boot_sector *) bh->b_data;
- MSDOS_SB(s)->cluster_size = b->cluster_size;
- MSDOS_SB(s)->fats = b->fats;
- MSDOS_SB(s)->fat_start = b->reserved;
- MSDOS_SB(s)->fat_length = b->fat_length;
- MSDOS_SB(s)->dir_start = b->reserved+b->fats*b->fat_length;
- MSDOS_SB(s)->dir_entries = *((unsigned short *) &b->dir_entries);
- MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+((MSDOS_SB(s)->
- dir_entries << 5) >> 9);
- data_sectors = (*((unsigned short *) &b->sectors) ? *((unsigned short *)
- &b->sectors) : b->total_sect)-MSDOS_SB(s)->data_start;
- MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/b->cluster_size :
- 0;
- MSDOS_SB(s)->fat_bits = MSDOS_SB(s)->clusters > MSDOS_FAT12 ? 16 : 12;
- brelse(bh);
-printk("[MS-DOS FS Rel. alpha.5, FAT %d, check=%c, conv=%c]\r\n",
- MSDOS_SB(s)->fat_bits,check,conversion);
-printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,se=%d,ts=%d]\r\n",
- b->media,MSDOS_SB(s)->cluster_size,MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,
- MSDOS_SB(s)->fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries,
- MSDOS_SB(s)->data_start,*(unsigned short *) &b->sectors,b->total_sect);
- if (!MSDOS_SB(s)->fats || (MSDOS_SB(s)->dir_entries & (MSDOS_DPS-1))
- || !b->cluster_size || MSDOS_SB(s)->clusters+2 > MSDOS_SB(s)->
- fat_length*SECTOR_SIZE*8/MSDOS_SB(s)->fat_bits) {
- s->s_dev = 0;
- printk("Unsupported FS parameters\r\n");
- return NULL;
- }
- if (!MSDOS_CAN_BMAP(MSDOS_SB(s))) printk("No bmap support\r\n");
- s->s_magic = MSDOS_SUPER_MAGIC;
- MSDOS_SB(s)->name_check = check;
- MSDOS_SB(s)->conversion = conversion;
- /* set up enough so that it can read an inode */
- s->s_op = &msdos_sops;
- MSDOS_SB(s)->fs_uid = current->uid;
- MSDOS_SB(s)->fs_gid = current->gid;
- MSDOS_SB(s)->fs_umask = current->umask;
- if (!(s->s_mounted = iget(s->s_dev,MSDOS_ROOT_INO))) {
- s->s_dev = 0;
- printk("get root inode failed\n");
- return NULL;
- }
- return s;
-}
-
-
-void msdos_statfs(struct super_block *sb,struct statfs *buf)
-{
- int cluster_size,free,this;
-
- cluster_size = MSDOS_SB(sb)->cluster_size;
- put_fs_long(sb->s_magic,&buf->f_type);
- put_fs_long(SECTOR_SIZE,&buf->f_bsize);
- put_fs_long(MSDOS_SB(sb)->clusters*cluster_size,&buf->f_blocks);
- free = 0;
- for (this = 2; this < MSDOS_SB(sb)->clusters+2; this++)
- if (!fat_access(sb,this,-1)) free++;
- free *= cluster_size;
- put_fs_long(free,&buf->f_bfree);
- put_fs_long(free,&buf->f_bavail);
- put_fs_long(0,&buf->f_files);
- put_fs_long(0,&buf->f_ffree);
-}
-
-
-int msdos_bmap(struct inode *inode,int block)
-{
- struct msdos_sb_info *sb;
- int cluster,offset;
-
- sb = MSDOS_SB(inode->i_sb);
- if ((sb->cluster_size & 1) || (sb->data_start & 1)) return 0;
- if (inode->i_ino == MSDOS_ROOT_INO) {
- if (sb->dir_start & 1) return 0;
- return (sb->dir_start >> 1)+block;
- }
- cluster = (block*2)/sb->cluster_size;
- offset = (block*2) % sb->cluster_size;
- if (!(cluster = get_cluster(inode,cluster))) return 0;
- return ((cluster-2)*sb->cluster_size+sb->data_start+offset) >> 1;
-}
-
-
-void msdos_read_inode(struct inode *inode)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *raw_entry;
- int this;
-
-/* printk("read inode %d\r\n",inode->i_ino); */
- inode->i_data[D_BUSY] = inode->i_data[D_DEPEND] =
- inode->i_data[D_OLD] = 0;
- inode->i_data[D_BINARY] = 1;
- inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
- inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
- if (inode->i_ino == MSDOS_ROOT_INO) {
- inode->i_mode = (0777 & ~MSDOS_SB(inode->i_sb)->fs_umask) |
- S_IFDIR;
- inode->i_op = &msdos_dir_inode_operations;
- inode->i_nlink = 1;
- inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries*
- sizeof(struct msdos_dir_entry);
- inode->i_data[D_START] = 0;
- inode->i_data[D_ATTRS] = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
- return;
- }
- if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS)))
- panic("unable to read i-node block");
- raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
- [inode->i_ino & (MSDOS_DPB-1)];
- if (raw_entry->attr & ATTR_DIR) {
- inode->i_mode = MSDOS_MKMODE(raw_entry->attr,0777 &
- ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR;
- inode->i_op = &msdos_dir_inode_operations;
- inode->i_nlink = 3;
- inode->i_size = 0;
- for (this = raw_entry->start; this && this != -1; this =
- fat_access(inode->i_sb,this,-1))
- inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->i_sb)->
- cluster_size;
- }
- else {
- inode->i_mode = MSDOS_MKMODE(raw_entry->attr,0666 &
- ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG;
- inode->i_op = MSDOS_CAN_BMAP(MSDOS_SB(inode->i_sb)) ?
- &msdos_file_inode_operations :
- &msdos_file_inode_operations_no_bmap;
- inode->i_nlink = 1;
- inode->i_size = raw_entry->size;
- }
- inode->i_data[D_BINARY] = is_binary(MSDOS_SB(inode->i_sb)->conversion,
- raw_entry->ext);
- inode->i_data[D_START] = raw_entry->start;
- inode->i_data[D_ATTRS] = raw_entry->attr & ATTR_UNUSED;
- inode->i_mtime = inode->i_atime = inode->i_ctime =
- date_dos2unix(raw_entry->time,raw_entry->date);
- brelse(bh);
-}
-
-
-void msdos_write_inode(struct inode *inode)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *raw_entry;
-
- inode->i_dirt = 0;
- if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
- if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS)))
- panic("unable to read i-node block");
- raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
- [inode->i_ino & (MSDOS_DPB-1)];
- if (S_ISDIR(inode->i_mode)) {
- raw_entry->attr = ATTR_DIR;
- raw_entry->size = 0;
- }
- else {
- raw_entry->attr = ATTR_NONE;
- raw_entry->size = inode->i_size;
- }
- raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) | inode->i_data[D_ATTRS];
- raw_entry->start = inode->i_data[D_START];
- date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
- bh->b_dirt = 1;
- brelse(bh);
-}
+++ /dev/null
-/*
- * linux/fs/msdos/misc.c
- *
- * Written 1992 by Werner Almesberger
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/msdos_fs.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-
-static char bin_extensions[] =
- "EXECOMAPPSYSOVLOBJLIB" /* program code */
- "ARCZIPLHALZHZOOTARZ ARJ" /* common archivers */
- "GIFBMPTIFGL JPG" /* graphics */
- "TFMVF GF PK PXLDVI"; /* TeX */
-
-
-/* Select binary/text conversion */
-
-int is_binary(char conversion,char *extension)
-{
- char *walk;
-
- switch (conversion) {
- case 'b':
- return 1;
- case 't':
- return 0;
- case 'a':
- for (walk = bin_extensions; *walk; walk += 3)
- if (!strncmp(extension,walk,3)) return 1;
- return 0;
- default:
- panic("Invalid conversion mode");
- }
-}
-
-
-static struct wait_queue *creation_wait = NULL;
-static creation_lock = 0;
-
-
-void lock_creation(void)
-{
- while (creation_lock) sleep_on(&creation_wait);
- creation_lock = 1;
-}
-
-
-void unlock_creation(void)
-{
- creation_lock = 0;
- wake_up(&creation_wait);
-}
-
-
-int msdos_add_cluster(struct inode *inode)
-{
- static struct wait_queue *wait = NULL;
- static int lock = 0;
- static int previous = 0; /* works best if one FS is being used */
- int count,this,limit,last,current,sector;
- void *data;
- struct buffer_head *bh;
-
- if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
- while (lock) sleep_on(&wait);
- lock = 1;
- limit = MSDOS_SB(inode->i_sb)->clusters;
- this = limit; /* to keep GCC happy */
- for (count = 0; count < limit; count++) {
- this = ((count+previous) % limit)+2;
- if (fat_access(inode->i_sb,this,-1) == 0) break;
- }
-#ifdef DEBUG
-printk("free cluster: %d\r\n",this);
-#endif
- previous = (count+previous+1) % limit;
- if (count >= limit) {
- lock = 0;
- wake_up(&wait);
- return -ENOSPC;
- }
- fat_access(inode->i_sb,this,MSDOS_SB(inode->i_sb)->fat_bits == 12 ?
- 0xff8 : 0xfff8);
- lock = 0;
- wake_up(&wait);
-#ifdef DEBUG
-printk("set to %x\r\n",fat_access(inode->i_sb,this,-1));
-#endif
- if (!S_ISDIR(inode->i_mode)) {
- last = inode->i_size ? get_cluster(inode,(inode->i_size-1)/
- SECTOR_SIZE/MSDOS_SB(inode->i_sb)->cluster_size) : 0;
- }
- else {
- last = 0;
- if (current = inode->i_data[D_START]) {
- cache_lookup(inode,INT_MAX,&last,¤t);
- while (current && current != -1)
- if (!(current = fat_access(inode->i_sb,
- last = current,-1)))
- panic("File without EOF");
- }
- }
-#ifdef DEBUG
-printk("last = %d\r\n",last);
-#endif
- if (last) fat_access(inode->i_sb,last,this);
- else {
- inode->i_data[D_START] = this;
- inode->i_dirt = 1;
- }
-#ifdef DEBUG
-if (last) printk("next set to %d\r\n",fat_access(inode->i_sb,last,-1));
-#endif
- for (current = 0; current < MSDOS_SB(inode->i_sb)->cluster_size;
- current++) {
- sector = MSDOS_SB(inode->i_sb)->data_start+(this-2)*
- MSDOS_SB(inode->i_sb)->cluster_size+current;
-#ifdef DEBUG
-printk("zeroing sector %d\r\n",sector);
-#endif
- if (current < MSDOS_SB(inode->i_sb)->cluster_size-1 &&
- !(sector & 1)) {
- if (!(bh = getblk(inode->i_dev,sector >> 1)))
- printk("getblk failed\r\n");
- else {
- memset(bh->b_data,0,BLOCK_SIZE);
- bh->b_uptodate = 1;
- }
- current++;
- }
- else {
- if (!(bh = msdos_sread(inode->i_dev,sector,&data)))
- printk("msdos_sread failed\r\n");
- else memset(data,0,SECTOR_SIZE);
- }
- if (bh) {
- bh->b_dirt = 1;
- brelse(bh);
- }
- }
- if (S_ISDIR(inode->i_mode)) {
- if (inode->i_size & (SECTOR_SIZE-1))
- panic("Odd directory size");
- inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->i_sb)->
- cluster_size;
-#ifdef DEBUG
-printk("size is %d now (%x)\r\n",inode->i_size,inode);
-#endif
- inode->i_dirt = 1;
- }
- return 0;
-}
-
-
-/* Linear day numbers of the respective 1sts in non-leap years. */
-
-static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
- /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
-
-
-/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-
-int date_dos2unix(unsigned short time,unsigned short date)
-{
- int month,year;
-
- month = ((date >> 5) & 4)-1;
- year = date >> 9;
- return (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
- ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
- month < 2 ? 1 : 0)+3653);
- /* days since 1.1.70 plus 80's leap day */
-}
-
-
-/* Convert linear UNIX date to a MS-DOS time/date pair. */
-
-void date_unix2dos(int unix_date,unsigned short *time,
- unsigned short *date)
-{
- int day,year,nl_day,month;
-
- *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
- (((unix_date/3600) % 24) << 11);
- day = unix_date/86400-3652;
- year = day/365;
- if ((year+3)/4+365*year > day) year--;
- day -= (year+3)/4+365*year;
- if (day == 59 && !(year & 3)) {
- nl_day = day;
- month = 2;
- }
- else {
- nl_day = (year & 3) || day <= 59 ? day : day-1;
- for (month = 0; month < 12; month++)
- if (day_n[month] > nl_day) break;
- }
- *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
-}
-
-
-/* Returns the inode number of the directory entry at offset pos. If bh is
- non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
- returned in bh. */
-
-int msdos_get_entry(struct inode *dir,int *pos,struct buffer_head **bh,
- struct msdos_dir_entry **de)
-{
- int sector,offset;
- void *data;
-
- while (1) {
- offset = *pos;
- if ((sector = msdos_smap(dir,*pos >> SECTOR_BITS)) == -1)
- return -1;
- if (!sector) return -1; /* FAT error ... */
- *pos += sizeof(struct msdos_dir_entry);
- if (*bh) brelse(*bh);
- if (!(*bh = msdos_sread(dir->i_dev,sector,&data))) continue;
- *de = (struct msdos_dir_entry *) (data+(offset &
- (SECTOR_SIZE-1)));
- return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
- MSDOS_DIR_BITS);
- }
-}
-
-
-/* Scans a directory for a given file (name points to its formatted name) or
- for an empty directory slot (name is NULL). Returns the inode number. */
-
-int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh,
- struct msdos_dir_entry **res_de,int *ino)
-{
- int pos;
- struct msdos_dir_entry *de;
- struct inode *inode;
-
- pos = 0;
- *res_bh = NULL;
- while ((*ino = msdos_get_entry(dir,&pos,res_bh,&de)) > -1) {
- if (name) {
- if (de->name[0] && ((unsigned char *) (de->name))[0]
- != DELETED_FLAG && !(de->attr & ATTR_VOLUME) &&
- !strncmp(de->name,name,MSDOS_NAME)) break;
- }
- else if (!de->name[0] || ((unsigned char *) (de->name))[0] ==
- DELETED_FLAG) {
- if (!(inode = iget(dir->i_dev,*ino))) break;
- if (!inode->i_data[D_BUSY]) {
- iput(inode);
- break;
- }
- /* skip deleted files that haven't been closed yet */
- iput(inode);
- }
- }
- if (*ino == -1) {
- if (*res_bh) brelse(*res_bh);
- *res_bh = NULL;
- return name ? -ENOENT : -ENOSPC;
- }
- *res_de = de;
- return 0;
-}
-
-
-/* Now an ugly part: this set of directory scan routines works on clusters
- rather than on inodes and sectors. They are necessary to locate the '..'
- directory "inode". */
-
-
-static int raw_found(struct super_block *sb,int sector,char *name,int number,
- int *ino)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *data;
- int entry,start;
-
- if (!(bh = msdos_sread(sb->s_dev,sector,(void **) &data))) return -EIO;
- for (entry = 0; entry < MSDOS_DPS; entry++)
- if (name ? !strncmp(data[entry].name,name,MSDOS_NAME) :
- *(unsigned char *) data[entry].name != DELETED_FLAG &&
- data[entry].start == number) {
- if (ino) *ino = sector*MSDOS_DPS+entry;
- start = data[entry].start;
- brelse(bh);
- return start;
- }
- brelse(bh);
- return -1;
-}
-
-
-static int raw_scan_root(struct super_block *sb,char *name,int number,int *ino)
-{
- int count,cluster;
-
- for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
- if ((cluster = raw_found(sb,MSDOS_SB(sb)->dir_start+count,name,
- number,ino)) >= 0) return cluster;
- }
- return -ENOENT;
-}
-
-
-static int raw_scan_nonroot(struct super_block *sb,int start,char *name,
- int number,int *ino)
-{
- int count,cluster;
-
- do {
- for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
- if ((cluster = raw_found(sb,(start-2)*MSDOS_SB(sb)->
- cluster_size+MSDOS_SB(sb)->data_start+count,name,
- number,ino)) >= 0) return cluster;
- }
- if (!(start = fat_access(sb,start,-1))) panic("FAT error");
- }
- while (start != -1);
- return -ENOENT;
-}
-
-
-static int raw_scan(struct super_block *sb,int start,char *name,int number,
- int *ino)
-{
- if (start) return raw_scan_nonroot(sb,start,name,number,ino);
- else return raw_scan_root(sb,name,number,ino);
-}
-
-
-int msdos_parent_ino(struct inode *dir,int locked)
-{
- int error,current,prev,this;
-
- if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i");
- if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
- if (!locked) lock_creation(); /* prevent renames */
- if ((current = raw_scan(dir->i_sb,dir->i_data[D_START],MSDOS_DOTDOT,0,
- NULL)) < 0) {
- if (!locked) unlock_creation();
- return current;
- }
- if (!current) this = MSDOS_ROOT_INO;
- else {
- if ((prev = raw_scan(dir->i_sb,current,MSDOS_DOTDOT,0,NULL)) <
- 0) {
- if (!locked) unlock_creation();
- return prev;
- }
- if ((error = raw_scan(dir->i_sb,prev,NULL,current,&this)) < 0) {
- if (!locked) unlock_creation();
- return error;
- }
- }
- if (!locked) unlock_creation();
- return this;
-}
+++ /dev/null
-/*
- * linux/fs/msdos/namei.c
- *
- * Written 1992 by Werner Almesberger
- */
-
-#include <errno.h>
-#include <asm/segment.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/msdos_fs.h>
-#include <linux/kernel.h>
-
-
-/* MS-DOS "device special files" */
-
-static char *reserved_names[] = {
- "CON ","PRN ","NUL ","AUX ",
- "LPT1 ","LPT2 ","LPT3 ","LPT4 ",
- "COM1 ","COM2 ","COM3 ","COM4 ",
- NULL };
-
-
-/* Formats an MS-DOS file name. Rejects invalid names. */
-
-static int msdos_format_name(char conv,const char *name,int len,char *res)
-{
- char *walk,**reserved;
- char c;
- int space;
-
- if (get_fs_byte(name) == DELETED_FLAG) return -EINVAL;
- if (get_fs_byte(name) == '.' && (len == 1 || (len == 2 &&
- get_fs_byte(name+1) == '.'))) {
- memset(res+1,' ',10);
- while (len--) *res++ = '.';
- return 0;
- }
- space = 0; /* to make GCC happy */
- c = 0;
- for (walk = res; len && walk-res < 8; walk++) {
- c = get_fs_byte(name++);
- len--;
- if (c == ' ' && conv != 'r') return -EINVAL;
- if (c >= 'A' && c <= 'Z') {
- if (conv != 'r') return -EINVAL;
- c += 32;
- }
- if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
- if (c == '.') break;
- space = c == ' ';
- *walk = c >= 'a' && c <= 'z' ? c-32 : c;
- }
- if (space) return -EINVAL;
- if (conv == 's' && len && c != '.') {
- c = get_fs_byte(name++);
- len--;
- if (c != '.') return -EINVAL;
- }
- while (c != '.' && len--) c = get_fs_byte(name++);
- if (walk == res) return -EINVAL;
- if (c == '.') {
- while (walk-res < 8) *walk++ = ' ';
- while (len > 0 && walk-res < MSDOS_NAME) {
- c = get_fs_byte(name++);
- len--;
- if (c == ' ' && conv != 'r') return -EINVAL;
- if (c < ' ' || c == ':' || c == '\\' || c == '.')
- return -EINVAL;
- if (c >= 'A' && c <= 'Z') {
- if (conv != 'r') return -EINVAL;
- c += 32;
- }
- space = c == ' ';
- *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
- }
- if (space) return -EINVAL;
- if (conv == 's' && len) return -EINVAL;
- }
- while (walk-res < MSDOS_NAME) *walk++ = ' ';
- for (reserved = reserved_names; *reserved; reserved++)
- if (!strncmp(res,*reserved,8)) return -EINVAL;
- return 0;
-}
-
-
-/* Locates a directory entry. */
-
-static int msdos_find(struct inode *dir,const char *name,int len,
- struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
-{
- char msdos_name[MSDOS_NAME];
- int res;
-
- if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
- msdos_name)) < 0) return res;
- return msdos_scan(dir,msdos_name,bh,de,ino);
-}
-
-
-int msdos_lookup(struct inode *dir,const char *name,int len,
- struct inode **result)
-{
- int ino,res;
- struct msdos_dir_entry *de;
- struct buffer_head *bh;
- struct inode *next;
-
- *result = NULL;
- if (!dir) return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- if (len == 1 && get_fs_byte(name) == '.') {
- *result = dir;
- return 0;
- }
- if (len == 2 && get_fs_byte(name) == '.' && get_fs_byte(name+1) == '.')
- {
- ino = msdos_parent_ino(dir,0);
- iput(dir);
- if (ino < 0) return ino;
- if (!(*result = iget(dir->i_dev,ino))) return -EACCES;
- return 0;
- }
- if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) {
- iput(dir);
- return res;
- }
- if (bh) brelse(bh);
-/* printk("lookup: ino=%d\r\n",ino); */
- if (!(*result = iget(dir->i_dev,ino))) {
- iput(dir);
- return -EACCES;
- }
- if ((*result)->i_data[D_BUSY]) { /* mkdir in progress */
- iput(*result);
- iput(dir);
- return -ENOENT;
- }
- while ((*result)->i_data[D_OLD]) {
- next = (struct inode *) ((*result)->i_data[D_OLD]);
- iput(*result);
- if (!(*result = iget(next->i_dev,next->i_ino)))
- panic("msdos_lookup: Can't happen");
- }
- iput(dir);
- return 0;
-}
-
-
-/* Creates a directory entry (name is already formatted). */
-
-static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
- struct inode **result)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
- int res,ino;
-
- if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) {
- if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
- if ((res = msdos_add_cluster(dir)) < 0) return res;
- if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res;
- }
- memcpy(de->name,name,MSDOS_NAME);
- de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
- de->start = 0;
- date_unix2dos(CURRENT_TIME,&de->time,&de->date);
- de->size = 0;
- bh->b_dirt = 1;
- if (*result = iget(dir->i_dev,ino)) msdos_read_inode(*result);
- brelse(bh);
- if (!*result) return -EIO;
- (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
- CURRENT_TIME;
- (*result)->i_dirt = 1;
- return 0;
-}
-
-
-int msdos_create(struct inode *dir,const char *name,int len,int mode,
- struct inode **result)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
- char msdos_name[MSDOS_NAME];
- int ino,res;
-
- if (!dir) return -ENOENT;
- if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
- msdos_name)) < 0) {
- iput(dir);
- return res;
- }
- lock_creation();
- if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
- unlock_creation();
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),result);
- unlock_creation();
- iput(dir);
- return res;
-}
-
-
-int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
-{
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
- struct inode *inode,*dot;
- char msdos_name[MSDOS_NAME];
- int ino,res;
-
- if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
- msdos_name)) < 0) {
- iput(dir);
- return res;
- }
- lock_creation();
- if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
- unlock_creation();
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- if ((res = msdos_create_entry(dir,msdos_name,1,&inode)) < 0) {
- unlock_creation();
- iput(dir);
- return res;
- }
- inode->i_data[D_BUSY] = 1; /* prevent lookups */
- if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
- if ((res = msdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0)
- goto mkdir_error;
- dot->i_size = inode->i_size;
- dot->i_data[D_START] = inode->i_data[D_START];
- dot->i_dirt = 1;
- iput(dot);
- if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,&dot)) < 0)
- goto mkdir_error;
- unlock_creation();
- dot->i_size = dir->i_size;
- dot->i_data[D_START] = dir->i_data[D_START];
- dot->i_dirt = 1;
- inode->i_data[D_BUSY] = 0;
- iput(dot);
- iput(inode);
- iput(dir);
- return 0;
-mkdir_error:
- iput(inode);
- if (msdos_rmdir(dir,name,len) < 0) panic("rmdir in mkdir failed");
- unlock_creation();
- return res;
-}
-
-
-int msdos_rmdir(struct inode *dir,const char *name,int len)
-{
- int res,ino,pos;
- struct buffer_head *bh,*dbh;
- struct msdos_dir_entry *de,*dde;
- struct inode *inode;
-
- bh = NULL;
- inode = NULL;
- res = -EINVAL;
- if (len == 1 && get_fs_byte(name) == '.') goto rmdir_done;
- if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
- res = -ENOENT;
- if (!(inode = iget(dir->i_dev,ino))) goto rmdir_done;
- res = -ENOTDIR;
- if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
- res = -EBUSY;
- if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done;
- if (inode->i_count > 1) goto rmdir_done;
- res = -ENOTEMPTY;
- pos = 0;
- dbh = NULL;
- while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1)
- if (dde->name[0] && ((unsigned char *) dde->name)[0] !=
- DELETED_FLAG && strncmp(dde->name,MSDOS_DOT,MSDOS_NAME) &&
- strncmp(dde->name,MSDOS_DOTDOT,MSDOS_NAME)) goto rmdir_done;
- if (dbh) brelse(dbh);
- inode->i_nlink = 0;
- dir->i_mtime = CURRENT_TIME;
- inode->i_dirt = dir->i_dirt = 1;
- de->name[0] = DELETED_FLAG;
- bh->b_dirt = 1;
- res = 0;
-rmdir_done:
- brelse(bh);
- iput(dir);
- iput(inode);
- return res;
-}
-
-
-int msdos_unlink(struct inode *dir,const char *name,int len)
-{
- int res,ino;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
- struct inode *inode;
-
- bh = NULL;
- inode = NULL;
- if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
- goto unlink_done;
- if (!(inode = iget(dir->i_dev,ino))) {
- res = -ENOENT;
- goto unlink_done;
- }
- if (!S_ISREG(inode->i_mode)) {
- res = -EPERM;
- goto unlink_done;
- }
- inode->i_nlink = 0;
- inode->i_data[D_BUSY] = 1;
- inode->i_dirt = 1;
- de->name[0] = DELETED_FLAG;
- bh->b_dirt = 1;
-unlink_done:
- brelse(bh);
- iput(inode);
- iput(dir);
- return res;
-}
-
-
-static int rename_same_dir(struct inode *old_dir,char *old_name,
- struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
- struct msdos_dir_entry *old_de,int old_ino)
-{
- struct buffer_head *new_bh;
- struct msdos_dir_entry *new_de;
- struct inode *new_inode,*old_inode;
- int new_ino;
- int exists;
-
- if (!strncmp(old_name,new_name,MSDOS_NAME)) return 0;
- exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
- if (*(unsigned char *) old_de->name == DELETED_FLAG) {
- if (exists) brelse(new_bh);
- return -ENOENT;
- }
- if (exists) {
- if (!(new_inode = iget(new_dir->i_dev,new_ino))) {
- brelse(new_bh);
- return -EIO;
- }
- if (S_ISDIR(new_inode->i_mode)) {
- iput(new_inode);
- brelse(new_bh);
- return -EPERM;
- }
- new_inode->i_nlink = 0;
- new_inode->i_data[D_BUSY] = 1;
- new_inode->i_dirt = 1;
- new_de->name[0] = DELETED_FLAG;
- new_bh->b_dirt = 1;
- iput(new_inode);
- brelse(new_bh);
- }
- memcpy(old_de->name,new_name,MSDOS_NAME);
- old_bh->b_dirt = 1;
- if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
- if (old_inode = iget(old_dir->i_dev,old_ino)) {
- msdos_read_inode(old_inode);
- iput(old_inode);
- }
- return 0;
-}
-
-
-static int rename_diff_dir(struct inode *old_dir,char *old_name,
- struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
- struct msdos_dir_entry *old_de,int old_ino)
-{
- struct buffer_head *new_bh,*free_bh,*dotdot_bh;
- struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
- struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
- int new_ino,free_ino,dotdot_ino;
- int error,exists,ino;
-
- if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
- if (old_ino == new_dir->i_ino) return -EINVAL;
- if (!(walk = iget(new_dir->i_dev,new_dir->i_ino))) return -EIO;
- while (walk->i_ino != MSDOS_ROOT_INO) {
- ino = msdos_parent_ino(walk,1);
- iput(walk);
- if (ino < 0) return ino;
- if (ino == old_ino) return -EINVAL;
- if (!(walk = iget(new_dir->i_dev,ino))) return -EIO;
- }
- iput(walk);
- if ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) < 0)
- return error;
- exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)
- >= 0;
- if (!(old_inode = iget(old_dir->i_dev,old_ino))) {
- brelse(free_bh);
- if (exists) brelse(new_bh);
- return -EIO;
- }
- if (*(unsigned char *) old_de->name == DELETED_FLAG) {
- iput(old_inode);
- brelse(free_bh);
- if (exists) brelse(new_bh);
- return -ENOENT;
- }
- new_inode = NULL; /* to make GCC happy */
- if (exists) {
- if (!(new_inode = iget(new_dir->i_dev,new_ino))) {
- iput(old_inode);
- brelse(new_bh);
- return -EIO;
- }
- if (S_ISDIR(new_inode->i_mode)) {
- iput(new_inode);
- iput(old_inode);
- brelse(new_bh);
- return -EPERM;
- }
- new_inode->i_nlink = 0;
- new_inode->i_data[D_BUSY] = 1;
- new_inode->i_dirt = 1;
- new_de->name[0] = DELETED_FLAG;
- new_bh->b_dirt = 1;
- }
- memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
- memcpy(free_de->name,new_name,MSDOS_NAME);
- if (!(free_inode = iget(new_dir->i_dev,free_ino))) {
- free_de->name[0] = DELETED_FLAG;
-/* Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
- brelse(free_bh);
- if (exists) {
- iput(new_inode);
- brelse(new_bh);
- }
- return -EIO;
- }
- msdos_read_inode(free_inode);
- old_inode->i_data[D_BUSY] = 1;
- old_inode->i_dirt = 1;
- old_de->name[0] = DELETED_FLAG;
- old_bh->b_dirt = 1;
- free_bh->b_dirt = 1;
- if (!exists) iput(free_inode);
- else {
- new_inode->i_data[D_DEPEND] = (int) free_inode;
- free_inode->i_data[D_OLD] = (int) new_inode;
- /* free_inode is put when putting new_inode */
- iput(new_inode);
- brelse(new_bh);
- }
- if (S_ISDIR(old_inode->i_mode)) {
- if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
- &dotdot_de,&dotdot_ino)) < 0) goto rename_done;
- if (!(dotdot_inode = iget(old_inode->i_dev,dotdot_ino))) {
- brelse(dotdot_bh);
- error = -EIO;
- goto rename_done;
- }
- dotdot_de->start = dotdot_inode->i_data[D_START] =
- new_dir->i_data[D_START];
- dotdot_inode->i_dirt = 1;
- dotdot_bh->b_dirt = 1;
- iput(dotdot_inode);
- brelse(dotdot_bh);
- }
- error = 0;
-rename_done:
- brelse(free_bh);
- iput(old_inode);
- return error;
-}
-
-
-int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
- struct inode *new_dir,const char *new_name,int new_len)
-{
- char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
- struct buffer_head *old_bh;
- struct msdos_dir_entry *old_de;
- int old_ino,error;
-
- if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
- old_name,old_len,old_msdos_name)) < 0) goto rename_done;
- if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
- new_name,new_len,new_msdos_name)) < 0) goto rename_done;
- if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
- &old_ino)) < 0) goto rename_done;
- lock_creation();
- if (old_dir == new_dir)
- error = rename_same_dir(old_dir,old_msdos_name,new_dir,
- new_msdos_name,old_bh,old_de,old_ino);
- else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
- new_msdos_name,old_bh,old_de,old_ino);
- unlock_creation();
- brelse(old_bh);
-rename_done:
- iput(old_dir);
- iput(new_dir);
- return error;
-}
* Some corrections by tytso.
*/
-#include <errno.h>
-#include <const.h>
-
-#include <asm/segment.h>
-
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <asm/segment.h>
+
#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <const.h>
+#include <sys/stat.h>
struct inode * _namei(const char * filename, struct inode * base,
int follow_links);
inode = follow_link(base,inode);
else
iput(base);
+ if (inode) {
+ inode->i_atime=CURRENT_TIME;
+ inode->i_dirt=1;
+ }
return inode;
}
struct inode ** res_inode)
{
const char * basename;
- int namelen,error,i;
+ int namelen,error;
struct inode * dir, *inode;
- struct task_struct ** p;
if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
flag |= O_WRONLY;
- mode &= 07777 & ~current->umask;
+ mode &= 0777 & ~current->umask;
mode |= I_REGULAR;
if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
return -ENOENT;
iput(dir);
return -EACCES;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
return dir->i_op->create(dir,basename,namelen,mode,res_inode);
}
if (flag & O_EXCL) {
}
if (!(inode = follow_link(dir,inode)))
return -ELOOP;
- if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
- if (IS_NODEV(inode)) {
- iput(inode);
- return -EACCES;
- }
- } else {
- if (IS_RDONLY(inode) && (flag & (O_TRUNC | O_ACCMODE))) {
- iput(inode);
- return -EROFS;
- }
- }
if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
!permission(inode,ACC_MODE(flag))) {
iput(inode);
return -EPERM;
}
- if ((inode->i_count > 1) && (flag & O_ACCMODE))
- for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
- if (!*p)
- continue;
- if (inode == (*p)->executable) {
- iput(inode);
- return -ETXTBSY;
- }
- for (i=0; i < (*p)->numlibraries; i++)
- if (inode == (*p)->libraries[i].library) {
- iput(inode);
- return -ETXTBSY;
- }
- }
+ inode->i_atime = CURRENT_TIME;
if (flag & O_TRUNC)
if (inode->i_op && inode->i_op->truncate) {
inode->i_size = 0;
inode->i_op->truncate(inode);
}
- if (!IS_RDONLY(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
*res_inode = inode;
return 0;
}
-int do_mknod(const char * filename, int mode, int dev)
+int sys_mknod(const char * filename, int mode, int dev)
{
const char * basename;
int namelen;
struct inode * dir;
+ if (!suser())
+ return -EPERM;
if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
return -ENOENT;
if (!namelen) {
iput(dir);
return -ENOENT;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
return dir->i_op->mknod(dir,basename,namelen,mode,dev);
}
-int sys_mknod(const char * filename, int mode, int dev)
-{
- if (S_ISFIFO(mode) || suser())
- return do_mknod(filename,mode,dev);
- return -EPERM;
-}
-
int sys_mkdir(const char * pathname, int mode)
{
const char * basename;
iput(dir);
return -ENOENT;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
iput(dir);
return -ENOENT;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
iput(dir);
return -EPERM;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
iput(dir);
return -ENOENT;
}
- if (IS_RDONLY(dir)) {
- iput(dir);
- return -EROFS;
- }
if (!permission(dir,MAY_WRITE)) {
iput(dir);
return -EACCES;
iput(dir);
return -EPERM;
}
- if (IS_RDONLY(dir)) {
- iput(oldinode);
- iput(dir);
- return -EROFS;
- }
if (dir->i_dev != oldinode->i_dev) {
iput(dir);
iput(oldinode);
iput(new_dir);
return -EXDEV;
}
- if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
- iput(old_dir);
- iput(new_dir);
- return -EROFS;
- }
if (!old_dir->i_op || !old_dir->i_op->rename) {
iput(old_dir);
iput(new_dir);
*/
#include <errno.h>
+#include <fcntl.h>
#include <sys/types.h>
#include <utime.h>
+#include <sys/stat.h>
#include <sys/vfs.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
int sys_statfs(const char * path, struct statfs * buf)
{
- struct inode * inode;
-
- verify_area(buf, sizeof(struct statfs));
- if (!(inode = namei(path)))
- return -ENOENT;
- if (!inode->i_sb->s_op->statfs) {
- iput(inode);
- return -ENOSYS;
- }
- inode->i_sb->s_op->statfs(inode->i_sb, buf);
- iput(inode);
- return 0;
+ printk("statfs not implemented\n");
+ return -ENOSYS;
}
int sys_fstatfs(unsigned int fd, struct statfs * buf)
{
- struct inode * inode;
- struct file * file;
-
- verify_area(buf, sizeof(struct statfs));
- if (fd >= NR_OPEN || !(file = current->filp[fd]))
- return -EBADF;
- if (!(inode = file->f_inode))
- return -ENOENT;
- if (!inode->i_sb->s_op->statfs)
- return -ENOSYS;
- inode->i_sb->s_op->statfs(inode->i_sb, buf);
- return 0;
+ printk("fstatfs not implemented\n");
+ return -ENOSYS;
}
int sys_truncate(const char * path, unsigned int length)
if (!(inode = namei(path)))
return -ENOENT;
- if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
+ if (!permission(inode,MAY_WRITE)) {
iput(inode);
- return -EACCES;
- }
- if (IS_RDONLY(inode)) {
- iput(inode);
- return -EROFS;
+ return -EPERM;
}
inode->i_size = length;
if (inode->i_op && inode->i_op->truncate)
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
- if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
- return -EACCES;
+ if (!(file->f_flags & 2))
+ return -EPERM;
inode->i_size = length;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
return 0;
}
-/* If times==NULL, set access and modification to current time,
- * must be owner or have write permission.
- * Else, update from *times, must be owner or super user.
- */
int sys_utime(char * filename, struct utimbuf * times)
{
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
- if (IS_RDONLY(inode)) {
- iput(inode);
- return -EROFS;
- }
if (times) {
- if ((current->euid != inode->i_uid) && !suser()) {
+ if (current->euid != inode->i_uid &&
+ !permission(inode,MAY_WRITE)) {
iput(inode);
return -EPERM;
}
actime = get_fs_long((unsigned long *) ×->actime);
modtime = get_fs_long((unsigned long *) ×->modtime);
- } else {
- if ((current->euid != inode->i_uid) &&
- !permission(inode,MAY_WRITE)) {
- iput(inode);
- return -EACCES;
- }
+ } else
actime = modtime = CURRENT_TIME;
- }
inode->i_atime = actime;
inode->i_mtime = modtime;
inode->i_dirt = 1;
iput(inode);
if (current->uid == inode->i_uid)
res >>= 6;
- else if (in_group_p(inode->i_gid))
- res >>= 3;
+ else if (current->gid == inode->i_gid)
+ res >>= 6;
if ((res & 0007 & mode) == mode)
return 0;
/*
iput(inode);
return -ENOTDIR;
}
- if (!permission(inode,MAY_EXEC)) {
- iput(inode);
- return -EACCES;
- }
iput(current->pwd);
current->pwd = inode;
return (0);
iput(inode);
return -ENOTDIR;
}
- if (!suser()) {
- iput(inode);
- return -EPERM;
- }
iput(current->root);
current->root = inode;
return (0);
if (!(inode = file->f_inode))
return -ENOENT;
if ((current->euid != inode->i_uid) && !suser())
- return -EPERM;
- if (IS_RDONLY(inode))
- return -EROFS;
+ return -EACCES;
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1;
return 0;
return -ENOENT;
if ((current->euid != inode->i_uid) && !suser()) {
iput(inode);
- return -EPERM;
- }
- if (IS_RDONLY(inode)) {
- iput(inode);
- return -EROFS;
+ return -EACCES;
}
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1;
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
- if (IS_RDONLY(inode))
- return -EROFS;
- if ((current->euid == inode->i_uid && user == inode->i_uid &&
- (in_group_p(group) || group == inode->i_gid)) ||
- suser()) {
- inode->i_uid = user;
- inode->i_gid = group;
- inode->i_dirt=1;
- return 0;
- }
- return -EPERM;
+ if (!suser())
+ return -EACCES;
+ inode->i_uid = user;
+ inode->i_gid = group;
+ inode->i_dirt=1;
+ return 0;
}
int sys_chown(const char * filename, uid_t user, gid_t group)
{
struct inode * inode;
- if (!(inode = lnamei(filename)))
+ if (!(inode = namei(filename)))
return -ENOENT;
- if (IS_RDONLY(inode)) {
- iput(inode);
- return -EROFS;
- }
- if ((current->euid == inode->i_uid && user == inode->i_uid &&
- (in_group_p(group) || group == inode->i_gid)) ||
- suser()) {
- inode->i_uid = user;
- inode->i_gid = group;
- inode->i_dirt=1;
+ if (!suser()) {
iput(inode);
- return 0;
+ return -EACCES;
}
+ inode->i_uid = user;
+ inode->i_gid = group;
+ inode->i_dirt = 1;
iput(inode);
- return -EPERM;
+ return 0;
}
int sys_open(const char * filename,int flag,int mode)
if (!current->filp[fd])
break;
if (fd>=NR_OPEN)
- return -EMFILE;
+ return -EINVAL;
current->close_on_exec &= ~(1<<fd);
f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break;
if (i>=NR_FILE)
- return -ENFILE;
+ return -EINVAL;
(current->filp[fd] = f)->f_count++;
if ((i = open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
f->f_count=0;
return i;
}
+ f->f_op = NULL;
+ if (inode)
+ if (S_ISCHR(inode->i_mode)) {
+ i = MAJOR(inode->i_rdev);
+ if (i < MAX_CHRDEV)
+ f->f_op = chrdev_fops[i];
+ } else if (S_ISBLK(inode->i_mode)) {
+ i = MAJOR(inode->i_rdev);
+ if (i < MAX_CHRDEV)
+ f->f_op = blkdev_fops[i];
+ }
f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
f->f_pos = 0;
- f->f_reada = 0;
- f->f_op = NULL;
- if (inode->i_op)
- f->f_op = inode->i_op->default_file_ops;
- if (f->f_op && f->f_op->open)
- if (i = f->f_op->open(inode,f)) {
+ if (inode->i_op && inode->i_op->open)
+ if (i = inode->i_op->open(inode,f)) {
iput(inode);
f->f_count=0;
current->filp[fd]=NULL;
int sys_close(unsigned int fd)
{
struct file * filp;
- struct inode * inode;
if (fd >= NR_OPEN)
return -EINVAL;
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
- if (filp->f_count == 0) {
- printk("Close: file count is 0\n");
- return 0;
- }
- if (filp->f_count > 1) {
- filp->f_count--;
- return 0;
- }
- inode = filp->f_inode;
- if (filp->f_op && filp->f_op->release)
- filp->f_op->release(inode,filp);
- filp->f_count--;
- iput(inode);
+ if (filp->f_count == 0)
+ panic("Close: file count is 0");
+ if (--filp->f_count)
+ return (0);
+ if (filp->f_op && filp->f_op->close)
+ return filp->f_op->close(filp->f_inode,filp);
+ iput(filp->f_inode);
return 0;
}
#include <signal.h>
#include <errno.h>
#include <termios.h>
+#include <fcntl.h>
#include <asm/segment.h>
-#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/kernel.h>
if (!(filp->f_flags & O_NONBLOCK))
while (!PIPE_SIZE(*inode)) {
wake_up(& PIPE_WRITE_WAIT(*inode));
- if (!PIPE_WRITERS(*inode)) /* are there any writers? */
+ if (inode->i_count != 2) /* are there any writers? */
return 0;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
chars = count;
if (chars > size)
chars = size;
- memcpy_tofs(buf, (char *)inode->i_size+PIPE_TAIL(*inode), chars );
+ count -= chars;
read += chars;
+ size = PIPE_TAIL(*inode);
PIPE_TAIL(*inode) += chars;
PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
- count -= chars;
- buf += chars;
+ while (chars-->0)
+ put_fs_byte(((char *)inode->i_size)[size++],buf++);
}
wake_up(& PIPE_WRITE_WAIT(*inode));
return read?read:-EAGAIN;
{
int chars, size, written = 0;
- if (!PIPE_READERS(*inode)) { /* no readers */
- send_sig(SIGPIPE,current,0);
- return -EPIPE;
- }
-/* if count < PAGE_SIZE, we have to make it atomic */
- if (count < PAGE_SIZE)
- size = PAGE_SIZE-count;
- else
- size = PAGE_SIZE-1;
while (count>0) {
- while (PIPE_SIZE(*inode) >= size) {
- if (!PIPE_READERS(*inode)) { /* no readers */
- send_sig(SIGPIPE,current,0);
- return written?written:-EPIPE;
+ while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
+ wake_up(& PIPE_READ_WAIT(*inode));
+ if (inode->i_count != 2) { /* no readers */
+ current->signal |= (1<<(SIGPIPE-1));
+ return written?written:-EINTR;
}
if (current->signal & ~current->blocked)
- return written?written:-ERESTARTSYS;
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- else
- interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
+ return written?written:-EINTR;
+ interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
}
- while (count>0 && (size = (PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
- chars = PAGE_SIZE-PIPE_HEAD(*inode);
- if (chars > count)
- chars = count;
- if (chars > size)
- chars = size;
- memcpy_fromfs((char *)inode->i_size+PIPE_HEAD(*inode), buf, chars );
- written += chars;
- PIPE_HEAD(*inode) += chars;
- PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
- count -= chars;
- buf += chars;
- }
- wake_up(& PIPE_READ_WAIT(*inode));
- size = PAGE_SIZE-1;
+ chars = PAGE_SIZE-PIPE_HEAD(*inode);
+ if (chars > count)
+ chars = count;
+ if (chars > size)
+ chars = size;
+ count -= chars;
+ written += chars;
+ size = PIPE_HEAD(*inode);
+ PIPE_HEAD(*inode) += chars;
+ PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
+ while (chars-->0)
+ ((char *)inode->i_size)[size++]=get_fs_byte(buf++);
}
+ wake_up(& PIPE_READ_WAIT(*inode));
return written;
}
}
}
-static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
-{
- switch (sel_type) {
- case SEL_IN:
- if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
- return 1;
- select_wait(&PIPE_READ_WAIT(*inode), wait);
- return 0;
- case SEL_OUT:
- if (!PIPE_FULL(*inode) || !PIPE_WRITERS(*inode))
- return 1;
- select_wait(&PIPE_WRITE_WAIT(*inode), wait);
- return 0;
- case SEL_EX:
- if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
- return 1;
- select_wait(&inode->i_wait,wait);
- return 0;
- }
- return 0;
-}
-
-/*
- * Ok, these three routines NOW keep track of readers/writers,
- * Linus previously did it with inode->i_count checking.
- */
-static void pipe_read_release(struct inode * inode, struct file * filp)
-{
- PIPE_READERS(*inode)--;
- wake_up(&PIPE_WRITE_WAIT(*inode));
-}
-
-static void pipe_write_release(struct inode * inode, struct file * filp)
-{
- PIPE_WRITERS(*inode)--;
- wake_up(&PIPE_READ_WAIT(*inode));
-}
-
-static void pipe_rdwr_release(struct inode * inode, struct file * filp)
-{
- PIPE_READERS(*inode)--;
- PIPE_WRITERS(*inode)--;
- wake_up(&PIPE_READ_WAIT(*inode));
- wake_up(&PIPE_WRITE_WAIT(*inode));
-}
-
-/*
- * The three file_operations structs are not static because they
- * are also used in linux/fs/fifo.c to do operations on fifo's.
- */
-struct file_operations read_pipe_fops = {
+static struct file_operations read_pipe_fops = {
pipe_lseek,
pipe_read,
bad_pipe_rw,
pipe_readdir,
- pipe_select,
- pipe_ioctl,
- NULL, /* no special open code */
- pipe_read_release
+ NULL, /* pipe_close */
+ NULL, /* pipe_select */
+ pipe_ioctl
};
-struct file_operations write_pipe_fops = {
+static struct file_operations write_pipe_fops = {
pipe_lseek,
bad_pipe_rw,
pipe_write,
pipe_readdir,
- pipe_select,
- pipe_ioctl,
- NULL, /* no special open code */
- pipe_write_release
-};
-
-struct file_operations rdwr_pipe_fops = {
- pipe_lseek,
- pipe_read,
- pipe_write,
- pipe_readdir,
- pipe_select,
- pipe_ioctl,
- NULL, /* no special open code */
- pipe_rdwr_release
+ NULL, /* pipe_close */
+ NULL, /* pipe_select */
+ pipe_ioctl
};
int sys_pipe(unsigned long * fildes)
int fd[2];
int i,j;
- verify_area(fildes,8);
j=0;
for(i=0;j<2 && i<NR_FILE;i++)
if (!file_table[i].f_count)
}
f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0;
- f[0]->f_flags = f[1]->f_flags = 0;
f[0]->f_op = &read_pipe_fops;
f[0]->f_mode = 1; /* read */
f[1]->f_op = &write_pipe_fops;
#include <errno.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/dirent.h>
-#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
{
struct file * file;
- int tmp = -1;
+ int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
return -EBADF;
if (tmp < 0)
return -EINVAL;
file->f_pos = tmp;
- file->f_reada = 0;
return file->f_pos;
}
verify_area(buf,count);
if (file->f_op && file->f_op->read)
return file->f_op->read(inode,file,buf,count);
+ printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
return 0;
if (file->f_op && file->f_op->write)
return file->f_op->write(inode,file,buf,count);
+ printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
#include <linux/fs.h>
#include <linux/kernel.h>
+#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/stat.h>
#include <asm/segment.h>
#include <asm/system.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
* understand what I'm doing here, then you understand how the linux sleep/wakeup
* mechanism works.
*
- * Two very simple procedures, select_wait() and free_wait() make all the work.
- * select_wait() is a inline-function defined in <linux/fs.h>, as all select
- * functions have to call it to add an entry to the select table.
+ * Two very simple procedures, add_wait() and free_wait() make all the work. We
+ * have to have interrupts disabled throughout the select, but that's not really
+ * such a loss: sleeping automatically frees interrupts when we aren't in this
+ * task.
*/
static select_table * sel_tables = NULL;
+static void add_wait(struct task_struct ** wait_address, select_table * p)
+{
+ int i;
+
+ if (!wait_address)
+ return;
+ for (i = 0 ; i < p->nr ; i++)
+ if (p->entry[i].wait_address == wait_address)
+ return;
+ current->next_wait = NULL;
+ p->entry[p->nr].wait_address = wait_address;
+ p->entry[p->nr].old_task = *wait_address;
+ *wait_address = current;
+ p->nr++;
+}
+
+/*
+ * free_wait removes the current task from any wait-queues and then
+ * wakes up the queues.
+ */
+static void free_one_table(select_table * p)
+{
+ int i;
+ struct task_struct ** tpp;
+
+ for(tpp = &LAST_TASK ; tpp > &FIRST_TASK ; --tpp)
+ if (*tpp && ((*tpp)->next_wait == p->current))
+ (*tpp)->next_wait = NULL;
+ if (!p->nr)
+ return;
+ for (i = 0; i < p->nr ; i++) {
+ wake_up(p->entry[i].wait_address);
+ wake_up(&p->entry[i].old_task);
+ }
+ p->nr = 0;
+}
+
static void free_wait(select_table * p)
{
- struct select_table_entry * entry = p->entry + p->nr;
+ select_table * tmp;
- while (p->nr > 0) {
- p->nr--;
- entry--;
- remove_wait_queue(entry->wait_address,&entry->wait);
+ if (p->woken)
+ return;
+ p = sel_tables;
+ sel_tables = NULL;
+ while (p) {
+ wake_up(&p->current);
+ p->woken = 1;
+ tmp = p->next_table;
+ p->next_table = NULL;
+ free_one_table(p);
+ p = tmp;
}
}
+static struct tty_struct * get_tty(struct inode * inode)
+{
+ int major, minor;
+
+ if (!S_ISCHR(inode->i_mode))
+ return NULL;
+ if ((major = MAJOR(inode->i_rdev)) != 5 && major != 4)
+ return NULL;
+ if (major == 5)
+ minor = current->tty;
+ else
+ minor = MINOR(inode->i_rdev);
+ if (minor < 0)
+ return NULL;
+ return TTY_TABLE(minor);
+}
+
/*
* The check_XX functions check out a file. We know it's either
- * a pipe, a character device or a fifo
+ * a pipe, a character device or a fifo (fifo's not implemented)
*/
-static int check_in(select_table * wait, struct inode * inode, struct file * file)
+static int check_in(select_table * wait, struct inode * inode)
{
- if (file->f_op && file->f_op->select)
- return file->f_op->select(inode,file,SEL_IN,wait);
+ struct tty_struct * tty;
+
+ if (tty = get_tty(inode))
+ if (!EMPTY(tty->secondary))
+ return 1;
+ else
+ add_wait(&tty->secondary->proc_list, wait);
+ else if (inode->i_pipe)
+ if (!PIPE_EMPTY(*inode) || inode->i_count < 2)
+ return 1;
+ else
+ add_wait(&inode->i_wait, wait);
return 0;
}
-static int check_out(select_table * wait, struct inode * inode, struct file * file)
+static int check_out(select_table * wait, struct inode * inode)
{
- if (file->f_op && file->f_op->select)
- return file->f_op->select(inode,file,SEL_OUT,wait);
+ struct tty_struct * tty;
+
+ if (tty = get_tty(inode))
+ if (!FULL(tty->write_q))
+ return 1;
+ else
+ add_wait(&tty->write_q->proc_list, wait);
+ else if (inode->i_pipe)
+ if (!PIPE_FULL(*inode))
+ return 1;
+ else
+ add_wait(&inode->i_wait, wait);
return 0;
}
-static int check_ex(select_table * wait, struct inode * inode, struct file * file)
+static int check_ex(select_table * wait, struct inode * inode)
{
- if (file->f_op && file->f_op->select)
- return file->f_op->select(inode,file,SEL_EX,wait);
+ struct tty_struct * tty;
+
+ if (tty = get_tty(inode))
+ if (!FULL(tty->write_q))
+ return 0;
+ else
+ return 0;
+ else if (inode->i_pipe)
+ if (inode->i_count < 2)
+ return 1;
+ else
+ add_wait(&inode->i_wait,wait);
return 0;
}
{
int count;
select_table wait_table;
- struct file * file;
int i;
fd_set mask;
continue;
if (S_ISFIFO(current->filp[i]->f_inode->i_mode))
continue;
- if (S_ISSOCK(current->filp[i]->f_inode->i_mode))
- continue;
return -EBADF;
}
repeat:
wait_table.nr = 0;
+ wait_table.woken = 0;
+ wait_table.current = current;
+ wait_table.next_table = sel_tables;
+ sel_tables = &wait_table;
*inp = *outp = *exp = 0;
count = 0;
- current->state = TASK_INTERRUPTIBLE;
mask = 1;
for (i = 0 ; i < NR_OPEN ; i++, mask += mask) {
- file = current->filp[i];
if (mask & in)
- if (check_in(&wait_table,file->f_inode,file)) {
+ if (check_in(&wait_table,current->filp[i]->f_inode)) {
*inp |= mask;
count++;
}
if (mask & out)
- if (check_out(&wait_table,file->f_inode,file)) {
+ if (check_out(&wait_table,current->filp[i]->f_inode)) {
*outp |= mask;
count++;
}
if (mask & ex)
- if (check_ex(&wait_table,file->f_inode,file)) {
+ if (check_ex(&wait_table,current->filp[i]->f_inode)) {
*exp |= mask;
count++;
}
}
if (!(current->signal & ~current->blocked) &&
current->timeout && !count) {
+ current->state = TASK_INTERRUPTIBLE;
+ sti();
schedule();
+ cli();
free_wait(&wait_table);
goto repeat;
}
free_wait(&wait_table);
- current->state = TASK_RUNNING;
return count;
}
timeout += jiffies;
}
current->timeout = timeout;
+ cli();
i = do_select(in, out, ex, &res_in, &res_out, &res_ex);
if (current->timeout > jiffies)
timeout = current->timeout - jiffies;
else
timeout = 0;
+ sti();
current->timeout = 0;
if (i < 0)
return i;
*/
#include <errno.h>
+#include <sys/stat.h>
-#include <linux/stat.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
-static void cp_old_stat(struct inode * inode, struct old_stat * statbuf)
+static void cp_stat(struct inode * inode, struct stat * statbuf)
{
- struct old_stat tmp;
+ struct stat tmp;
+ int i;
- if (inode->i_ino & 0xffff0000)
- printk("Warning: using old stat() call on bigfs\n");
- verify_area(statbuf,sizeof (*statbuf));
+ verify_area(statbuf,sizeof (struct stat));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_ino;
tmp.st_mode = inode->i_mode;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_rdev;
- if( S_ISFIFO(inode->i_mode) )
- tmp.st_size = 0;
- else
- tmp.st_size = inode->i_size;
+ tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
- memcpy_tofs(statbuf,&tmp,sizeof(tmp));
+ for (i=0 ; i<sizeof (tmp) ; i++)
+ put_fs_byte(((char *) &tmp)[i],i + (char *) statbuf);
}
-static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
-{
- struct new_stat tmp = {0, };
- unsigned int blocks, indirect;
-
- verify_area(statbuf,sizeof (*statbuf));
- tmp.st_dev = inode->i_dev;
- tmp.st_ino = inode->i_ino;
- tmp.st_mode = inode->i_mode;
- tmp.st_nlink = inode->i_nlink;
- tmp.st_uid = inode->i_uid;
- tmp.st_gid = inode->i_gid;
- tmp.st_rdev = inode->i_rdev;
- if( S_ISFIFO(inode->i_mode) )
- tmp.st_size = 0;
- else
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
- tmp.st_ctime = inode->i_ctime;
-/*
- * Right now we fake the st_blocks numbers: we'll eventually have to
- * add st_blocks to the inode, and let the vfs routines keep track of
- * it all. This algorithm doesn't guarantee correct block numbers, but
- * at least it tries to come up with a plausible answer...
- *
- * In fact, the minix fs doesn't use these numbers (it uses 7 and 512
- * instead of 10 and 256), but who cares... It's not that exact anyway.
- */
- blocks = (tmp.st_size + 1023) / 1024;
- if (blocks > 10) {
- indirect = (blocks - 11)/256+1;
- if (blocks > 10+256) {
- indirect += (blocks - 267)/(256*256)+1;
- if (blocks > 10+256+256*256)
- indirect++;
- }
- blocks += indirect;
- }
- tmp.st_blksize = 1024;
- tmp.st_blocks = blocks;
- memcpy_tofs(statbuf,&tmp,sizeof(tmp));
-}
-
-int sys_stat(char * filename, struct old_stat * statbuf)
+int sys_stat(char * filename, struct stat * statbuf)
{
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
- cp_old_stat(inode,statbuf);
+ cp_stat(inode,statbuf);
iput(inode);
return 0;
}
-int sys_newstat(char * filename, struct new_stat * statbuf)
-{
- struct inode * inode;
-
- if (!(inode=namei(filename)))
- return -ENOENT;
- cp_new_stat(inode,statbuf);
- iput(inode);
- return 0;
-}
-
-int sys_lstat(char * filename, struct old_stat * statbuf)
-{
- struct inode * inode;
-
- if (!(inode = lnamei(filename)))
- return -ENOENT;
- cp_old_stat(inode,statbuf);
- iput(inode);
- return 0;
-}
-
-int sys_newlstat(char * filename, struct new_stat * statbuf)
+int sys_lstat(char * filename, struct stat * statbuf)
{
struct inode * inode;
if (!(inode = lnamei(filename)))
return -ENOENT;
- cp_new_stat(inode,statbuf);
+ cp_stat(inode,statbuf);
iput(inode);
return 0;
}
-int sys_fstat(unsigned int fd, struct old_stat * statbuf)
-{
- struct file * f;
- struct inode * inode;
-
- if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
- return -EBADF;
- cp_old_stat(inode,statbuf);
- return 0;
-}
-
-int sys_newfstat(unsigned int fd, struct new_stat * statbuf)
+int sys_fstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
struct inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF;
- cp_new_stat(inode,statbuf);
+ cp_stat(inode,statbuf);
return 0;
}
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
-#include <linux/ext_fs.h>
-#include <linux/msdos_fs.h>
#include <linux/kernel.h>
-#include <linux/stat.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <errno.h>
-
+#include <sys/stat.h>
int sync_dev(int dev);
void wait_for_keypress(void);
static struct file_system_type file_systems[] = {
{minix_read_super,"minix"},
- {ext_read_super,"ext"},
- {msdos_read_super,"msdos"},
{NULL,NULL}
};
void free_super(struct super_block * sb)
{
+ cli();
sb->s_lock = 0;
wake_up(&(sb->s_wait));
+ sti();
}
void wait_on_super(struct super_block * sb)
sb->s_op->put_super(sb);
}
-static struct super_block * read_super(int dev,char *name,int flags,void *data)
+static struct super_block * read_super(int dev,char *name,void *data)
{
struct super_block * s;
struct file_system_type *type;
break;
}
s->s_dev = dev;
- s->s_flags = flags;
if (!type->read_super(s,data))
return(NULL);
s->s_dev = dev;
sb->s_covered = NULL;
iput(sb->s_mounted);
sb->s_mounted = NULL;
- if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
- sb->s_op->write_super (sb);
put_super(dev);
sync_dev(dev);
return 0;
}
-/*
- * do_mount() does the actual mounting after sys_mount has done the ugly
- * parameter parsing. When enough time has gone by, and everything uses the
- * new mount() parameters, sys_mount() can then be cleaned up.
- *
- * We cannot mount a filesystem if it has active, used, or dirty inodes.
- * We also have to flush all inode-data for this device, as the new mount
- * might need new info.
- */
-static int do_mount(int dev, const char * dir, char * type, int flags, void * data)
+int sys_mount(char * dev_name, char * dir_name, char * type, int rw_flag)
{
- struct inode * inode, * dir_i;
+ struct inode * dev_i, * dir_i;
struct super_block * sb;
+ int dev;
+ char tmp[100],*t;
+ int i;
- if (!(dir_i = namei(dir)))
+ if (!suser())
+ return -EPERM;
+ if (!(dev_i = namei(dev_name)))
return -ENOENT;
- if (dir_i->i_count != 1 || dir_i->i_mount) {
+ dev = dev_i->i_rdev;
+ if (!S_ISBLK(dev_i->i_mode)) {
+ iput(dev_i);
+ return -EPERM;
+ }
+ iput(dev_i);
+ if (!(dir_i=namei(dir_name)))
+ return -ENOENT;
+ if (dir_i->i_count != 1 || dir_i->i_ino == MINIX_ROOT_INO) {
iput(dir_i);
return -EBUSY;
}
iput(dir_i);
return -EPERM;
}
- for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
- if (inode->i_dev != dev)
- continue;
- if (inode->i_count || inode->i_dirt || inode->i_lock) {
- iput(dir_i);
- return -EBUSY;
- }
- inode->i_dev = 0;
- }
- sb = read_super(dev,type,flags,data);
- if (!sb || sb->s_covered) {
+ if (dir_i->i_mount) {
iput(dir_i);
- return -EBUSY;
- }
- sb->s_flags = flags;
- sb->s_covered = dir_i;
- dir_i->i_mount = 1;
- return 0; /* we don't iput(dir_i) - see umount */
-}
-
-/*
- * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
- * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
- *
- * data is a (void *) that can point to any structure up to 4095 bytes, which
- * can contain arbitrary fs-dependent information (or be NULL).
- *
- * NOTE! As old versions of mount() didn't use this setup, the flags has to have
- * a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
- * isn't present, the flags and data info isn't used, as the syscall assumes we
- * are talking to an older version that didn't understand them.
- */
-int sys_mount(char * dev_name, char * dir_name, char * type,
- unsigned long new_flags, void *data)
-{
- struct inode * inode;
- int dev;
- int retval = 0;
- char tmp[100],*t;
- int i;
- unsigned long flags = 0;
- unsigned long page = 0;
-
- if (!suser())
return -EPERM;
- if (!(inode = namei(dev_name)))
- return -ENOENT;
- dev = inode->i_rdev;
- if (!S_ISBLK(inode->i_mode))
- retval = -EPERM;
- else if (IS_NODEV(inode))
- retval = -EACCES;
- iput(inode);
- if (retval)
- return retval;
- if ((new_flags & 0xffff0000) == 0xC0ED0000) {
- flags = new_flags & 0xffff;
- if (data && (unsigned long) data < TASK_SIZE)
- page = get_free_page();
- }
- if (page) {
- i = TASK_SIZE - (unsigned long) data;
- if (i < 0 || i > 4095)
- i = 4095;
- memcpy_fromfs((void *) page,data,i);
}
if (type) {
- for (i = 0 ; i < 100 ; i++)
- if (!(tmp[i] = get_fs_byte(type++)))
- break;
+ i = 0;
+ while (i < 100 && (tmp[i] = get_fs_byte(type++)))
+ i++;
t = tmp;
} else
t = "minix";
- retval = do_mount(dev,dir_name,t,flags,(void *) page);
- free_page(page);
- return retval;
+ if (!(sb = read_super(dev,t,NULL))) {
+ iput(dir_i);
+ return -EBUSY;
+ }
+ if (sb->s_covered) {
+ iput(dir_i);
+ return -EBUSY;
+ }
+ sb->s_covered = dir_i;
+ dir_i->i_mount = 1;
+ dir_i->i_dirt = 1; /* NOTE! we don't iput(dir_i) */
+ return 0; /* we do that in umount */
}
void mount_root(void)
p->s_lock = 0;
p->s_wait = NULL;
}
- if (!(p=read_super(ROOT_DEV,"minix",0,NULL)))
+ if (!(p=read_super(ROOT_DEV,"minix",NULL)))
panic("Unable to mount root");
/*wait_for_keypress();
if (!(mi=iget(ROOT_DEV,MINIX_ROOT_INO)))
mi=p->s_mounted;
mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
p->s_mounted = p->s_covered = mi;
- p->s_flags = 0;
current->pwd = mi;
current->root = mi;
free=0;
/* Code indicating demand-paged executable. */
#define ZMAGIC 0413
-/* Code indicating core file. */
-#define CMAGIC 0421
#if !defined (N_BADMAG)
#define N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
#ifndef _ASM_IO_H
#define _ASM_IO_H
-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * Linus
- */
-
extern void inline outb(char value, unsigned short port)
{
-__asm__ __volatile__ ("outb %0,%1"
+__asm__ volatile ("outb %0,%1"
::"a" ((char) value),"d" ((unsigned short) port));
}
extern void inline outb_p(char value, unsigned short port)
{
-__asm__ __volatile__ ("outb %0,%1\n\t"
-#ifdef REALLY_SLOW_IO
- "outb %0,$0x80\n\t"
- "outb %0,$0x80\n\t"
- "outb %0,$0x80\n\t"
-#endif
- "outb %0,$0x80"
+__asm__ volatile ("outb %0,%1\n"
+ "\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:"
::"a" ((char) value),"d" ((unsigned short) port));
}
extern unsigned char inline inb(unsigned short port)
{
unsigned char _v;
-__asm__ __volatile__ ("inb %1,%0"
+__asm__ volatile ("inb %1,%0"
:"=a" (_v):"d" ((unsigned short) port));
return _v;
}
extern unsigned char inline inb_p(unsigned short port)
{
unsigned char _v;
-__asm__ __volatile__ ("inb %1,%0\n\t"
-#ifdef REALLY_SLOW_IO
- "outb %0,$0x80\n\t"
- "outb %0,$0x80\n\t"
- "outb %0,$0x80\n\t"
-#endif
- "outb %0,$0x80"
+__asm__ volatile ("inb %1,%0\n"
+ "\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:\tjmp 1f\n"
+ "1:"
:"=a" (_v):"d" ((unsigned short) port));
return _v;
}
+++ /dev/null
-#ifndef _ASM_IRQ_H
-#define _ASM_IRQ_H
-
-/*
- * linux/include/asm/irq.h
- *
- * (C) 1992 Linus Torvalds
- */
-
-#define SAVE_ALL \
- "cld\n\t" \
- "push %gs\n\t" \
- "push %fs\n\t" \
- "push %es\n\t" \
- "push %ds\n\t" \
- "pushl %eax\n\t" \
- "pushl %ebp\n\t" \
- "pushl %edi\n\t" \
- "pushl %esi\n\t" \
- "pushl %edx\n\t" \
- "pushl %ecx\n\t" \
- "pushl %ebx\n\t" \
- "movl $0x10,%edx\n\t" \
- "mov %dx,%ds\n\t" \
- "mov %dx,%es\n\t" \
- "movl $0x17,%edx\n\t" \
- "mov %dx,%fs\n\t"
-
-#define ACK_FIRST(mask) \
- "inb $0x21,%al\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\torb $" #mask ",%al\n\t" \
- "outb %al,$0x21\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\tmovb $0x20,%al\n\t" \
- "outb %al,$0x20\n\t"
-
-#define ACK_SECOND(mask) \
- "inb $0xA1,%al\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\torb $" #mask ",%al\n\t" \
- "outb %al,$0xA1\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\tmovb $0x20,%al\n\t" \
- "outb %al,$0xA0\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\toutb %al,$0x20\n\t"
-
-#define UNBLK_FIRST(mask) \
- "inb $0x21,%al\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\tandb $~(" #mask "),%al\n\t" \
- "outb %al,$0x21\n\t"
-
-#define UNBLK_SECOND(mask) \
- "inb $0xA1,%al\n\t" \
- "jmp 1f\n" \
- "1:\tjmp 1f\n" \
- "1:\tandb $~(" #mask "),%al\n\t" \
- "outb %al,$0xA1\n\t"
-
-#define IRQ_NAME2(nr) nr##_interrupt()
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
-#define BUILD_IRQ(chip,nr,mask) \
-extern void IRQ_NAME(nr); \
-__asm__( \
-"\n.align 2\n" \
-".globl _IRQ" #nr "_interrupt\n" \
-"_IRQ" #nr "_interrupt:\n\t" \
- "pushl $-1\n\t" \
- SAVE_ALL \
- "cli\n\t" \
- ACK_##chip(mask) \
- "sti\n\t" \
- "movl %esp,%ebx\n\t" \
- "pushl %ebx\n\t" \
- "pushl $" #nr "\n\t" \
- "call _do_IRQ\n\t" \
- "addl $8,%esp\n\t" \
- "testl %eax,%eax\n\t" \
- "jne ret_from_sys_call\n\t" \
- "cli\n\t" \
- UNBLK_##chip(mask) \
- "sti\n\t" \
- "jmp ret_from_sys_call");
-
-#endif
*/
#define memcpy(dest,src,n) ({ \
void * _res = dest; \
-__asm__ __volatile__ ("cld;rep;movsb" \
+__asm__ ("cld;rep;movsb" \
::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
:"di","si","cx"); \
_res; \
extern inline void set_fs(unsigned long val)
{
- __asm__ __volatile__("mov %0,%%fs"::"r" ((unsigned short) val));
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) val));
}
#define move_to_user_mode() \
-__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
+__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"mov %%ax,%%gs" \
:::"ax")
-#define sti() __asm__ __volatile__ ("sti"::)
-#define cli() __asm__ __volatile__ ("cli"::)
-#define nop() __asm__ __volatile__ ("nop"::)
+#define sti() __asm__ ("sti"::)
+#define cli() __asm__ ("cli"::)
+#define nop() __asm__ ("nop"::)
-#define iret() __asm__ __volatile__ ("iret"::)
+#define iret() __asm__ ("iret"::)
#define _set_gate(gate_addr,type,dpl,addr) \
-__asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
+__asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,type) \
-__asm__ __volatile__ ("movw $232,%1\n\t" \
+__asm__ ("movw $232,%1\n\t" \
"movw %%ax,%2\n\t" \
"rorl $16,%%eax\n\t" \
"movb %%al,%3\n\t" \
--- /dev/null
+#ifndef _FCNTL_H
+#define _FCNTL_H
+
+#include <sys/types.h>
+
+/* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
+#define O_ACCMODE 00003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 00100 /* not fcntl */
+#define O_EXCL 00200 /* not fcntl */
+#define O_NOCTTY 00400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+
+/* Defines for fcntl-commands. Note that currently
+ * locking isn't supported, and other things aren't really
+ * tested.
+ */
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get f_flags */
+#define F_SETFD 2 /* set f_flags */
+#define F_GETFL 3 /* more flags (cloexec) */
+#define F_SETFL 4
+#define F_GETLK 5 /* not implemented */
+#define F_SETLK 6
+#define F_SETLKW 7
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* Ok, these are locking features, and aren't implemented at any
+ * level. POSIX wants them.
+ */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* Once again - not implemented, but ... */
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+
+extern int creat(const char * filename,mode_t mode);
+extern int fcntl(int fildes,int cmd, ...);
+extern int open(const char * filename, int flags, ...);
+
+#endif
+++ /dev/null
-#ifndef _CONFIG_DIST_H
-#define _CONFIG_DIST_H
-#ifdef CONFIG_DISTRIBUTION
-
-#undef CONFG_SCSI
-#define CONFIG_SCSI
-
-#undef CONFIG_SCSI_AHA1542
-#define CONFIG_SCSI_AHA1542
-#undef CONFIG_SCSI_CSC
-#define CONFIG_SCSI_CSC
-#undef CONFIG_SCSI_DTC
-#define CONFIG_SCSI_DTC
-#undef CONFIG_SCSI_FUTURE_DOMAIN
-#define CONFIG_SCSI_FUTURE_DOMAIN
-#undef CONFIG_SCSI_SEAGATE
-#define CONFIG_SCSI_SEAGATE
-#undef CONFIG_SCSI_ULTRASTOR
-#define CONFIG_SCSI_ULTRASTOR
-
-#undef CONFIG_BLK_DEV_SD
-#define CONFIG_BLK_DEV_SD
-#undef CONFIG_BLK_DEV_ST
-#define CONFIG_BLK_DEV_ST
-
-#endif
-#endif
#ifndef _CONFIG_H
#define _CONFIG_H
-#define CONFIG_DISTRIBUTION
-
/*
* Defines for what uname() should return
*/
#define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000
#define DEF_SETUPSEG 0x9020
-#define DEF_SYSSIZE 0x5000
+#define DEF_SYSSIZE 0x4000
/*
* The root-device is no longer hard-coded. You can change the default
leave HD_TYPE undefined. This is the normal thing to do.
*/
-#undef HD_TYPE
-
-#undef CONFIG_BLK_DEV_SD
-#undef CONFIG_BLK_DEV_ST
-
-/*
- Choose supported SCSI adapters here.
-*/
-
-#undef CONFIG_SCSI_AHA1542
-#undef CONFIG_SCSI_ALWAYS
-#undef CONFIG_SCSI_CSC
-#undef CONFIG_SCSI_DTC
-#undef CONFIG_SCSI_FUTURE_DOMAIN
-#undef CONFIG_SCSI_SEAGATE
-#undef CONFIG_SCSI_ULTRASTOR
-
-#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_ST)
- #ifndef CONFIG_SCSI
- #define CONFIG_SCSI
- #endif
-
- #if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
- !defined(CONFIG_SCSI_FUTURE_DOMAIN) && !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR)
-
- #error Error : SCSI devices enabled, but no low level drivers have been enabled.
- #endif
-#endif
-
-#ifdef CONFIG_DISTRIBUTION
- #include <linux/config.dist.h>
-#else
- #include <linux/config.site.h>
-#endif
-
-/*
- File type specific stuff goes into this.
-*/
-
-#ifdef ASM_SRC
-#endif
-
-#ifdef C_SRC
-#endif
-
-#ifdef MAKE
-#endif
-
#endif
+++ /dev/null
-#ifndef _CONFIG_SITE_H
-#define _CONFIG_SITE_H
-
-/*
- This configuration file contains site specific things, things
- that you have added and config.dist will not know about.
-*/
-
-#endif
-#define UTS_RELEASE "0.96b-63"
+#define UTS_RELEASE "0.95c-54"
-#define UTS_VERSION "07/04/92"
+#define UTS_VERSION "04/22/92"
+++ /dev/null
-/*
- * The ext filesystem constants/structures
- */
-
-#ifndef _EXT_FS_H
-#define _EXT_FS_H
-
-#include <sys/types.h>
-
-/*
- * Free blocks/inodes management style
- *
- * One of these two constants must be defined
- *
- */
-/* #define EXTFS_BITMAP */ /* use a bitmap */
-#define EXTFS_FREELIST /* use a linked list */
-
-#define EXT_NAME_LEN 255
-#define EXT_ROOT_INO 1
-
-#define EXT_I_MAP_SLOTS 8
-#define EXT_Z_MAP_SLOTS 8
-#define EXT_SUPER_MAGIC 0x137D
-
-#define EXT_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_inode)))
-/* #define EXT_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_dir_entry))) */
-
-struct ext_inode {
- unsigned short i_mode;
- unsigned short i_uid;
- unsigned long i_size;
- unsigned long i_time;
- unsigned short i_gid;
- unsigned short i_nlinks;
- unsigned long i_zone[12];
-};
-
-struct ext_free_inode {
- unsigned long count;
- unsigned long free[14];
- unsigned long next;
-};
-
-struct ext_free_block {
- unsigned long count;
- unsigned long free[254];
- unsigned long next;
-};
-
-struct ext_super_block {
- unsigned long s_ninodes;
- unsigned long s_nzones;
-#ifdef EXTFS_BITMAP
- unsigned long s_imap_blocks;
- unsigned long s_zmap_blocks;
-#endif
-#ifdef EXTFS_FREELIST
- unsigned long s_firstfreeblock;
- unsigned long s_freeblockscount;
- unsigned long s_firstfreeinode;
- unsigned long s_freeinodescount;
-#endif
- unsigned long s_firstdatazone;
- unsigned long s_log_zone_size;
- unsigned long s_max_size;
- unsigned long s_reserved1;
- unsigned long s_reserved2;
- unsigned long s_reserved3;
- unsigned long s_reserved4;
- unsigned long s_reserved5;
- unsigned short s_magic;
-};
-
-struct ext_dir_entry {
- unsigned long inode;
- unsigned short rec_len;
- unsigned short name_len;
- char name[EXT_NAME_LEN];
-};
-
-extern int ext_open(struct inode * inode, struct file * filp);
-extern void ext_release(struct inode * inode, struct file * filp);
-extern int ext_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result);
-extern int ext_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result);
-extern int ext_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int ext_rmdir(struct inode * dir, const char * name, int len);
-extern int ext_unlink(struct inode * dir, const char * name, int len);
-extern int ext_symlink(struct inode * inode, const char * name, int len,
- const char * symname);
-extern int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
-extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
-extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len);
-extern struct inode * ext_new_inode(int dev);
-extern void ext_free_inode(struct inode * inode);
-extern unsigned long ext_count_free_inodes(struct super_block *sb);
-extern int ext_new_block(int dev);
-extern int ext_free_block(int dev, int block);
-extern unsigned long ext_count_free_blocks(struct super_block *sb);
-
-extern int ext_create_block(struct inode *, int);
-extern int ext_bmap(struct inode *,int);
-
-extern void ext_truncate(struct inode *);
-extern void ext_put_super(struct super_block *);
-extern void ext_write_super(struct super_block *);
-extern struct super_block *ext_read_super(struct super_block *,void *);
-extern void ext_read_inode(struct inode *);
-extern void ext_write_inode(struct inode *);
-extern void ext_put_inode(struct inode *);
-extern void ext_statfs(struct super_block *, struct statfs *);
-
-extern int ext_lseek(struct inode *, struct file *, off_t, int);
-extern int ext_read(struct inode *, struct file *, char *, int);
-extern int ext_write(struct inode *, struct file *, char *, int);
-
-extern struct inode_operations ext_file_inode_operations;
-extern struct inode_operations ext_dir_inode_operations;
-extern struct inode_operations ext_symlink_inode_operations;
-extern struct inode_operations ext_chrdev_inode_operations;
-extern struct inode_operations ext_blkdev_inode_operations;
-extern struct inode_operations ext_fifo_inode_operations;
-
-extern struct file_operations ext_file_operations;
-extern struct file_operations ext_dir_operations;
-
-#endif
+++ /dev/null
-#ifndef _FCNTL_H
-#define _FCNTL_H
-
-#include <sys/types.h>
-
-/* open/fcntl - O_SYNC isn't implemented yet */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-
-/* Defines for fcntl-commands. Note that currently
- * locking isn't supported, and other things aren't really
- * tested.
- */
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get f_flags */
-#define F_SETFD 2 /* set f_flags */
-#define F_GETFL 3 /* more flags (cloexec) */
-#define F_SETFL 4
-#define F_GETLK 5 /* not implemented */
-#define F_SETLK 6
-#define F_SETLKW 7
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* Ok, these are locking features, and aren't implemented at any
- * level. POSIX wants them.
- */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* Once again - not implemented, but ... */
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-#endif
+++ /dev/null
-#ifndef _FD_H
-#define _FD_H
-
-#define FDCLRPRM 0 /* clear user-defined parameters */
-#define FDSETPRM 1 /* set user-defined parameters for current media */
-#define FDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
-#define FDGETPRM 3 /* get disk parameters */
-#define FDMSGON 4 /* issue kernel messages on media type change */
-#define FDMSGOFF 5 /* don't issue kernel messages on media type change */
-#define FDFMTBEG 6 /* begin formatting a disk */
-#define FDFMTTRK 7 /* format the specified track */
-#define FDFMTEND 8 /* end formatting a disk */
-
-#define FD_FILL_BYTE 0xF6 /* format fill byte */
-
-#define FORMAT_NONE 0 /* no format request */
-#define FORMAT_WAIT 1 /* format request is waiting */
-#define FORMAT_BUSY 2 /* formatting in progress */
-#define FORMAT_OKAY 3 /* successful completion */
-#define FORMAT_ERROR 4 /* formatting error */
-
-struct floppy_struct {
- unsigned int size, sect, head, track, stretch;
- unsigned char gap,rate,spec1,fmt_gap;
- char *name; /* used only for predefined formats */
-};
-
-struct format_descr {
- unsigned int device,head,track;
-};
-
-#endif
#define FD_WRITE 0xC5 /* write with MT, MFM */
#define FD_SENSEI 0x08 /* Sense Interrupt Status */
#define FD_SPECIFY 0x03 /* specify HUT etc */
-#define FD_FORMAT 0x4D /* format one track */
/* DMA commands */
#define DMA_READ 0x46
#ifndef _FS_H
#define _FS_H
-#include <linux/limits.h>
-#include <linux/wait.h>
-
#include <sys/types.h>
#include <sys/dirent.h>
-#include <sys/vfs.h>
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
- * 8 - /dev/sd
- * 9 - /dev/st
*/
-#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3 || (x)==8)
+#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)
+#define NR_OPEN 20
+#define NR_INODE 128
+#define NR_FILE 64
+#define NR_SUPER 8
+#define NR_HASH 307
+#define NR_BUFFERS nr_buffers
+#define BLOCK_SIZE 1024
+#define BLOCK_SIZE_BITS 10
+#define MAX_CHRDEV 16
+#define MAX_BLKDEV 16
+
#ifndef NULL
#define NULL ((void *) 0)
#endif
#define PIPE_WRITE_WAIT(inode) ((inode).i_wait2)
#define PIPE_HEAD(inode) ((inode).i_data[0])
#define PIPE_TAIL(inode) ((inode).i_data[1])
-#define PIPE_READERS(inode) ((inode).i_data[2])
-#define PIPE_WRITERS(inode) ((inode).i_data[3])
#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_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#define SEL_OUT 2
#define SEL_EX 4
-/*
- * These are the fs-independent mount-flags: up to 16 flags are supported
- */
-#define MS_RDONLY 1 /* mount read-only */
-#define MS_NOSUID 2 /* ignore suid and sgid bits */
-#define MS_NODEV 4 /* disallow access to device special files */
-#define MS_NOEXEC 8 /* disallow program execution */
-#define MS_SYNC 16 /* writes are synced at once */
-
-/*
- * Note that read-only etc flags are inode-specific: setting some file-system
- * flags just means all the inodes inherit those flags by default. It might be
- * possible to overrride it sevelctively if you really wanted to with some
- * ioctl() that is not currently implemented.
- */
-#define IS_RDONLY(inode) ((inode)->i_flags & MS_RDONLY)
-#define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID)
-#define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
-#define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
-#define IS_SYNC(inode) ((inode)->i_flags & MS_SYNC)
-
-/* the read-only stuff doesn't really belong here, but any other place is
- probably as bad and I don't want to create yet another include file. */
-
-#define BLKROSET 4701 /* set device read-only (0 = read-write) */
-#define BLKROGET 4702 /* get read-only status (0 = read_write) */
-
-#define BMAP_IOCTL 1
-
typedef char buffer_block[BLOCK_SIZE];
struct buffer_head {
unsigned char b_dirt; /* 0-clean,1-dirty */
unsigned char b_count; /* users using this block */
unsigned char b_lock; /* 0 - ok, 1 -locked */
- struct wait_queue * b_wait;
+ struct task_struct * b_wait;
struct buffer_head * b_prev;
struct buffer_head * b_next;
struct buffer_head * b_prev_free;
struct buffer_head * b_next_free;
- struct buffer_head * b_reqnext;
};
struct inode {
- dev_t i_dev;
- unsigned long i_ino;
- umode_t i_mode;
- nlink_t i_nlink;
- uid_t i_uid;
- gid_t i_gid;
- dev_t i_rdev;
- off_t i_size;
- time_t i_atime;
- time_t i_mtime;
- time_t i_ctime;
+ dev_t i_dev;
+ ino_t i_ino;
+ umode_t i_mode;
+ nlink_t i_nlink;
+ uid_t i_uid;
+ gid_t i_gid;
+ dev_t i_rdev;
+ off_t i_size;
+ time_t i_atime;
+ time_t i_mtime;
+ time_t i_ctime;
unsigned long i_data[16];
struct inode_operations * i_op;
struct super_block * i_sb;
- struct wait_queue * i_wait;
- struct wait_queue * i_wait2; /* for pipes */
+ struct task_struct * i_wait;
+ struct task_struct * i_wait2; /* for pipes */
unsigned short i_count;
- unsigned short i_flags;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
- unsigned short f_reada;
- unsigned short f_rdev; /* needed for /dev/tty */
struct inode * f_inode;
struct file_operations * f_op;
off_t f_pos;
};
+typedef struct {
+ struct task_struct * old_task;
+ struct task_struct ** wait_address;
+} wait_entry;
+
+typedef struct select_table_struct {
+ int nr, woken;
+ struct task_struct * current;
+ struct select_table_struct * next_table;
+ wait_entry entry[NR_OPEN*3];
+} select_table;
+
struct super_block {
- unsigned long s_ninodes;
- unsigned long s_nzones;
- unsigned long s_imap_blocks;
- unsigned long s_zmap_blocks;
- unsigned long s_firstdatazone;
- unsigned long s_log_zone_size;
+ unsigned short s_ninodes;
+ unsigned short s_nzones;
+ unsigned short s_imap_blocks;
+ unsigned short s_zmap_blocks;
+ unsigned short s_firstdatazone;
+ unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
/* These are only in memory */
struct inode * s_covered;
struct inode * s_mounted;
unsigned long s_time;
- struct wait_queue * s_wait;
+ struct task_struct * s_wait;
unsigned char s_lock;
unsigned char s_rd_only;
unsigned char s_dirt;
/* TUBE */
struct super_operations *s_op;
- int s_flags;
};
struct file_operations {
int (*read) (struct inode *, struct file *, char *, int);
int (*write) (struct inode *, struct file *, char *, int);
int (*readdir) (struct inode *, struct file *, struct dirent *, int count);
+ int (*close) (struct inode *, struct file *);
int (*select) (struct inode *, struct file *, int, select_table *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned int);
- int (*open) (struct inode *, struct file *);
- void (*release) (struct inode *, struct file *);
};
struct inode_operations {
- struct file_operations * default_file_ops;
int (*create) (struct inode *,const char *,int,int,struct inode **);
int (*lookup) (struct inode *,const char *,int,struct inode **);
int (*link) (struct inode *,struct inode *,const char *,int);
int (*mknod) (struct inode *,const char *,int,int,int);
int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int);
int (*readlink) (struct inode *,char *,int);
+ int (*open) (struct inode *, struct file *);
+ void (*release) (struct inode *, struct file *);
struct inode * (*follow_link) (struct inode *, struct inode *);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
+ /* added by entropy */
+ void (*write_inode)(struct inode *inode);
+ void (*put_inode)(struct inode *inode);
};
struct super_operations {
void (*read_inode)(struct inode *inode);
- void (*write_inode) (struct inode *inode);
- void (*put_inode) (struct inode *inode);
void (*put_super)(struct super_block *sb);
- void (*write_super) (struct super_block *sb);
- void (*statfs) (struct super_block *sb, struct statfs *buf);
};
struct file_system_type {
extern int nr_buffers;
extern void check_disk_change(int dev);
-extern void invalidate_inodes(int dev);
extern int floppy_change(struct buffer_head * first_block);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
+extern void truncate(struct inode * inode);
extern void sync_inodes(void);
extern void wait_on(struct inode * inode);
extern int bmap(struct inode * inode,int block);
int follow_links);
extern int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode);
-extern int do_mknod(const char * filename, int mode, int dev);
extern void iput(struct inode * inode);
extern struct inode * iget(int dev,int nr);
extern struct inode * get_empty_inode(void);
extern struct buffer_head * breada(int dev,int block,...);
extern int sync_dev(int dev);
extern struct super_block * get_super(int dev);
-extern void put_super(int dev);
extern int ROOT_DEV;
extern void mount_root(void);
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
- unsigned long start;
};
#endif
void verify_area(void * addr,int count);
volatile void panic(const char * str);
volatile void do_exit(long error_code);
+int printf(const char * fmt, ...);
int printk(const char * fmt, ...);
+void console_print(const char * str);
void * malloc(unsigned int size);
void free_s(void * obj, int size);
+++ /dev/null
-#ifndef _LINUX_LIMITS_H
-#define _LINUX_LIMITS_H
-
-#define NR_OPEN 32
-#define NR_INODE 128
-#define NR_FILE 128
-#define NR_SUPER 8
-#define NR_HASH 307
-#define NR_BUFFERS nr_buffers
-#define BLOCK_SIZE 1024
-#define BLOCK_SIZE_BITS 10
-#define MAX_CHRDEV 16
-#define MAX_BLKDEV 16
-
-
-#endif
#define LP_B(minor) lp_table[(minor)].base
#define LP_F(minor) lp_table[(minor)].flags
+#define LP_T(minor) lp_table[(minor)].lp_task
#define LP_S(minor) inb(LP_B((minor)) + 1)
+#define LP_R(minor) lp_table[(minor)].remainder
/*
since we are dealing with a horribly slow device
struct lp_struct {
int base;
int flags;
+ /* number of characters yet to be printed in current block */
+ int remainder;
+ /* needed for busy determination */
+ int lp_task;
};
/*
* function prototypes
*/
-extern long lp_init(long);
+extern void lp_init(void);
void fdiv(const temp_real *, const temp_real *, temp_real *);
-/* sqrt.c */
-
-void fsqrt(const temp_real *, temp_real *);
-
/* compare.c */
void fcom(const temp_real *, const temp_real *);
extern int minix_open(struct inode * inode, struct file * filp);
extern void minix_release(struct inode * inode, struct file * filp);
+extern struct inode * minix_follow_link(struct inode * dir, struct inode * inode);
extern int minix_lookup(struct inode * dir,const char * name, int len,
struct inode ** result);
extern int minix_create(struct inode * dir,const char * name, int len, int mode,
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
+extern int minix_readlink(struct inode * inode, char * buffer, int buflen);
extern struct inode * minix_new_inode(int dev);
extern void minix_free_inode(struct inode * inode);
-extern unsigned long minix_count_free_inodes(struct super_block *sb);
extern int minix_new_block(int dev);
extern int minix_free_block(int dev, int block);
-extern unsigned long minix_count_free_blocks(struct super_block *sb);
extern int minix_create_block(struct inode *, int);
extern int minix_bmap(struct inode *,int);
extern struct super_block *minix_read_super(struct super_block *,void *);
extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
-extern void minix_put_inode(struct inode *);
-extern void minix_statfs(struct super_block *, struct statfs *);
extern int minix_lseek(struct inode *, struct file *, off_t, int);
extern int minix_read(struct inode *, struct file *, char *, int);
extern int minix_write(struct inode *, struct file *, char *, int);
+extern int minix_readdir(struct inode *, struct file *, struct dirent *, int);
extern int minix_file_read(struct inode *, struct file *, char *, int);
+extern int minix_file_write(struct inode *, struct file *, char *, int);
-extern struct inode_operations minix_file_inode_operations;
-extern struct inode_operations minix_dir_inode_operations;
-extern struct inode_operations minix_symlink_inode_operations;
-extern struct inode_operations minix_chrdev_inode_operations;
-extern struct inode_operations minix_blkdev_inode_operations;
-extern struct inode_operations minix_fifo_inode_operations;
+extern struct inode_operations minix_inode_operations;
extern struct file_operations minix_file_operations;
extern struct file_operations minix_dir_operations;
#define write_swap_page(nr,buf) \
rw_swap_page(WRITE,(nr),(buf))
-/* memory.c */
-
extern unsigned long get_free_page(void);
extern unsigned long put_dirty_page(unsigned long page,unsigned long address);
extern void free_page(unsigned long addr);
-extern int free_page_tables(unsigned long from,unsigned long size);
-extern int copy_page_tables(unsigned long from,unsigned long to,long size);
-extern int unmap_page_range(unsigned long from, unsigned long size);
-extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
- int permiss);
-extern void un_wp_page(unsigned long * table_entry);
-extern void do_wp_page(unsigned long error_code,unsigned long address);
-extern void write_verify(unsigned long address);
-extern void do_no_page(unsigned long error_code, unsigned long address,
- struct task_struct *tsk, unsigned long user_esp);
-extern void mem_init(long start_mem, long end_mem);
-extern void show_mem(void);
-extern void do_page_fault(unsigned long *esp, unsigned long error_code);
-
-/* swap.c */
-
-extern void swap_free(int page_nr);
-extern void swap_in(unsigned long *table_ptr);
+void swap_free(int page_nr);
+void swap_in(unsigned long *table_ptr);
extern inline volatile void oom(void)
{
+++ /dev/null
-/*
- * linux/include/linux/mouse.h: header file for Logitech Bus Mouse driver
- * by James Banks
- *
- * based on information gleamed from various mouse drivers on the net
- *
- * Heavily modified by David giller (rafetmad@oxy.edu)
- *
- * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
- * gt7080a@prism.gatech.edu (13JUL92)
- *
- */
-
-#ifndef _MOUSE_H
-#define _MOUSE_H
-
-#define MOUSE_IRQ 5
-
-#define MSE_DATA_PORT 0x23c
-#define MSE_SIGNATURE_PORT 0x23d
-#define MSE_CONTROL_PORT 0x23e
-#define MSE_INTERRUPT_PORT 0x23e
-#define MSE_CONFIG_PORT 0x23f
-
-#define MSE_ENABLE_INTERRUPTS 0x00
-#define MSE_DISABLE_INTERRUPTS 0x10
-
-#define MSE_READ_X_LOW 0x80
-#define MSE_READ_X_HIGH 0xa0
-#define MSE_READ_Y_LOW 0xc0
-#define MSE_READ_Y_HIGH 0xe0
-
-/* Magic number used to check if the mouse exists */
-#define MSE_CONFIG_BYTE 0x91
-#define MSE_DEFAULT_MODE 0x90
-#define MSE_SIGNATURE_BYTE 0xa5
-
-/* useful macros */
-
-#define MSE_INT_OFF() outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
-#define MSE_INT_ON() outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
-
-struct mouse_status
- {
- char buttons;
- char latch_buttons;
- int dx;
- int dy;
-
- int present;
- int ready;
- int active;
-
- struct inode *inode;
- };
-
-/* Function Prototypes */
-extern long mouse_init(long);
-
-#endif
-
+++ /dev/null
-/*
- * The MS-DOS filesystem constants/structures
- */
-
-#ifndef _MSDOS_FS_H
-#define _MSDOS_FS_H
-
-#include <sys/types.h>
-#include <linux/fs.h>
-
-#define MSDOS_ROOT_INO 1
-#define SECTOR_SIZE 512 /* sector size (bytes) */
-#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */
-#define MSDOS_DPB (MSDOS_DPS*2) /* dir entries per block */
-#define MSDOS_DPB_BITS 5 /* log2(MSDOS_DPB) */
-#define MSDOS_DPS (SECTOR_SIZE/sizeof(struct msdos_dir_entry))
-#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */
-#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */
-
-#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
-
-#define FAT_CACHE 8 /* FAT cache size */
-
-#define ATTR_RO 1 /* read-only */
-#define ATTR_HIDDEN 2 /* hidden */
-#define ATTR_SYS 4 /* system */
-#define ATTR_VOLUME 8 /* volume label */
-#define ATTR_DIR 16 /* directory */
-#define ATTR_ARCH 32 /* archived */
-
-#define ATTR_NONE 0 /* no attribute bits */
-#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS)
- /* attribute bits that are copied "as is" */
-
-#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
-
-#define D_START 0 /* i_data[0]: first cluster or 0 */
-#define D_ATTRS 1 /* i_data[1]: unused attribute bits */
-#define D_BUSY 2 /* i_data[2]: file is either deleted but still open, or
- inconsistent (mkdir) */
-#define D_DEPEND 3 /* i_data[3]: pointer to inode that depends on the current
- inode */
-#define D_OLD 4 /* i_data[4]: pointer to the old inode this inode depends
- on */
-#define D_BINARY 5 /* i_data[5]: file contains non-text data */
-
-#define SET_DIRTY(i) (i)->i_dirt = (i)->i_data[D_DIRT] = 1
-
-#define MSDOS_SB(s) ((struct msdos_sb_info *) s)
-
-#define MSDOS_NAME 11 /* maximum name length */
-#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
-#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
-
-#define MSDOS_FAT12 4086 /* maximum number of clusters in a 12 bit FAT */
-
-struct msdos_boot_sector {
- char ignored[13];
- unsigned char cluster_size; /* sectors/cluster */
- unsigned short reserved; /* reserved sectors */
- unsigned char fats; /* number of FATs */
- unsigned char dir_entries[2];/* root directory entries */
- unsigned char sectors[2]; /* number of sectors */
- unsigned char media; /* media code (unused) */
- unsigned short fat_length; /* sectors/FAT */
- unsigned short secs_track; /* sectors per track (unused) */
- unsigned short heads; /* number of heads (unused) */
- unsigned long hidden; /* hidden sectors (unused) */
- unsigned long total_sect; /* number of sectors (if sectors == 0) */
-};
-
-struct msdos_sb_info { /* space in struct super_block is 28 bytes */
- unsigned short cluster_size; /* sectors/cluster */
- unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
- unsigned short fat_start,fat_length; /* FAT start & length (sec.) */
- unsigned short dir_start,dir_entries; /* root dir start & entries */
- unsigned short data_start; /* first data sector */
- unsigned long clusters; /* number of clusters */
- uid_t fs_uid;
- gid_t fs_gid;
- unsigned short fs_umask;
- unsigned char name_check; /* r = releaxed, n = normal, s = strict */
- unsigned char conversion; /* b = binary, t = text, a = auto */
-}; /* 28 bytes */
-
-struct msdos_dir_entry {
- char name[8],ext[3]; /* name and extension */
- unsigned char attr; /* attribute bits */
- char unused[10];
- unsigned short time,date,start; /* time, date and first cluster */
- unsigned long size; /* file size (in bytes) */
-};
-
-struct fat_cache {
- int device; /* device number. 0 means unused. */
- int ino; /* inode number. */
- int file_cluster; /* cluster number in the file. */
- int disk_cluster; /* cluster number on disk. */
- struct fat_cache *next; /* next cache entry */
-};
-
-/* Determine whether this FS has kB-aligned data. */
-
-#define MSDOS_CAN_BMAP(mib) (!(((mib)->cluster_size & 1) || \
- ((mib)->data_start & 1)))
-
-/* Convert attribute bits and a mask to the UNIX mode. */
-
-#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? 0444 : (a & ATTR_HIDDEN ? 0 : \
- 0777)))
-
-/* Convert the UNIX mode to MS-DOS attribute bits. */
-
-#define MSDOS_MKATTR(m) (!(m & 0600) ? ATTR_HIDDEN : ((m & 0600) == 0400 ? \
- ATTR_RO : ATTR_NONE))
-
-
-static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
-{
- struct buffer_head *bh;
-
- if (!(bh = bread(dev,sector >> 1))) return NULL;
- *start = bh->b_data+((sector & 1) << SECTOR_BITS);
- return bh;
-}
-
-
-/* misc.c */
-
-extern int is_binary(char conversion,char *extension);
-extern void lock_creation(void);
-extern void unlock_creation(void);
-extern int msdos_add_cluster(struct inode *inode);
-extern int date_dos2unix(unsigned short time,unsigned short date);
-extern void date_unix2dos(int unix_date,unsigned short *time,
- unsigned short *date);
-extern int msdos_get_entry(struct inode *dir,int *pos,struct buffer_head **bh,
- struct msdos_dir_entry **de);
-extern int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh,
- struct msdos_dir_entry **res_de,int *ino);
-extern int msdos_parent_ino(struct inode *dir,int locked);
-
-/* fat.c */
-
-extern int fat_access(struct super_block *sb,int this,int new_value);
-extern int msdos_smap(struct inode *inode,int sector);
-extern int fat_free(struct inode *inode,int skip);
-extern void cache_init(void);
-void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu);
-void cache_add(struct inode *inode,int f_clu,int d_clu);
-void cache_inval_inode(struct inode *inode);
-void cache_inval_dev(int device);
-int get_cluster(struct inode *inode,int cluster);
-
-/* namei.c */
-
-extern int msdos_lookup(struct inode *dir,const char *name,int len,
- struct inode **result);
-extern int msdos_create(struct inode *dir,const char *name,int len,int mode,
- struct inode **result);
-extern int msdos_mkdir(struct inode *dir,const char *name,int len,int mode);
-extern int msdos_rmdir(struct inode *dir,const char *name,int len);
-extern int msdos_unlink(struct inode *dir,const char *name,int len);
-extern int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
- struct inode *new_dir,const char *new_name,int new_len);
-
-/* inode.c */
-
-extern void msdos_put_inode(struct inode *inode);
-extern void msdos_put_super(struct super_block *sb);
-extern struct super_block *msdos_read_super(struct super_block *s,void *data);
-extern void msdos_statfs(struct super_block *sb,struct statfs *buf);
-extern int msdos_bmap(struct inode *inode,int block);
-extern void msdos_read_inode(struct inode *inode);
-extern void msdos_write_inode(struct inode *inode);
-
-/* dir.c */
-
-extern struct file_operations msdos_dir_operations;
-extern struct inode_operations msdos_dir_inode_operations;
-
-/* file.c */
-
-extern struct file_operations msdos_file_operations;
-extern struct inode_operations msdos_file_inode_operations;
-extern struct inode_operations msdos_file_inode_operations_no_bmap;
-
-extern void msdos_truncate(struct inode *inode);
-
-#endif
#define MAX_SHARED_LIBS 6
+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 void sched_init(void);
-extern void show_state(void);
extern void schedule(void);
extern void trap_init(void);
extern void panic(const char * str);
long blocked; /* bitmap of masked signals */
/* various fields */
int exit_code;
- int dumpable;
unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,pgrp,session,leader;
int groups[NGROUPS];
/*
- * pointers to (original) parent process, youngest child, younger sibling,
+ * pointers to parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->p_pptr->pid)
*/
- struct task_struct *p_opptr,*p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
/*
- * For ease of programming... Normal sleeps don't need to
- * keep track of a wait-queue: every task has an entry of it's own
+ * sleep makes a singly linked list with this.
*/
- struct wait_queue wait;
+ struct task_struct *next_wait;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
- unsigned long timeout;
- unsigned long it_real_value, it_prof_value, it_virt_value;
- unsigned long it_real_incr, it_prof_incr, it_virt_incr;
+ unsigned long timeout,alarm;
long utime,stime,cutime,cstime,start_time;
unsigned long min_flt, maj_flt;
unsigned long cmin_flt, cmaj_flt;
#define INIT_TASK \
/* state etc */ { 0,15,15, \
/* signals */ 0,{{},},0, \
-/* ec,brk... */ 0,0,0,0,0,0,0, \
+/* ec,brk... */ 0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \
-/* proc links*/ &init_task.task,&init_task.task,NULL,NULL,NULL, \
-/* wait queue*/ {&init_task.task,NULL}, \
+/* proc links*/ &init_task.task,NULL,NULL,NULL,NULL, \
/* uid etc */ 0,0,0,0,0,0, \
-/* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
+/* timeout */ 0,0,0,0,0,0,0, \
/* min_flt */ 0,0,0,0, \
/* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
{0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
#define CURRENT_TIME (startup_time+(jiffies+jiffies_offset)/HZ)
extern void add_timer(long jiffies, void (*fn)(void));
-
-extern void sleep_on(struct wait_queue ** p);
-extern void interruptible_sleep_on(struct wait_queue ** p);
-extern void wake_up(struct wait_queue ** p);
-extern void wake_one_task(struct task_struct * p);
-
-extern int send_sig(long sig,struct task_struct * p,int priv);
+extern void sleep_on(struct task_struct ** p);
+extern void interruptible_sleep_on(struct task_struct ** p);
+extern void wake_up(struct task_struct ** p);
extern int in_group_p(gid_t grp);
-extern int request_irq(unsigned int irq,void (*handler)(int));
-extern void free_irq(unsigned int irq);
-extern int irqaction(unsigned int irq,struct sigaction * new);
-
/*
* Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
* 4-TSS0, 5-LDT0, 6-TSS1 etc ...
__asm__("cmpl %%ecx,_current\n\t" \
"je 1f\n\t" \
"movw %%dx,%1\n\t" \
- "cli\n\t" \
"xchgl %%ecx,_current\n\t" \
"ljmp %0\n\t" \
- "sti\n\t" \
"cmpl %%ecx,_last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
-extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
-{
- unsigned long flags;
- struct wait_queue * tmp;
-
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- wait->next = *p;
- tmp = wait;
- while (tmp->next)
- if ((tmp = tmp->next)->next == *p)
- break;
- *p = tmp->next = wait;
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
-}
-
-extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
-{
- unsigned long flags;
- struct wait_queue * tmp;
-
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- if (*p == wait)
- if ((*p = wait->next) == wait)
- *p = NULL;
- tmp = wait;
- while (tmp && tmp->next != wait)
- tmp = tmp->next;
- if (tmp)
- tmp->next = wait->next;
- wait->next = NULL;
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
-}
-
-extern inline void select_wait(struct wait_queue ** wait_address, select_table * p)
-{
- struct select_table_entry * entry = p->entry + p->nr;
-
- if (!wait_address)
- return;
- entry->wait_address = wait_address;
- entry->wait.task = current;
- add_wait_queue(wait_address,&entry->wait);
- p->nr++;
-}
-
static unsigned long inline _get_base(char * addr)
{
unsigned long __base;
return __limit+1;
}
-#define REMOVE_LINKS(p) \
- if ((p)->p_osptr) \
- (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
- if ((p)->p_ysptr) \
- (p)->p_ysptr->p_osptr = (p)->p_osptr; \
- else \
- (p)->p_pptr->p_cptr = (p)->p_osptr
-
-#define SET_LINKS(p) \
- (p)->p_ysptr = NULL; \
- if ((p)->p_osptr = (p)->p_pptr->p_cptr) \
- (p)->p_osptr->p_ysptr = p; \
- (p)->p_pptr->p_cptr = p
-
#endif
+++ /dev/null
-#ifndef _LINUX_STAT_H
-#define _LINUX_STAT_H
-
-struct old_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
-struct new_stat {
- unsigned short st_dev;
- unsigned short __pad1;
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned short __pad2;
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long __unused1;
- unsigned long st_mtime;
- unsigned long __unused2;
- unsigned long st_ctime;
- unsigned long __unused3;
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#define S_IFMT 00170000
-#define S_IFSOCK 0140000
-#define S_IFLNK 0120000
-#define S_IFREG 0100000
-#define S_IFBLK 0060000
-#define S_IFDIR 0040000
-#define S_IFCHR 0020000
-#define S_IFIFO 0010000
-#define S_ISUID 0004000
-#define S_ISGID 0002000
-#define S_ISVTX 0001000
-
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
-#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
-
-#define S_IRWXU 00700
-#define S_IRUSR 00400
-#define S_IWUSR 00200
-#define S_IXUSR 00100
-
-#define S_IRWXG 00070
-#define S_IRGRP 00040
-#define S_IWGRP 00020
-#define S_IXGRP 00010
-
-#define S_IRWXO 00007
-#define S_IROTH 00004
-#define S_IWOTH 00002
-#define S_IXOTH 00001
-
-#endif
#ifndef _STRING_H_
#define _STRING_H_
-#include <sys/types.h>
-
#ifndef NULL
#define NULL ((void *) 0)
#endif
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
extern char * strerror(int errno);
/*
extern inline char * strtok(char * s,const char * ct)
{
-register char * __res;
+register char * __res __asm__("si");
__asm__("testl %1,%1\n\t"
"jne 1f\n\t"
"testl %0,%0\n\t"
"jne 8f\n\t"
"movl %0,%1\n"
"8:"
- :"=b" (__res),"=S" (___strtok)
+#if __GNUC__ == 2
+ :"=r" (__res)
+#else
+ :"=b" (__res)
+#endif
+ ,"=S" (___strtok)
:"0" (___strtok),"1" (s),"g" (ct)
:"ax","cx","dx","di");
return __res;
extern int sys_statfs();
extern int sys_fstatfs();
extern int sys_ioperm();
-extern int sys_socketcall();
-extern int sys_syslog();
-extern int sys_getitimer();
-extern int sys_setitimer();
-extern int sys_newstat();
-extern int sys_newlstat();
-extern int sys_newfstat();
-extern int sys_newuname();
-extern int sys_iopl();
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_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
-sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
-sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat,
-sys_newlstat, sys_newfstat, sys_newuname, sys_iopl };
+sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
* HD_TIMER harddisk timer
*
* FLOPPY_TIMER floppy disk timer (not used right now)
- *
- * SCSI_TIMER scsi.c timeout timer
*/
#define BLANK_TIMER 0
#define HD_TIMER 16
#define FLOPPY_TIMER 17
-#define SCSI_TIMER 18
struct timer_struct {
unsigned long expires;
#ifndef _TTY_H
#define _TTY_H
-#include <asm/system.h>
-
-#define NR_CONSOLES 8
+#define MAX_CONSOLES 8
#define NR_SERIALS 4
#define NR_PTYS 4
-/*
- * This character is the same as _POSIX_VDISABLE: it cannot be used as
- * a c_cc[] character, but indicates that a particular special character
- * isn't in use (eg VINTR ahs no character etc)
- */
-#define __DISABLED_CHAR '\0'
+extern int NR_CONSOLES;
#include <termios.h>
unsigned long data;
unsigned long head;
unsigned long tail;
- struct wait_queue * proc_list;
- unsigned char buf[TTY_BUF_SIZE];
+ struct task_struct * proc_list;
+ char buf[TTY_BUF_SIZE];
};
-struct serial_struct {
- unsigned short type;
- unsigned short line;
- unsigned short port;
- unsigned short irq;
- struct tty_struct * tty;
-};
-
-/*
- * These are the supported serial types.
- */
-#define PORT_UNKNOWN 0
-#define PORT_8250 1
-#define PORT_16450 2
-#define PORT_16550 3
-#define PORT_16550A 4
-
#define IS_A_CONSOLE(min) (((min) & 0xC0) == 0x00)
#define IS_A_SERIAL(min) (((min) & 0xC0) == 0x40)
#define IS_A_PTY(min) ((min) & 0x80)
#define LAST(a) ((a)->buf[(TTY_BUF_SIZE-1)&((a)->head-1)])
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a)->head-(a)->tail)&(TTY_BUF_SIZE-1))
-
-extern void put_tty_queue(char c, struct tty_queue * queue);
-extern int get_tty_queue(struct tty_queue * queue);
+#define GETCH(queue,c) \
+(void)({c=(queue)->buf[(queue)->tail];INC((queue)->tail);})
+#define PUTCH(c,queue) \
+(void)({(queue)->buf[(queue)->head]=(c);INC((queue)->head);})
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
#define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP])
-#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
-#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
-#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
-
-#define L_CANON(tty) _L_FLAG((tty),ICANON)
-#define L_ISIG(tty) _L_FLAG((tty),ISIG)
-#define L_ECHO(tty) _L_FLAG((tty),ECHO)
-#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
-#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
-#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
-#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
-#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
-#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
-
-#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
-#define I_NLCR(tty) _I_FLAG((tty),INLCR)
-#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
-#define I_NOCR(tty) _I_FLAG((tty),IGNCR)
-#define I_IXON(tty) _I_FLAG((tty),IXON)
-#define I_STRP(tty) _I_FLAG((tty),ISTRIP)
-
-#define O_POST(tty) _O_FLAG((tty),OPOST)
-#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
-#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
-#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
-#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
-
-#define C_SPEED(tty) ((tty)->termios.c_cflag & CBAUD)
-#define C_HUP(tty) (C_SPEED((tty)) == B0)
-
struct tty_struct {
struct termios termios;
int pgrp;
int session;
int stopped;
- int flags;
- int count;
+ int busy;
struct winsize winsize;
void (*write)(struct tty_struct * tty);
- struct tty_struct *link;
struct tty_queue *read_q;
struct tty_queue *write_q;
struct tty_queue *secondary;
/*
* so that interrupts won't be able to mess up the
* queues, copy_to_cooked must be atomic with repect
- * to itself, as must tty->write. These are the flag
- * bit-numbers. Use the set_bit() and clear_bit()
- * macros to make it all atomic.
+ * to itself, as must tty->write.
*/
-#define TTY_WRITE_BUSY 0
-#define TTY_READ_BUSY 1
-#define TTY_CR_PENDING 2
-
-/*
- * These have to be done with inline assembly: that way the bit-setting
- * is guaranteed to be atomic. Both set_bit and clear_bit return 0
- * if the bit-setting went ok, != 0 if the bit already was set/cleared.
- */
-extern inline int set_bit(int nr,int * addr)
-{
- char ok;
-
- __asm__ __volatile__("btsl %1,%2\n\tsetb %0":
- "=q" (ok):"r" (nr),"m" (*(addr)));
- return ok;
-}
-
-extern inline int clear_bit(int nr, int * addr)
-{
- char ok;
-
- __asm__ __volatile__("btrl %1,%2\n\tsetnb %0":
- "=q" (ok):"r" (nr),"m" (*(addr)));
- return ok;
-}
-
-#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
-#define TTY_READ_FLUSH(tty) tty_read_flush((tty))
-
-extern void tty_write_flush(struct tty_struct *);
-extern void tty_read_flush(struct tty_struct *);
+#define TTY_WRITE_BUSY 1
+#define TTY_READ_BUSY 2
+
+#define TTY_WRITE_FLUSH(tty) \
+do { \
+ cli(); \
+ if (!EMPTY((tty)->write_q) && !(TTY_WRITE_BUSY & (tty)->busy)) { \
+ (tty)->busy |= TTY_WRITE_BUSY; \
+ sti(); \
+ (tty)->write((tty)); \
+ cli(); \
+ (tty)->busy &= ~TTY_WRITE_BUSY; \
+ } \
+ sti(); \
+} while (0)
+
+#define TTY_READ_FLUSH(tty) \
+do { \
+ cli(); \
+ if (!EMPTY((tty)->read_q) && !(TTY_READ_BUSY & (tty)->busy)) { \
+ (tty)->busy |= TTY_READ_BUSY; \
+ sti(); \
+ copy_to_cooked((tty)); \
+ cli(); \
+ (tty)->busy &= ~TTY_READ_BUSY; \
+ } \
+ sti(); \
+} while (0)
extern struct tty_struct tty_table[];
-extern struct serial_struct serial_table[];
-extern struct tty_struct * redirect;
extern int fg_console;
extern unsigned long video_num_columns;
extern unsigned long video_num_lines;
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-extern long rs_init(long);
-extern long lp_init(long);
-extern long con_init(long);
-extern long tty_init(long);
-
-extern void flush_input(struct tty_struct * tty);
-extern void flush_output(struct tty_struct * tty);
-extern void wait_until_sent(struct tty_struct * tty);
-extern void copy_to_cooked(struct tty_struct * tty);
+extern void rs_init(void);
+extern void lp_init(void);
+extern void con_init(void);
+extern void tty_init(void);
extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
-extern int is_orphaned_pgrp(int pgrp);
-extern int is_ignored(int sig);
-extern int tty_signal(int sig, struct tty_struct *tty);
-extern int kill_pg(int pgrp, int sig, int priv);
-
-/* tty write functions */
extern void rs_write(struct tty_struct * tty);
extern void con_write(struct tty_struct * tty);
extern void mpty_write(struct tty_struct * tty);
extern void spty_write(struct tty_struct * tty);
-/* serial.c */
-
-extern int serial_open(unsigned int line, struct file * filp);
-extern void serial_close(unsigned int line, struct file * filp);
-extern void change_speed(unsigned int line);
-extern void send_break(unsigned int line);
-extern int get_serial_info(unsigned int, struct serial_struct *);
-extern int set_serial_info(unsigned int, struct serial_struct *);
-
-/* pty.c */
-
-extern int pty_open(unsigned int dev, struct file * filp);
-extern void pty_close(unsigned int dev, struct file * filp);
+extern void serial_open(unsigned int line);
-/* console.c */
+void copy_to_cooked(struct tty_struct * tty);
void update_screen(int new_console);
-void blank_screen(void);
-void unblank_screen(void);
#endif
+++ /dev/null
-#ifndef _LINUX_UNISTD_H
-#define _LINUX_UNISTD_H
-
-/*
- * This file contains the system call numbers and the syscallX
- * macros
- */
-
-#define __NR_setup 0 /* used only by init, to get system going */
-#define __NR_exit 1
-#define __NR_fork 2
-#define __NR_read 3
-#define __NR_write 4
-#define __NR_open 5
-#define __NR_close 6
-#define __NR_waitpid 7
-#define __NR_creat 8
-#define __NR_link 9
-#define __NR_unlink 10
-#define __NR_execve 11
-#define __NR_chdir 12
-#define __NR_time 13
-#define __NR_mknod 14
-#define __NR_chmod 15
-#define __NR_chown 16
-#define __NR_break 17
-#define __NR_oldstat 18
-#define __NR_lseek 19
-#define __NR_getpid 20
-#define __NR_mount 21
-#define __NR_umount 22
-#define __NR_setuid 23
-#define __NR_getuid 24
-#define __NR_stime 25
-#define __NR_ptrace 26
-#define __NR_alarm 27
-#define __NR_oldfstat 28
-#define __NR_pause 29
-#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
-#define __NR_access 33
-#define __NR_nice 34
-#define __NR_ftime 35
-#define __NR_sync 36
-#define __NR_kill 37
-#define __NR_rename 38
-#define __NR_mkdir 39
-#define __NR_rmdir 40
-#define __NR_dup 41
-#define __NR_pipe 42
-#define __NR_times 43
-#define __NR_prof 44
-#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
-#define __NR_acct 51
-#define __NR_phys 52
-#define __NR_lock 53
-#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_mpx 56
-#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_olduname 59
-#define __NR_umask 60
-#define __NR_chroot 61
-#define __NR_ustat 62
-#define __NR_dup2 63
-#define __NR_getppid 64
-#define __NR_getpgrp 65
-#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_sgetmask 68
-#define __NR_ssetmask 69
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit 75
-#define __NR_getrlimit 76
-#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
-#define __NR_symlink 83
-#define __NR_oldlstat 84
-#define __NR_readlink 85
-#define __NR_uselib 86
-#define __NR_swapon 87
-#define __NR_reboot 88
-#define __NR_readdir 89
-#define __NR_mmap 90
-#define __NR_munmap 91
-#define __NR_truncate 92
-#define __NR_ftruncate 93
-#define __NR_fchmod 94
-#define __NR_fchown 95
-#define __NR_getpriority 96
-#define __NR_setpriority 97
-#define __NR_profil 98
-#define __NR_statfs 99
-#define __NR_fstatfs 100
-#define __NR_ioperm 101
-#define __NR_socketcall 102
-#define __NR_syslog 103
-#define __NR_setitimer 104
-#define __NR_getitimer 105
-#define __NR_stat 106
-#define __NR_lstat 107
-#define __NR_fstat 108
-#define __NR_uname 109
-#define __NR_iopl 110
-
-extern int errno;
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-#define _syscall0(type,name) \
-type name(void) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name)); \
-if (__res >= 0) \
- return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall1(type,name,atype,a) \
-type name(atype a) \
-{ \
-long __res; \
-__asm__ volatile ("movl %2,%%ebx\n\t" \
- "int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name),"g" ((long)(a)):"bx"); \
-if (__res >= 0) \
- return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall2(type,name,atype,a,btype,b) \
-type name(atype a,btype b) \
-{ \
-long __res; \
-__asm__ volatile ("movl %2,%%ebx\n\t" \
- "int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)):"bx"); \
-if (__res >= 0) \
- return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
-type name(atype a,btype b,ctype c) \
-{ \
-long __res; \
-__asm__ volatile ("movl %2,%%ebx\n\t" \
- "int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)),"d" ((long)(c)):"bx"); \
-if (__res>=0) \
- return (type) __res; \
-errno=-__res; \
-return -1; \
-}
-
-#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
-type name (atype a, btype b, ctype c, dtype d) \
-{ \
-long __res; \
-__asm__ volatile ("movl %2,%%ebx\n\t" \
- "int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
- "d" ((long)(c)),"S" ((long)(d))); \
-if (__res>=0) \
- return (type) __res; \
-errno=-__res; \
-return -1; \
-}
-
-#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
-type name (atype a,btype b,ctype c,dtype d,etype e) \
-{ \
-long __res; \
-__asm__ volatile ("movl %2,%%ebx\n\t" \
- "int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
- "d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \
-if (__res>=0) \
- return (type) __res; \
-errno=-__res; \
-return -1; \
-}
-
-#endif /* _LINUX_UNISTD_H */
+++ /dev/null
-#ifndef _LINUX_UTSNAME_H
-#define _LINUX_UTSNAME_H
-
-#define __OLD_UTS_LEN 8
-
-struct old_utsname {
- char sysname[9];
- char nodename[9];
- char release[9];
- char version[9];
- char machine[9];
-};
-
-#define __NEW_UTS_LEN 64
-
-struct new_utsname {
- char sysname[65];
- char nodename[65];
- char release[65];
- char version[65];
- char machine[65];
-};
-
-#endif
+++ /dev/null
-#ifndef _LINUX_WAIT_H
-#define _LINUX_WAIT_H
-
-#include <linux/limits.h>
-
-struct wait_queue {
- struct task_struct * task;
- struct wait_queue * next;
-};
-
-typedef struct select_table_struct {
- int nr;
- struct select_table_entry {
- struct wait_queue wait;
- struct wait_queue ** wait_address;
- } entry[NR_OPEN*3];
-} select_table;
-
-#endif
#define SIGPOLL SIGIO
#define SIGXCPU 24
#define SIGXFSZ 25
-*/
-
#define SIGVTALRM 26
#define SIGPROF 27
+*/
#define SIGWINCH 28
void (*sa_restorer)(void);
};
-#ifdef __cplusplus
-extern "C" {
-#endif
-
void (*signal(int _sig, void (*_func)(int)))(int);
int raise(int sig);
int kill(pid_t pid, int sig);
int sigsuspend(sigset_t *sigmask);
int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _SIGNAL_H */
#ifndef _SIZE_T
#define _SIZE_T
-typedef unsigned int size_t;
+typedef unsigned long size_t;
#endif
#undef NULL
#define _SYS_DIRENT_H
#include <limits.h>
-#include <sys/types.h>
struct dirent {
long d_ino;
#ifndef _SYS_PTRACE_H
#define _SYS_PTRACE_H
/* has the defines to get at the registers. */
-
-#define PTRACE_TRACEME 0
-#define PTRACE_PEEKTEXT 1
-#define PTRACE_PEEKDATA 2
-#define PTRACE_PEEKUSR 3
-#define PTRACE_POKETEXT 4
-#define PTRACE_POKEDATA 5
-#define PTRACE_POKEUSR 6
-#define PTRACE_CONT 7
-#define PTRACE_KILL 8
-#define PTRACE_SINGLESTEP 9
-
-#define PTRACE_ATTACH 0x10
-#define PTRACE_DETACH 0x11
-
/* use ptrace (3 or 6, pid, PT_EXCL, data); to read or write
the processes registers. */
int rlim_max;
};
-#define PRIO_MIN -99
-#define PRIO_MAX 14
-
-#define PRIO_PROCESS 0
-#define PRIO_PGRP 1
-#define PRIO_USER 2
-
#endif /* _SYS_RESOURCE_H */
+++ /dev/null
-#ifndef _SOCKET_H
-#define _SOCKET_H
-
-struct sockaddr {
- u_short sa_family; /* address family, AF_xxx */
- char sa_data[14]; /* 14 bytes of protocol address */
-};
-
-/*
- * socket types
- */
-#define SOCK_STREAM 1 /* stream (connection) socket */
-#define SOCK_DGRAM 2 /* datagram (connectionless) socket */
-#define SOCK_SEQPACKET 3 /* sequential packet socket */
-#define SOCK_RAW 4 /* raw socket */
-
-/*
- * supported address families
- */
-#define AF_UNSPEC 0
-#define AF_UNIX 1
-#define AF_INET 2
-
-/*
- * protocol families, same as address families
- */
-#define PF_UNIX AF_UNIX
-#define PF_INET AF_INET
-
-int socket(int family, int type, int protocol);
-int socketpair(int family, int type, int protocol, int sockvec[2]);
-int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
-int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
-int listen(int sockfd, int backlog);
-int accept(int sockfd, struct sockaddr *peer, int *paddrlen);
-int getsockname(int sockfd, struct sockaddr *addr, int *paddrlen);
-int getpeername(int sockfd, struct sockaddr *peer, int *paddrlen);
-
-#endif /* _SOCKET_H */
--- /dev/null
+#ifndef _SYS_STAT_H
+#define _SYS_STAT_H
+
+#include <sys/types.h>
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ umode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+};
+
+#define S_IFMT 00170000
+#define S_IFSOCK 0140000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+extern int chmod(const char *_path, mode_t mode);
+extern int fstat(int fildes, struct stat *stat_buf);
+extern int mkdir(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 mode_t umask(mode_t mask);
+
+#endif
struct timeval it_value; /* current value */
};
-int getitimer(int which, struct itimerval *value);
-int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
-
#include <time.h>
#include <sys/types.h>
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
-#include <stddef.h>
-
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif
-#ifndef _SSIZE_T
-#define _SSIZE_T
-typedef int ssize_t;
-#endif
-
#ifndef _TIME_T
#define _TIME_T
typedef long time_t;
#endif
-#ifndef _CLOCK_T
-#define _CLOCK_T
-typedef long clock_t;
-#endif
-
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef long ptrdiff_t;
typedef unsigned short uid_t;
typedef unsigned short gid_t;
typedef unsigned short dev_t;
-#ifdef OLD_LINUX
typedef unsigned short ino_t;
-#else
-typedef unsigned long ino_t;
-#endif
typedef unsigned short mode_t;
typedef unsigned short umode_t;
typedef unsigned short nlink_t;
typedef int daddr_t;
typedef long off_t;
-
-/* bsd */
typedef unsigned char u_char;
typedef unsigned short u_short;
-typedef unsigned int u_int;
typedef unsigned long u_long;
-
-/* sysv */
-typedef unsigned char unchar;
typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-
typedef char *caddr_t;
typedef unsigned char cc_t;
+++ /dev/null
-#ifndef _UN_H
-#define _UN_H
-
-struct sockaddr_un {
- u_short sun_family; /* AF_UNIX */
- char sun_path[108]; /* pathname */
-};
-
-#endif /* _UN_H */
+++ /dev/null
-#include <sys/ptrace.h>
-/* Core file format: The core file is written in such a way that gdb
- can understand it and provide useful information to the user (under
- linux we use the 'trad-core' bfd). There are quite a number of
- obstacles to being able to view the contents of the floating point
- registers, and until these are solved you will not be able to view the
- contents of them. Actually, you can read in the core file and look at
- the contents of the user struct to find out what the floating point
- registers contain.
- The actual file contents are as follows:
- UPAGE: 1 page consisting of a user struct that tells gdb what is present
- in the file. Directly after this is a copy of the task_struct, which
- is currently not used by gdb, but it may come in useful at some point.
- All of the registers are stored as part of the upage. The upage should
- always be only one page.
- DATA: The data area is stored. We use current->end_text to
- current->brk to pick up all of the user variables, plus any memory
- that may have been malloced. No attempt is made to determine if a page
- is demand-zero or if a page is totally unused, we just cover the entire
- range. All of the addresses are rounded in such a way that an integral
- number of pages is written.
- STACK: We need the stack information in order to get a meaningful
- backtrace. We need to write the data from (esp) to
- current->start_stack, so we round each of these off in order to be able
- to write an integer number of pages.
- The minimum core file size is 3 pages, or 12288 bytes.
-*/
-
-struct user_i387_struct {
- long cwd;
- long swd;
- long twd;
- long fip;
- long fcs;
- long foo;
- long fos;
- long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
-};
-
-/* When the kernel dumps core, it starts by dumping the user struct -
- this will be used by gdb to figure out where the data and stack segments
- are within the file, and what virtual addresses to use. */
-struct user{
-/* We start with the registers, to mimic the way that "memory" is returned
- from the ptrace(3,...) function. */
- struct pt_regs regs; /* Where the registers are actually stored */
-/* ptrace does not yet supply these. Someday.... */
- int u_fpvalid; /* True if math co-processor being used. */
- /* for this mess. Not yet used. */
- struct user_i387_struct i387; /* Math Co-processor registers. */
-/* The rest of this junk is to help gdb figure out what goes where */
- unsigned long int u_tsize; /* Text segment size (pages). */
- unsigned long int u_dsize; /* Data segment size (pages). */
- unsigned long int u_ssize; /* Stack segment size (pages). */
- unsigned long start_code; /* Starting virtual address of text. */
- unsigned long start_stack; /* Starting virtual address of stack area.
- This is actually the bottom of the stack,
- the top of the stack is always found in the
- esp register. */
- long int signal; /* Signal that caused the core dump. */
- char * u_comm; /* User command that was responsible */
- struct pt_regs * u_ar0; /* Used by gdb to help find the values for */
- /* the registers. */
- struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */
- unsigned long magic; /* To uniquely identify a core file */
-};
-#define NBPG 4096
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
--- /dev/null
+#ifndef _SYS_UTSNAME_H
+#define _SYS_UTSNAME_H
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+struct utsname {
+ char sysname[9];
+ char nodename[MAXHOSTNAMELEN+1];
+ char release[9];
+ char version[9];
+ char machine[9];
+};
+
+extern int uname(struct utsname * utsbuf);
+
+#endif
#define FIONREAD 0x541B
#define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
struct winsize {
unsigned short ws_row;
#define TCSADRAIN 1
#define TCSAFLUSH 2
-#ifdef __cplusplus
-extern "C" {
-#endif
-
extern speed_t cfgetispeed(struct termios *termios_p);
extern speed_t cfgetospeed(struct termios *termios_p);
extern int cfsetispeed(struct termios *termios_p, speed_t speed);
extern int tcsetattr(int fildes, int optional_actions,
struct termios *termios_p);
-#ifdef __cplusplus
-}
-#endif
-
#endif
#define CLOCKS_PER_SEC 100
-#ifndef _CLOCK_T
-#define _CLOCK_T
typedef long clock_t;
-#endif
struct tm {
int tm_sec;
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-#ifdef __cplusplus
-extern "C" {
-#endif
-
clock_t clock(void);
time_t time(time_t * tp);
double difftime(time_t time2, time_t time1);
size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
void tzset(void);
-#ifdef __cplusplus
-}
-#endif
-
#endif
#include <utime.h>
#ifdef __LIBRARY__
-#include <linux/unistd.h>
+
+#define __NR_setup 0 /* used only by init, to get system going */
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_waitpid 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_chown 16
+#define __NR_break 17
+#define __NR_stat 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_umount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_fstat 28
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_stty 31
+#define __NR_gtty 32
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_ftime 35
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_prof 44
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_phys 52
+#define __NR_lock 53
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_mpx 56
+#define __NR_setpgid 57
+#define __NR_ulimit 58
+#define __NR_uname 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_sgetmask 68
+#define __NR_ssetmask 69
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_select 82
+#define __NR_symlink 83
+#define __NR_lstat 84
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+/*
+ * Not all of these are implemented yet, but these are the
+ * numbers they will use.
+ */
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_profil 98
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name)); \
+if (__res >= 0) \
+ return (type) __res; \
+errno = -__res; \
+return -1; \
+}
+
+#define _syscall1(type,name,atype,a) \
+type name(atype a) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"g" ((long)(a)):"bx"); \
+if (__res >= 0) \
+ return (type) __res; \
+errno = -__res; \
+return -1; \
+}
+
+#define _syscall2(type,name,atype,a,btype,b) \
+type name(atype a,btype b) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)):"bx"); \
+if (__res >= 0) \
+ return (type) __res; \
+errno = -__res; \
+return -1; \
+}
+
+#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
+type name(atype a,btype b,ctype c) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)),"d" ((long)(c)):"bx"); \
+if (__res>=0) \
+ return (type) __res; \
+errno=-__res; \
+return -1; \
+}
+
+#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
+type name (atype a, btype b, ctype c, dtype d) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
+ "d" ((long)(c)),"S" ((long)(d))); \
+if (__res>=0) \
+ return (type) __res; \
+errno=-__res; \
+return -1; \
+}
+
+#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
+type name (atype a,btype b,ctype c,dtype d,etype e) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
+ "d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \
+if (__res>=0) \
+ return (type) __res; \
+errno=-__res; \
+return -1; \
+}
+
#endif /* __LIBRARY__ */
/* XXX - illegal. */
extern int errno;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* XXX - several non-POSIX functions here, and POSIX functions that are
* supposed to be declared elsewhere. Non-promotion of short types in
* prototypes may cause trouble. Arg names should be prefixed by
int select(int width, fd_set * readfds, fd_set * writefds,
fd_set * exceptfds, struct timeval * timeout);
int swapon(const char * specialfile);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif
time_t modtime;
};
-#ifdef __cplusplus
-extern "C" {
-#endif
-
extern int utime(const char *filename, struct utimbuf *times);
-#ifdef __cplusplus
-}
-#endif
-
#endif
* (C) 1991 Linus Torvalds
*/
-#include <stddef.h>
-#include <stdarg.h>
+#define __LIBRARY__
+#include <unistd.h>
#include <time.h>
-#include <sys/types.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <linux/fcntl.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/head.h>
-#include <linux/unistd.h>
-
/*
* we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
static inline _syscall0(int,sync)
-static inline _syscall0(pid_t,setsid)
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static inline _syscall1(int,dup,int,fd)
-static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-static inline _syscall1(int,close,int,fd)
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-static inline pid_t wait(int * wait_stat)
-{
- return waitpid(-1,wait_stat,0);
-}
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/head.h>
+#include <linux/string.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
static char printbuf[1024];
+extern char *strcpy();
extern int vsprintf();
extern void init(void);
-extern void init_IRQ(void);
-extern long blk_dev_init(long,long);
-extern long chr_dev_init(long,long);
+extern void blk_dev_init(void);
+extern void chr_dev_init(void);
extern void hd_init(void);
extern void floppy_init(void);
-extern void sock_init(void);
extern void mem_init(long start, long end);
extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm);
-#ifdef CONFIG_SCSI
-extern void scsi_dev_init(void);
-#endif
-
static int sprintf(char * str, const char *fmt, ...)
{
va_list args;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
- trap_init();
- init_IRQ();
- sched_init();
- main_memory_start = chr_dev_init(main_memory_start,memory_end);
- main_memory_start = blk_dev_init(main_memory_start,memory_end);
+#ifdef RAMDISK
+ main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
+#endif
mem_init(main_memory_start,memory_end);
+ trap_init();
+ chr_dev_init();
+ blk_dev_init();
time_init();
- printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
+ sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
- sock_init();
sti();
-#ifdef CONFIG_SCSI
- scsi_dev_init();
-#endif
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
}
/*
- * task[0] is meant to be used as an "idle" task: it may not sleep, but
- * it might do some general things like count free pages or it could be
- * used to implement a reasonable LRU algorithm for the paging routines:
- * anything that can be useful, but shouldn't take time from the real
- * processes.
- *
- * Right now task[0] just does a infinite loop in user mode.
+ * NOTE!! For any other task 'pause()' would mean we have to get a
+ * signal to awaken, but task0 is the sole exception (see 'schedule()')
+ * 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
+ * task can run, and if not we return here.
*/
for(;;)
- /* nothing */ ;
+ __asm__("int $0x80"::"a" (__NR_pause):"ax");
}
static int printf(const char *fmt, ...)
#
# Note 2! The CFLAGS definitions are now in the main makefile...
+AR =ar
+AS =as
+LD =ld
+LDFLAGS =-s -x
+CC =gcc -nostdinc -I../include
+CPP =cpp -nostdinc -I../include
+
+
.S.s:
$(CPP) -traditional $< -o $*.s
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) -c $<
-
-SUBDIRS = chr_drv blk_drv math
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
-OBJS = sched.o sys_call.o traps.o irq.o fork.o \
+OBJS = sched.o sys_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
- signal.o mktime.o ptrace.o ioport.o itimer.o
-
-all: kernel.o subdirs
+ signal.o mktime.o ptrace.o ioport.o
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS)
sync
-subdirs: dummy
- for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
-
sys_call.s: sys_call.S
sys_call.o: sys_call.s
clean:
rm -f core *.o *.a tmp_make sys_call.s
for i in *.c;do rm -f `basename $$i .c`.s;done
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
+ (cd chr_drv; make clean)
+ (cd blk_drv; make clean)
+ (cd math; make clean)
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+ $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
- for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
-
-dummy:
+ (cd chr_drv; make dep)
+ (cd blk_drv; make dep)
+ (cd math; make dep)
### Dependencies:
-exit.o : exit.c /usr/src/linux/include/errno.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/wait.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/asm/segment.h
-fork.o : fork.c /usr/src/linux/include/errno.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/asm/system.h
-ioport.o : ioport.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/errno.h
-irq.o : irq.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/ptrace.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/irq.h
-itimer.o : itimer.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h
-mktime.o : mktime.c /usr/src/linux/include/time.h
-panic.o : panic.c /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h
-printk.o : printk.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-ptrace.o : ptrace.c /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/errno.h /usr/src/linux/include/sys/ptrace.h
-sched.o : sched.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/sys.h \
- /usr/src/linux/include/linux/fdreg.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h
-signal.o : signal.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/wait.h \
- /usr/src/linux/include/sys/ptrace.h /usr/src/linux/include/errno.h
-sys.o : sys.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/config.h \
- /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
- /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/sys/times.h /usr/src/linux/include/linux/utsname.h /usr/src/linux/include/linux/string.h
-traps.o : traps.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/system.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/errno.h
-vsprintf.o : vsprintf.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.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/linux/head.h ../include/linux/fs.h \
+ ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/linux/tty.h ../include/termios.h ../include/asm/segment.h
+fork.s fork.o : fork.c ../include/errno.h ../include/stddef.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+ ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+ ../include/asm/segment.h ../include/asm/system.h
+ioport.s ioport.o : ioport.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+ ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+ ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/errno.h
+mktime.s mktime.o : mktime.c ../include/time.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/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h
+printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h ../include/linux/kernel.h
+ptrace.s ptrace.o : ptrace.c ../include/linux/head.h ../include/linux/kernel.h ../include/linux/sched.h \
+ ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/errno.h ../include/asm/segment.h \
+ ../include/asm/system.h ../include/sys/ptrace.h
+sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+ ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+ ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/linux/timer.h ../include/linux/sys.h \
+ ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h \
+ ../include/errno.h
+signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+ ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+ ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+ ../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/sys/wait.h \
+ ../include/errno.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/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/linux/tty.h \
+ ../include/termios.h ../include/linux/config.h ../include/linux/config_rel.h \
+ ../include/linux/config_ver.h ../include/asm/segment.h ../include/sys/times.h \
+ ../include/sys/utsname.h ../include/linux/string.h
+traps.s traps.o : traps.c ../include/linux/string.h ../include/linux/head.h ../include/linux/sched.h \
+ ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/system.h \
+ ../include/asm/segment.h ../include/asm/io.h ../include/errno.h
+vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/linux/string.h
* care about the stack layout etc.
*/
-.globl _floppy_interrupt,_parallel_interrupt
+.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
+
+_hd_interrupt:
+ cld
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ push %ds
+ push %es
+ push %fs
+ movl $0x10,%eax
+ mov %ax,%ds
+ mov %ax,%es
+ movl $0x17,%eax
+ mov %ax,%fs
+ movb $0x20,%al
+ outb %al,$0xA0 # EOI to interrupt controller #1
+ jmp 1f # give port chance to breathe
+1: jmp 1f
+1: outb %al,$0x20
+ andl $0xfffeffff,_timer_active
+ xorl %edx,%edx
+ xchgl _do_hd,%edx
+ testl %edx,%edx
+ jne 1f
+ movl $_unexpected_hd_interrupt,%edx
+1: call *%edx # "interesting" way of handling intr.
+ pop %fs
+ pop %es
+ pop %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ iret
_floppy_interrupt:
cld
# parent makefile.
#
+AR =ar
+AS =as
+LD =ld
+LDFLAGS =-s -x
+CC =gcc -nostdinc -I../../include
+CPP =cpp -nostdinc -I../../include
+
.c.s:
- $(CC) $(CFLAGS) $(RAMDISK) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) $(RAMDISK) -c $<
-
-SUBDIRS = scsi
-
-OBJS = hd.o ll_rw_blk.o floppy.o ramdisk.o
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
-all: blk_drv.a subdirs
+OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o
blk_drv.a: $(OBJS)
- rm -f blk_drv.a
$(AR) rcs blk_drv.a $(OBJS)
sync
-subdirs: dummy
- for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
-
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
- cd scsi; $(MAKE) clean
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+ $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
-dummy:
-
### Dependencies:
-floppy.o : floppy.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/fdreg.h \
- /usr/src/linux/include/linux/fd.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
- /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h blk.h
-hd.o : hd.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/config.h \
- /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
- /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/timer.h \
- /usr/src/linux/include/linux/hdreg.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
- /usr/src/linux/include/asm/segment.h blk.h
-ll_rw_blk.o : ll_rw_blk.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/system.h \
- blk.h
-ramdisk.o : ramdisk.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
- /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/minix_fs.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/memory.h \
+floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+ ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/linux/fdreg.h ../../include/asm/system.h ../../include/asm/io.h \
+ ../../include/asm/segment.h blk.h
+hd.s hd.o : hd.c ../../include/errno.h ../../include/linux/config.h ../../include/linux/config_rel.h \
+ ../../include/linux/config_ver.h ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/timer.h ../../include/linux/hdreg.h \
+ ../../include/asm/system.h ../../include/asm/io.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 \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/asm/system.h blk.h
+ramdisk.s ramdisk.o : ramdisk.c ../../include/linux/string.h ../../include/linux/config.h \
+ ../../include/linux/config_rel.h ../../include/linux/config_ver.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/asm/system.h \
+ ../../include/asm/segment.h ../../include/asm/memory.h blk.h
#ifndef _BLK_H
#define _BLK_H
-#define NR_BLK_DEV 10
+#define NR_BLK_DEV 7
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
unsigned long sector;
unsigned long nr_sectors;
char * buffer;
- struct wait_queue * waiting;
+ struct task_struct * waiting;
struct buffer_head * bh;
- struct buffer_head * bhtail;
struct request * next;
};
extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
extern struct request request[NR_REQUEST];
-extern struct wait_queue * wait_for_request;
+extern struct task_struct * wait_for_request;
extern int * blk_size[NR_BLK_DEV];
-extern int is_read_only(int dev);
-extern void set_device_ro(int dev,int flag);
-
-#define RO_IOCTLS(dev,where) \
- case BLKROSET: if (!suser()) return -EPERM; \
- set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
- case BLKROGET: put_fs_long(is_read_only(dev),(long *) (where)); return 0;
-
#ifdef MAJOR_NR
/*
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
-#elif (MAJOR_NR == 8)
-/* scsi disk */
-#define DEVICE_NAME "scsidisk"
-#define DEVICE_INTR do_sd
-#define DEVICE_REQUEST do_sd_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#elif (MAJOR_NR == 9)
-/* scsi tape */
-#define DEVICE_NAME "scsitape"
-#define DEVICE_INTR do_st
-#define DEVICE_REQUEST do_st_request
-#define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
#elif
/* unknown blk device */
#error "unknown blk device"
wake_up(&bh->b_wait);
}
-static void end_request(int uptodate)
+extern inline void end_request(int uptodate)
{
- struct request * req;
- struct buffer_head * bh;
-
- req = CURRENT;
- req->errors = 0;
+ DEVICE_OFF(CURRENT->dev);
+ if (CURRENT->bh) {
+ CURRENT->bh->b_uptodate = uptodate;
+ unlock_buffer(CURRENT->bh);
+ }
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
- printk("dev %04x, sector %d\n\r",req->dev,req->sector);
- req->nr_sectors--;
- req->nr_sectors &= ~1;
- req->sector += 2;
- req->sector &= ~1;
- }
- if (bh = req->bh) {
- req->bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
- bh->b_uptodate = uptodate;
- unlock_buffer(bh);
- if (bh = req->bh) {
- if (req->nr_sectors < 2) {
- req->nr_sectors = 2;
- printk("end_request: buffer-list destroyed\n");
- }
- req->buffer = bh->b_data;
- return;
- }
+ printk("dev %04x, block %d\n\r",CURRENT->dev,
+ CURRENT->bh->b_blocknr);
}
- DEVICE_OFF(req->dev);
- CURRENT = req->next;
- wake_up(&req->waiting);
- req->dev = -1;
+ wake_up(&CURRENT->waiting);
wake_up(&wait_for_request);
+ CURRENT->dev = -1;
+ CURRENT = CURRENT->next;
}
#ifdef DEVICE_INTR
* by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
*/
-/*
- * Automatic floppy-detection and formatting written by Werner Almesberger
- * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
- * the floppy-change signal detection.
- */
-
-#define FLOPPY_IRQ 6
-
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
#include <linux/fdreg.h>
-#include <linux/fd.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
-#include <errno.h>
#define MAJOR_NR 2
#include "blk.h"
-static unsigned int changed_floppies = 0, fake_change = 0;
+unsigned int changed_floppies = 0;
static int recalibrate = 0;
static int reset = 0;
-static int recover = 0; /* recalibrate immediately after resetting */
static int seek = 0;
extern unsigned char current_DOR;
*/
#define MAX_ERRORS 12
-/*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
- */
-
-#define MAX_DISK_SIZE 1440
-
-/*
- * Maximum number of sectors in a track buffer. Track buffering is disabled
- * if tracks are bigger.
- */
-
-#define MAX_BUFFER_SECTORS 18
-
/*
* globals used by 'result()'
*/
* types (ie 360kB diskette in 1.2MB drive etc). Others should
* be self-explanatory.
*/
-
-static struct floppy_struct floppy_type[] = {
- { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* no testing */
- { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,NULL }, /* 360kB PC diskettes */
- { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,NULL }, /* 1.2 MB AT-diskettes */
- { 720, 9,2,40,1,0x2A,0x02,0xDF,0x50,NULL }, /* 360kB in 720kB drive */
- { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,NULL }, /* 3.5" 720kB diskette */
- { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,NULL }, /* 360kB in 1.2MB drive */
- { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,NULL }, /* 720kB in 1.2MB drive */
- { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }, /* 1.44MB diskette */
-};
-
-/* For auto-detection. Each drive type has a pair of formats to try. */
-
-static struct floppy_struct floppy_types[] = {
- { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
- { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
- { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M" }, /* 1.2 MB AT-diskettes */
- { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"360k/AT" }, /* 360kB in 1.2MB drive */
- { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" }, /* 3.5" 720kB diskette */
- { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" }, /* 3.5" 720kB diskette */
- { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M" }, /* 1.44MB diskette */
- { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k/AT" }, /* 3.5" 720kB diskette */
+struct floppy_struct {
+ unsigned int size, sect, head, track, stretch;
+ unsigned char gap,rate,spec1;
};
-/* Auto-detection: Disk type used until the next media change occurs. */
-
-struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
-
-/* This type is tried first. */
-
-struct floppy_struct *base_type[4];
-
-/* User-provided type information. current_type points to the respective entry
- of this array. */
-
-struct floppy_struct user_params[4];
-
-static int floppy_sizes[] ={
- MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE,
- 360, 360 ,360, 360,
- 1200,1200,1200,1200,
- 360, 360, 360, 360,
- 720, 720, 720, 720,
- 360, 360, 360, 360,
- 720, 720, 720, 720,
- 1440,1440,1440,1440
+static struct floppy_struct floppy_type[] = {
+ { 0, 0,0, 0,0,0x00,0x00,0x00 }, /* no testing */
+ { 720, 9,2,40,0,0x2A,0x02,0xDF }, /* 360kB PC 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 */
+ { 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 */
+ { 1440, 9,2,80,0,0x23,0x01,0xDF }, /* 720kB in 1.2MB drive */
+ { 2880,18,2,80,0,0x1B,0x00,0xCF }, /* 1.44MB diskette */
};
-/* The driver is trying to determine the correct media format while probing
- is set. rw_interrupts clears it after a successful access. */
-
-static int probing = 0;
-
-/* (User-provided) media information is _not_ discarded after a media change
- if the corresponding keep_data flag is non-zero. Positive values are
- decremented after each probe. */
-
-static int keep_data[4] = { 0,0,0,0 };
-
-/* Announce successful media type detection and media information loss after
- disk changes. */
-
-static ftd_msg[4] = { 1,1,1,1 };
-
-/* Synchronization of FDC access. */
-
-static volatile int format_status = FORMAT_NONE, fdc_busy = 0;
-static struct wait_queue *fdc_wait = NULL, *format_done = NULL;
-
-/* Errors during formatting are counted here. */
-
-static int format_errors;
-
-/* Format request descriptor. */
-
-static struct format_descr format_req;
-
-/* Current device number. Taken either from the block header or from the
- format request descriptor. */
-
-#define CURRENT_DEVICE (format_status == FORMAT_BUSY ? format_req.device : \
- (CURRENT->dev))
-
-/* Current error count. */
-
-#define CURRENT_ERRORS (format_status == FORMAT_BUSY ? format_errors : \
- (CURRENT->errors))
-
/*
* 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),
* and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
*/
+extern void floppy_interrupt(void);
extern char tmp_floppy_area[1024];
-extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
-
-static void redo_fd_request(void);
+extern char floppy_track_buffer[512*2*18];
/*
* These are global variables, as that's the easiest way to give
static unsigned char current_track = NO_TRACK;
static unsigned char command = 0;
unsigned char selected = 0;
-struct wait_queue * wait_on_floppy_select = NULL;
+struct task_struct * wait_on_floppy_select = NULL;
void floppy_deselect(unsigned int nr)
{
wake_up(&wait_on_floppy_select);
}
-void request_done(int uptodate)
-{
- timer_active &= ~(1 << FLOPPY_TIMER);
- if (format_status != FORMAT_BUSY) end_request(uptodate);
- else {
- format_status = uptodate ? FORMAT_OKAY : FORMAT_ERROR;
- wake_up(&format_done);
- }
-}
-
/*
* 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
unsigned int mask = 1 << (bh->b_dev & 0x03);
if (MAJOR(bh->b_dev) != 2) {
- printk("floppy_changed: not a floppy\r\n");
+ printk("floppy_changed: not a floppy\n");
return 0;
}
- if (fake_change & mask) {
- fake_change &= ~mask;
-/* omitting the next line breaks formatting in a horrible way ... */
- changed_floppies &= ~mask;
- return 1;
- }
if (changed_floppies & mask) {
changed_floppies &= ~mask;
recalibrate = 1;
changed_floppies &= ~mask;
recalibrate = 1;
return 1;
- }
+ }
return 0;
}
static void setup_DMA(void)
{
- unsigned long addr,count;
+ unsigned long addr = (long) CURRENT->buffer;
+ unsigned long count = 1024;
- if (command == FD_FORMAT) {
- addr = (long) tmp_floppy_area;
- count = floppy->sect*4;
- }
- else {
- addr = (long) CURRENT->buffer;
- count = 1024;
- }
+ cli();
if (read_track) {
/* mark buffer-track bad, in case all this fails.. */
buffer_drive = buffer_track = -1;
copy_buffer(CURRENT->buffer,tmp_floppy_area);
}
/* mask DMA 2 */
- cli();
immoutb_p(4|2,10);
/* output command byte. I don't know why, but everyone (minix, */
/* sanches & canton) output this twice, first to 12 then to 11 */
static void bad_flp_intr(void)
{
current_track = NO_TRACK;
- CURRENT_ERRORS++;
- if (CURRENT_ERRORS > MAX_ERRORS) {
+ CURRENT->errors++;
+ if (CURRENT->errors > MAX_ERRORS) {
floppy_deselect(current_drive);
- request_done(0);
+ end_request(0);
}
- if (CURRENT_ERRORS > MAX_ERRORS/2)
+ if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
else
recalibrate = 1;
if (ST1 & 0x02) {
printk("Drive %d is write protected\n\r",current_drive);
floppy_deselect(current_drive);
- request_done(0);
+ end_request(0);
} else
bad_flp_intr();
- redo_fd_request();
+ do_fd_request();
return;
}
- if (probing) {
- int drive = MINOR(CURRENT->dev);
-
- if (ftd_msg[drive])
- printk("Auto-detected floppy type %s in fd%d\r\n",
- floppy->name,drive);
- current_type[drive] = floppy;
- floppy_sizes[drive] = floppy->size >> 1;
- probing = 0;
- }
if (read_track) {
buffer_track = seek_track;
buffer_drive = current_drive;
(unsigned long)(CURRENT->buffer) >= 0x100000)
copy_buffer(tmp_floppy_area,CURRENT->buffer);
floppy_deselect(current_drive);
- request_done(1);
- redo_fd_request();
+ end_request(1);
+ do_fd_request();
}
/*
setup_DMA();
do_floppy = rw_interrupt;
output_byte(command);
- if (command != FD_FORMAT) {
- if (read_track) {
- output_byte(current_drive);
- output_byte(track);
- output_byte(0);
- output_byte(1);
- } else {
- output_byte(head<<2 | current_drive);
- output_byte(track);
- output_byte(head);
- output_byte(sector);
- }
- output_byte(2); /* sector size = 512 */
- output_byte(floppy->sect);
- output_byte(floppy->gap);
- output_byte(0xFF); /* sector size (0xff when n!=0 ?) */
+ if (read_track) {
+ output_byte(current_drive);
+ output_byte(track);
+ output_byte(0);
+ output_byte(1);
} else {
output_byte(head<<2 | current_drive);
- output_byte(2);
- output_byte(floppy->sect);
- output_byte(floppy->fmt_gap);
- output_byte(FD_FILL_BYTE);
- }
+ output_byte(track);
+ output_byte(head);
+ output_byte(sector);
+ }
+ output_byte(2); /* sector size = 512 */
+ output_byte(floppy->sect);
+ output_byte(floppy->gap);
+ output_byte(0xFF); /* sector size (0xff when n!=0 ?) */
if (reset)
- redo_fd_request();
+ do_fd_request();
}
/*
if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
recalibrate = 1;
bad_flp_intr();
- redo_fd_request();
+ do_fd_request();
return;
}
current_track = ST1;
*/
static void transfer(void)
{
- read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) &&
- (floppy->sect <= MAX_BUFFER_SECTORS);
+ read_track = (command == FD_READ) && (CURRENT->errors < 4);
if (cur_spec1 != floppy->spec1) {
cur_spec1 = floppy->spec1;
output_byte(FD_SPECIFY);
if (cur_rate != floppy->rate)
outb_p(cur_rate = floppy->rate,FD_DCR);
if (reset) {
- redo_fd_request();
+ do_fd_request();
return;
}
if (!seek) {
output_byte((head<<2) | current_drive);
output_byte(seek_track);
if (reset)
- redo_fd_request();
+ do_fd_request();
}
/*
* Special case - used after a unexpected interrupt (or reset)
*/
-
-static void recalibrate_floppy();
-
static void recal_interrupt(void)
{
output_byte(FD_SENSEI);
current_track = NO_TRACK;
if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1;
-/* Recalibrate until track 0 is reached. Might help on some errors. */
- if ((ST0 & 0x10) == 0x10) recalibrate_floppy();
- else redo_fd_request();
+ do_fd_request();
}
-static void unexpected_floppy_interrupt(void)
+void unexpected_floppy_interrupt(void)
{
current_track = NO_TRACK;
output_byte(FD_SENSEI);
output_byte(FD_RECALIBRATE);
output_byte(head<<2 | current_drive);
if (reset)
- redo_fd_request();
+ do_fd_request();
}
static void reset_interrupt(void)
output_byte(FD_SPECIFY);
output_byte(cur_spec1); /* hut etc */
output_byte(6); /* Head load time =6ms, DMA */
- if (!recover) redo_fd_request();
- else {
- recalibrate_floppy();
- recover = 0;
- }
+ do_fd_request();
}
/*
sti();
}
-static void floppy_shutdown(void)
-{
- cli();
- request_done(0);
- recover = 1;
- reset_floppy();
- sti();
-}
-
-static void shake_done(void)
-{
- current_track = NO_TRACK;
- if (inb(FD_DIR) & 0x80) request_done(0);
- redo_fd_request();
-}
-
-static int retry_recal(void (*proc)(void))
-{
- output_byte(FD_SENSEI);
- if (result() == 2 && (ST0 & 0x10) != 0x10) return 0;
- do_floppy = proc;
- output_byte(FD_RECALIBRATE);
- output_byte(head<<2 | current_drive);
- return 1;
-}
-
-static void shake_zero(void)
-{
- if (!retry_recal(shake_zero)) shake_done();
-}
-
-static void shake_one(void)
-{
- if (retry_recal(shake_one)) return;
- do_floppy = shake_done;
- output_byte(FD_SEEK);
- output_byte(head << 2 | current_drive);
- output_byte(1);
-}
-
static void floppy_on_interrupt(void)
{
if (inb(FD_DIR) & 0x80) {
changed_floppies |= 1<<current_drive;
buffer_track = -1;
- if (keep_data[current_drive]) {
- if (keep_data[current_drive] > 0)
- keep_data[current_drive]--;
- }
- else {
- if (ftd_msg[current_drive] && current_type[
- current_drive] != NULL)
- printk("Disk type is undefined after disk "
- "change in fd%d\r\n",current_drive);
- current_type[current_drive] = NULL;
- floppy_sizes[current_drive] = MAX_DISK_SIZE;
- }
-/* Forcing the drive to seek makes the "media changed" condition go away.
- There should be a cleaner solution for that ... */
- if (!reset && !recalibrate) {
- do_floppy = (current_track && current_track != NO_TRACK)
- ? shake_zero : shake_one;
- output_byte(FD_RECALIBRATE);
- output_byte(head<<2 | current_drive);
- return;
- }
}
if (reset) {
reset_floppy();
transfer();
}
-static void setup_format_params(void)
-{
- unsigned char *here = (unsigned char *) tmp_floppy_area;
- int count;
-
- for (count = 1; count <= floppy->sect; count++) {
- *here++ = track;
- *here++ = head;
- *here++ = count;
- *here++ = 2; /* 512 bytes */
- }
-}
-
-static void redo_fd_request(void)
+void do_fd_request(void)
{
unsigned int block;
char * buffer_area;
- int device;
-
-repeat:
- if (format_status == FORMAT_WAIT) format_status = FORMAT_BUSY;
- if (format_status != FORMAT_BUSY) {
- if (!CURRENT) {
- if (!fdc_busy) panic("FDC access conflict");
- fdc_busy = 0;
- wake_up(&fdc_wait);
- CLEAR_INTR;
- return;
- }
- if (MAJOR(CURRENT->dev) != MAJOR_NR)
- panic(DEVICE_NAME ": request list destroyed"); \
- if (CURRENT->bh) {
- if (!CURRENT->bh->b_lock)
- panic(DEVICE_NAME ": block not locked");
- }
- }
+
+ INIT_REQUEST;
seek = 0;
- probing = 0;
- device = MINOR(CURRENT_DEVICE);
- if (device > 3)
- floppy = (device >> 2) + floppy_type;
- else { /* Auto-detection */
- if ((floppy = current_type[device & 3]) == NULL) {
- probing = 1;
- if ((floppy = base_type[device & 3]) ==
- NULL) {
- request_done(0);
- goto repeat;
- }
- floppy += CURRENT_ERRORS & 1;
- }
- }
- if (format_status != FORMAT_BUSY) {
- if (current_drive != CURRENT_DEV)
- current_track = NO_TRACK;
- current_drive = CURRENT_DEV;
- block = CURRENT->sector;
- if (block+2 > floppy->size) {
- request_done(0);
- goto repeat;
- }
- sector = block % floppy->sect;
- block /= floppy->sect;
- head = block % floppy->head;
- track = block / floppy->head;
- seek_track = track << floppy->stretch;
- if (CURRENT->cmd == READ)
- command = FD_READ;
- else if (CURRENT->cmd == WRITE)
- command = FD_WRITE;
- else {
- printk("do_fd_request: unknown command\n");
- request_done(0);
- goto repeat;
- }
- }
+ floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
+ if (current_drive != CURRENT_DEV)
+ current_track = NO_TRACK;
+ current_drive = CURRENT_DEV;
+ block = CURRENT->sector;
+ if (block+2 > floppy->size) {
+ end_request(0);
+ goto repeat;
+ }
+ sector = block % floppy->sect;
+ block /= floppy->sect;
+ head = block % floppy->head;
+ track = block / floppy->head;
+ seek_track = track << floppy->stretch;
+ if (CURRENT->cmd == READ)
+ command = FD_READ;
+ else if (CURRENT->cmd == WRITE)
+ command = FD_WRITE;
else {
- if (current_drive != (format_req.device & 3))
- current_track = NO_TRACK;
- current_drive = format_req.device & 3;
- if (((unsigned) format_req.track) >= floppy->track ||
- (format_req.head & 0xfffe) || probing) {
- request_done(0);
- goto repeat;
- }
- head = format_req.head;
- track = format_req.track;
- seek_track = track << floppy->stretch;
- if (seek_track == buffer_track) buffer_track = -1;
- command = FD_FORMAT;
- setup_format_params();
+ printk("do_fd_request: unknown command\n");
+ end_request(0);
+ goto repeat;
}
- timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ;
- timer_active |= 1 << FLOPPY_TIMER;
if ((seek_track == buffer_track) &&
(current_drive == buffer_drive)) {
buffer_area = floppy_track_buffer +
((sector + head*floppy->sect)<<9);
if (command == FD_READ) {
copy_buffer(buffer_area,CURRENT->buffer);
- request_done(1);
+ end_request(1);
goto repeat;
- } else if (command == FD_WRITE)
+ } else
copy_buffer(CURRENT->buffer,buffer_area);
}
if (seek_track != current_track)
add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
}
-void do_fd_request(void)
-{
- cli();
- while (fdc_busy) sleep_on(&fdc_wait);
- fdc_busy = 1;
- sti();
- redo_fd_request();
-}
-
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned int param)
-{
- int drive,cnt,okay;
- struct floppy_struct *this;
-
- switch (cmd) {
- RO_IOCTLS(inode->i_rdev,param);
- }
- if (!suser()) return -EPERM;
- drive = MINOR(inode->i_rdev);
- switch (cmd) {
- case FDFMTBEG:
- return 0;
- case FDFMTEND:
- cli();
- fake_change |= 1 << (drive & 3);
- sti();
- drive &= 3;
- cmd = FDCLRPRM;
- break;
- case FDGETPRM:
- if (drive > 3) this = &floppy_type[drive >> 2];
- else if ((this = current_type[drive & 3]) == NULL)
- return -ENODEV;
- verify_area((void *) param,sizeof(struct floppy_struct));
- for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
- put_fs_byte(((char *) this)[cnt],
- (char *) param+cnt);
- return 0;
- case FDFMTTRK:
- cli();
- while (format_status != FORMAT_NONE)
- sleep_on(&format_done);
- for (cnt = 0; cnt < sizeof(struct format_descr); cnt++)
- ((char *) &format_req)[cnt] = get_fs_byte(
- (char *) param+cnt);
- format_req.device = drive;
- format_status = FORMAT_WAIT;
- format_errors = 0;
- while (format_status != FORMAT_OKAY && format_status !=
- FORMAT_ERROR) {
- if (fdc_busy) sleep_on(&fdc_wait);
- else {
- fdc_busy = 1;
- redo_fd_request();
- }
- }
- while (format_status != FORMAT_OKAY && format_status !=
- FORMAT_ERROR)
- sleep_on(&format_done);
- sti();
- okay = format_status == FORMAT_OKAY;
- format_status = FORMAT_NONE;
- wake_up(&format_done);
- return okay ? 0 : -EIO;
- }
- if (drive < 0 || drive > 3) return -EINVAL;
- switch (cmd) {
- case FDCLRPRM:
- current_type[drive] = NULL;
- floppy_sizes[drive] = MAX_DISK_SIZE;
- keep_data[drive] = 0;
- break;
- case FDSETPRM:
- case FDDEFPRM:
- for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
- ((char *) &user_params[drive])[cnt] =
- get_fs_byte((char *) param+cnt);
- current_type[drive] = &user_params[drive];
- floppy_sizes[drive] = user_params[drive].size >> 1;
- if (cmd == FDDEFPRM) keep_data[drive] = -1;
- else {
- cli();
- while (fdc_busy) sleep_on(&fdc_wait);
- fdc_busy = 1;
- sti();
- outb_p((current_DOR & 0xfc) | drive |
- (0x10 << drive),FD_DOR);
- for (cnt = 0; cnt < 1000; cnt++) __asm__("nop");
- keep_data[drive] = (inb(FD_DIR) & 0x80) ? 1 : 0;
- outb_p(current_DOR,FD_DOR);
- fdc_busy = 0;
- wake_up(&fdc_wait);
- }
- break;
- case FDMSGON:
- ftd_msg[drive] = 1;
- break;
- case FDMSGOFF:
- ftd_msg[drive] = 0;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
-inb_p(0x71); \
-})
-
-static struct floppy_struct *find_base(int drive,int code)
-{
- struct floppy_struct *base;
-
- if (code > 0 && code < 5) {
- base = &floppy_types[(code-1)*2];
- printk("fd%d is %s",drive,base->name);
- return base;
- }
- printk("fd%d is unknown type %d",drive,code);
- return NULL;
-}
-
-static void config_types(void)
-{
- printk("Floppy drive(s): ");
- base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
- if (((CMOS_READ(0x14) >> 6) & 1) == 0)
- base_type[1] = NULL;
- else {
- printk(", ");
- base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
- }
- base_type[2] = base_type[3] = NULL;
- printk("\r\n");
-}
-
-static int floppy_open(struct inode * inode, struct file * filp)
-{
- if (filp->f_mode)
- check_disk_change(inode->i_rdev);
- return 0;
-}
-
-static void floppy_release(struct inode * inode, struct file * filp)
-{
- sync_dev(inode->i_rdev);
-}
+static int floppy_sizes[] ={
+ 0, 0, 0, 0,
+ 360, 360 ,360, 360,
+ 1200,1200,1200,1200,
+ 360, 360, 360, 360,
+ 720, 720, 720, 720,
+ 360, 360, 360, 360,
+ 720, 720, 720, 720,
+ 1440,1440,1440,1440
+};
static struct file_operations floppy_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
+ NULL, /* close - default */
NULL, /* select */
- fd_ioctl, /* ioctl */
- floppy_open, /* open */
- floppy_release /* release */
-};
-
-static void floppy_interrupt(int cpl)
-{
- void (*handler)(void) = DEVICE_INTR;
-
- DEVICE_INTR = NULL;
- if (!handler)
- handler = unexpected_floppy_interrupt;
- handler();
-}
-
-/*
- * This is the harddisk IRQ descruption. The SA_INTERRUPT in sa_flags
- * means we run the IRQ-handler with interrupts disabled: this is bad for
- * interrupt latency, but may be safer...
- */
-static struct sigaction floppy_sigaction = {
- floppy_interrupt,
- 0,
- SA_INTERRUPT,
- NULL
+ NULL /* ioctl */
};
void floppy_init(void)
blk_size[MAJOR_NR] = floppy_sizes;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &floppy_fops;
- timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
- timer_active &= ~(1 << FLOPPY_TIMER);
- config_types();
- if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
- printk("Unable to grab IRQ%d for the floppy driver\n",FLOPPY_IRQ);
+ set_intr_gate(0x26,&floppy_interrupt);
+ outb(inb_p(0x21)&~0x40,0x21);
}
* in the early extended-partition checks and added DM partitions
*/
-#define HD_IRQ 14
-
#include <errno.h>
-#include <signal.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
-
-#define REALLY_SLOW_IO
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
return inb_p(0x71);
}
-#define HD_DELAY 0
-
/* Max read/write errors/sector */
#define MAX_ERRORS 7
#define MAX_HD 2
static int recalibrate = 0;
static int reset = 0;
-#if (HD_DELAY > 0)
-unsigned long last_req, read_timer();
-#endif
-
/*
* This struct defines the HD's and their types.
*/
#define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
+extern void hd_interrupt(void);
extern void rd_load(void);
static unsigned int current_minor;
blk_size[MAJOR_NR] = hd_sizes;
if (NR_HD)
printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
-#ifdef RAMDISK
rd_load();
-#endif
mount_root();
return (0);
}
-#if (HD_DELAY > 0)
-unsigned long read_timer(void)
-{
- unsigned long t;
- int i;
-
- cli();
- outb_p(0xc2, 0x43);
- t = jiffies * 11931 + (inb_p(0x40) & 0x80 ? 5966 : 11932);
- i = inb_p(0x40);
- i |= inb(0x40) << 8;
- sti();
- return(t - i / 2);
-}
-#endif
-
static int controller_ready(void)
{
int retries = 100000;
if (drive>1 || head>15)
panic("Trying to write bad sector");
-#if (HD_DELAY > 0)
- while (read_timer() - last_req < HD_DELAY)
- /* nothing */;
-#endif
if (reset || !controller_ready()) {
reset = 1;
return;
outb_p(cyl,++port);
outb_p(cyl>>8,++port);
outb_p(0xA0|(drive<<4)|head,++port);
- outb_p(cmd,++port);
+ outb(cmd,++port);
}
static int drive_busy(void)
{
int i;
- printk("HD-controller reset\r\n");
outb(4,HD_CMD);
for(i = 0; i < 1000; i++) nop();
outb(hd_info[0].ctl & 0x0f ,HD_CMD);
return;
if (++CURRENT->errors >= MAX_ERRORS)
end_request(0);
- else if (CURRENT->errors > MAX_ERRORS/2)
+ if (CURRENT->errors > MAX_ERRORS/2)
reset = 1;
else
recalibrate = 1;
}
-#define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
-#define STAT_OK (READY_STAT | SEEK_STAT)
-
static void read_intr(void)
{
- int i;
-
- i = (unsigned) inb_p(HD_STATUS);
- if (!(i & DRQ_STAT))
- goto bad_read;
- if ((i & STAT_MASK) != STAT_OK)
- goto bad_read;
+ SET_INTR(&read_intr);
+ if (win_result()) {
+ SET_INTR(NULL);
+ bad_rw_intr();
+ do_hd_request();
+ return;
+ }
port_read(HD_DATA,CURRENT->buffer,256);
- i = (unsigned) inb_p(HD_STATUS);
- if (!(i & BUSY_STAT))
- if ((i & STAT_MASK) != STAT_OK)
- goto bad_read;
CURRENT->errors = 0;
CURRENT->buffer += 512;
CURRENT->sector++;
- i = --CURRENT->nr_sectors;
- if (!i || (CURRENT->bh && !(i&1)))
- end_request(1);
- if (i > 0) {
- SET_INTR(&read_intr);
+ if (--CURRENT->nr_sectors)
return;
- }
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- do_hd_request();
- return;
-bad_read:
- if (i & ERR_STAT)
- i = (unsigned) inb(HD_ERROR);
- bad_rw_intr();
+ SET_INTR(NULL);
+ end_request(1);
do_hd_request();
- return;
}
static void write_intr(void)
{
- int i;
-
- i = (unsigned) inb_p(HD_STATUS);
- if ((i & STAT_MASK) != STAT_OK)
- goto bad_write;
- if (CURRENT->nr_sectors > 1 && !(i & DRQ_STAT))
- goto bad_write;
- CURRENT->sector++;
- i = --CURRENT->nr_sectors;
- CURRENT->buffer += 512;
- if (!i || (CURRENT->bh && !(i & 1)))
- end_request(1);
- if (i > 0) {
+ if (win_result()) {
+ bad_rw_intr();
+ do_hd_request();
+ return;
+ }
+ if (--CURRENT->nr_sectors) {
+ CURRENT->sector++;
+ CURRENT->buffer += 512;
SET_INTR(&write_intr);
port_write(HD_DATA,CURRENT->buffer,256);
- } else {
-#if (HD_DELAY > 0)
- last_req = read_timer();
-#endif
- do_hd_request();
+ return;
}
- return;
-bad_write:
- if (i & ERR_STAT)
- i = (unsigned) inb(HD_ERROR);
- bad_rw_intr();
+ end_request(1);
do_hd_request();
- return;
}
static void recal_intr(void)
*/
static void hd_times_out(void)
{
- DEVICE_INTR = NULL;
+ do_hd = NULL;
reset = 1;
if (!CURRENT)
return;
dev = MINOR(CURRENT->dev);
block = CURRENT->sector;
nsect = CURRENT->nr_sectors;
- if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
+ if (dev >= (NR_HD<<6) || block+nsect > hd[dev].nr_sects) {
end_request(0);
goto repeat;
}
}
if (recalibrate) {
recalibrate = 0;
- hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+ hd_out(dev,hd_info[dev].sect,0,0,0,
+ WIN_RESTORE,&recal_intr);
if (reset)
goto repeat;
return;
return -EINVAL;
switch (cmd) {
case HDIO_REQ:
- verify_area(loc, sizeof(*loc));
put_fs_byte(hd_info[dev].head,
(char *) &loc->heads);
put_fs_byte(hd_info[dev].sect,
(char *) &loc->sectors);
put_fs_word(hd_info[dev].cyl,
(short *) &loc->cylinders);
- put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
- (long *) &loc->start);
return 0;
- RO_IOCTLS(inode->i_rdev,arg);
default:
return -EINVAL;
}
}
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-static void hd_release(struct inode * inode, struct file * file)
-{
- sync_dev(inode->i_rdev);
-}
-
static struct file_operations hd_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
+ NULL, /* close - default */
NULL, /* select */
- hd_ioctl, /* ioctl */
- NULL, /* no special open code */
- hd_release /* release */
-};
-
-static void hd_interrupt(int cpl)
-{
- void (*handler)(void) = DEVICE_INTR;
-
- DEVICE_INTR = NULL;
- timer_active &= ~(1<<HD_TIMER);
- if (!handler)
- handler = unexpected_hd_interrupt;
- handler();
-}
-
-/*
- * This is the harddisk IRQ descruption. The SA_INTERRUPT in sa_flags
- * means we run the IRQ-handler with interrupts disabled: this is bad for
- * interrupt latency, but anything else has led to problems on some
- * machines...
- */
-static struct sigaction hd_sigaction = {
- hd_interrupt,
- 0,
- SA_INTERRUPT,
- NULL
+ hd_ioctl /* ioctl */
};
void hd_init(void)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &hd_fops;
- if (irqaction(HD_IRQ,&hd_sigaction))
- printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
+ set_intr_gate(0x2E,&hd_interrupt);
+ outb_p(inb_p(0x21)&0xfb,0x21);
+ outb(inb_p(0xA1)&0xbf,0xA1);
timer_table[HD_TIMER].fn = hd_times_out;
}
* This handles all read/write requests to block devices
*/
#include <errno.h>
-#include <linux/string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include "blk.h"
-extern long rd_init(long mem_start, int length);
-
/*
* The request-struct contains all necessary data
* to load a nr of sectors into memory
/*
* used to wait on when there are no free requests
*/
-struct wait_queue * wait_for_request = NULL;
+struct task_struct * wait_for_request = NULL;
/* blk_dev_struct is:
* do_request-address
{ NULL, NULL }, /* dev hd */
{ NULL, NULL }, /* dev ttyx */
{ NULL, NULL }, /* dev tty */
- { NULL, NULL }, /* dev lp */
- { NULL, NULL }, /* dev pipes */
- { NULL, NULL }, /* dev sd */
- { NULL, NULL } /* dev st */
+ { NULL, NULL } /* dev lp */
};
/*
wake_up(&bh->b_wait);
}
-/* RO fail safe mechanism */
-
-static long ro_bits[NR_BLK_DEV][8];
-
-int is_read_only(int dev)
-{
- int minor,major;
-
- major = MAJOR(dev);
- minor = MINOR(dev);
- if (major < 0 || major >= NR_BLK_DEV) return 0;
- return ro_bits[major][minor >> 5] & (1 << (minor & 31));
-}
-
-void set_device_ro(int dev,int flag)
-{
- int minor,major;
-
- major = MAJOR(dev);
- minor = MINOR(dev);
- if (major < 0 || major >= NR_BLK_DEV) return;
- if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
- else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
-}
-
/*
* add-request adds a request to the linked list.
* It disables interrupts so that it can muck with the
printk("Bad block dev command, must be R/W/RA/WA\n");
return;
}
- if (blk_size[major])
- if (blk_size[major][MINOR(bh->b_dev)] <= bh->b_blocknr) {
- bh->b_dirt = bh->b_uptodate = 0;
- return;
- }
lock_buffer(bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
unlock_buffer(bh);
return;
}
repeat:
- cli();
- if (major == 3 && (req = blk_dev[major].current_request)) {
- while (req = req->next) {
- if (req->dev == bh->b_dev &&
- !req->waiting &&
- req->cmd == rw &&
- req->sector + req->nr_sectors == bh->b_blocknr << 1 &&
- req->nr_sectors < 254) {
- req->bhtail->b_reqnext = bh;
- req->bhtail = bh;
- req->nr_sectors += 2;
- bh->b_dirt = 0;
- sti();
- return;
- }
- }
- }
/* 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
* of the requests are only for reads.
else
req = request+(NR_REQUEST/2);
/* find an empty request */
+ cli();
while (--req >= request)
if (req->dev < 0)
goto found;
/* fill up the request-info, and add it to the queue */
req->dev = bh->b_dev;
req->cmd = rw;
- req->errors = 0;
+ req->errors=0;
req->sector = bh->b_blocknr<<1;
req->nr_sectors = 2;
req->buffer = bh->b_data;
req->waiting = NULL;
req->bh = bh;
- req->bhtail = bh;
req->next = NULL;
add_request(major+blk_dev,req);
}
}
if (rw!=READ && rw!=WRITE)
panic("Bad block dev command, must be R/W");
- if (rw == WRITE && is_read_only(dev)) {
- printk("Can't page to read-only device 0x%X\n\r",dev);
- return;
- }
cli();
repeat:
req = request+NR_REQUEST;
req->sector = page<<3;
req->nr_sectors = 8;
req->buffer = buffer;
- req->waiting = ¤t->wait;
+ req->waiting = current;
req->bh = NULL;
req->next = NULL;
current->state = TASK_UNINTERRUPTIBLE;
{
unsigned int major;
- if (!bh)
- return;
if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
!(blk_dev[major].request_fn)) {
printk("ll_rw_block: Trying to read nonexistent block-device\n\r");
- bh->b_dirt = bh->b_uptodate = 0;
- return;
- }
- if ((rw == WRITE || rw == WRITEA) && is_read_only(bh->b_dev)) {
- printk("Can't write to read-only device 0x%X\n\r",bh->b_dev);
- bh->b_dirt = bh->b_uptodate = 0;
return;
}
make_request(major,rw,bh);
}
-long blk_dev_init(long mem_start, long mem_end)
+void blk_dev_init(void)
{
int i;
request[i].dev = -1;
request[i].next = NULL;
}
- memset(ro_bits,0,sizeof(ro_bits));
-#ifdef RAMDISK
- mem_start += rd_init(mem_start, RAMDISK*1024);
-#endif
- return mem_start;
}
void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
printk("ll_rw_swap: bad block dev command, must be R/W");
return;
}
- if (rw == WRITE && is_read_only(dev)) {
- printk("Can't swap to read-only device 0x%X\n\r",dev);
- return;
- }
for (i=0; i<nb; i++, buf += BLOCK_SIZE)
{
req->sector = b[i] << 1;
req->nr_sectors = 2;
req->buffer = buf;
- req->waiting = ¤t->wait;
+ req->waiting = current;
req->bh = NULL;
req->next = NULL;
current->state = TASK_UNINTERRUPTIBLE;
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
+ NULL, /* close - default */
NULL, /* select */
- NULL, /* ioctl */
- NULL, /* no special open code */
- NULL /* no special release code */
+ NULL /* ioctl */
};
/*
void rd_load(void)
{
struct buffer_head *bh;
- struct minix_super_block s;
+ struct super_block s;
int block = 256; /* Start at block 256 */
int i = 1;
int nblocks;
nblocks, rd_length >> BLOCK_SIZE_BITS);
return;
}
- printk("Loading %d bytes into ram disk\n",
+ printk("Loading %d bytes into ram disk... 0000k",
nblocks << BLOCK_SIZE_BITS);
cp = rd_start;
while (nblocks) {
}
(void) memcpy(cp, bh->b_data, BLOCK_SIZE);
brelse(bh);
- if (!(nblocks-- & 15))
- printk(".");
+ printk("\010\010\010\010\010%4dk",i);
cp += BLOCK_SIZE;
block++;
+ nblocks--;
i++;
}
- printk("\ndone\n");
+ printk("\010\010\010\010\010done \n");
ROOT_DEV=0x0101;
}
+++ /dev/null
-#
-# Makefile for the linux kernel block device drivers.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-#DEBUG = -DDEBUG=0xffffffff -DDEBUG_NO_CMD
-
-.c.s:
- $(CC) $(CFLAGS) $(DEBUG) -S $<
-.s.o:
- $(AS) -c -o $*.o $<
-.c.o:
- $(CC) $(CFLAGS) $(DEBUG) -c $<
-
-LOWLEVELCSRC = aha1542.c seagate.c ultrastor.c
-LOWLEVELHSRC = aha1542.c seagate.h ultrastor.h
-
-CSRC = hosts.c sd.c st.c scsi.c $(LOWLEVELCSRC)
-HSRC = hosts.h sd.h st.h scsi.h $(LOWLEVELHSRC)
-
-OBJS = scsi.o hosts.o scsi_ioctl.o sd.o sd_ioctl.o st.o st_ioctl.o \
- aha1542.o seagate.o ultrastor.o
-
-all: scsi.a
-
-config.out : config.in $(KERNELHDRS)/linux/config.h
- rm -f foo.c
- ln -s config.in foo.c
- $(CPP) foo.c | grep '\.o' > config.out
- rm foo.c
-
-figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c config.out
- $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
-
-max_hosts.h : figure
- (echo "#ifndef _MAX_HOSTS_H"; \
- echo "#define _MAX_HOSTS_H"; \
- echo "#define MAX_SCSI_HOSTS `./figure`";\
- echo "#endif") > tmp_max
- cp tmp_max max_hosts.h
-
-scsi.a: $(OBJS)
- $(AR) rcs scsi.a $(OBJS)
- sync
-
-scsi.shar: Makefile scsi.doc $(CSRC) $(HSRC) ../ll_rw_blk.c ../blk.h all.diff
- (cd ..; shar scsi/scsi.doc scsi/Makefile scsi/*.{c,h} scsi/all.diff blk.h ll_rw_blk.c) > scsi.shar;
-
-clean:
- rm -f core *.o *.a tmp_make tmp_max figure config.out Makefile.tag max_hosts.h
-
-seagate.s seagate.o : seagate.c ../../../include/linux/config.h \
- ../../../include/linux/config.dist.h ../../../include/linux/sched.h \
- ../../../include/linux/head.h ../../../include/linux/fs.h \
- ../../../include/sys/types.h ../../../include/linux/mm.h \
- ../../../include/linux/kernel.h ../../../include/signal.h \
- ../../../include/sys/param.h ../../../include/sys/time.h \
- ../../../include/time.h ../../../include/sys/resource.h \
- ../../../include/linux/string.h seagate.h scsi.h hosts.h max_hosts.h
- $(CC) -Wall -c seagate.c $(DEBUG)
-
-dep:
- sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c ;do $(CPP) -M $$i;done >> tmp_make
- cp tmp_make Makefile
-
-### Dependencies:
-aha1542.s aha1542.o : aha1542.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
- ../../../include/linux/head.h ../../../include/linux/string.h ../../../include/asm/system.h \
- ../../../include/asm/io.h scsi.h hosts.h max_hosts.h aha1542.h
-hosts.s hosts.o : hosts.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
- scsi.h hosts.h max_hosts.h aha1542.h seagate.h ultrastor.h
-scsi.s scsi.o : scsi.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/asm/system.h \
- ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
- ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
- ../../../include/linux/mm.h ../../../include/linux/kernel.h ../../../include/signal.h \
- ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
- ../../../include/sys/resource.h ../../../include/linux/timer.h ../../../include/linux/string.h \
- scsi.h hosts.h max_hosts.h sd.h st.h
-scsi_ioctl.s scsi_ioctl.o : scsi_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/errno.h \
- ../../../include/asm/io.h ../../../include/asm/segment.h ../../../include/asm/system.h \
- ../../../include/linux/kernel.h ../../../include/linux/sched.h ../../../include/linux/head.h \
- ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
- ../../../include/limits.h ../../../include/linux/mm.h ../../../include/signal.h \
- ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
- ../../../include/sys/resource.h ../../../include/linux/string.h scsi.h hosts.h \
- max_hosts.h scsi_ioctl.h
-sd.s sd.o : sd.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/string.h \
- ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
- ../../../include/limits.h ../../../include/linux/kernel.h ../../../include/linux/sched.h \
- ../../../include/linux/head.h ../../../include/linux/mm.h ../../../include/signal.h \
- ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
- ../../../include/sys/resource.h scsi.h sd.h ../blk.h
-sd_ioctl.s sd_ioctl.o : sd_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
- ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
- ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
- ../../../include/linux/mm.h ../../../include/signal.h ../../../include/sys/param.h \
- ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
- scsi.h sd.h
-seagate.s seagate.o : seagate.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/sched.h \
- ../../../include/linux/head.h ../../../include/linux/fs.h ../../../include/sys/types.h \
- ../../../include/sys/dirent.h ../../../include/limits.h ../../../include/linux/mm.h \
- ../../../include/linux/kernel.h ../../../include/signal.h ../../../include/sys/param.h \
- ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
- seagate.h scsi.h hosts.h max_hosts.h
-st.s st.o : st.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h scsi.h \
- st.h ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
- ../../../include/limits.h ../../../include/linux/kernel.h ../../../include/linux/sched.h \
- ../../../include/linux/head.h ../../../include/linux/mm.h ../../../include/signal.h \
- ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
- ../../../include/sys/resource.h ../blk.h
-st_ioctl.s st_ioctl.o : st_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
- ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
- ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
- ../../../include/linux/mm.h ../../../include/signal.h ../../../include/sys/param.h \
- ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
- st.h scsi.h
-ultrastor.s ultrastor.o : ultrastor.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
- ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/stddef.h \
- ../../../include/linux/string.h ../../../include/linux/sched.h ../../../include/linux/head.h \
- ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
- ../../../include/limits.h ../../../include/linux/mm.h ../../../include/linux/kernel.h \
- ../../../include/signal.h ../../../include/sys/param.h ../../../include/sys/time.h \
- ../../../include/time.h ../../../include/sys/resource.h ../../../include/linux/hdreg.h \
- ../../../include/asm/system.h ../../../include/asm/io.h ../../../include/asm/segment.h \
- ultrastor.h scsi.h hosts.h max_hosts.h
+++ /dev/null
-/* $Id: aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $
- * linux/kernel/aha1542.c
- *
- * (C) 1992 Tommy Thorn
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/head.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <sys/types.h>
-#include "scsi.h"
-#include "hosts.h"
-
-#include "aha1542.h"
-#ifdef DEBUG
-#define DEB(x) x
-#else
-#define DEB(x)
-#endif
-
-/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
-*/
-
-#define base 0x330
-#define intr_chan 11
-
-static struct mailbox mb[2];
-static struct ccb ccb;
-
-long WAITtimeout, WAITnexttimeout = 3000000;
-
-void (*do_done)() = NULL;
-
-#define aha1542_intr_reset() outb(IRST, CONTROL)
-#define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
-#define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1)
-
-#define WAIT(port, mask, allof, noneof) \
- { register WAITbits; \
- register WAITtimeout = WAITnexttimeout; \
- while (1) { \
- WAITbits = inb(port) & (mask); \
- if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
- break; \
- if (--WAITtimeout == 0) goto fail; \
- } \
- }
-
-static void aha1542_stat(void)
-{
- int s = inb(STATUS), i = inb(INTRFLAGS);
-/* printk("status = %x, intrflags = %x served %d last %x timeout %d\n", s, i, intr_flag, intr_last, WAITtimeout); */
- printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout);
-}
-
-static int aha1542_out(unchar *cmdp, int len)
-{
- while (len--)
- {
- WAIT(STATUS, CDF, 0, CDF);
- outb(*cmdp++, DATA);
- }
- return 0;
- fail:
- printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
- return 1;
-}
-
-int makecode(unsigned hosterr, unsigned scsierr)
-{
- switch (hosterr) {
- case 0x0:
- case 0xa: /* Linked command complete without error and linked normally */
- case 0xb: /* Linked command complete without error, interrupt generated */
- hosterr = 0;
- break;
-
- case 0x11: /* Selection time out-The initiator selection or target
- reselection was not complete within the SCSI Time out period */
- hosterr = DID_TIME_OUT;
- break;
-
- case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
- thean was allocated by the Data Length field or the sum of the
- Scatter / Gather Data Length fields. */
-
- case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
-
- case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
- invalid. This usually indicates a software failure. */
-
- case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
- This usually indicates a software failure. */
-
- case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
- of linked CCB's does not specify the same logical unit number as
- the first. */
- case 0x18: /* Invalid Target Direction received from Host-The direction of a
- Target Mode CCB was invalid. */
-
- case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
- received to service data transfer between the same target LUN
- and initiator SCSI ID in the same direction. */
-
- case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
- length segment or invalid segment list boundaries was received.
- A CCB parameter was invalid. */
- hosterr = DID_ERROR; /* Couldn't find any better */
- break;
-
- case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
- phase sequence was requested by the target. The host adapter
- will generate a SCSI Reset Condition, notifying the host with
- a SCRD interrupt */
- hosterr = DID_RESET;
- break;
- default:
- printk("makecode: unknown hoststatus %x\n", hosterr);
- break;
- }
- return scsierr|(hosterr << 16);
-}
-
-int aha1542_test_port(void)
-{
- volatile int debug = 0;
-
- /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
-
- /* DEB(printk("aha1542_test_port called \n")); */
-
- outb(SRST|IRST/*|SCRST*/, CONTROL);
-
- debug = 1;
- /* Expect INIT and IDLE, any of the others are bad */
- WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
-
- debug = 2;
- /* Shouldn't have generated any interrupts during reset */
- if (inb(INTRFLAGS)&INTRMASK) goto fail;
-
- debug = 3;
- /* Test the basic ECHO command */
- outb(CMD_ECHO, DATA);
-
- debug = 4;
- /* Wait for CDF=0. If any of the others are set, it's bad */
- WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
-
- debug = 5;
- /* The meaning of life */
- outb(42, DATA);
-
- debug = 6;
- /* Expect only DF, that is, data ready */
- WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
-
- debug = 7;
- /* Is the answer correct? */
- if (inb(DATA) != 42) goto fail;
-
- debug = 8;
- /* Reading port should reset DF */
- if (inb(STATUS) & DF) goto fail;
-
- debug = 9;
- /* When HACC, command is completed, and we're though testing */
- WAIT(INTRFLAGS, HACC, HACC, 0);
- /* now initialize adapter */
-
- debug = 10;
- /* Clear interrupts */
- outb(IRST, CONTROL);
-
- debug = 11;
-
- return debug; /* 1 = ok */
- fail:
- return 0; /* 0 = not ok */
-}
-
-/* What's this little function for? */
-char *aha1542_info(void)
-{
- static char buffer[] = "Adaptec 1542";
- return buffer;
-}
-
-/* A "high" level interrupt handler */
-static void aha1542_interrupt(int cpl)
-{
- int flag = inb(INTRFLAGS);
- void (*my_done)() = do_done;
- int errstatus;
-
- do_done = NULL;
-#ifdef DEBUG
- printk("aha1542_interrupt: ");
- if (!(flag&ANYINTR)) printk("no interrupt?");
- if (flag&MBIF) printk("MBIF ");
- if (flag&MBOA) printk("MBOF ");
- if (flag&HACC) printk("HACC ");
- if (flag&SCRD) printk("SCRD ");
- printk("status %02x\n", inb(STATUS));
- if (ccb.tarstat|ccb.hastat)
- printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
-#endif
- aha1542_intr_reset();
- if (!my_done) {
- printk("aha1542_interrupt: Unexpected interrupt\n");
- return;
- }
-
- /* is there mail :-) */
-
- if (!mb[1].status) {
- DEB(printk("aha1542_interrupt: strange: mbif but no mail!\n"));
- my_done(DID_TIME_OUT << 16);
- return;
- }
-
- /* more error checking left out here */
- if (mb[1].status != 1)
- /* This is surely wrong, but I don't know what's right */
- errstatus = makecode(ccb.hastat, ccb.tarstat);
- else
- errstatus = 0;
-
- mb[1].status = 0;
-
- if (ccb.tarstat == 2) {
- int i;
- DEB(printk("aha1542_interrupt: sense:"));
- for (i = 0; i < 12; i++)
- printk("%02x ", ccb.cdb[ccb.cdblen+i]);
- printk("\n");
-/*
- DEB(printk("aha1542_interrupt: buf:"));
- for (i = 0; i < bufflen; i++)
- printk("%02x ", ((unchar *)buff)[i]);
- printk("\n");
-*/
- }
- DEB(if (errstatus) printk("aha1542_interrupt: returning %6x\n", errstatus));
- my_done(errstatus);
- return;
-}
-
-int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int))
-{
- unchar ahacmd = CMD_START_SCSI;
- int i;
- unchar *cmd = (unchar *) cmnd;
-
- DEB(if (target > 1) {done(DID_TIME_OUT << 16); return 0;});
-
-#ifdef DEBUG
- if (*cmd == READ_10 || *cmd == WRITE_10)
- i = xscsi2int(cmd+2);
- else if (*cmd == READ_6 || *cmd == WRITE_6)
- i = scsi2int(cmd+2);
- else
- i = -1;
- if (done)
- printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
- else
- printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
- aha1542_stat();
- printk("aha1542_queuecommand: dumping scsi cmd:");
- for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
- printk("\n");
- if (*cmd == WRITE_10 || *cmd == WRITE_6)
- return 0; /* we are still testing, so *don't* write */
-#endif
- memset(&ccb, 0, sizeof ccb);
-
- ccb.cdblen = (*cmd<=0x1f)?6:10; /* SCSI Command Descriptor Block Length */
-
- memcpy(ccb.cdb, cmd, ccb.cdblen);
- ccb.op = 0; /* SCSI Initiator Command */
- ccb.idlun = (target&7)<<5; /* SCSI Target Id */
- ccb.rsalen = 12;
- any2scsi(ccb.datalen, bufflen);
- any2scsi(ccb.dataptr, buff);
- ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0;
- ccb.commlinkid = 0;
-
- mb[0].status = 1;
- mb[1].status = 0;
-
-#ifdef DEBUGd
- printk("aha1542_command: sending.. ");
- for (i = 0; i < sizeof(ccb)-10; i++)
- printk("%02x ", ((unchar *)&ccb)[i]);
-#endif
-
- if (done) {
- DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
- if (do_done)
- printk("aha1542_queuecommand: Two concurrent queuecommand?\n");
- else
- do_done = done;
- aha1542_out(&ahacmd, 1); /* start scsi command */
- DEB(aha1542_stat());
- aha1542_enable_intr();
- }
- else
- printk("aha1542_queuecommand: done can't be NULL\n");
-
- return 0;
-}
-
-volatile static int internal_done_flag = 0;
-volatile static int internal_done_errcode = 0;
-static void internal_done(int errcode)
-{
- internal_done_errcode = errcode;
- ++internal_done_flag;
-}
-
-int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
-{
- DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
- aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done);
-
- while (!internal_done_flag);
- internal_done_flag = 0;
- return internal_done_errcode;
-}
-
-/* Initialize mailboxes */
-static void setup_mailboxes()
-{
- static unchar cmd[5] = {CMD_MBINIT, 1};
-
- mb[0].status = mb[1].status = 0;
- aha1542_intr_reset(); /* reset interrupts, so they don't block */
- any2scsi((cmd+2), mb);
- any2scsi(mb[0].ccbptr, &ccb);
- aha1542_out(cmd, 5);
- WAIT(INTRFLAGS, INTRMASK, HACC, 0);
- while (0) {
- fail:
- printk("aha1542_detect: failed setting up mailboxes\n");
- }
- aha1542_intr_reset();
-}
-
-/* a hack to avoid a strange compilation error */
-
-void call_buh()
-{
- struct sigaction sa;
-
- sa.sa_handler = aha1542_interrupt;
- sa.sa_flags = SA_INTERRUPT;
- sa.sa_mask = 0;
- sa.sa_restorer = NULL;
- if (irqaction(intr_chan,&sa))
- printk("Unable to allocate IRQ%d for aha controller\n", intr_chan);
-}
-
-/* return non-zero on detection */
-int aha1542_detect(int hostnum) /* hostnum ignored for now */
-{
- int i;
-
- DEB(printk("aha1542_detect: \n"));
-
- if (!(i = aha1542_test_port())) {
- return 0;
- }
-
- /* Set the Bus on/off-times as not to ruin floppy performens */
- {
- static unchar oncmd[] = {CMD_BUSON_TIME, 5};
- static unchar offcmd[] = {CMD_BUSOFF_TIME, 9};
-
- aha1542_intr_reset();
- aha1542_out(oncmd, 2);
- WAIT(INTRFLAGS, INTRMASK, HACC, 0);
- aha1542_intr_reset();
- aha1542_out(offcmd, 2);
- WAIT(INTRFLAGS, INTRMASK, HACC, 0);
- while (0) {
- fail:
- printk("aha1542_detect: setting bus on/off-time failed\n");
- }
- aha1542_intr_reset();
- }
-
- aha1542_stat();
- setup_mailboxes();
-
- aha1542_stat();
-
- DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
- call_buh();
-
- if (intr_chan >= 8)
- outb(inb_p(0x21)&0xfb,0x21); /* open for slave ?? */
-
- DEB(printk("aha1542_detect: enabling interrupts\n"));
- aha1542_enable_intr();
-
-#ifdef DEBUG
- DEB(printk(" *** READ CAPACITY ***\n"));
-
- {
- unchar buf[8];
- static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i;
-
- for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
- for (i = 0; i < 2; ++i)
- if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
- printk("aha_detect: LU %d sector_size %d device_size %d\n",
- i, xscsi2int(buf+4), xscsi2int(buf));
- }
- }
-
- DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
-
- for (i = 0; i < 4; ++i)
- {
- unsigned char cmd[10];
- static buffer[512];
-
- cmd[0] = READ_10;
- cmd[1] = 0;
- xany2scsi(cmd+2, i);
- cmd[6] = 0;
- cmd[7] = 0;
- cmd[8] = 1;
- cmd[9] = 0;
- aha1542_command(0, cmd, buffer, 512);
- }
-#endif
- return 1;
-}
-
-int aha1542_abort(int i)
-{
- DEB(printk("aha1542_abort\n"));
- return 0;
-}
-
-int aha1542_reset(void)
-{
- DEB(printk("aha1542_reset called\n"));
- return 0;
-}
+++ /dev/null
-#ifndef _AHA1542_H
-
-/* $Id: aha1542.h,v 1.1 1992/04/24 18:01:50 root Exp root $
- *
- * Header file for the adaptec 1542 driver for Linux
- *
- * $Log: aha1542.h,v $
- * Revision 1.1 1992/04/24 18:01:50 root
- * Initial revision
- *
- * Revision 1.1 1992/04/02 03:23:13 drew
- * Initial revision
- *
- * Revision 1.3 1992/01/27 14:46:29 tthorn
- * *** empty log message ***
- *
- */
-
-/* I/O Port interface 4.2 */
-/* READ */
-#define STATUS base
-#define STST 0x80 /* Self Test in Progress */
-#define DIAGF 0x40 /* Internal Diagonostic Failure */
-#define INIT 0x20 /* Mailbox Initialization Required */
-#define IDLE 0x10 /* SCSI Host Adapter Idle */
-#define CDF 0x08 /* Command/Data Out Port Full */
-#define DF 0x04 /* Data In Port Full */
-#define INVDCMD 0x01 /* Invalid H A Command */
-#define STATMASK 0xfd /* 0x02 is reserved */
-
-#define INTRFLAGS STATUS+2
-#define ANYINTR 0x80 /* Any Interrupt */
-#define SCRD 0x08 /* SCSI Reset Detected */
-#define HACC 0x04 /* HA Command Complete */
-#define MBOA 0x02 /* MBO Empty */
-#define MBIF 0x01 /* MBI Full */
-#define INTRMASK 0x8f
-
-/* WRITE */
-#define CONTROL STATUS
-#define HRST 0x80 /* Hard Reset */
-#define SRST 0x40 /* Soft Reset */
-#define IRST 0x20 /* Interrupt Reset */
-#define SCRST 0x10 /* SCSI Bus Reset */
-
-/* READ/WRITE */
-#define DATA STATUS+1
-#define CMD_NOP 0x00 /* No Operation */
-#define CMD_MBINIT 0x01 /* Mailbox Initialization */
-#define CMD_START_SCSI 0x02 /* Start SCSI Command */
-#define CMD_INQUIRY 0x04 /* Adapter Inquiry */
-#define CMD_EMBOI 0x05 /* Enable MailBox Out Interrupt */
-#define CMD_BUSON_TIME 0x07 /* Set Bus-On Time */
-#define CMD_BUSOFF_TIME 0x08 /* Set Bus-Off Time */
-#define CMD_RETDEVS 0x0a /* Return Installed Devices */
-#define CMD_RETCONF 0x0b /* Return Configuration Data */
-#define CMD_RETSETUP 0x0d /* Return Setup Data */
-#define CMD_ECHO 0x1f /* ECHO Command Data */
-
-/* Mailbox Definition 5.2.1 and 5.2.2 */
-struct mailbox {
- unchar status; /* Command/Status */
- unchar ccbptr[3]; /* msb, .., lsb */
-};
-
-/* These belong in scsi.h also */
-#define any2scsi(up, p) \
-(up)[0] = (((long)(p)) >> 16) & 0xff; \
-(up)[1] = ((long)(p)) >> 8; \
-(up)[2] = ((long)(p));
-
-#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
-
-#define xany2scsi(up, p) \
-(up)[0] = ((long)(p)) >> 24; \
-(up)[1] = ((long)(p)) >> 16; \
-(up)[2] = ((long)(p)) >> 8; \
-(up)[3] = ((long)(p));
-
-#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
- + (((long)(up)[2]) << 8) + ((long)(up)[3]) )
-
-#define MAX_CDB 12
-#define MAX_SENSE 14
-
-struct ccb { /* Command Control Block 5.3 */
- unchar op; /* Command Control Block Operation Code */
- unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
- /* Outbound data transfer, length is checked*/
- /* Inbound data transfer, length is checked */
- /* Logical Unit Number */
- unchar cdblen; /* SCSI Command Length */
- unchar rsalen; /* Request Sense Allocation Length/Disable */
- unchar datalen[3]; /* Data Length (msb, .., lsb) */
- unchar dataptr[3]; /* Data Pointer */
- unchar linkptr[3]; /* Link Pointer */
- unchar commlinkid; /* Command Linking Identifier */
- unchar hastat; /* Host Adapter Status (HASTAT) */
- unchar tarstat; /* Target Device Status */
- unchar reserved[2];
- unchar cdb[MAX_CDB+MAX_SENSE];/* SCSI Command Descriptor Block */
- /* REQUEST SENSE */
-};
-
-int aha1542_detect(int);
-int aha1542_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
-/*int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int));*/
-int aha1542_abort(int);
-char *aha1542_info(void);
-int aha1542_reset(void);
-
-#ifndef NULL
- #define NULL 0
-#endif
-
-#define AHA1542 {"Adaptec 1542", aha1542_detect, \
- aha1542_info, aha1542_command, \
- /*aha1542_queuecommand*/ NULL, \
- aha1542_abort, \
- aha1542_reset, \
- 0, 7, 0}
-#endif
+++ /dev/null
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI
-scsi.o
-hosts.o
-scsi_ioctl.o
-#endif
-
-#ifdef CONFIG_BLK_DEV_SD
-sd.o
-sd_ioctl.o
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-st.o
-st_ioctl.o
-#endif
-
-#ifdef CONFIG_SCSI_AHA1542
-aha1542.o
-#endif
-
-#ifdef CONFIG_SCSI_SEAGATE
-seagate.o
-#endif
-
-#ifdef CONFIG_SCSI_ULTRASTOR
-ultrastor.o
-#endif
+++ /dev/null
-/*
- * hosts.c Copyright (C) 1992 Drew Eckhardt
- * mid to lowlevel SCSI driver interface by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-
-/*
- This file contains the medium level SCSI
- host interface initialization, as well as the scsi_hosts array of SCSI
- hosts currently present in the system.
-*/
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI
-#include <linux/kernel.h>
-#include "scsi.h"
-
-#ifndef NULL
- #define NULL 0L
-#endif
-
-#ifdef FIGURE_MAX_SCSI_HOSTS
- #define MAX_SCSI_HOSTS
-#endif
-
-#include "hosts.h"
-
-#ifdef CONFIG_SCSI_AHA1542
-#include <sys/types.h>
-#include "aha1542.h"
-#endif
-
-#ifdef CONFIG_SCSI_SEAGATE
-#include "seagate.h"
-#endif
-
-#ifdef CONFIG_SCSI_ULTRASTOR
-#include "ultrastor.h"
-#endif
-
-/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
-*/
-
-/*
- The scsi host entries should be in the order you wish the
- cards to be detected. A driver may appear more than once IFF
- it can deal with being detected (and therefore initialized)
- with more than one simulatenous host number, can handle being
- rentrant, etc.
-
- They may appear in any order, as each SCSI host is told which host number it is
- during detection.
-*/
-
-/*
- When figure is run, we don't want to link to any object code. Since
- the macro for each host will contain function pointers, we cannot
- use it and instead must use a "blank" that does no such
- idiocy.
-*/
-
-#ifdef FIGURE_MAX_SCSI_HOSTS
- #define BLANKIFY(what) BLANK_HOST
-#else
- #define BLANKIFY(what) what
-#endif
-
-Scsi_Host scsi_hosts[] =
- {
-#ifdef CONFIG_SCSI_AHA1542
- BLANKIFY(AHA1542),
-#endif
-
-#ifdef CONFIG_SCSI_SEAGATE
- BLANKIFY(SEAGATE_ST0X),
-#endif
-#ifdef CONFIG_SCSI_ULTRASTOR
- BLANKIFY(ULTRASTOR_14F),
-#endif
- };
-
-#ifdef FIGURE_MAX_SCSI_HOSTS
- #undef MAX_SCSI_HOSTS
- #define MAX_SCSI_HOSTS (sizeof(scsi_hosts) / sizeof(Scsi_Host))
-#endif
-
-#ifdef FIGURE_MAX_SCSI_HOSTS
-#include <stdio.h>
-void main (void)
-{
- printf("%d", MAX_SCSI_HOSTS);
-}
-#else
-/*
- Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here.
-*/
-
-volatile unsigned char host_busy[MAX_SCSI_HOSTS];
-volatile int host_timeout[MAX_SCSI_HOSTS];
-volatile Scsi_Cmnd *host_queue[MAX_SCSI_HOSTS];
-/*
- scsi_init initializes the scsi hosts.
-*/
-
-void scsi_init(void)
- {
- static int called = 0;
- int i, count;
- if (!called)
- {
- called = 1;
- for (count = i = 0; i < MAX_SCSI_HOSTS; ++i)
- {
- /*
- Initialize our semaphores. -1 is interpreted to mean
- "inactive" - where as 0 will indicate a time out condition.
- */
-
- host_busy[i] = 0;
- host_timeout[i] = 0;
- host_queue[i] = NULL;
-
- if ((scsi_hosts[i].detect) && (scsi_hosts[i].present = scsi_hosts[i].detect(i)))
- {
- printk ("Host %d is detected as a(n) %s.\n\r",
- count, scsi_hosts[i].name);
- printk ("%s", scsi_hosts[i].info());
- ++count;
- }
- }
- printk ("%d host adapters detected. \n\r", count);
- }
-
- }
-
-#endif
-
-#endif
+++ /dev/null
-/*
- * hosts.h Copyright (C) 1992 Drew Eckhardt
- * mid to low-level SCSI driver interface header by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-#ifndef _HOSTS_H
- #define _HOSTS_H
-
-#ifndef MAX_SCSI_HOSTS
- #include "max_hosts.h"
-#endif
-
-/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.h,v 1.1 1992/04/24 18:01:50 root Exp root $
-*/
-
-/*
- The Scsi_Cmnd structure is used by scsi.c internally, and for communication with
- low level drivers that support multiple outstanding commands.
-*/
-
-typedef struct scsi_cmnd {
- int host;
- unsigned char target, lun;
- unsigned char cmnd[10];
- unsigned bufflen;
- void *buffer;
-
- unsigned char sense_cmnd[6];
- unsigned char *sense_buffer;
-
- unsigned flags;
-
- int retries;
- int allowed;
- int timeout_per_command, timeout_total, timeout;
-
- void (*done)(int,int);
- struct scsi_cmnd *next, *prev;
- } Scsi_Cmnd;
-
-/*
- The Scsi_Host type has all that is needed to interface with a SCSI
- host in a device independant matter.
-*/
-
-typedef struct
- {
- /*
- The name pointer is a pointer to the name of the SCSI
- device detected.
- */
-
- char *name;
-
- /*
- The detect function shall return non zero on detection,
- and initialize all data necessary for this particular
- SCSI driver. It is passed the host number, so this host
- knows where it is in the hosts array
- */
-
- int (* detect)(int);
-
- /*
- The info function will return whatever useful
- information the developer sees fit.
- */
-
- char *(* info)(void);
-
- /*
- The command function takes a target, a command (this is a SCSI
- command formatted as per the SCSI spec, nothing strange), a
- data buffer pointer, and data buffer length pointer. The return
- is a status int, bit fielded as follows :
- Byte What
- 0 SCSI status code
- 1 SCSI 1 byte message
- 2 host error return.
- 3 mid level error return
- */
-
- int (* command)(unsigned char target, const void *cmnd,
- void *buff, int bufflen);
-
- /*
- The QueueCommand function works in a similar manner
- to the command function. It takes an additional parameter,
- void (* done)(int host, int code) which is passed the host
- # and exit result when the command is complete.
- Host number is the POSITION IN THE hosts array of THIS
- host adapter.
- */
-
- int (* queuecommand)(unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int,int));
-
-
- /*
- Since the mid level driver handles time outs, etc, we want to
- be able to abort the current command. Abort returns 0 if the
- abortion was successful. If non-zero, the code passed to it
- will be used as the return code, otherwise
- DID_ABORT should be returned.
-
- Note that the scsi driver should "clean up" after itself,
- resetting the bus, etc. if necessary.
- */
-
- int (* abort)(int);
-
- /*
- The reset function will reset the SCSI bus. Any executing
- commands should fail with a DID_RESET in the host byte.
- */
-
- int (* reset)(void);
-
- /*
- This determines if we will use a non-interrupt driven
- or an interrupt driven scheme, It is set to the maximum number
- of simulataneous commands a given host adapter will accept.
- */
-
- int can_queue;
-
- /*
- In many instances, especially where disconnect / reconnect are
- supported, our host also has an ID on the SCSI bus. If this is
- the case, then it must be reserved. Please set this_id to -1 if your settup is in single initiator mode, and the host lacks an
- ID.
- */
-
- int this_id;
-
- /*
- present contains a flag as to weather we are present -
- so we don't have to call detect multiple times.
- */
-
- unsigned present:1;
- } Scsi_Host;
-
-/*
- The scsi_hosts array is the array containing the data for all
- possible <supported> scsi hosts.
-*/
-
-extern Scsi_Host scsi_hosts[];
-
-/*
- This is our semaphore array, used by scsi.c, sd.c, st.c.
- Other routines SHOULD NOT mess with it. Your driver should NOT mess with it.
- This is used to protect against contention by disk and tape drivers.
-*/
-
-extern volatile unsigned char host_busy[];
-extern volatile int host_timeout[];
-
-/*
- This is the queue of currently pending commands for a given
- SCSI host.
-*/
-
-extern volatile Scsi_Cmnd *host_queue[];
-
-/*
- scsi_init initializes the scsi hosts.
-*/
-
-
-void scsi_init(void);
-
-#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0}
-#endif
+++ /dev/null
-/*
- * scsi.c Copyright (C) 1992 Drew Eckhardt
- * generic mid-level SCSI driver by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI
-#include <asm/system.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-
-#include "scsi.h"
-#include "hosts.h"
-
-#ifdef CONFIG_BLK_DEV_SD
-#include "sd.h"
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-#include "st.h"
-#endif
-
-/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
-*/
-
-#define INTERNAL_ERROR (printk ("Internal error in file %s, line %s.\n", __FILE__, __LINE__), panic(""))
-
-static void scsi_done (int host, int result);
-static void update_timeout (void);
-
-static int time_start;
-static int time_elapsed;
-
-/*
- global variables :
- NR_SCSI_DEVICES is the number of SCSI devices we have detected,
- scsi_devices an array of these specifing the address for each
- (host, id, LUN)
-*/
-
-int NR_SCSI_DEVICES=0;
-Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
-
-#define SENSE_LENGTH 255
-/*
- As the scsi do command functions are inteligent, and may need to
- redo a command, we need to keep track of the last command
- executed on each one.
-*/
-
-#define WAS_RESET 0x01
-#define WAS_TIMEDOUT 0x02
-#define WAS_SENSE 0x04
-#define IS_RESETTING 0x08
-
-static Scsi_Cmnd last_cmnd[MAX_SCSI_HOSTS];
-static int last_reset[MAX_SCSI_HOSTS];
-
-/*
- This is the number of clock ticks we should wait before we time out
- and abort the command. This is for where the scsi.c module generates
- the command, not where it originates from a higher level, in which
- case the timeout is specified there.
-
-
- ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT
- respectively.
-*/
-#ifdef DEBUG
- #define SCSI_TIMEOUT 500
-#else
- #define SCSI_TIMEOUT 100
-#endif
-#ifdef DEBUG
- #define SENSE_TIMEOUT SCSI_TIMEOUT
- #define ABORT_TIMEOUT SCSI_TIMEOUT
- #define RESET_TIMEOUT SCSI_TIMEOUT
-#else
-
- #define SENSE_TIMEOUT 50
- #define RESET_TIMEOUT 50
- #define ABORT_TIMEOUT 50
- #define MIN_RESET_DELAY 25
-
-#endif
-/*
- As the actual SCSI command runs in the background, we must set up a
- flag that tells scan_scsis() when the result it has is valid.
- scan_scsis can set the_result to -1, and watch for it to become the
- actual return code for that call. the scan_scsis_done function() is
- our user specified completion function that is passed on to the
- scsi_do_cmd() function.
-*/
-
-static int the_result;
-static unsigned char sense_buffer[SENSE_LENGTH];
-static void scan_scsis_done (int host, int result)
- {
-
-#ifdef DEBUG
- printk ("scan_scsis_done(%d, %06x\n\r", host, result);
-#endif
- the_result = result;
- }
-/*
- Detecting SCSI devices :
- We scan all present host adapter's busses, from ID 0 to ID 6.
- We use the INQUIRY command, determine device type, and pass the ID /
- lun address of all sequential devices to the tape driver, all random
- devices to the disk driver.
-*/
-
-static void scan_scsis (void)
- {
- int host_nr , dev, lun, type, maxed;
- static unsigned char scsi_cmd [12];
- static unsigned char scsi_result [256];
-
- for (host_nr = 0; host_nr < MAX_SCSI_HOSTS; ++host_nr)
- if (scsi_hosts[host_nr].present)
- {
- for (dev = 0; dev < 7; ++dev)
- if (scsi_hosts[host_nr].this_id != dev)
- #ifdef MULTI_LUN
- for (lun = 0; lun < 8; ++lun)
- {
- #else
- {
- lun = 0;
- #endif
- /* Build an INQUIRY command block. */
-
- scsi_cmd[0] = INQUIRY;
- scsi_cmd[1] = (lun << 5) & 0xe0;
- scsi_cmd[2] = 0;
- scsi_cmd[3] = 0;
- scsi_cmd[4] = 255;
- scsi_cmd[5] = 0;
- the_result = -1;
-#ifdef DEBUG
- memset ((void *) scsi_result , 0, 255);
-#endif
- scsi_do_cmd (host_nr, dev, (void *) scsi_cmd, (void *)
- scsi_result, 256, scan_scsis_done,
- SCSI_TIMEOUT, sense_buffer, 3);
-
- /* Wait for valid result */
-
- while (the_result < 0);
-
-
- if (!the_result)
- {
- scsi_devices[NR_SCSI_DEVICES].
- host_no = host_nr;
- scsi_devices[NR_SCSI_DEVICES].
- id = dev;
- scsi_devices[NR_SCSI_DEVICES].
- lun = lun;
- scsi_devices[NR_SCSI_DEVICES].
- removable = (0x80 &
- scsi_result[1]) >> 7;
-
-
-
-/*
- Currently, all sequential devices are assumed to be tapes,
- all random devices disk, with the appropriate read only
- flags set for ROM / WORM treated as RO.
-*/
-
- switch (type = scsi_result[0])
- {
- case TYPE_TAPE:
- case TYPE_DISK:
- scsi_devices[NR_SCSI_DEVICES].writeable = 1;
- break;
- case TYPE_WORM:
- case TYPE_ROM:
- scsi_devices[NR_SCSI_DEVICES].writeable = 0;
- break;
- default:
- type = -1;
- }
-
- scsi_devices[NR_SCSI_DEVICES].random = (type == TYPE_TAPE) ? 0 : 1;
-
- maxed = 0;
- switch (type)
- {
- case -1:
- break;
- case TYPE_TAPE:
- printk("Detected scsi tape at host %d, ID %d, lun %d \n", host_nr, dev, lun);
-#ifdef CONFIG_BLK_DEV_ST
- if (!(maxed = (NR_ST == MAX_ST)))
- scsi_tapes[NR_ST].device = &scsi_devices[NR_SCSI_DEVICES];
-#endif
- default:
- printk("Detected scsi disk at host %d, ID %d, lun %d \n", host_nr, dev, lun);
-#ifdef CONFIG_BLK_DEV_SD
- if (!(maxed = (NR_SD >= MAX_SD)))
- rscsi_disks[NR_SD].device = &scsi_devices[NR_SCSI_DEVICES];
-#endif
- }
-
- if (maxed)
- {
- printk ("Already have detected maximum number of SCSI %ss Unable to \n"
- "add drive at SCSI host %s, ID %d, LUN %d\n\r", (type == TYPE_TAPE) ?
- "tape" : "disk", scsi_hosts[host_nr].name,
- dev, lun);
- type = -1;
- break;
- }
-
- else if (type != -1)
- {
- if (type == TYPE_TAPE)
-#ifdef CONFIG_BLK_DEV_ST
- ++NR_ST;
-#else
-;
-#endif
-
- else
-#ifdef CONFIG_BLK_DEV_SD
- ++NR_SD;
-#else
-;
-#endif
- }
- ++NR_SCSI_DEVICES;
- } /* if result == DID_OK ends */
- } /* for lun ends */
- } /* if present */
-
- printk("Detected "
-#ifdef CONFIG_BLK_DEV_SD
-"%d disk%s "
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-"%d tape%s "
-#endif
-
-"total.\n",
-
-#ifdef CONFIG_BLK_DEV_SD
-NR_SD, (NR_SD != 1) ? "s" : ""
-#ifdef CONFIG_BLK_DEV_ST
-,
-#endif
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
-NR_ST, (NR_ST != 1) ? "s" : ""
-#endif
-);
- } /* scan_scsis ends */
-
-/*
- We handle the timeout differently if it happens when a reset,
- abort, etc are in process.
-*/
-
-static unsigned char internal_timeout[MAX_SCSI_HOSTS];
-
-/* Flag bits for the internal_timeout array */
-
-#define NORMAL_TIMEOUT 0
-#define IN_ABORT 1
-#define IN_RESET 2
-/*
- This is our time out function, called when the timer expires for a
- given host adapter. It will attempt to abort the currently executing
- command, that failing perform a kernel panic.
-*/
-
-static void scsi_times_out (int host)
- {
-
- switch (internal_timeout[host] & (IN_ABORT | IN_RESET))
- {
- case NORMAL_TIMEOUT:
- printk("SCSI host %d timed out - aborting command \r\n",
- host);
-
- if (!scsi_abort (host, DID_TIME_OUT))
- return;
- case IN_ABORT:
- printk("SCSI host %d abort() timed out - reseting \r\n",
- host);
- if (!scsi_reset (host))
- return;
- case IN_RESET:
- case (IN_ABORT | IN_RESET):
- printk("Unable to reset scsi host %d\r\n",host);
- panic("");
- default:
- INTERNAL_ERROR;
- }
-
- }
-
-/*
- This is inline because we have stack problemes if we recurse to deeply.
-*/
-
-static void internal_cmnd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int))
- {
- int temp;
-
-#ifdef DEBUG_DELAY
- int clock;
-#endif
-
- if ((host < 0) || (host > MAX_SCSI_HOSTS))
- panic ("Host number in internal_cmnd() is out of range.\n");
-
-
-/*
- We will wait MIN_RESET_DELAY clock ticks after the last reset so
- we can avoid the drive not being ready.
-*/
-temp = last_reset[host];
-while (jiffies < temp);
-
-host_timeout[host] = last_cmnd[host].timeout_per_command;
-update_timeout();
-
-/*
- We will use a queued command if possible, otherwise we will emulate the
- queing and calling of completion function ourselves.
-*/
-#ifdef DEBUG
- printk("internal_cmnd (host = %d, target = %d, command = %08x, buffer = %08x, \n"
- "bufflen = %d, done = %08x)\n", host, target, cmnd, buffer, bufflen, done);
-#endif
-
-
- if (scsi_hosts[host].can_queue)
- {
-#ifdef DEBUG
- printk("queuecommand : routine at %08x\n",
- scsi_hosts[host].queuecommand);
-#endif
- scsi_hosts[host].queuecommand (target, cmnd, buffer, bufflen,
- done);
- }
- else
- {
-
-#ifdef DEBUG
- printk("command() : routine at %08x\n", scsi_hosts[host].command);
-#endif
- temp=scsi_hosts[host].command (target, cmnd, buffer, bufflen);
-
-#ifdef DEBUG_DELAY
- clock = jiffies + 400;
- while (jiffies < clock);
- printk("done(host = %d, result = %04x) : routine at %08x\n", host, temp, done);
-#endif
- done(host, temp);
- }
-#ifdef DEBUG
- printk("leaving internal_cmnd()\n");
-#endif
- }
-
-static void scsi_request_sense (int host, unsigned char target,
- unsigned char lun)
- {
- cli();
- host_timeout[host] = SENSE_TIMEOUT;
- update_timeout();
- last_cmnd[host].flags |= WAS_SENSE;
- sti();
-
- last_cmnd[host].sense_cmnd[1] = lun << 5;
-
- internal_cmnd (host, target, (void *) last_cmnd[host].sense_cmnd,
- (void *) last_cmnd[host].sense_buffer, SENSE_LENGTH,
- scsi_done);
- }
-
-
-
-
-
-/*
- scsi_do_cmd sends all the commands out to the low-level driver. It
- handles the specifics required for each low level driver - ie queued
- or non queud. It also prevents conflicts when different high level
- drivers go for the same host at the same time.
-*/
-
-void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int),
- int timeout, unsigned char *sense_buffer, int retries
- )
- {
- int ok = 0;
-
-#ifdef DEBUG
- int i;
- printk ("scsi_do_cmd (host = %d, target = %d, buffer =%08x, "
- "bufflen = %d, done = %08x, timeout = %d, retries = %d)\n"
- "command : " , host, target, buffer, bufflen, done, timeout, retries);
- for (i = 0; i < 10; ++i)
- printk ("%02x ", ((unsigned char *) cmnd)[i]);
- printk("\n");
-#endif
-
- if ((host >= MAX_SCSI_HOSTS) || !scsi_hosts[host].present)
- {
- printk ("Invalid or not present host number. %d\n", host);
- panic("");
- }
-
-
-/*
- We must prevent reentrancy to the lowlevel host driver. This prevents
- it - we enter a loop until the host we want to talk to is not busy.
- Race conditions are prevented, as interrupts are disabled inbetween the
- time we check for the host being not busy, and the time we mark it busy
- ourselves.
-*/
-
- do {
- cli();
- if (host_busy[host])
- {
- sti();
-#ifdef DEBUG
- printk("Host %d is busy.\n" );
-#endif
- while (host_busy[host]);
-#ifdef DEBUG
- printk("Host %d is no longer busy.");
-#endif
- }
- else
- {
- host_busy[host] = 1;
- ok = 1;
- sti();
- }
- } while (!ok);
-
-
-/*
- Our own function scsi_done (which marks the host as not busy, disables
- the timeout counter, etc) will be called by us or by the
- scsi_hosts[host].queuecommand() function needs to also call
- the completion function for the high level driver.
-
-*/
-
- memcpy ((void *) last_cmnd[host].cmnd , (void *) cmnd, 10);
- last_cmnd[host].host = host;
- last_cmnd[host].target = target;
- last_cmnd[host].lun = (last_cmnd[host].cmnd[1] >> 5);
- last_cmnd[host].bufflen = bufflen;
- last_cmnd[host].buffer = buffer;
- last_cmnd[host].sense_buffer = sense_buffer;
- last_cmnd[host].flags=0;
- last_cmnd[host].retries=0;
- last_cmnd[host].allowed=retries;
- last_cmnd[host].done = done;
- last_cmnd[host].timeout_per_command = timeout;
-
- /* Start the timer ticking. */
-
- internal_timeout[host] = 0;
- internal_cmnd (host, target, cmnd , buffer, bufflen, scsi_done);
-
-#ifdef DEBUG
- printk ("Leaving scsi_do_cmd()\n");
-#endif
- }
-
-
-/*
- The scsi_done() function disables the timeout timer for the scsi host,
- marks the host as not busy, and calls the user specified completion
- function for that host's current command.
-*/
-
-static void reset (int host)
- {
- #ifdef DEBUG
- printk("reset(%d)\n", host);
- #endif
-
- last_cmnd[host].flags |= (WAS_RESET | IS_RESETTING);
- scsi_reset(host);
-
- #ifdef DEBUG
- printk("performing request sense\n");
- #endif
-
- scsi_request_sense (host, last_cmnd[host].target, last_cmnd[host].lun);
- }
-
-
-
-static int check_sense (int host)
- {
- if (((sense_buffer[0] & 0x70) >> 4) == 7)
- switch (sense_buffer[2] & 0xf)
- {
- case NO_SENSE:
- case RECOVERED_ERROR:
- return 0;
-
- case ABORTED_COMMAND:
- case NOT_READY:
- case UNIT_ATTENTION:
- return SUGGEST_RETRY;
-
- /* these three are not supported */
- case COPY_ABORTED:
- case VOLUME_OVERFLOW:
- case MISCOMPARE:
-
- case MEDIUM_ERROR:
- return SUGGEST_REMAP;
- case BLANK_CHECK:
- case DATA_PROTECT:
- case HARDWARE_ERROR:
- case ILLEGAL_REQUEST:
- default:
- return SUGGEST_ABORT;
- }
- else
- return SUGGEST_RETRY;
- }
-
-static void scsi_done (int host, int result)
- {
- int status=0;
- int exit=0;
- int checked;
- int oldto;
- oldto = host_timeout[host];
- host_timeout[host] = 0;
- update_timeout();
-
-#define FINISHED 0
-#define MAYREDO 1
-#define REDO 3
-
-#ifdef DEBUG
- printk("In scsi_done(host = %d, result = %06x)\n", host, result);
-#endif
- if (host > MAX_SCSI_HOSTS || host < 0)
- {
- host_timeout[host] = 0;
- update_timeout();
- panic("scsi_done() called with invalid host number.\n");
- }
-
- switch (host_byte(result))
- {
- case DID_OK:
- if (last_cmnd[host].flags & IS_RESETTING)
- {
- last_cmnd[host].flags &= ~IS_RESETTING;
- status = REDO;
- break;
- }
-
- if (status_byte(result) && (last_cmnd[host].flags &
- WAS_SENSE))
- {
- last_cmnd[host].flags &= ~WAS_SENSE;
- cli();
- internal_timeout[host] &= ~SENSE_TIMEOUT;
- sti();
-
- if (!(last_cmnd[host].flags & WAS_RESET))
- reset(host);
- else
- {
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- status = FINISHED;
- }
- }
- else switch(msg_byte(result))
- {
- case COMMAND_COMPLETE:
- switch (status_byte(result))
- {
- case GOOD:
- if (last_cmnd[host].flags & WAS_SENSE)
- {
-#ifdef DEBUG
- printk ("In scsi_done, GOOD status, COMMAND COMPLETE, parsing sense information.\n");
-#endif
-
- last_cmnd[host].flags &= ~WAS_SENSE;
- cli();
- internal_timeout[host] &= ~SENSE_TIMEOUT;
- sti();
-
- switch (checked = check_sense(host))
- {
- case 0:
-#ifdef DEBUG
- printk("NO SENSE. status = REDO\n");
-#endif
-
- host_timeout[host] = oldto;
- update_timeout();
- status = REDO;
- break;
- case SUGGEST_REMAP:
- case SUGGEST_RETRY:
-#ifdef DEBUG
- printk("SENSE SUGGEST REMAP or SUGGEST RETRY - status = MAYREDO\n");
-#endif
-
- status = MAYREDO;
- exit = SUGGEST_RETRY;
- break;
- case SUGGEST_ABORT:
-#ifdef DEBUG
- printk("SENSE SUGGEST ABORT - status = FINISHED");
-#endif
-
- status = FINISHED;
- exit = DRIVER_SENSE;
- break;
- default:
- printk ("Internal error %s %s \n", __FILE__,
- __LINE__);
- }
- }
- else
- {
-#ifdef DEBUG
- printk("COMMAND COMPLETE message returned, status = FINISHED. \n");
-#endif
-
- exit = DRIVER_OK;
- status = FINISHED;
- }
- break;
-
- case CHECK_CONDITION:
-
-#ifdef DEBUG
- printk("CHECK CONDITION message returned, performing request sense.\n");
-#endif
-
- scsi_request_sense (host, last_cmnd[host].target, last_cmnd[host].lun);
- break;
-
- case CONDITION_GOOD:
- case INTERMEDIATE_GOOD:
- case INTERMEDIATE_C_GOOD:
-#ifdef DEBUG
- printk("CONDITION GOOD, INTERMEDIATE GOOD, or INTERMEDIATE CONDITION GOOD recieved and ignored. \n");
-#endif
- break;
-
- case BUSY:
-#ifdef DEBUG
- printk("BUSY message returned, performing REDO");
-#endif
- host_timeout[host] = oldto;
- update_timeout();
- status = REDO;
- break;
-
- case RESERVATION_CONFLICT:
- reset(host);
- exit = DRIVER_SOFT | SUGGEST_ABORT;
- status = MAYREDO;
- break;
- default:
- printk ("Internal error %s %s \n"
- "status byte = %d \n", __FILE__,
- __LINE__, status_byte(result));
-
- }
- break;
- default:
- panic ("unsupported message byte recieved.");
- }
- break;
- case DID_TIME_OUT:
-#ifdef DEBUG
- printk("Host returned DID_TIME_OUT - ");
-#endif
-
- if (last_cmnd[host].flags & WAS_TIMEDOUT)
- {
-#ifdef DEBUG
- printk("Aborting\n");
-#endif
- exit = (DRIVER_TIMEOUT | SUGGEST_ABORT);
- }
- else
- {
-#ifdef DEBUG
- printk ("Retrying.\n");
-#endif
- last_cmnd[host].flags |= WAS_TIMEDOUT;
- status = REDO;
- }
- break;
- case DID_BUS_BUSY:
- case DID_PARITY:
- status = REDO;
- break;
- case DID_NO_CONNECT:
-#ifdef DEBUG
- printk("Couldn't connect.\n");
-#endif
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- break;
- case DID_ERROR:
- status = MAYREDO;
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- break;
- case DID_BAD_TARGET:
- case DID_ABORT:
- exit = (DRIVER_INVALID | SUGGEST_ABORT);
- break;
- default :
- exit = (DRIVER_ERROR | SUGGEST_DIE);
- }
-
- switch (status)
- {
- case FINISHED:
- break;
- case MAYREDO:
-
-#ifdef DEBUG
- printk("In MAYREDO, allowing %d retries, have %d\n\r",
- last_cmnd[host].allowed, last_cmnd[host].retries);
-#endif
-
- if ((++last_cmnd[host].retries) < last_cmnd[host].allowed)
- {
- if ((last_cmnd[host].retries >= (last_cmnd[host].allowed >> 1))
- && !(last_cmnd[host].flags & WAS_RESET))
- reset(host);
- break;
-
- }
- else
- {
- status = FINISHED;
- break;
- }
- /* fall through to REDO */
-
- case REDO:
- if (last_cmnd[host].flags & WAS_SENSE)
- scsi_request_sense (host, last_cmnd[host].target,
- last_cmnd[host].lun);
- else
- internal_cmnd (host, last_cmnd[host].target,
- last_cmnd[host].cmnd,
- last_cmnd[host].buffer,
- last_cmnd[host].bufflen, scsi_done);
- break;
- default:
- INTERNAL_ERROR;
- }
-
- if (status == FINISHED)
- {
- #ifdef DEBUG
- printk("Calling done function - at address %08x\n", last_cmnd[host].done);
- #endif
- last_cmnd[host].done (host, (result | ((exit & 0xff) << 24)));
- host_busy[host] = 0;
- }
-
-
-#undef FINISHED
-#undef REDO
-#undef MAYREDO
-
- }
-
-/*
- The scsi_abort function interfaces with the abort() function of the host
- we are aborting, and causes the current command to not complete. The
- caller should deal with any error messages or status returned on the
- next call.
-
- This will not be called rentrantly for a given host.
-*/
-
-/*
- Since we're nice guys and specified that abort() and reset()
- can be non-reentrant. The internal_timeout flags are used for
- this.
-*/
-
-
-int scsi_abort (int host, int why)
- {
- int temp, oldto;
-
- while(1)
- {
- cli();
- if (internal_timeout[host] & IN_ABORT)
- {
- sti();
- while (internal_timeout[host] & IN_ABORT);
- }
- else
- {
- internal_timeout[host] |= IN_ABORT;
- host_timeout[host] = ABORT_TIMEOUT;
- update_timeout();
-
- oldto = host_timeout[host];
-
- sti();
- if (!host_busy[host] || !scsi_hosts[host].abort(why))
- temp = 0;
- else
- temp = 1;
-
- cli();
- internal_timeout[host] &= ~IN_ABORT;
- host_timeout[host]=oldto;
- update_timeout();
- sti();
- return temp;
- }
- }
- }
-
-int scsi_reset (int host)
- {
- int temp, oldto;
-
- while (1) {
- cli();
- if (internal_timeout[host] & IN_RESET)
- {
- sti();
- while (internal_timeout[host] & IN_RESET);
- }
- else
- {
- oldto = host_timeout[host];
- host_timeout[host] = RESET_TIMEOUT;
- update_timeout();
- internal_timeout[host] |= IN_RESET;
-
- if (host_busy[host])
- {
- sti();
- if (!(last_cmnd[host].flags & IS_RESETTING) && !(internal_timeout[host] & IN_ABORT))
- scsi_abort(host, DID_RESET);
-
- temp = scsi_hosts[host].reset();
- }
- else
- {
- host_busy[host]=1;
-
- sti();
- temp = scsi_hosts[host].reset();
- last_reset[host] = jiffies;
- host_busy[host]=0;
- }
-
- cli();
- host_timeout[host] = oldto;
- update_timeout();
- internal_timeout[host] &= ~IN_RESET;
- sti();
- return temp;
- }
- }
- }
-
-
-static void scsi_main_timeout(void)
- {
- /*
- We must not enter update_timeout with a timeout condition still pending.
- */
-
- int i, timed_out;
-
- do {
- cli();
-
- /*
- Find all timers such that they have 0 or negative (shouldn't happen)
- time remaining on them.
- */
-
- for (i = timed_out = 0; i < MAX_SCSI_HOSTS; ++i)
- if (host_timeout[i] != 0 && host_timeout[i] <= time_elapsed)
- {
- sti();
- host_timeout[i] = 0;
- scsi_times_out(i);
- ++timed_out;
- }
-
- update_timeout();
- } while (timed_out);
- sti();
- }
-
-/*
- These are used to keep track of things.
-*/
-
-static int time_start, time_elapsed;
-
-/*
- The strategy is to cause the timer code to call scsi_times_out()
- when the soonest timeout is pending.
-*/
-
-static void update_timeout(void)
- {
- int i, least, used;
-
- cli();
-
-/*
- Figure out how much time has passed since the last time the timeouts
- were updated
-*/
- used = (time_start) ? (jiffies - time_start) : 0;
-
-/*
- Find out what is due to timeout soonest, and adjust all timeouts for
- the amount of time that has passed since the last time we called
- update_timeout.
-*/
-
- for (i = 0, least = 0xffffffff; i < MAX_SCSI_HOSTS; ++i)
- if (host_timeout[i] > 0 && (host_timeout[i] -= used) < least)
- least = host_timeout[i];
-
-/*
- If something is due to timeout again, then we will set the next timeout
- interrupt to occur. Otherwise, timeouts are disabled.
-*/
-
- if (least != 0xffffffff)
- {
- time_start = jiffies;
- timer_table[SCSI_TIMER].expires = (time_elapsed = least) + jiffies;
- timer_active |= 1 << SCSI_TIMER;
- }
- else
- {
- timer_table[SCSI_TIMER].expires = time_start = time_elapsed = 0;
- timer_active &= ~(1 << SCSI_TIMER);
- }
- sti();
- }
-/*
- scsi_dev_init() is our initialization routine, which inturn calls host
- initialization, bus scanning, and sd/st initialization routines. It
- should be called from main().
-*/
-
-static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
-void scsi_dev_init (void)
- {
- int i;
-#ifdef FOO_ON_YOU
- return;
-#endif
- timer_table[SCSI_TIMER].fn = scsi_main_timeout;
- timer_table[SCSI_TIMER].expires = 0;
-
- scsi_init(); /* initialize all hosts */
- /*
- Set up sense command in each host structure.
- */
-
- for (i = 0; i < MAX_SCSI_HOSTS; ++i)
- {
- memcpy ((void *) last_cmnd[i].sense_cmnd, (void *) generic_sense,
- 6);
- last_reset[i] = 0;
- }
-
- scan_scsis(); /* scan for scsi devices */
-
-#ifdef CONFIG_BLK_DEV_SD
- sd_init(); /* init scsi disks */
-#endif
-
-#ifdef CONFIG_BLK_DEV_ST
- st_init(); /* init scsi tapes */
-#endif
- }
-#endif
+++ /dev/null
-/*
- * scsi.h Copyright (C) 1992 Drew Eckhardt
- * generic SCSI package header file by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-#ifndef _SCSI_H
- #define _SCSI_H
-/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.h,v 1.1 1992/04/24 18:01:50 root Exp root $
-
- For documentation on the OPCODES, MESSAGES, and SENSE values,
- please consult the SCSI standard.
-
-*/
-
-/*
- SCSI opcodes
-*/
-
-#define TEST_UNIT_READY 0x00
-#define REZERO_UNIT 0x01
-#define REQUEST_SENSE 0x03
-#define FORMAT_UNIT 0x04
-#define REASSIGN_BLOCKS 0x07
-#define READ_6 0x08
-#define WRITE_6 0x0a
-#define SEEK_6 0x0b
-#define INQUIRY 0x12
-#define MODE_SELECT 0x15
-#define RESERVE 0x16
-#define RELEASE 0x17
-#define COPY 0x18
-#define MODE_SENSE 0x1a
-#define START_STOP 0x1b
-#define RECIEVE_DAIGNOSTIC 0x1c
-#define SEND_DIAGNOSTIC 0x1d
-#define ALLOW_MEDIUM_REMOVAL 0x1e
-
-#define READ_CAPACITY 0x25
-#define READ_10 0x28
-#define WRITE_10 0x2a
-#define SEEK_10 0x2b
-#define WRITE_VERIFY 0x2e
-#define VERIFY 0x2f
-#define SEARCH_HIGH 0x30
-#define SEARCH_EQUAL 0x31
-#define SEARCH_LOW 0x32
-#define SET_LIMITS 0x33
-#define COMPARE 0x39
-#define COPY_VERIFY 0x3a
-
-#define COMMAND_SIZE(opcode) ((opcode) ? ((opcode) > 0x20 ? 10 : 6) : 0)
-
-/*
- MESSAGE CODES
-*/
-
-#define COMMAND_COMPLETE 0x00
-#define EXTENDED_MESSAGE 0x01
-#define SAVE_POINTERS 0x02
-#define RESTORE_POINTERS 0x03
-#define DISCONNECT 0x04
-#define INITIATOR_ERROR 0x05
-#define ABORT 0x06
-#define MESSAGE_REJECT 0x07
-#define NOP 0x08
-#define MSG_PARITY_ERROR 0x09
-#define LINKED_CMD_COMPLETE 0x0a
-#define LINKED_FLG_CMD_COMPLETE 0x0b
-#define BUS_DEVICE_RESET 0x0c
-#define IDENTIFY 0x80
-/*
- Status codes
-*/
-
-#define GOOD 0x00
-#define CHECK_CONDITION 0x01
-#define CONDITION_GOOD 0x02
-#define BUSY 0x04
-#define INTERMEDIATE_GOOD 0x08
-#define INTERMEDIATE_C_GOOD 0x0a
-#define RESERVATION_CONFLICT 0x0c
-
-#define STATUS_MASK 0x1e
-
-/*
- the return of the status word will be in the following format :
- The low byte is the status returned by the SCSI command,
- with vendor specific bits masked.
-
- The next byte is the message which followed the SCSI status.
- This allows a stos to be used, since the Intel is a little
- endian machine.
-
- The final byte is a host return code, which is one of the following.
-
- IE
- lsb msb
- status msg host code
-
- Our errors returned by OUR driver, NOT SCSI message. Orr'd with
- SCSI message passed back to driver <IF any>.
-*/
-
-/* NO error */
-#define DID_OK 0x00
-/* Couldn't connect before timeout period */
-#define DID_NO_CONNECT 0x01
-/* BUS stayed busy through time out period */
-#define DID_BUS_BUSY 0x02
-/* TIMED OUT for other reason */
-#define DID_TIME_OUT 0x03
-/* BAD target. */
-#define DID_BAD_TARGET 0x04
-/* Told to abort for some other reason */
-#define DID_ABORT 0x05
-/*
- Parity error
-*/
-#define DID_PARITY 0x06
-/*
- Internal error
-*/
-#define DID_ERROR 0x07
-/*
- Reset by somebody.
-*/
-#define DID_RESET 0x08
-
-/*
- Driver status
-*/
-#define DRIVER_OK 0x00
-
-/*
- These indicate the error that occured, and what is available.
-*/
-
-#define DRIVER_BUSY 0x01
-#define DRIVER_SOFT 0x02
-#define DRIVER_MEDIA 0x03
-#define DRIVER_ERROR 0x04
-
-#define DRIVER_INVALID 0x05
-#define DRIVER_TIMEOUT 0x06
-#define DRIVER_HARD 0x07
-
-#define SUGGEST_RETRY 0x08
-#define SUGGEST_ABORT 0x09
-#define SUGGEST_REMAP 0x0a
-#define SUGGEST_DIE 0x0b
-
-#define DRIVER_SENSE 0x10
-
-#define DRIVER_MASK 0x0f
-#define SUGGEST_MASK 0xf0
-
-/*
-
- SENSE KEYS
-*/
-
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define BLANK_CHECK 0x08
-#define COPY_ABORTED 0x0a
-#define ABORTED_COMMAND 0x0b
-#define VOLUME_OVERFLOW 0x0d
-#define MISCOMPARE 0x0e
-
-
-/*
- DEVICE TYPES
-
-*/
-
-#define TYPE_DISK 0x00
-#define TYPE_TAPE 0x01
-#define TYPE_WORM 0x04 /* Treated as ROM by our system */
-#define TYPE_ROM 0x05
-#define TYPE_NO_LUN 0x7f
-/*
- Every SCSI command starts with a one byte OP-code.
- The next byte's high three bits are the LUN of the
- device. Any multi-byte quantities are stored high byte
- first, and may have a 5 bit MSB in the same byte
- as the LUN.
-*/
-
-
-/*
- The scsi_device struct contains what we know about each given scsi
- device.
-*/
-
-typedef struct scsi_device {
- unsigned char host_no, id, lun;
- unsigned writeable:1;
- unsigned removable:1;
- unsigned random:1;
- } Scsi_Device;
-/*
- Use these to separate status msg and our bytes
-*/
-
-#define status_byte(result) (((result) >> 1) & 0xf)
-#define msg_byte(result) (((result) >> 8) & 0xff)
-#define host_byte(result) (((result) >> 16) & 0xff)
-#define driver_byte(result) (((result) >> 24) & 0xff)
-#define sugestion(result) (driver_byte(result) & SUGGEST_MASK)
-
-#define sense_class(sense) (((sense) >> 4) & 0x7)
-#define sense_error(sense) ((sense) & 0xf)
-#define sense_valid(sense) ((sense) & 0x80);
-
-/*
- These are the SCSI devices available on the system.
-*/
-
-#define MAX_SCSI_DEVICE 2
-extern int NR_SCSI_DEVICES;
-extern Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
-/*
- scsi_abort aborts the current command that is executing on host host.
- The error code, if non zero is returned in the host byte, otherwise
- DID_ABORT is returned in the hostbyte.
-*/
-
-extern int scsi_abort (int host, int code);
-
-/*
- Initializes all SCSI devices. This scans all scsi busses.
-*/
-
-extern void scsi_dev_init (void);
-
-/*
- You guesed it. This sends a command to the selected SCSI host
-*/
-
-
-
-extern void scsi_do_cmd (int host, unsigned char target, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(int,int),
- int timeout, unsigned char *sense_buffer, int retries);
-
-int scsi_reset (int host);
-#endif
+++ /dev/null
-#include <linux/config.h>
-#ifdef CONFIG_SCSI
-
-#include <errno.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include "scsi.h"
-#include "hosts.h"
-#include "scsi_ioctl.h"
-
-#define MAX_RETRIES 5
-#define MAX_TIMEOUT 200
-#define MAX_BUF 1024
-
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-
-/*
- * If we are told to probe a host, we will return 0 if the host is not
- * present, 1 if the host is present, and will return an identifying
- * string at *arg, if arg is non null, filling to the length stored at
- * (int *) arg
- */
-
-static int ioctl_probe(int dev, void *buffer)
-{
- int temp;
- int len;
-
- if ((temp = scsi_hosts[dev].present) && buffer) {
- len = get_fs_long ((int *) buffer);
- memcpy_tofs (buffer, scsi_hosts[dev].info(), len);
- }
- return temp;
-}
-
-/*
- *
- * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
- * The MAX_TIMEOUT and MAX_RETRIES variables are used.
- *
- * dev is the SCSI device number, *(int *) arg the length of the input
- * data, *((int *)arg + 1) the output buffer.
- *
- * *(char *) ((int *) arg)[1] the actual command.
- *
- * Note that no more than MAX_BUF bytes will be transfered. Since
- * SCSI block device size is 512 bytes, I figured 1K was good.
- *
- * This size * does * include the initial lengths that were passed.
- *
- * The SCSI command is read from the memory location immediately after the
- * length words, and the out data after the command. The SCSI routines know the
- * command size based on the length byte.
- *
- * The area is then filled in from the byte at offset 0.
- */
-
-static int the_result[MAX_SCSI_HOSTS];
-
-static void scsi_ioctl_done (int host, int result)
-{
- the_result[host] = result;
-}
-
-static int ioctl_command(Scsi_Device *dev, void *buffer)
-{
- char buf[MAX_BUF];
- char cmd[10];
- char * cmd_in;
- unsigned char opcode;
- int inlen, outlen, cmdlen, temp, host;
-
- if (!buffer)
- return -EINVAL;
-
- inlen = get_fs_long((int *) buffer);
- outlen = get_fs_long(((int *) buffer) + 1);
-
- cmd_in = (char *) ( ((int *)buffer) + 2);
- opcode = get_fs_byte(cmd_in);
-
- memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode));
- memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen);
- host = dev->host_no;
-
-#ifndef DEBUG_NO_CMD
- do {
- cli();
- if (the_result[host]) {
- sti();
- while(the_result[host])
- /* nothing */;
- } else {
- the_result[host]=-1;
- sti();
- break;
- }
- } while (1);
-
- scsi_do_cmd(host, dev->id, cmd, buf, ((outlen > MAX_BUF) ?
- MAX_BUF : outlen), scsi_ioctl_done, MAX_TIMEOUT,
- buf, MAX_RETRIES);
-
- while (the_result[host] == -1)
- /* nothing */;
- temp = the_result[host];
- the_result[host]=0;
- memcpy_tofs (buffer, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen);
- return temp;
-#else
- {
- int i;
- printk("scsi_ioctl : device %d. command = ", dev);
- for (i = 0; i < 10; ++i)
- printk("%02x ", cmd[i]);
- printk("\r\nbuffer =");
- for (i = 0; i < 20; ++i)
- printk("%02x ", buf[i]);
- printk("\r\n");
- }
- return 0;
-#endif
-}
-
-
-/*
- the scsi_ioctl() function differs from most ioctls in that it does
- not take a major/minor number as the dev filed. Rather, it takes
- an index in scsi_devices[]
-*/
-int scsi_ioctl (int dev, int cmd, void *arg)
-{
- if ((cmd != 0 && dev > NR_SCSI_DEVICES) || dev < 0)
- return -ENODEV;
- if ((cmd == 0 && dev > MAX_SCSI_HOSTS))
- return -ENODEV;
-
- switch (cmd) {
- case SCSI_IOCTL_PROBE_HOST:
- return ioctl_probe(dev, arg);
- case SCSI_IOCTL_SEND_COMMAND:
- return ioctl_command((Scsi_Device *) dev, arg);
- default :
- return -EINVAL;
- }
-}
-#endif
+++ /dev/null
-#ifndef _SCSI_IOCTL_H
-#define _SCSI_IOCTL_H
-
-#ifndef _CONFIG_H
-#include <linux/config.h>
-#endif
-
-#define SCSI_IOCTL_PROBE_HOST 0
-#define SCSI_IOCTL_SEND_COMMAND 1
-
-#ifdef CONFIG_BLK_DEV_SD
-/* Should start at 128 */
-#endif
-
-#ifdef CONFIG_BLK_DEV_SD
-/* Should start at 256 */
-#endif
-
-#endif
-
-
+++ /dev/null
-/*
- * sd.c Copyright (C) 1992 Drew Eckhardt
- * Linux scsi disk driver by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-#include <linux/config.h>
-
-#ifdef CONFIG_BLK_DEV_SD
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include "scsi.h"
-#include "sd.h"
-
-#define MAJOR_NR 8
-
-#include "../blk.h"
-
-/*
-static const char RCSid[] = "$Header:";
-*/
-
-#define MAX_RETRIES 5
-
-/*
- * Time out in seconds
- */
-
-#define SD_TIMEOUT 100
-
-Partition scsi_disks[MAX_SD << 4];
-int NR_SD=0;
-Scsi_Disk rscsi_disks[MAX_SD];
-static int sd_sizes[MAX_SD << 4];
-static int this_count;
-static int the_result;
-
-extern int sd_ioctl(struct inode *, struct file *, unsigned long, unsigned long);
-
-static void sd_release(struct inode * inode, struct file * file)
-{
- sync_dev(inode->i_rdev);
-}
-
-static struct file_operations sd_fops = {
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* select */
- sd_ioctl, /* ioctl */
- NULL, /* no special open code */
- sd_release /* release */
-};
-
-/*
- The sense_buffer is where we put data for all mode sense commands
- performed.
-*/
-
-static unsigned char sense_buffer[255];
-
-/*
- rw_intr is the interrupt routine for the device driver. It will
- be notified on the end of a SCSI read / write, and
- will take on of several actions based on success or failure.
-*/
-
-static void rw_intr (int host, int result)
-{
- if (HOST != host)
- panic ("sd.o : rw_intr() recieving interrupt for different host.");
-
-/*
- First case : we assume that the command succeeded. One of two things will
- happen here. Either we will be finished, or there will be more
- sectors that we were unable to read last time.
-*/
-
- if (!result)
- if (!(CURRENT->nr_sectors -= this_count)) {
- end_request(1);
- do_sd_request();
- } else {
- CURRENT->nr_sectors -= this_count;
-/*
- The CURRENT->nr_sectors field is always done in 512 byte sectors,
- even if this really isn't the case.
-*/
-
- (char *) CURRENT->buffer += this_count << 9;
- CURRENT->sector += this_count;
- CURRENT->errors = 0;
- do_sd_request();
- }
-
-/*
- Now, if we were good little boys and girls, Santa left us a request
- sense buffer. We can extract information from this, so we
- can choose a block to remap, etc.
-*/
-
- else if (driver_byte(result) & DRIVER_SENSE) {
- if (sugestion(result) == SUGGEST_REMAP) {
-#ifdef REMAP
-/*
- Not yet implemented. A read will fail after being remapped,
- a write will call the strategy routine again.
-*/
-
- if rscsi_disks[DEVICE_NR(CURRENT->dev)].remap
- {
- result = 0;
- }
- else
-
-#endif
- }
-/*
- If we had an ILLEGAL REQUEST returned, then we may have performed
- an unsupported command. The only thing this should be would be a ten
- byte read where only a six byte read was supportted. Also, on a
- system where READ CAPACITY failed, we mave have read past the end of the
- disk.
-*/
-
- else if (sense_buffer[7] == ILLEGAL_REQUEST) {
- if (rscsi_disks[DEVICE_NR(CURRENT->dev)].ten) {
- rscsi_disks[DEVICE_NR(CURRENT->dev)].ten = 0;
- do_sd_request();
- result = 0;
- } else {
- }
- }
- }
- if (result) {
- printk("SCSI disk error : host %d id %d lun %d return code = %03x\n",
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no,
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id,
- rscsi_disks[DEVICE_NR(CURRENT->dev)].device->lun);
-
- if (driver_byte(result) & DRIVER_SENSE)
- printk("\tSense class %x, sense error %x, extended sense %x\n",
- sense_class(sense_buffer[0]),
- sense_error(sense_buffer[0]),
- sense_buffer[2] & 0xf);
-
- end_request(0);
- }
-}
-
-/*
- do_sd_request() is the request handler function for the sd driver.
- Its function in life is to take block device requests, and translate
- them to SCSI commands.
-*/
-
-void do_sd_request (void)
-{
- int dev, block;
- unsigned char cmd[10];
-
- INIT_REQUEST;
- dev = MINOR(CURRENT->dev);
- block = CURRENT->sector;
-
-#ifdef DEBUG
- printk("Doing sd request, dev = %d, block = %d\n", dev, block);
-#endif
-
- if (dev >= (NR_SD << 4) || block + 2 > scsi_disks[dev].nr_sects ||
- (dev % 16) > 5)
- {
- end_request(0);
- goto repeat;
- }
-
- block += scsi_disks[dev].start_sect;
- dev = DEVICE_NR(dev);
-
-#ifdef DEBUG
- printk("Real dev = %d, block = %d\n", dev, block);
-#endif
-
- if (!rscsi_disks[dev].use)
- {
- end_request(0);
- goto repeat;
- }
-
- this_count = CURRENT->nr_sectors;
- switch (CURRENT->cmd)
- {
- case WRITE :
- if (!rscsi_disks[dev].device->writeable)
- {
- end_request(0);
- goto repeat;
- }
- cmd[0] = WRITE_6;
- break;
- case READ :
- cmd[0] = READ_6;
- break;
- default :
- printk ("Unknown sd command %d\r\n", CURRENT->cmd);
- panic("");
- }
-
- cmd[1] = (LUN << 5) & 0xe0;
-
- if (((this_count > 0xff) || (block > 0x1fffff)) && rscsi_disks[dev].ten)
- {
- if (this_count > 0xffff)
- this_count = 0xffff;
-
- cmd[0] += READ_10 - READ_6 ;
- cmd[2] = (unsigned char) (block >> 24) & 0xff;
- cmd[3] = (unsigned char) (block >> 16) & 0xff;
- cmd[4] = (unsigned char) (block >> 8) & 0xff;
- cmd[5] = (unsigned char) block & 0xff;
- cmd[6] = cmd[9] = 0;
- cmd[7] = (unsigned char) (this_count >> 8) & 0xff;
- cmd[8] = (unsigned char) this_count & 0xff;
- }
- else
- {
- if (this_count > 0xff)
- this_count = 0xff;
-
- cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
- cmd[2] = (unsigned char) ((block >> 8) & 0xff);
- cmd[3] = (unsigned char) block & 0xff;
- cmd[4] = (unsigned char) this_count;
- cmd[5] = 0;
- }
-
- scsi_do_cmd (HOST, ID, (void *) cmd, CURRENT->buffer, this_count << 9,
- rw_intr, SD_TIMEOUT, sense_buffer, MAX_RETRIES);
-}
-
-static void sd_init_done (int host, int result)
-{
- the_result = result;
-}
-
-/*
- The sd_init() function looks at all SCSI drives present, determines
- their size, and reads partition table entries for them.
-*/
-
-void sd_init(void)
-{
- int i,j,k;
- unsigned char cmd[10];
- unsigned char buffer[513];
-
- Partition *p;
-
-
- for (i = 0; i < NR_SD; ++i)
- {
- cmd[0] = READ_CAPACITY;
- rscsi_disks[i].use = 1;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
- memset ((void *) &cmd[2], 0, 8);
- the_result = -1;
-#ifdef DEBUG
- printk("Read capacity, disk %d at host = %d, id = %d\n", i,
- rscsi_disks[i].device->host_no, rscsi_disks[i].device->id);
-#endif
- scsi_do_cmd (rscsi_disks[i].device->host_no ,
- rscsi_disks[i].device->id,
- (void *) cmd, (void *) buffer,
- 512, sd_init_done, SD_TIMEOUT, sense_buffer,
- MAX_RETRIES);
-
- while(the_result < 0);
-/*
- The SCSI standard says "READ CAPACITY is necessary for self confuring software"
- While not mandatory, support of READ CAPACITY is strongly encouraged.
-
- We used to die if we couldn't successfully do a READ CAPACITY.
- But, now we go on about our way. The side effects of this are
-
- 1. We can't know block size with certainty. I have said "512 bytes is it"
- as this is most common.
-
- 2. Recovery from when some one attempts to read past the end of the raw device will
- be slower.
-*/
-
- if (the_result)
- {
- printk ("Warning : SCSI device at host %d, id %d, lun %d failed READ CAPACITY.\n"
- "status = %x, message = %02x, host = %02x, driver = %02x \n",
- rscsi_disks[i].device->host_no, rscsi_disks[i].device->id,
- rscsi_disks[i].device->lun,
- status_byte(the_result),
- msg_byte(the_result),
- host_byte(the_result),
- driver_byte(the_result)
- );
- if (driver_byte(the_result) & DRIVER_SENSE)
- printk("Extended sense code = %1x \n", sense_buffer[2] & 0xf);
- else
- printk("Sense not available. \n");
-
- printk("Block size assumed to be 512 bytes, disk size 1GB. \n");
- rscsi_disks[i].capacity = 0x1fffff;
- rscsi_disks[i].sector_size = 512;
- }
- else
- {
- rscsi_disks[i].capacity = (buffer[0] << 24) |
- (buffer[1] << 16) |
- (buffer[2] << 8) |
- buffer[3];
-
- if ((rscsi_disks[i].sector_size = (buffer[4] << 24) |
- (buffer[5] << 16) |
- (buffer[6] << 8) |
- buffer[7]) != 512)
- {
- printk ("Unsupported sector size %d for sd %d",
- rscsi_disks[i].sector_size, i);
- rscsi_disks[i].use = 0;
- }
- }
-
- if (rscsi_disks[i].use)
- {
- scsi_disks[j = (i << 4)].start_sect = 0;
-
- sd_sizes[j]=(scsi_disks[j].nr_sects = rscsi_disks[i].capacity)>>1;
-#ifdef DEBUG
- printk("/dev/sd%1d size = %d\n", j, sd_sizes[j]);
-#endif
- cmd[0] = READ_6;
- cmd[2] = cmd[3] = cmd[5] = 0;
- cmd[4] = 1;
- the_result = -1;
-
- scsi_do_cmd (rscsi_disks[i].device->host_no , rscsi_disks[i].device->id,
- (void *) cmd, (void *) buffer, 512, sd_init_done, SD_TIMEOUT,
- sense_buffer, MAX_RETRIES);
-
- while (the_result < 0);
-
-
- if (the_result || (0xaa55 != *(unsigned short *)(buffer + 510)))
- {
- printk ("Cannot read partition table for sd %d"
- "\n\r",i);
- rscsi_disks[i].use = 0;
- }
- else
- for (++j, k=j+4, p=(Partition *) (buffer + 0x1be); j < k; ++j, ++p)
- {
- memcpy ((void *) &scsi_disks[j], (void *) p, sizeof(Partition));
- sd_sizes[j]=(scsi_disks[j].nr_sects)>>1;
-#ifdef DEBUG
- printk("/dev/sd%1d size = %d (%d blocks), offset = %d\n", j, scsi_disks[j].nr_sects, sd_sizes[j], scsi_disks[j].start_sect);
-#endif
- }
-
- rscsi_disks[i].ten = 1;
- rscsi_disks[i].remap = 1;
- }
- }
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- blk_size[MAJOR_NR] = sd_sizes;
- blkdev_fops[MAJOR_NR] = &sd_fops;
-}
-#endif
-
+++ /dev/null
-/*
- * sd.h Copyright (C) 1992 Drew Eckhardt
- * SCSI disk driver header file by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-#ifndef _SD_H
- #define _SD_H
-/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/04/24 18:01:50 root Exp root $
-*/
-
-#ifndef _SCSI_H
-#include "scsi.h"
-#endif
-
-#define MAX_SD 2
-
-typedef struct partition {
- unsigned char boot_ind; /* 0x80 - active (unused) */
- unsigned char head; /* ? */
- unsigned char sector; /* ? */
- unsigned char cyl; /* ? */
- unsigned char sys_ind; /* ? */
- unsigned char end_head; /* ? */
- unsigned char end_sector; /* ? */
- unsigned char end_cyl; /* ? */
- unsigned int start_sect; /* starting sector counting from 0 */
- unsigned int nr_sects; /* nr of sectors in partition */
-} Partition;
-
-extern int NR_SD;
-
-extern Partition scsi_disks[MAX_SD << 4] ;
-
-
-typedef struct {
- unsigned capacity; /* size in blocks */
- unsigned sector_size; /* size in bytes */
- Scsi_Device *device;
- unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */
- unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
- unsigned ten:1; /* support ten byte read / write */
- unsigned remap:1; /* support remapping */
- unsigned use:1; /* after the initial inquiry, is
- the device still supported ? */
- } Scsi_Disk;
-
-extern Scsi_Disk rscsi_disks[MAX_SD];
-
-void sd_init(void);
-
-#define HOST (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->host_no)
-#define ID (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->id)
-#define LUN (rscsi_disks[DEVICE_NR(CURRENT->dev)].device->lun)
-#endif
+++ /dev/null
-#include <linux/config.h>
-#ifdef CONFIG_BLK_DEV_SD
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <asm/segment.h>
-#include "../blk.h"
-#include <errno.h>
-#include "scsi.h"
-#include "sd.h"
-
-extern int scsi_ioctl (int dev, int cmd, void *arg);
-
-int sd_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
-{
- int dev = inode->i_rdev;
-
- switch (cmd) {
- RO_IOCTLS(dev,arg);
- default:
- return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device,cmd,(void *) arg);
- }
-}
-#endif
+++ /dev/null
-/*
- * seagate.c Copyright (C) 1992 Drew Eckhardt
- * low level scsi driver for ST01/ST02 by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI_SEAGATE
-#include <linux/sched.h>
-
-#include "seagate.h"
-#include "scsi.h"
-#include "hosts.h"
-
-static int incommand; /*
- set if arbitration has finished and we are
- in some command phase.
- */
-
-static void *base_address = NULL; /*
- Where the card ROM starts,
- used to calculate memory mapped
- register location.
- */
-static volatile int abort_confirm = 0;
-
-volatile void *st0x_cr_sr; /*
- control register write,
- status register read.
- 256 bytes in length.
-
- Read is status of SCSI BUS,
- as per STAT masks.
-
- */
-
-
-static volatile void *st0x_dr; /*
- data register, read write
- 256 bytes in length.
- */
-
-
-static volatile int st0x_aborted=0; /*
- set when we are aborted, ie by a time out, etc.
- */
-
- /*
- In theory, we have a nice auto
- detect routine - but this
- overides it.
- */
-
-
-#define retcode(result) (((result) << 16) | (message << 8) | status)
-#define STATUS (*(unsigned char *) st0x_cr_sr)
-#define CONTROL STATUS
-#define DATA (*(unsigned char *) st0x_dr)
-
-#ifndef OVERRIDE
-static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
- (char *) 0xdc000, (char *) 0xde000};
-typedef struct
- {
- char *signature ;
- unsigned offset;
- unsigned length;
- } Signature;
-
-static const Signature signatures[] = {
-{"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
-{"SEAGATE SCSI BIOS ",16, 17},
-{"SEAGATE SCSI BIOS ",17, 17}};
-/*
- Note that the last signature handles BIOS revisions 3.0.0 and
- 3.2 - the real ID's are
-
-SEAGATE SCSI BIOS REVISION 3.0.0
-SEAGATE SCSI BIOS REVISION 3.2
-
-*/
-
-#define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
-#endif
-
-int seagate_st0x_detect (int hostnum)
- {
- #ifndef OVERRIDE
- int i,j;
- #endif
-
- /*
- First, we try for the manual override.
- */
- #ifdef DEBUG
- printk("Autodetecting seagate ST0x\n");
- #endif
-
- base_address = NULL;
- #ifdef OVERRIDE
- base_address = (void *) OVERRIDE;
- #ifdef DEBUG
- printk("Base address overridden to %x\n", base_address);
- #endif
- #else
- /*
- To detect this card, we simply look for the SEAGATE SCSI
- from the BIOS version notice in all the possible locations
- of the ROM's.
- */
-
- for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
- for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
- if (!memcmp ((void *) (seagate_bases[i] +
- signatures[j].offset), (void *) signatures[j].signature,
- signatures[j].length))
- base_address = (void *) seagate_bases[i];
- #endif
-
- if (base_address)
- {
- st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
- st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
- #ifdef DEBUG
- printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
- #endif
- return -1;
- }
- else
- {
- #ifdef DEBUG
- printk("ST0x not detected.\n");
- #endif
- return 0;
- }
- }
-
-
-
-char *seagate_st0x_info(void)
-{
- static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
-"$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/04/24 18:01:50 root Exp root $\n";
- return buffer;
-}
-
-
-
-int seagate_st0x_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen)
- {
- int len;
- unsigned char *data;
-
- int clock; /*
- We use clock for timeouts, etc. This replaces the
- seagate_st0x_timeout that we had been using.
- */
- #if (DEBUG & PHASE_SELECTION)
- int temp;
- #endif
-
- #if (DEBUG & PHASE_EXIT)
- void *retaddr, *realretaddr;
- #endif
-
- #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
- int i;
- #endif
-
- #if (DEBUG & PHASE_ETC)
- int phase=0, newphase;
- #endif
-
- int done = 0;
- unsigned char status = 0;
- unsigned char message = 0;
- register unsigned char status_read;
-
- #if (DEBUG & PHASE_EXIT)
- __asm__("
-movl 4(%%ebp), %%eax
-":"=a" (realretaddr):);
- printk("return address = %08x\n", realretaddr);
- #endif
-
-
- len=bufflen;
- data=(unsigned char *) buff;
-
- incommand = 0;
- st0x_aborted = 0;
-
- #if (DEBUG & PRINT_COMMAND)
- printk ("seagate_st0x_command, target = %d, command = ", target);
- for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
- printk("%02x ", ((unsigned char *) cmnd)[i]);
- printk("\n");
- #endif
-
- if (target > 6)
- return DID_BAD_TARGET;
-
-
- #if (DEBUG & PHASE_BUS_FREE)
- printk ("SCSI PHASE = BUS FREE \n");
- #endif
-
- /*
-
- BUS FREE PHASE
-
- On entry, we make sure that the BUS is in a BUS FREE
- phase, by insuring that both BSY and SEL are low for
- at least one bus settle delay. The standard requires a
- minimum of 400 ns, which is 16 clock cycles on a
- 386-40 .
-
- This doesn't give us much time - so we'll do two several
- reads to be sure be sure.
- */
-
- clock = jiffies + ST0X_BUS_FREE_DELAY;
-
- while (((STATUS | STATUS | STATUS) &
- (STAT_BSY | STAT_SEL)) &&
- (!st0x_aborted) && (jiffies < clock));
-
- if (jiffies > clock)
- return retcode(DID_BUS_BUSY);
- else if (st0x_aborted)
- return retcode(st0x_aborted);
-
- /*
- Bus free has been detected, within BUS settle. I used to support an arbitration
- phase - however, on the seagate, this degraded performance by a factor > 10 - so
- it is no more.
- */
-
- /*
- SELECTION PHASE
-
- Now, we select the disk, giving it the SCSI ID at data
- and a command of PARITY if necessary, plus driver enable,
- plus raise select signal.
- */
-
- #if (DEBUG & PHASE_SELECTION)
- printk("SCSI PHASE = SELECTION\n");
- #endif
-
- clock = jiffies + ST0X_SELECTION_DELAY;
- DATA = (unsigned char) (1 << target);
-
- CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL;
-
- /*
- When the SCSI device decides that we're gawking at it, it will respond by asserting BUSY on the bus.
- */
- while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock) && !st0x_aborted)
-
-#if (DEBUG & PHASE_SELECTION)
- {
- temp = clock - jiffies;
-
- if (!(jiffies % 5))
- printk("seagate_st0x_timeout : %d \r",temp);
-
- }
- printk("Done. \n\r");
- printk("Status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", status_read, temp,
- st0x_aborted);
-#else
- ;
-#endif
-
-
- if ((jiffies > clock) || (!st0x_aborted & !(status_read & STAT_BSY)))
- {
- #if (DEBUG & PHASE_SELECT)
- printk ("NO CONNECT with target %d, status = %x \n", target, STATUS);
- #endif
- return retcode(DID_NO_CONNECT);
- }
-
- /*
- If we have been aborted, and we have a command in progress, IE the target still has
- BSY asserted, then we will reset the bus, and notify the midlevel driver to
- expect sense.
- */
-
- if (st0x_aborted)
- {
- CONTROL = BASE_CMD;
- if (STATUS & STAT_BSY)
- {
- seagate_st0x_reset();
- return retcode(DID_RESET);
- }
-
- return retcode(st0x_aborted);
- }
-
- /*
- COMMAND PHASE
- The device has responded with a BSY, so we may now enter
- the information transfer phase, where we will send / recieve
- data and command as directed by the target.
-
-
- The nasty looking read / write inline assembler loops we use for
- DATAIN and DATAOUT phases are approximately 4-5 times as fast as
- the 'C' versions - since we're moving 1024 bytes of data, this
- really adds up.
- */
-
- #if (DEBUG & PHASE_ETC)
- printk("PHASE = information transfer\n");
- #endif
-
- incommand = 1;
-
- /*
- Enable command
- */
-
- CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
-
- /*
- Now, we poll the device for status information,
- and handle any requests it makes. Note that since we are unsure of
- how much data will be flowing across the system, etc and cannot
- make reasonable timeouts, that we will instead have the midlevel
- driver handle any timeouts that occur in this phase.
- */
-
- while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
- {
- #ifdef PARITY
- if (status_read & STAT_PARITY)
- {
- done = 1;
- st0x_aborted = DID_PARITY;
- }
- #endif
-
- if (status_read & STAT_REQ)
- {
- #if (DEBUG & PHASE_ETC)
- if ((newphase = (status_read & REQ_MASK)) != phase)
- {
- phase = newphase;
- switch (phase)
- {
- case REQ_DATAOUT : printk("SCSI PHASE = DATA OUT\n"); break;
- case REQ_DATAIN : printk("SCSI PHASE = DATA IN\n"); break;
- case REQ_CMDOUT : printk("SCSI PHASE = COMMAND OUT\n"); break;
- case REQ_STATIN : printk("SCSI PHASE = STATUS IN\n"); break;
- case REQ_MSGOUT : printk("SCSI PHASE = MESSAGE OUT\n"); break;
- case REQ_MSGIN : printk("SCSI PHASE = MESSAGE IN\n"); break;
- default : printk("UNKNOWN PHASE"); st0x_aborted = 1; done = 1;
- }
- }
- #endif
-
- switch (status_read & REQ_MASK)
- {
- case REQ_DATAOUT :
-
- /*
- We loop as long as we are in a data out phase, there is data to send, and BSY is still
- active
- */
- __asm__ ("
-
-/*
- Local variables :
- len = ecx
- data = esi
- st0x_cr_sr = ebx
- st0x_dr = edi
-
- Test for any data here at all.
-*/
- movl %0, %%esi /* local value of data */
- movl %1, %%ecx /* local value of len */
- orl %%ecx, %%ecx
- jz 2f
-
- cld
-
- movl _st0x_cr_sr, %%ebx
- movl _st0x_dr, %%edi
-
-1: movb (%%ebx), %%al
-/*
- Test for BSY
-*/
-
- test $1, %%al
- jz 2f
-
-/*
- Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
-*/
- test $0xe, %%al
- jnz 2f
-/*
- Test for REQ
-*/
- test $0x10, %%al
- jz 1b
- lodsb
- movb %%al, (%%edi)
- loop 1b
-
-2:
- movl %%esi, %2
- movl %%ecx, %3
- ":
-/* output */
-"=r" (data), "=r" (len) :
-/* input */
-"0" (data), "1" (len) :
-/* clobbered */
-"ebx", "ecx", "edi", "esi");
-
- break;
-
- case REQ_DATAIN :
- /*
- We loop as long as we are in a data out phase, there is room to read, and BSY is still
- active
- */
-
- __asm__ ("
-/*
- Local variables :
- ecx = len
- edi = data
- esi = st0x_cr_sr
- ebx = st0x_dr
-
- Test for room to read
-*/
-
- movl %0, %%edi /* data */
- movl %1, %%ecx /* len */
- orl %%ecx, %%ecx
- jz 2f
-
- cld
- movl _st0x_cr_sr, %%esi
- movl _st0x_dr, %%ebx
-
-1: movb (%%esi), %%al
-/*
- Test for BSY
-*/
-
- test $1, %%al
- jz 2f
-
-/*
- Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
-*/
- movb $0xe, %%ah
- andb %%al, %%ah
- cmpb $0x04, %%ah
- jne 2f
-
-/*
- Test for REQ
-*/
- test $0x10, %%al
- jz 1b
-
- movb (%%ebx), %%al
- stosb
- loop 1b
-
-2: movl %%edi, %2 /* data */
- movl %%ecx, %3 /* len */
- ":
-/* output */
-"=r" (data), "=r" (len) :
-/* input */
-"0" (data), "1" (len) :
-/* clobbered */
-"ebx", "ecx", "edi", "esi");
- break;
-
- case REQ_CMDOUT :
- while (((status_read = STATUS) & STAT_BSY) && ((status_read & REQ_MASK) ==
- REQ_CMDOUT))
- DATA = *(unsigned char *) cmnd ++;
- break;
-
- case REQ_STATIN :
- status = DATA;
- break;
-
- case REQ_MSGOUT :
- DATA = MESSAGE_REJECT;
- break;
-
- case REQ_MSGIN :
- if ((message = DATA) == COMMAND_COMPLETE)
- done=1;
-
- break;
-
- default : printk("UNKNOWN PHASE"); st0x_aborted = DID_ERROR;
- }
- }
-
- }
-
-#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
- printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
-#endif
-
-#if (DEBUG & PHASE_EXIT)
- printk("Buffer : \n");
- for (i = 0; i < 20; ++i)
- printk ("%02x ", ((unsigned char *) buff)[i]);
- printk("\n");
- printk("Status = %02x, message = %02x\n", status, message);
-#endif
-
-
- if (st0x_aborted)
- {
- if (STATUS & STAT_BSY)
- {
- seagate_st0x_reset();
- st0x_aborted = DID_RESET;
- }
- abort_confirm = 1;
- }
-
- CONTROL = BASE_CMD;
-
-#if (DEBUG & PHASE_EXIT)
- __asm__("
-mov 4(%%ebp), %%eax
-":"=a" (retaddr):);
-
- printk("Exiting seagate_st0x_command() - return address is %08x \n", retaddr);
- if (retaddr != realretaddr)
- panic ("Corrupted stack : return address on entry != return address on exit.\n");
-
-#endif
-
- return retcode (st0x_aborted);
- }
-
-int seagate_st0x_abort (int code)
- {
- if (code)
- st0x_aborted = code;
- else
- st0x_aborted = DID_ABORT;
-
- return 0;
- }
-
-/*
- the seagate_st0x_reset function resets the SCSI bus
-*/
-
-int seagate_st0x_reset (void)
- {
- unsigned clock;
- /*
- No timeouts - this command is going to fail because
- it was reset.
- */
-
-#ifdef DEBUG
- printk("In seagate_st0x_reset()\n");
-#endif
-
-
- /* assert RESET signal on SCSI bus. */
-
- CONTROL = BASE_CMD | CMD_RST;
- clock=jiffies+2;
-
-
- /* Wait. */
-
- while (jiffies < clock);
-
- CONTROL = BASE_CMD;
-
- st0x_aborted = DID_RESET;
-
-#ifdef DEBUG
- printk("SCSI bus reset.\n");
-#endif
- return 0;
- }
-#endif
+++ /dev/null
-/*
- * seagate.h Copyright (C) 1992 Drew Eckhardt
- * low level scsi driver header for ST01/ST02 by
- * Drew Eckhardt
- *
- * <drew@colorado.edu>
- */
-
-#ifndef _SEAGATE_H
- #define SEAGATE_H
-/*
- $Header
-*/
-#ifndef ASM
-int seagate_st0x_detect(int);
-int seagate_st0x_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
-int seagate_st0x_abort(int);
-char *seagate_st0x_info(void);
-int seagate_st0x_reset(void);
-
-#ifndef NULL
- #define NULL 0
-#endif
-
-#define SEAGATE_ST0X {"Seagate ST-01/ST-02", seagate_st0x_detect, \
- seagate_st0x_info, seagate_st0x_command, \
- NULL, seagate_st0x_abort, seagate_st0x_reset, \
- 0, 7, 0}
-#endif
-
-
-/*
- defining PARITY causes parity data to be checked
-*/
-
-#define PARITY
-
-/*
- defining ARBITRATE causes the arbitration sequence to be used. And speed to drop by a
- factor of ten.
-*/
-
-#undef ARBITRATE
-
-
-/*
- Thanks to Brian Antoine for the example code in his Messy-Loss ST-01
- driver, and Mitsugu Suzuki for information on the ST-01
- SCSI host.
-*/
-
-/*
- CONTROL defines
-*/
-
-#define CMD_RST 0x01
-#define CMD_SEL 0x02
-#define CMD_BSY 0x04
-#define CMD_ATTN 0x08
-#define CMD_START_ARB 0x10
-#define CMD_EN_PARITY 0x20
-#define CMD_INTR 0x40
-#define CMD_DRVR_ENABLE 0x80
-
-/*
- STATUS
-*/
-
-#define STAT_BSY 0x01
-#define STAT_MSG 0x02
-#define STAT_IO 0x04
-#define STAT_CD 0x08
-#define STAT_REQ 0x10
-#define STAT_SEL 0x20
-#define STAT_PARITY 0x40
-#define STAT_ARB_CMPL 0x80
-
-/*
- REQUESTS
-*/
-
-#define REQ_MASK (STAT_CD | STAT_IO | STAT_MSG)
-#define REQ_DATAOUT 0
-#define REQ_DATAIN STAT_IO
-#define REQ_CMDOUT STAT_CD
-#define REQ_STATIN (STAT_CD | STAT_IO)
-#define REQ_MSGOUT (STAT_MSG | STAT_CD)
-#define REQ_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
-
-extern volatile int seagate_st0x_timeout;
-
-#ifdef PARITY
- #define BASE_CMD CMD_EN_PARITY
-#else
- #define BASE_CMD 0
-#endif
-
-/*
- Debugging code
-*/
-
-#define PHASE_BUS_FREE 1
-#define PHASE_ARBITRATION 2
-#define PHASE_SELECTION 4
-#define PHASE_DATAIN 8
-#define PHASE_DATAOUT 0x10
-#define PHASE_CMDOUT 0x20
-#define PHASE_MSGIN 0x40
-#define PHASE_MSGOUT 0x80
-#define PHASE_STATUSIN 0x100
-#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
-#define PRINT_COMMAND 0x200
-#define PHASE_EXIT 0x400
-
-/*
- Control options - these are timeouts specified in .01 seconds.
-*/
-
-#define ST0X_BUS_FREE_DELAY 25
-#define ST0X_SELECTION_DELAY 25
-
-#endif
-
+++ /dev/null
-/*
- The st.c file is a sub-stub file. I just wanted to have all the detect code, etc in the
- mid level driver present and working. If no one else volunteers for this, I'll
- do it - but it's low on my list of priorities.
-*/
-#include <linux/config.h>
-
-#ifdef CONFIG_BLK_DEV_ST
-#include "scsi.h"
-#include "st.h"
-
-#define MAJOR_NR 9
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include "../blk.h"
-
-/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
-*/
-
-Scsi_Tape scsi_tapes[MAX_ST];
-static int st_sizes[MAX_ST];
-int NR_ST=0;
-
-void do_st_request(void)
-{
- panic("There is no st driver.\n\r");
-}
-
-void st_init(void)
-{
- blk_dev[MAJOR_NR].request_fn = do_st_request;
- blk_size[MAJOR_NR] = st_sizes;
-}
-#endif
+++ /dev/null
-
-#ifndef _ST_H
- #define _ST_H
-/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/04/24 18:01:50 root Exp root $
-*/
-
-#ifndef _SCSI_H
-#include "scsi.h"
-#endif
-
-#define MAX_ST 1
-
-typedef struct
- {
- /*
- Undecided goodies go here!!!
- */
- Scsi_Device* device;
- } Scsi_Tape;
-
-
-extern int NR_ST;
-extern Scsi_Tape scsi_tapes[MAX_ST];
-void st_init(void);
-#endif
+++ /dev/null
-#include <linux/config.h>
-#ifdef CONFIG_BLK_DEV_ST
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include "st.h"
-
-extern int scsi_ioctl(int dev, int cmd, void *arg);
-
-int st_ioctl(struct inode * inode,struct file * file, unsigned long cmd, unsigned long arg)
-{
- int dev = inode->i_rdev;
-
- switch (cmd) {
- default:
- return scsi_ioctl(scsi_tapes[MINOR(dev)].device,cmd,(void *) arg);
- }
-}
-#endif
+++ /dev/null
-/*
- * ultrastor.c (C) 1991 David B. Gentzel
- * Low-level SCSI driver for UltraStor 14F
- * by David B. Gentzel, Whitfield Software Services, Carnegie, PA
- * (gentzel@nova.enet.dec.com)
- * Thanks to UltraStor for providing the necessary documentation
- */
-
-/*
- * NOTES:
- * The UltraStor 14F is an intelligent, high performance ISA SCSI-2 host
- * adapter. It is essentially an ISA version of the UltraStor 24F EISA
- * adapter. It supports first-party DMA, command queueing, and
- * scatter/gather I/O. It can also emulate the standard AT MFM/RLL/IDE
- * interface for use with OS's which don't support SCSI.
- *
- * This driver may also work (with some small changes) with the UltraStor
- * 24F. I have no way of confirming this...
- *
- * Places flagged with a triple question-mark are things which are either
- * unfinished, questionable, or wrong.
- */
-
-/*
- * CAVEATS: ???
- * This driver is VERY stupid. It takes no advantage of much of the power
- * of the UltraStor controller. We just sit-and-spin while waiting for
- * commands to complete. I hope to go back and beat it into shape, but
- * PLEASE, anyone else who would like to, please make improvements!
- *
- * By defining USE_QUEUECOMMAND as TRUE in ultrastor.h, you enable the
- * queueing feature of the mid-level SCSI driver. This should improve
- * performance somewhat. However, it does not seem to work. I believe
- * this is due to a bug in the mid-level driver, but I haven't looked
- * too closely.
- */
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SCSI_ULTRASTOR
-
-#include <stddef.h>
-
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */
-#include "ultrastor.h"
-#include "scsi.h"
-#include "hosts.h"
-
-#define VERSION "1.0 beta"
-
-#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
-#define BIT(n) (1ul << (n))
-#define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
-
-/* Simply using "unsigned long" in these structures won't work as it causes
- alignment. Perhaps the "aligned" attribute may be used in GCC 2.0 to get
- around this, but for now I use this hack. */
-typedef struct {
- unsigned char bytes[4];
-} Longword;
-
-/* Used to fetch the configuration info from the config i/o registers. We
- then store (in a friendlier format) in config. */
-struct config_1 {
- unsigned char bios_segment: 3;
- unsigned char reserved: 1;
- unsigned char interrupt: 2;
- unsigned char dma_channel: 2;
-};
-struct config_2 {
- unsigned char ha_scsi_id: 3;
- unsigned char mapping_mode: 2;
- unsigned char bios_drive_number: 1;
- unsigned char tfr_port: 2;
-};
-
-/* Used to store configuration info read from config i/o registers. Most of
- this is not used yet, but might as well save it. */
-struct config {
- unsigned short port_address;
- const void *bios_segment;
- unsigned char interrupt: 4;
- unsigned char dma_channel: 3;
- unsigned char ha_scsi_id: 3;
- unsigned char heads: 6;
- unsigned char sectors: 6;
- unsigned char bios_drive_number: 1;
-};
-
-/* MailBox SCSI Command Packet. Basic command structure for communicating
- with controller. */
-struct mscp {
- unsigned char opcode: 3; /* type of command */
- unsigned char xdir: 2; /* data transfer direction */
- unsigned char dcn: 1; /* disable disconnect */
- unsigned char ca: 1; /* use cache (if available) */
- unsigned char sg: 1; /* scatter/gather operation */
- unsigned char target_id: 3; /* target SCSI id */
- unsigned char ch_no: 2; /* SCSI channel (always 0 for 14f) */
- unsigned char lun: 3; /* logical unit number */
- Longword transfer_data; /* transfer data pointer */
- Longword transfer_data_length; /* length in bytes */
- Longword command_link; /* for linking command chains */
- unsigned char scsi_command_link_id; /* identifies command in chain */
- unsigned char number_of_sg_list; /* (if sg is set) 8 bytes per list */
- unsigned char length_of_sense_byte;
- unsigned char length_of_scsi_cdbs; /* 6, 10, or 12 */
- unsigned char scsi_cdbs[12]; /* SCSI commands */
- unsigned char adapter_status; /* non-zero indicates HA error */
- unsigned char target_status; /* non-zero indicates target error */
- Longword sense_data;
-};
-
-/* Allowed BIOS base addresses for 14f (NULL indicates reserved) */
-static const void *const bios_segment_table[8] = {
- NULL, (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
- (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
-};
-
-/* Allowed IRQs for 14f */
-static const unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
-
-/* Allowed DMA channels for 14f (0 indicates reserved) */
-static const unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
-
-/* Head/sector mappings allowed by 14f */
-static const struct {
- unsigned char heads;
- unsigned char sectors;
-} mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
-
-/* Config info */
-static struct config config;
-
-/* Our index in the host adapter array maintained by higher-level driver */
-static int host_number;
-
-/* PORT_ADDRESS is first port address used for i/o of messages. */
-#ifdef PORT_OVERRIDE
-# define PORT_ADDRESS PORT_OVERRIDE
-#else
-# define PORT_ADDRESS (config.port_address)
-#endif
-
-static volatile int aborted = 0;
-
-#ifndef PORT_OVERRIDE
-static const unsigned short ultrastor_ports[] = {
- 0x330, 0x340, 0x310, 0x230, 0x240, 0x210, 0x130, 0x140,
-};
-#endif
-
-void ultrastor_interrupt(int cpl);
-
-static void (*ultrastor_done)(int, int) = 0;
-
-static const struct {
- const char *signature;
- size_t offset;
- size_t length;
-} signatures[] = {
- { "SBIOS 1.01 COPYRIGHT (C) UltraStor Corporation,1990-1992.", 0x10, 57 },
-};
-
-int ultrastor_14f_detect(int hostnum)
-{
- size_t i;
- unsigned char in_byte;
- struct config_1 config_1;
- struct config_2 config_2;
-
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: called\n");
-#endif
-
-#ifndef PORT_OVERRIDE
- PORT_ADDRESS = 0;
- for (i = 0; i < ARRAY_SIZE(ultrastor_ports); i++) {
- PORT_ADDRESS = ultrastor_ports[i];
-#endif
-
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: testing port address %03X\n", PORT_ADDRESS);
-#endif
-
- in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
- if (in_byte != US14F_PRODUCT_ID_0) {
-#if (ULTRASTOR_DEBUG & UD_DETECT)
-# ifdef PORT_OVERRIDE
- printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
-# else
- printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
-# endif
-#endif
-#ifdef PORT_OVERRIDE
- return FALSE;
-#else
- continue;
-#endif
- }
- in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
- /* Only upper nibble is defined for Product ID 1 */
- if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
-#if (ULTRASTOR_DEBUG & UD_DETECT)
-# ifdef PORT_OVERRIDE
- printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
-# else
- printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
-# endif
-#endif
-#ifdef PORT_OVERRIDE
- return FALSE;
-#else
- continue;
-#endif
- }
-#ifndef PORT_OVERRIDE
- break;
- }
- if (i == ARRAY_SIZE(ultrastor_ports)) {
-# if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: no port address found!\n");
-# endif
- return FALSE;
- }
-#endif
-
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: adapter found at port address %03X\n",
- PORT_ADDRESS);
-#endif
-
- /* All above tests passed, must be the right thing. Get some useful
- info. */
- *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
- *(char *)&config_2 = inb(CONFIG(PORT_ADDRESS + 1));
- config.bios_segment = bios_segment_table[config_1.bios_segment];
- config.interrupt = interrupt_table[config_1.interrupt];
- config.dma_channel = dma_channel_table[config_1.dma_channel];
- config.ha_scsi_id = config_2.ha_scsi_id;
- config.heads = mapping_table[config_2.mapping_mode].heads;
- config.sectors = mapping_table[config_2.mapping_mode].sectors;
- config.bios_drive_number = config_2.bios_drive_number;
-
- /* To verify this card, we simply look for the UltraStor SCSI from the
- BIOS version notice. */
- if (config.bios_segment != NULL) {
- int found = 0;
-
- for (i = 0; !found && i < ARRAY_SIZE(signatures); i++)
- if (memcmp((char *)config.bios_segment + signatures[i].offset,
- signatures[i].signature, signatures[i].length))
- found = 1;
- if (!found)
- config.bios_segment = NULL;
- }
- if (!config.bios_segment) {
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: not detected.\n");
-#endif
- return FALSE;
- }
-
- /* Final consistancy check, verify previous info. */
- if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: consistancy check failed\n");
-#endif
- return FALSE;
- }
-
- /* If we were TRULY paranoid, we could issue a host adapter inquiry
- command here and verify the data returned. But frankly, I'm
- exhausted! */
-
- /* Finally! Now I'm satisfied... */
-#if (ULTRASTOR_DEBUG & UD_DETECT)
- printk("US14F: detect: detect succeeded\n"
- " Port address: %03X\n"
- " BIOS segment: %05X\n"
- " Interrupt: %u\n"
- " DMA channel: %u\n"
- " H/A SCSI ID: %u\n",
- PORT_ADDRESS, config.bios_segment, config.interrupt,
- config.dma_channel, config.ha_scsi_id);
-#endif
- host_number = hostnum;
- scsi_hosts[hostnum].this_id = config.ha_scsi_id;
-#if USE_QUEUECOMMAND
- {
- struct sigaction sa;
- sa.sa_handler = ultrastor_interrupt;
- sa.sa_flags = SA_INTERRUPT;
- sa.sa_mask = 0;
- sa.sa_restorer = NULL;
- if (irqaction(config.interrupt,&sa)) {
- printk("unable to get IRQ%d for ultrastor controller\n",config.interrupt);
- return FALSE;
- }
- }
-#endif
- return TRUE;
-}
-
-const char *ultrastor_14f_info(void)
-{
- return "UltraStor 14F SCSI driver version "
- VERSION
- " by David B. Gentzel\n";
-}
-
-static struct mscp mscp = {
- OP_SCSI, DTD_SCSI, FALSE, TRUE, FALSE /* This stuff doesn't change */
-};
-
-int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
- void *buff, int bufflen, void (*done)(int, int))
-{
- unsigned char in_byte;
-
-#if (ULTRASTOR_DEBUG & UD_COMMAND)
- printk("US14F: queuecommand: called\n");
-#endif
-
- /* Skip first (constant) byte */
- memset((char *)&mscp + 1, 0, sizeof (struct mscp) - 1);
- mscp.target_id = target;
- /* mscp.lun = ???; */
- mscp.transfer_data = *(Longword *)&buff;
- mscp.transfer_data_length = *(Longword *)&bufflen,
- mscp.length_of_scsi_cdbs = ((*(unsigned char *)cmnd <= 0x1F) ? 6 : 10);
- memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
-
- /* Find free OGM slot (OGMINT bit is 0) */
- do
- in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
- while (!aborted && (in_byte & 1));
- if (aborted)
- /* ??? is this right? */
- return (aborted << 16);
-
- /* Store pointer in OGM address bytes */
- outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
- outb_p(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
- outb_p(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
- outb_p(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
-
- /* Issue OGM interrupt */
- outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
-
- ultrastor_done = done;
-
-#if (ULTRASTOR_DEBUG & UD_COMMAND)
- printk("US14F: queuecommand: returning\n");
-#endif
-
- return 0;
-}
-
-#if !USE_QUEUECOMMAND
-int ultrastor_14f_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen)
-{
- unsigned char in_byte;
-
-#if (ULTRASTOR_DEBUG & UD_COMMAND)
- printk("US14F: command: called\n");
-#endif
-
- (void)ultrastor_14f_queuecommand(target, cmnd, buff, bufflen, 0);
-
- /* Wait for ICM interrupt */
- do
- in_byte = inb_p(SYS_DOORBELL_INTR(PORT_ADDRESS));
- while (!aborted && !(in_byte & 1));
- if (aborted)
- /* ??? is this right? */
- return (aborted << 16);
-
- /* Clean ICM slot (set ICMINT bit to 0) */
- outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
-
-#if (ULTRASTOR_DEBUG & UD_COMMAND)
- printk("US14F: command: returning %08X\n",
- (mscp.adapter_status << 16) | mscp.target_status);
-#endif
-
- /* ??? not right, but okay for now? */
- return (mscp.adapter_status << 16) | mscp.target_status;
-}
-#endif
-
-int ultrastor_14f_abort(int code)
-{
- aborted = (code ? code : DID_ABORT);
- return 0;
-}
-
-int ultrastor_14f_reset(void)
-{
- unsigned char in_byte;
-
-#if (ULTRASTOR_DEBUG & UD_RESET)
- printk("US14F: reset: called\n");
-#endif
-
- /* Issue SCSI BUS reset */
- outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
-
- /* Wait for completion... */
- do
- in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
- while (in_byte & 0x20);
-
- aborted = DID_RESET;
-
-#if (ULTRASTOR_DEBUG & UD_RESET)
- printk("US14F: reset: returning\n");
-#endif
- return 0;
-}
-
-#if USE_QUEUECOMMAND
-void ultrastor_interrupt(int cpl)
-{
- if (ultrastor_done == 0) {
- printk("US14F: unexpected ultrastor interrupt\n\r");
- /* ??? Anything else we should do here? Reset? */
- return;
- }
- printk("US14F: got an ultrastor interrupt: %u\n\r",
- (mscp.adapter_status << 16) | mscp.target_status);
- ultrastor_done(host_number,
- (mscp.adapter_status << 16) | mscp.target_status);
- ultrastor_done = 0;
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * ultrastor.c (C) 1991 David B. Gentzel
- * Low-level scsi driver for UltraStor 14F
- * by David B. Gentzel, Whitfield Software Services, Carnegie, PA
- * (gentzel@nova.enet.dec.com)
- * Thanks to UltraStor for providing the necessary documentation
- */
-
-#ifndef _ULTRASTOR_H
-#define _ULTRASTOR_H
-
-/* ??? These don't really belong here */
-#ifndef TRUE
-# define TRUE 1
-#endif
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-/* ??? This should go eventually, once the queueing bug is fixed */
-#define USE_QUEUECOMMAND FALSE
-
-int ultrastor_14f_detect(int);
-const char *ultrastor_14f_info(void);
-int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
- void *buff, int bufflen,
- void (*done)(int, int));
-#if !USE_QUEUECOMMAND
-int ultrastor_14f_command(unsigned char target, const void *cmnd,
- void *buff, int bufflen);
-#endif
-int ultrastor_14f_abort(int);
-int ultrastor_14f_reset(void);
-
-#if !USE_QUEUECOMMAND
-#define ULTRASTOR_14F \
- { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
- ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
- FALSE, 0, 0 }
-#else
-#define ULTRASTOR_14F \
- { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
- ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
- TRUE, 0, 0 }
-#endif
-
-#define UD_DETECT 0x1
-#define UD_COMMAND 0x2
-#define UD_RESET 0x4
-
-#ifdef ULTRASTOR_PRIVATE
-
-/* #define PORT_OVERRIDE 0x330 */
-
-/* Port addresses (relative to the base address) */
-#define LCL_DOORBELL_MASK(port) ((port) + 0x0)
-#define LCL_DOORBELL_INTR(port) ((port) + 0x1)
-#define SYS_DOORBELL_MASK(port) ((port) + 0x2)
-#define SYS_DOORBELL_INTR(port) ((port) + 0x3)
-#define PRODUCT_ID(port) ((port) + 0x4)
-#define CONFIG(port) ((port) + 0x6)
-#define OGM_DATA_PTR(port) ((port) + 0x8)
-#define ICM_DATA_PTR(port) ((port) + 0xC)
-
-/* Values for the PRODUCT_ID ports for the 14F */
-#define US14F_PRODUCT_ID_0 0x56
-#define US14F_PRODUCT_ID_1 0x40 /* NOTE: Only upper nibble is used */
-
-/* MSCP field values */
-
-/* Opcode */
-#define OP_HOST_ADAPTER 0x1
-#define OP_SCSI 0x2
-#define OP_RESET 0x4
-
-/* Date Transfer Direction */
-#define DTD_SCSI 0x0
-#define DTD_IN 0x1
-#define DTD_OUT 0x2
-#define DTD_NONE 0x3
-
-/* Host Adapter command subcodes */
-#define HA_CMD_INQUIRY 0x1
-#define HA_CMD_SELF_DIAG 0x2
-#define HA_CMD_READ_BUFF 0x3
-#define HA_CMD_WRITE_BUFF 0x4
-
-#endif
-
-#endif
# parent makes..
#
+AR =ar
+AS =as
+LD =ld
+LDFLAGS =-s -x
+CC =gcc -nostdinc -I../../include
+CPP =cpp -nostdinc -I../../include
+
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
-OBJS = tty_io.o console.o keyboard.o serial.o \
- tty_ioctl.o pty.o lp.o vt.o mem.o mouse.o
+OBJS = tty_io.o console.o keyboard.o serial.o rs_io.o \
+ tty_ioctl.o pty.o lp.o vt.o mem.o
chr_drv.a: $(OBJS)
$(AR) rcs chr_drv.a $(OBJS)
sync
-keyboard.o: keyboard.c
- $(CC) $(CFLAGS) $(KEYBOARD) -c -o keyboard.o keyboard.c
+keyboard.s: keyboard.S
+ $(CPP) $(KEYBOARD) -traditional keyboard.S -o keyboard.s
clean:
rm -f core *.o *.a tmp_make keyboard.s
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M -DKBD_FINNISH $$i;done >> tmp_make
+ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+ $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
-console.o : console.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/config.h \
- /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
- /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/kd.h \
+console.s console.o : console.c ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/timer.h ../../include/linux/tty.h \
+ ../../include/termios.h ../../include/linux/config.h ../../include/linux/config_rel.h \
+ ../../include/linux/config_ver.h ../../include/asm/io.h ../../include/asm/system.h \
+ ../../include/asm/segment.h ../../include/linux/string.h ../../include/errno.h \
+ ../../include/sys/kd.h vt_kern.h
+lp.s lp.o : lp.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+ ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/linux/lp.h ../../include/errno.h ../../include/asm/io.h ../../include/asm/segment.h
+mem.s mem.o : mem.c ../../include/errno.h ../../include/sys/types.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/tty.h ../../include/termios.h \
+ ../../include/asm/segment.h ../../include/asm/io.h
+pty.s pty.o : pty.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+ ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/linux/tty.h ../../include/termios.h ../../include/asm/system.h \
+ ../../include/asm/io.h
+serial.s serial.o : serial.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+ ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/linux/timer.h ../../include/linux/tty.h ../../include/termios.h \
+ ../../include/asm/system.h ../../include/asm/io.h
+tty_io.s tty_io.o : tty_io.c ../../include/linux/ctype.h ../../include/errno.h ../../include/signal.h \
+ ../../include/sys/types.h ../../include/unistd.h ../../include/sys/stat.h ../../include/sys/time.h \
+ ../../include/time.h ../../include/sys/times.h ../../include/sys/utsname.h ../../include/sys/param.h \
+ ../../include/sys/resource.h ../../include/utime.h ../../include/fcntl.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/linux/tty.h ../../include/termios.h ../../include/asm/segment.h \
+ ../../include/asm/system.h
+tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h ../../include/sys/types.h \
+ ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/tty.h ../../include/asm/io.h \
+ ../../include/asm/segment.h ../../include/asm/system.h
+vt.s vt.o : vt.c ../../include/errno.h ../../include/sys/types.h ../../include/sys/kd.h \
+ ../../include/sys/vt.h ../../include/asm/io.h ../../include/asm/segment.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/linux/tty.h ../../include/termios.h \
vt_kern.h
-keyboard.o : keyboard.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/ctype.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/asm/io.h
-lp.o : lp.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/lp.h /usr/src/linux/include/errno.h \
- /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h
-mem.o : mem.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/asm/io.h
-pty.o : pty.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/tty.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/asm/io.h
-serial.o : serial.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/timer.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h
-tty_io.o : tty_io.c /usr/src/linux/include/errno.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/ctype.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/sys/kd.h vt_kern.h
-tty_ioctl.o : tty_ioctl.c /usr/src/linux/include/errno.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
- /usr/src/linux/include/asm/segment.h
-vt.o : vt.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/kd.h /usr/src/linux/include/sys/vt.h \
- /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
- /usr/src/linux/include/linux/timer.h vt_kern.h
* console.c
*
* This module implements the console io functions
- * 'long con_init(long)'
+ * 'void con_init(void)'
* 'void con_write(struct tty_queue * queue)'
* Hopefully this will be a rather complete VT102 implementation.
*
* <g-hunt@ee.utah.edu>
*/
-#define KEYBOARD_IRQ 1
-
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <sys/kd.h>
#include "vt_kern.h"
+#define DEF_TERMIOS \
+(struct termios) { \
+ ICRNL, \
+ OPOST | ONLCR, \
+ 0, \
+ IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, \
+ 0, \
+ INIT_C_CC \
+}
+
+static void blank_screen(void);
+static void unblank_screen(void);
+
/*
* These are set up by the setup-routine at boot-time:
*/
#define NPAR 16
+int NR_CONSOLES = 0;
+
extern void vt_init(void);
-extern void keyboard_interrupt(int cpl);
+extern void keyboard_interrupt(void);
extern void set_leds(void);
extern unsigned char kapplic;
-extern unsigned char ckmode;
-extern unsigned char krepeat;
extern unsigned char kleds;
extern unsigned char kmode;
extern unsigned char kraw;
extern unsigned char ke0;
-extern unsigned char lfnlmode;
unsigned long video_num_columns; /* Number of text columns */
unsigned long video_num_lines; /* Number of test lines */
static unsigned char video_page; /* Initial video page */
static unsigned short video_port_reg; /* Video register select port */
static unsigned short video_port_val; /* Video register value port */
-static int can_do_color = 0;
+static int can_do_colour = 0;
static struct {
- unsigned short vc_video_erase_char; /* Background erase character */
- unsigned char vc_attr; /* Current attributes */
- unsigned char vc_def_color; /* Default colors */
- unsigned char vc_color; /* Foreground & background */
- unsigned char vc_s_color; /* Saved foreground & background */
- unsigned char vc_ulcolor; /* Colour for underline mode */
- unsigned char vc_halfcolor; /* Colour for half intensity mode */
+ unsigned short vc_video_erase_char;
+ unsigned char vc_attr;
+ unsigned char vc_def_attr;
+ int vc_bold_attr;
+ unsigned long vc_ques;
+ unsigned long vc_state;
+ char * vc_restate;
+ unsigned long vc_checkin;
unsigned long vc_origin; /* Used for EGA/VGA fast scroll */
unsigned long vc_scr_end; /* Used for EGA/VGA fast scroll */
unsigned long vc_pos;
unsigned long vc_x,vc_y;
unsigned long vc_top,vc_bottom;
- unsigned long vc_state;
unsigned long vc_npar,vc_par[NPAR];
unsigned long vc_video_mem_start; /* Start of video RAM */
unsigned long vc_video_mem_end; /* End of video RAM (sort of) */
- unsigned long vc_saved_x;
- unsigned long vc_saved_y;
- /* mode flags */
- unsigned long vc_kbdapplic : 1; /* Application keyboard */
- unsigned long vc_charset : 1; /* Character set G0 / G1 */
- unsigned long vc_s_charset : 1; /* Saved character set */
- unsigned long vc_decckm : 1; /* Cursor Keys Mode */
- unsigned long vc_decscnm : 1; /* Screen Mode */
- unsigned long vc_decom : 1; /* Origin Mode */
- unsigned long vc_decawm : 1; /* Autowrap Mode */
- unsigned long vc_decarm : 1; /* Autorepeat Mode */
- unsigned long vc_deccm : 1; /* Cursor Visible */
- unsigned long vc_decim : 1; /* Insert Mode */
- unsigned long vc_lnm : 1; /* Line feed New line Mode */
- /* attribute flags */
- unsigned long vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
- unsigned long vc_underline : 1;
- unsigned long vc_blink : 1;
- unsigned long vc_reverse : 1;
- unsigned long vc_s_intensity : 2; /* saved rendition */
- unsigned long vc_s_underline : 1;
- unsigned long vc_s_blink : 1;
- unsigned long vc_s_reverse : 1;
- /* misc */
- unsigned long vc_ques : 1;
- unsigned long vc_need_wrap : 1;
- unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */
+ unsigned int vc_saved_x;
+ unsigned int vc_saved_y;
+ unsigned int vc_iscolor;
+ unsigned char vc_kbdapplic;
+ unsigned char vc_kbdleds;
unsigned char vc_kbdmode;
+ unsigned char vc_kbdraw;
+ unsigned char vc_kbde0;
char * vc_translate;
- char * vc_G0_charset;
- char * vc_G1_charset;
- char * vc_saved_G0;
- char * vc_saved_G1;
- /* additional information is in vt_kern.h */
-} vc_cons [NR_CONSOLES];
+} vc_cons [MAX_CONSOLES];
#define MEM_BUFFER_SIZE (2*80*50*8)
-unsigned short *vc_scrbuf[NR_CONSOLES];
-static unsigned short * vc_scrmembuf;
+unsigned short *vc_scrbuf[MAX_CONSOLES];
+unsigned short vc_scrmembuf[MEM_BUFFER_SIZE/2];
static int console_blanked = 0;
#define origin (vc_cons[currcons].vc_origin)
#define x (vc_cons[currcons].vc_x)
#define y (vc_cons[currcons].vc_y)
#define state (vc_cons[currcons].vc_state)
+#define restate (vc_cons[currcons].vc_restate)
+#define checkin (vc_cons[currcons].vc_checkin)
#define npar (vc_cons[currcons].vc_npar)
#define par (vc_cons[currcons].vc_par)
#define ques (vc_cons[currcons].vc_ques)
#define saved_x (vc_cons[currcons].vc_saved_x)
#define saved_y (vc_cons[currcons].vc_saved_y)
#define translate (vc_cons[currcons].vc_translate)
-#define G0_charset (vc_cons[currcons].vc_G0_charset)
-#define G1_charset (vc_cons[currcons].vc_G1_charset)
-#define saved_G0 (vc_cons[currcons].vc_saved_G0)
-#define saved_G1 (vc_cons[currcons].vc_saved_G1)
#define video_mem_start (vc_cons[currcons].vc_video_mem_start)
#define video_mem_end (vc_cons[currcons].vc_video_mem_end)
-#define video_erase_char (vc_cons[currcons].vc_video_erase_char)
-#define decckm (vc_cons[currcons].vc_decckm)
-#define decscnm (vc_cons[currcons].vc_decscnm)
-#define decom (vc_cons[currcons].vc_decom)
-#define decawm (vc_cons[currcons].vc_decawm)
-#define decarm (vc_cons[currcons].vc_decarm)
-#define deccm (vc_cons[currcons].vc_deccm)
-#define decim (vc_cons[currcons].vc_decim)
-#define lnm (vc_cons[currcons].vc_lnm)
+#define def_attr (vc_cons[currcons].vc_def_attr)
+#define video_erase_char (vc_cons[currcons].vc_video_erase_char)
+#define iscolor (vc_cons[currcons].vc_iscolor)
#define kbdapplic (vc_cons[currcons].vc_kbdapplic)
-#define need_wrap (vc_cons[currcons].vc_need_wrap)
-#define color (vc_cons[currcons].vc_color)
-#define s_color (vc_cons[currcons].vc_s_color)
-#define def_color (vc_cons[currcons].vc_def_color)
-#define foreground (color & 0x0f)
-#define background (color & 0xf0)
-#define charset (vc_cons[currcons].vc_charset)
-#define s_charset (vc_cons[currcons].vc_s_charset)
-#define intensity (vc_cons[currcons].vc_intensity)
-#define underline (vc_cons[currcons].vc_underline)
-#define blink (vc_cons[currcons].vc_blink)
-#define reverse (vc_cons[currcons].vc_reverse)
-#define s_intensity (vc_cons[currcons].vc_s_intensity)
-#define s_underline (vc_cons[currcons].vc_s_underline)
-#define s_blink (vc_cons[currcons].vc_s_blink)
-#define s_reverse (vc_cons[currcons].vc_s_reverse)
-#define ulcolor (vc_cons[currcons].vc_ulcolor)
-#define halfcolor (vc_cons[currcons].vc_halfcolor)
#define kbdmode (vc_cons[currcons].vc_kbdmode)
-#define tab_stop (vc_cons[currcons].vc_tab_stop)
-#define kbdraw (vt_cons[currcons].vc_kbdraw)
-#define kbdleds (vt_cons[currcons].vc_kbdleds)
-#define vtmode (vt_cons[currcons].vt_mode)
+#define kbdraw (vc_cons[currcons].vc_kbdraw)
+#define kbde0 (vc_cons[currcons].vc_kbde0)
+#define kbdleds (vc_cons[currcons].vc_kbdleds)
-#define SET(mode,fg,v) \
- (mode) = (v); \
- if (currcons == fg_console) \
- (fg) = (v)
-
-int blankinterval = 10*60*HZ;
+int blankinterval = 5*60*HZ;
static int screen_size = 0;
static void sysbeep(void);
/*
- * this is what the terminal answers to a ESC-Z or csi0c query.
+ * this is what the terminal answers to a ESC-Z or csi0c
+ * query (= vt100 response).
*/
-#define VT100ID "\033[?1;2c"
-#define VT102ID "\033[?6c"
+#define RESPONSE "\033[?1;2c"
static char * translations[] = {
/* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
- "\004\261\007\007\007\007\370\361\040\007\331\277\332\300\305\007"
- "\007\304\007\007\303\264\301\302\263\007\007\007\007\007\234\0"
+ "\004\261\007\007\007\007\370\361\007\007\275\267\326\323\327\304"
+ "\304\304\304\304\307\266\320\322\272\363\362\343\007\234\007\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
- "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
-/* IBM grapgics: minimal translations (CR, LF, LL and ESC) */
- "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
- "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
- "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
- "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
- "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
- "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
- "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
- "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
- "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
- "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
- "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
- "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
- "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
- "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
- "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
- "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+ "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230"
};
#define NORM_TRANS (translations[0])
#define GRAF_TRANS (translations[1])
-#define NULL_TRANS (translations[2])
-
-static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
- 8,12,10,14, 9,13,11,15 };
-/*
- * gotoxy() must verify all boundaries, because the arguments
- * might also be negative. If the given position is out of
- * bounds, the cursor is placed at the nearest margin.
- */
-static void gotoxy(int currcons, int new_x, int new_y)
+/* NOTE! gotoxy thinks x==video_num_columns is ok */
+static inline void gotoxy(int currcons, unsigned int new_x,unsigned int new_y)
{
- int max_y;
-
- if (new_x < 0)
- x = 0;
- else
- if (new_x >= video_num_columns)
- x = video_num_columns - 1;
- else
- x = new_x;
- if (decom) {
- new_y += top;
- max_y = bottom;
- } else
- max_y = video_num_lines;
- if (new_y < 0)
- y = 0;
- else
- if (new_y >= max_y)
- y = max_y - 1;
- else
- y = new_y;
+ if (new_x > video_num_columns || new_y >= video_num_lines)
+ return;
+ x = new_x;
+ y = new_y;
pos = origin + y*video_size_row + (x<<1);
- need_wrap = 0;
}
-static void set_origin(int currcons)
+static inline void set_origin(int currcons)
{
if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
return;
- if (currcons != fg_console || console_blanked || vtmode == KD_GRAPHICS)
+ if (currcons != fg_console)
return;
cli();
outb_p(12, video_port_reg);
return;
} else
scrup(currcons,top,bottom);
- need_wrap = 0;
}
static void ri(int currcons)
return;
} else
scrdown(currcons,top,bottom);
- need_wrap = 0;
}
-static inline void cr(int currcons)
+static void cr(int currcons)
{
pos -= x<<1;
- need_wrap = x = 0;
+ x=0;
}
-static inline void bs(int currcons)
-{
- if (x) {
- pos -= 2;
- x--;
- need_wrap = 0;
- }
-}
-
-static inline void del(int currcons)
+static void del(int currcons)
{
if (x) {
pos -= 2;
x--;
*(unsigned short *)pos = video_erase_char;
- need_wrap = 0;
}
}
start = pos;
break;
case 1: /* erase from start to cursor */
- count = ((pos-origin)>>1)+1;
+ count = (pos-origin)>>1;
start = origin;
break;
case 2: /* erase whole display */
::"c" (count),
"D" (start),"a" (video_erase_char)
:"cx","di");
- need_wrap = 0;
}
static void csi_K(int currcons, int vpar)
switch (vpar) {
case 0: /* erase from cursor to end of line */
+ if (x>=video_num_columns)
+ return;
count = video_num_columns-x;
start = pos;
break;
case 1: /* erase from start of line to cursor */
start = pos - (x<<1);
- count = x+1;
+ count = (x<video_num_columns)?x:video_num_columns;
break;
case 2: /* erase whole line */
start = pos - (x<<1);
::"c" (count),
"D" (start),"a" (video_erase_char)
:"cx","di");
- need_wrap = 0;
}
-/*
- * I hope this works. The monochrome part is untested.
- */
-static void update_attr(int currcons)
-{
- attr = color;
- if (can_do_color) {
- if (underline)
- attr = (attr & 0xf0) | ulcolor;
- else if (intensity == 0)
- attr = (attr & 0xf0) | halfcolor;
- }
- if (reverse ^ decscnm)
- attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
- if (blink)
- attr ^= 0x80;
- if (intensity == 2)
- attr ^= 0x08;
- if (!can_do_color) {
- if (underline)
- attr = (attr & 0xf8) | 0x01;
- else if (intensity == 0)
- attr = (attr & 0xf0) | 0x08;
- }
- if (decscnm)
- video_erase_char = ((color & 0x88) | (((color >> 4) |
- (color << 4)) & 0x77) << 8) | ' ';
- else
- video_erase_char = (color << 8) | ' ';
-}
-
-static void default_attr(int currcons) {
- intensity = 1;
- underline = 0;
- reverse = 0;
- blink = 0;
- color = def_color;
-}
-
-static void csi_m(int currcons)
+static void csi_m(int currcons )
{
int i;
+ static int conv_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
for (i=0;i<=npar;i++)
switch (par[i]) {
- case 0: /* all attributes off */
- default_attr(currcons);
- break;
- case 1:
- intensity = 2;
- break;
- case 2:
- intensity = 0;
- break;
- case 4:
- underline = 1;
- break;
- case 5:
- blink = 1;
- break;
- case 7:
- reverse = 1;
- break;
- case 21:
- case 22:
- intensity = 1;
- break;
- case 24:
- underline = 0;
- break;
- case 25:
- blink = 0;
- break;
- case 27:
- reverse = 0;
- break;
- case 39:
- color = (def_color & 0x0f) | background;
- break;
- case 49:
- color = (def_color & 0xf0) | foreground;
- break;
+ case 0: attr=def_attr;break; /* default */
+ case 1: attr=(iscolor?attr|0x08:attr|0x0f);break; /* bold */
+ /*case 4: attr=attr|0x01;break;*/ /* underline */
+ case 4: /* bold */
+ if (!iscolor)
+ attr |= 0x01;
+ else
+ { /* check if forground == background */
+ if (vc_cons[currcons].vc_bold_attr != -1)
+ attr = (vc_cons[currcons].vc_bold_attr&0x0f)|(0xf0&(attr));
+ else
+ { short newattr = (attr&0xf0)|(0xf&(~attr));
+ attr = ((newattr&0xf)==((attr>>4)&0xf)?
+ (attr&0xf0)|(((attr&0xf)+1)%0xf):
+ newattr);
+ }
+ }
+ break;
+ case 5: attr=attr|0x80;break; /* blinking */
+ case 7: attr=(attr&0x88)|((attr<<4)&0x70)|
+ ((attr>>4)&0x07);break; /* negative */
+ case 22: attr=attr&0xf7;break; /* not bold */
+ case 24: attr=attr&0xfe;break; /* not underline */
+ case 25: attr=attr&0x7f;break; /* not blinking */
+ case 27: attr=def_attr;break; /* positive image */
+ case 39: attr=(attr & 0xf8)|(def_attr & 0x07); break;
+ case 49: attr=(attr & 0x8f)|(def_attr & 0x70); break;
default:
- if (par[i] >= 30 && par[i] <= 37)
- color = color_table[par[i]-30]
- | background;
- else if (par[i] >= 40 && par[i] <= 47)
- color = (color_table[par[i]-40]<<4)
- | foreground;
+ if (!can_do_colour)
+ break;
+ iscolor = 1;
+ if ((par[i]>=30) && (par[i]<=37))
+ attr = (attr & 0xf8) | conv_table[par[i]-30];
+ else /* Background color */
+ if ((par[i]>=40) && (par[i]<=47))
+ attr = (attr & 0x8f) | (conv_table[par[i]-40]<<4);
+ else
break;
}
- update_attr(currcons);
+}
+
+static inline void set_cursor(int currcons)
+{
+ if (currcons != fg_console)
+ return;
+ cli();
+ outb_p(14, video_port_reg);
+ outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
+ outb_p(15, video_port_reg);
+ outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
+ sti();
}
static inline void hide_cursor(int currcons)
outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
}
-static inline void set_cursor(int currcons)
+static void respond(int currcons, struct tty_struct * tty)
{
- if (currcons != fg_console || console_blanked)
- return;
- cli();
- if (deccm) {
- outb_p(14, video_port_reg);
- outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
- outb_p(15, video_port_reg);
- outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
- } else
- hide_cursor(currcons);
- sti();
-}
+ char * p = RESPONSE;
-static void respond_string(char * p, int currcons, struct tty_struct * tty)
-{
+ cli();
while (*p) {
- put_tty_queue(*p,tty->read_q);
+ PUTCH(*p,tty->read_q);
p++;
}
+ sti();
TTY_READ_FLUSH(tty);
}
-static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
-{
- char buff[3];
- int i = 0;
-
- do {
- buff[i++] = (n%10)+'0';
- n /= 10;
- } while(n && i < 3); /* We'll take no chances */
- while (i--) {
- put_tty_queue(buff[i],tty->read_q);
- }
- /* caller must flush */
-}
-
-static void cursor_report(int currcons, struct tty_struct * tty)
-{
- put_tty_queue('\033', tty->read_q);
- put_tty_queue('[', tty->read_q);
- respond_num(y + (decom ? top+1 : 1), currcons, tty);
- put_tty_queue(';', tty->read_q);
- respond_num(x+1, currcons, tty);
- put_tty_queue('R', tty->read_q);
- TTY_READ_FLUSH(tty);
-}
-
-static inline void status_report(int currcons, struct tty_struct * tty)
-{
- respond_string("\033[0n", currcons, tty); /* Terminal ok */
-}
-
-static inline void respond_ID(int currcons, struct tty_struct * tty)
-{
- respond_string(VT102ID, currcons, tty);
-}
-
-static void invert_screen(int currcons) {
- unsigned char *p;
-
- if (can_do_color)
- for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
- *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
- else
- for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
- *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
-}
-
-static void set_mode(int currcons, int on_off)
-{
- int i;
-
- for (i=0; i<=npar; i++)
- if (ques) switch(par[i]) { /* DEC private modes set/reset */
- case 1: /* Cursor keys send ^[Ox/^[[x */
- SET(decckm,ckmode,on_off);
- break;
- case 3: /* 80/132 mode switch unimplemented */
- csi_J(currcons,2);
- gotoxy(currcons,0,0);
- break;
- case 5: /* Inverted screen on/off */
- if (decscnm != on_off) {
- decscnm = on_off;
- invert_screen(currcons);
- update_attr(currcons);
- }
- break;
- case 6: /* Origin relative/absolute */
- decom = on_off;
- gotoxy(currcons,0,0);
- break;
- case 7: /* Autowrap on/off */
- decawm = on_off;
- break;
- case 8: /* Autorepeat on/off */
- SET(decarm,krepeat,on_off);
- break;
- case 25: /* Cursor on/off */
- deccm = on_off;
- set_cursor(currcons);
- break;
- } else switch(par[i]) { /* ANSI modes set/reset */
- case 4: /* Insert Mode on/off */
- decim = on_off;
- break;
- case 20: /* Lf, Enter == CrLf/Lf */
- SET(lnm,lfnlmode,on_off);
- break;
- }
-}
-
-static void setterm_command(int currcons)
-{
- switch(par[0]) {
- case 1: /* set color for underline mode */
- if (can_do_color && par[1] < 16) {
- ulcolor = color_table[par[1]];
- if (underline)
- update_attr(currcons);
- }
- break;
- case 2: /* set color for half intensity mode */
- if (can_do_color && par[1] < 16) {
- halfcolor = color_table[par[1]];
- if (intensity == 0)
- update_attr(currcons);
- }
- break;
- case 8: /* store colors as defaults */
- def_color = attr;
- default_attr(currcons);
- update_attr(currcons);
- break;
- case 9: /* set blanking interval */
- blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
- break;
- }
-}
-
static void insert_char(int currcons)
{
unsigned int i = x;
old = tmp;
p++;
}
- need_wrap = 0;
}
static void insert_line(int currcons)
{
scrdown(currcons,y,bottom);
- need_wrap = 0;
}
static void delete_char(int currcons)
unsigned int i = x;
unsigned short * p = (unsigned short *) pos;
+ if (x >= video_num_columns)
+ return;
while (++i < video_num_columns) {
*p = *(p+1);
p++;
}
*p = video_erase_char;
- need_wrap = 0;
}
static void delete_line(int currcons)
{
scrup(currcons,y,bottom);
- need_wrap = 0;
}
static void csi_at(int currcons, unsigned int nr)
static void save_cur(int currcons)
{
- saved_x = x;
- saved_y = y;
- s_intensity = intensity;
- s_underline = underline;
- s_blink = blink;
- s_reverse = reverse;
- s_charset = charset;
- s_color = color;
- saved_G0 = G0_charset;
- saved_G1 = G1_charset;
+ saved_x = x;
+ saved_y = y;
}
static void restore_cur(int currcons)
{
- gotoxy(currcons,saved_x,saved_y);
- intensity = s_intensity;
- underline = s_underline;
- blink = s_blink;
- reverse = s_reverse;
- charset = s_charset;
- color = s_color;
- G0_charset = saved_G0;
- G1_charset = saved_G1;
- translate = charset ? G1_charset : G0_charset;
- update_attr(currcons);
- need_wrap = 0;
+ gotoxy(currcons, saved_x, saved_y);
}
-enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
- EShash, ESsetG0, ESsetG1, ESignore };
-static void reset_terminal(int currcons, int do_clear)
-{
- top = 0;
- bottom = video_num_lines;
- state = ESnormal;
- ques = 0;
- translate = NORM_TRANS;
- G0_charset = NORM_TRANS;
- G1_charset = GRAF_TRANS;
- charset = 0;
- need_wrap = 0;
-
- decscnm = 0;
- decom = 0;
- decawm = 1;
- deccm = 1;
- decim = 0;
-
- if (currcons == fg_console) {
- krepeat = 1;
- ckmode = 0;
- kapplic = 0;
- lfnlmode = 0;
- kleds = 2;
- kmode = 0;
- set_leds();
- } else {
- decarm = 1;
- decckm = 0;
- kbdapplic = 0;
- lnm = 0;
- kbdleds = 2;
- kbdmode = 0;
- }
-
- default_attr(currcons);
- update_attr(currcons);
-
- tab_stop[0] = 0x01010100;
- tab_stop[1] =
- tab_stop[2] =
- tab_stop[3] =
- tab_stop[4] = 0x01010101;
-
- if (do_clear) {
- gotoxy(currcons,0,0);
- csi_J(currcons,2);
- save_cur(currcons);
- }
-}
+enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
+ ESsetterm, ESsetgraph, ESgraph, ESgresc, ESignore };
void con_write(struct tty_struct * tty)
{
- int c;
+ unsigned char c;
unsigned int currcons;
wake_up(&tty->write_q->proc_list);
currcons = tty - tty_table;
- if (currcons >= NR_CONSOLES) {
+ if (currcons >= MAX_CONSOLES) {
printk("con_write: illegal tty\n\r");
return;
}
- while (!tty->stopped && (c = get_tty_queue(tty->write_q)) >= 0) {
- if (state == ESnormal && translate[c]) {
- if (need_wrap) {
- cr(currcons);
- lf(currcons);
- }
- if (decim)
- insert_char(currcons);
- c = translate[c];
- *(char *) pos = c;
- *(char *) (pos+1) = attr;
- if (x == video_num_columns - 1)
- need_wrap = decawm;
- else {
- x++;
- pos+=2;
- }
- continue;
- }
-
- /*
- * Control characters can be used in the _middle_
- * of an escape sequence.
- */
- if (c < 32 || c == 127) switch(c) {
- case 7:
- sysbeep();
- break;
- case 8:
- bs(currcons);
- break;
- case 9:
- pos -= (x << 1);
- while (x < video_num_columns - 1) {
+ while (!EMPTY(tty->write_q)) {
+ if (tty->stopped)
+ break;
+ GETCH(tty->write_q,c);
+ if (c == 24 || c == 26)
+ state = ESnormal;
+ switch(state) {
+ case ESnormal:
+ if (translate[c]) {
+ c = translate[c];
+ while (x >= video_num_columns) {
+ x -= video_num_columns;
+ pos -= video_size_row;
+ lf(currcons);
+ }
+ *(char *) pos = c;
+ *(char *) (pos+1) = attr;
+ pos += 2;
x++;
- if (tab_stop[x >> 5] & (1 << (x & 31)))
- break;
- }
- pos += (x << 1);
- break;
- case 10: case 11: case 12:
- lf(currcons);
- if (!lfnlmode)
- break;
- case 13:
- cr(currcons);
- break;
- case 14:
- charset = 1;
- translate = G1_charset;
- break;
- case 15:
- charset = 0;
- translate = G0_charset;
- break;
- case 24: case 26:
- state = ESnormal;
- break;
- case 27:
- state = ESesc;
- break;
- case 127:
- del(currcons);
+ } else if (c == 27)
+ state = ESesc;
+ else if (c == 10 || c == 11 || c == 12)
+ lf(currcons);
+ else if (c == 13)
+ cr(currcons);
+ else if (c == 127)
+ del(currcons);
+ else if (c == 8) {
+ if (x) {
+ x--;
+ pos -= 2;
+ }
+ } else if (c == 9) {
+ c = 8-(x&7);
+ x += c;
+ pos += c<<1;
+ if (x > video_num_columns) {
+ x -= video_num_columns;
+ pos -= video_size_row;
+ lf(currcons);
+ }
+ c = 9;
+ } else if (c == 7)
+ sysbeep();
+ else if (c == 14) {
+ checkin = 1;
+ translate = restate;
+ } else if (c == 15) {
+ translate = NORM_TRANS;
+ checkin = 0;
+ }
break;
- } else switch(state) {
case ESesc:
state = ESnormal;
switch (c) {
state = ESsquare;
break;
case 'E':
- cr(currcons);
- lf(currcons);
+ gotoxy(currcons,0,y+1);
break;
case 'M':
ri(currcons);
case 'D':
lf(currcons);
break;
- case 'H':
- tab_stop[x >> 5] |= (1 << (x & 31));
- break;
case 'Z':
- respond_ID(currcons,tty);
+ respond(currcons,tty);
break;
case '7':
save_cur(currcons);
restore_cur(currcons);
break;
case '(':
- state = ESsetG0;
- break;
case ')':
- state = ESsetG1;
+ state = ESsetgraph;
break;
+ case 'P':
+ state = ESsetterm;
+ break;
case '#':
- state = EShash;
- break;
+ state = -1;
+ break;
case 'c':
- reset_terminal(currcons,1);
- break;
+ tty->termios = DEF_TERMIOS;
+ state = ESnormal;
+ restate = NORM_TRANS;
+ checkin = 0;
+ top = 0;
+ bottom = video_num_lines;
+ translate = NORM_TRANS;
case '>': /* Numeric keypad */
- SET(kbdapplic,kapplic,0);
- break;
+ kbdapplic = 0;
+ if (currcons == fg_console)
+ kapplic = 0;
+ break;
case '=': /* Appl. keypad */
- SET(kbdapplic,kapplic,1);
+ kbdapplic = 1;
+ if (currcons == fg_console)
+ kapplic = 1;
break;
}
break;
if (c == '[') { /* Function key */
state=ESfunckey;
break;
- }
+ }
if (ques=(c=='?'))
break;
case ESgetpars:
} else state=ESgotpars;
case ESgotpars:
state = ESnormal;
- switch(c) {
- case 'h':
- set_mode(currcons,1);
- break;
- case 'l':
- set_mode(currcons,0);
- break;
- case 'n':
- if (!ques)
- if (par[0] == 5)
- status_report(currcons,tty);
- else if (par[0] == 6)
- cursor_report(currcons,tty);
- break;
- }
if (ques) {
ques = 0;
break;
- }
+ }
switch(c) {
case 'G': case '`':
if (par[0]) par[0]--;
case 'P':
csi_P(currcons,par[0]);
break;
- case 'c':
- if (!par[0])
- respond_ID(currcons,tty);
- break;
- case 'g':
- if (!par[0])
- tab_stop[x >> 5] &= ~(1 << (x & 31));
- else if (par[0] == 3) {
- tab_stop[0] =
- tab_stop[1] =
- tab_stop[2] =
- tab_stop[3] =
- tab_stop[4] = 0;
- }
+ case '@':
+ csi_at(currcons,par[0]);
break;
case 'm':
csi_m(currcons);
break;
case 'r':
- if (!par[0])
- par[0]++;
+ if (par[0])
+ par[0]--;
if (!par[1])
par[1] = video_num_lines;
- /* Minimum allowed region is 2 lines */
if (par[0] < par[1] &&
par[1] <= video_num_lines) {
- top=par[0]-1;
+ top=par[0];
bottom=par[1];
- gotoxy(currcons,0,0);
}
break;
case 's':
case 'u':
restore_cur(currcons);
break;
- case '@':
- csi_at(currcons,par[0]);
- break;
- case ']': /* setterm functions */
- setterm_command(currcons);
- break;
+ case 'l': /* blank interval */
+ case 'b': /* bold attribute */
+ if (!((npar >= 2) &&
+ ((par[1]-13) == par[0]) &&
+ ((par[2]-17) == par[0])))
+ break;
+ if ((c=='l') && (par[0]<=60)) {
+ blankinterval = HZ*60*par[0];
+ }
+ if (c=='b')
+ vc_cons[currcons].vc_bold_attr
+ = par[0];
}
break;
case ESfunckey:
state = ESnormal;
break;
- case EShash:
- state = ESnormal;
- if (c == '8') {
- /* DEC screen alignment test. kludge :-) */
- video_erase_char =
- (video_erase_char & 0xff00) | 'E';
- csi_J(currcons, 2);
- video_erase_char =
- (video_erase_char & 0xff00) | ' ';
- }
- break;
- case ESsetG0:
- if (c == '0')
- G0_charset = GRAF_TRANS;
- else if (c == 'B')
- G0_charset = NORM_TRANS;
- else if (c == 'U')
- G0_charset = NULL_TRANS;
- if (charset == 0)
- translate = G0_charset;
+ case ESsetterm: /* Setterm functions. */
state = ESnormal;
+ if (c == 'S') {
+ def_attr = attr;
+ video_erase_char = (video_erase_char&0x0ff) | (def_attr<<8);
+ } else if (c == 'L')
+ /*linewrap on*/;
+ else if (c == 'l')
+ /*linewrap off*/;
break;
- case ESsetG1:
- if (c == '0')
- G1_charset = GRAF_TRANS;
- else if (c == 'B')
- G1_charset = NORM_TRANS;
- else if (c == 'U')
- G1_charset = NULL_TRANS;
- if (charset == 1)
- translate = G1_charset;
+ case ESsetgraph:
+ if (c == '0') {
+ if (checkin)
+ translate = GRAF_TRANS;
+ restate = GRAF_TRANS;
+ } else if (c == 'B')
+ translate = restate = NORM_TRANS;
state = ESnormal;
break;
default:
state = ESnormal;
}
}
- if (vtmode == KD_GRAPHICS)
- return;
set_cursor(currcons);
+ timer_active &= ~(1<<BLANK_TIMER);
+ if (console_blanked) {
+ timer_table[BLANK_TIMER].expires = 0;
+ timer_active |= 1<<BLANK_TIMER;
+ } else if (blankinterval) {
+ timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
+ timer_active |= 1<<BLANK_TIMER;
+ }
}
void do_keyboard_interrupt(void)
{
TTY_READ_FLUSH(TTY_TABLE(0));
timer_active &= ~(1<<BLANK_TIMER);
- if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
- return;
if (console_blanked) {
timer_table[BLANK_TIMER].expires = 0;
timer_active |= 1<<BLANK_TIMER;
}
/*
- * long con_init(long);
+ * void con_init(void);
*
* This routine initalizes console interrupts, and does nothing
* else. If you want the screen to clear, call tty_write with
* Reads the information preserved by setup.s to determine the current display
* type and sets everything accordingly.
*/
-long con_init(long kmem_start)
+void con_init(void)
{
register unsigned char a;
char *display_desc = "????";
char *display_ptr;
int currcons = 0;
- long base;
- int orig_x = ORIG_X;
- int orig_y = ORIG_Y;
+ long base, term;
+ long video_memory;
+ long saveterm, savebase;
- vc_scrmembuf = (unsigned short *) kmem_start;
video_num_columns = ORIG_VIDEO_COLS;
video_size_row = video_num_columns * 2;
video_num_lines = ORIG_VIDEO_LINES;
video_page = ORIG_VIDEO_PAGE;
- screen_size = (video_num_lines * video_size_row);
- kmem_start += NR_CONSOLES * screen_size;
+ video_erase_char = 0x0720;
timer_table[BLANK_TIMER].fn = blank_screen;
timer_table[BLANK_TIMER].expires = 0;
if (blankinterval) {
}
else /* If not, it is color. */
{
- can_do_color = 1;
+ can_do_colour = 1;
video_mem_base = 0xb8000;
video_port_reg = 0x3d4;
video_port_val = 0x3d5;
}
}
- /* Let the user know what kind of display driver we are using */
+ /* Let the user known what kind of display driver we are using */
display_ptr = ((char *)video_mem_base) + video_size_row - 8;
while (*display_desc)
*display_ptr++ = *display_desc++;
display_ptr++;
}
-
+
+ savebase = video_mem_base;
+ saveterm = video_mem_term;
+ memsetw(vc_scrmembuf,video_erase_char,MEM_BUFFER_SIZE/2);
+ video_mem_base = (long)vc_scrmembuf;
+ video_mem_term = (long)&(vc_scrmembuf[MEM_BUFFER_SIZE/2]);
+ video_memory = video_mem_term - video_mem_base;
+ screen_size = (video_num_lines * video_size_row);
+ NR_CONSOLES = video_memory / screen_size;
+ if (NR_CONSOLES > MAX_CONSOLES)
+ NR_CONSOLES = MAX_CONSOLES;
+ if (!NR_CONSOLES)
+ NR_CONSOLES = 1;
+ video_memory = screen_size;
+
/* Initialize the variables used for scrolling (mostly EGA/VGA) */
-
- base = (long)vc_scrmembuf;
- for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
- pos = origin = video_mem_start = base;
- scr_end = video_mem_end = (base += screen_size);
- vc_scrbuf[currcons] = (unsigned short *) origin;
- vtmode = KD_TEXT;
- kbdraw = 0;
- def_color = 0x07; /* white */
- ulcolor = 0x0f; /* bold white */
- halfcolor = 0x08; /* grey */
- reset_terminal(currcons, currcons);
+
+ base = origin = video_mem_start = video_mem_base;
+ term = video_mem_end = base + video_memory;
+ scr_end = video_mem_start + screen_size;
+ top = 0;
+ bottom = video_num_lines;
+ attr = 0x07;
+ def_attr = 0x07;
+ restate = NORM_TRANS;
+ state = ESnormal;
+ checkin = 0;
+ ques = 0;
+ iscolor = 0;
+ translate = NORM_TRANS;
+ kbdleds = 2;
+ kbdmode = 0;
+ kbdraw = 0;
+ kbde0 = 0;
+ kbdapplic = 0;
+ vc_cons[0].vc_bold_attr = -1;
+
+ gotoxy(currcons,ORIG_X,ORIG_Y);
+ for (currcons = 1; currcons<NR_CONSOLES; currcons++) {
+ vc_cons[currcons] = vc_cons[0];
+ origin = video_mem_start = (base += video_memory);
+ scr_end = origin + video_num_lines * video_size_row;
+ video_mem_end = (term += video_memory);
+ gotoxy(currcons,0,0);
}
- currcons = fg_console = 0;
-
+ for (currcons = 0; currcons<NR_CONSOLES; currcons++)
+ vc_scrbuf[currcons] = (unsigned short *)origin;
+ currcons = 0;
+ video_mem_base = savebase;
+ video_mem_term = saveterm;
+
video_mem_start = video_mem_base;
video_mem_end = video_mem_term;
- origin = video_mem_start;
+ origin = video_mem_start;
scr_end = video_mem_start + video_num_lines * video_size_row;
- gotoxy(currcons,0,0);
- save_cur(currcons);
- gotoxy(currcons,orig_x,orig_y);
+ top = 0;
+ bottom = video_num_lines;
+ pos=origin + y*video_size_row + (x<<1);
update_screen(fg_console);
-
- if (request_irq(KEYBOARD_IRQ,keyboard_interrupt))
- printk("Unable to get IRQ%d for keyboard driver\n",KEYBOARD_IRQ);
+ set_trap_gate(0x21,&keyboard_interrupt);
+ outb_p(inb_p(0x21)&0xfd,0x21);
a=inb_p(0x61);
outb_p(a|0x80,0x61);
outb_p(a,0x61);
- return kmem_start;
+
+ vt_init();
}
void kbdsave(int new_console)
int currcons = fg_console;
kbdmode = kmode;
kbdraw = kraw;
+ kbde0 = ke0;
kbdleds = kleds;
kbdapplic = kapplic;
- decckm = ckmode;
- decarm = krepeat;
- lnm = lfnlmode;
currcons = new_console;
kmode = (kmode & 0x3F) | (kbdmode & 0xC0);
kraw = kbdraw;
+ ke0 = kbde0;
kleds = kbdleds;
kapplic = kbdapplic;
- ckmode = decckm;
- krepeat = decarm;
- lfnlmode = lnm;
set_leds();
}
{
memcpy((void *)vc_scrbuf[fg_console],(void *)origin, screen_size);
video_mem_start = (unsigned long)vc_scrbuf[fg_console];
- origin = video_mem_start;
+ origin = video_mem_start;
scr_end = video_mem_end = video_mem_start+screen_size;
- pos = origin + y*video_size_row + (x<<1);
+ pos = origin + y*video_size_row + (x<<1);
}
static void set_scrmem(int currcons)
verify_area(buf,2+video_num_columns*video_num_lines);
currcons = get_fs_byte(buf+1);
- if ((currcons<0) || (currcons>=NR_CONSOLES))
+ if ((currcons<0) || (currcons>NR_CONSOLES))
return -EIO;
put_fs_byte((char)(video_num_lines),buf++);
put_fs_byte((char)(video_num_columns),buf++);
if (currcons<0 || currcons>=NR_CONSOLES)
currcons = 0;
+ if (vt_info[currcons].mode == KD_GRAPHICS)
+ return; /* no output in graphics mode */
while (c = *(b++)) {
- if (c == 10 || c == 13 || need_wrap) {
+ if (c == 10) {
cr(currcons);
- if (c == 10 || need_wrap)
- lf(currcons);
- need_wrap = 0;
+ lf(currcons);
continue;
}
- *(char *) pos = c;
- *(char *) (pos+1) = attr;
- if (x == video_num_columns - 1) {
- need_wrap = 1;
+ if (c == 13) {
+ cr(currcons);
continue;
}
+ while (x >= video_num_columns) {
+ x -= video_num_columns;
+ pos -= video_size_row;
+ lf(currcons);
+ }
+ *(char *) pos = c;
+ *(char *) (pos+1) = attr;
+ pos += 2;
x++;
- pos+=2;
}
set_cursor(currcons);
- if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
- return;
- timer_active &= ~(1<<BLANK_TIMER);
- if (console_blanked) {
- timer_table[BLANK_TIMER].expires = 0;
- timer_active |= 1<<BLANK_TIMER;
- } else if (blankinterval) {
- timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
- timer_active |= 1<<BLANK_TIMER;
- }
}
--- /dev/null
+/*
+ * linux/kernel/keyboard.S
+ *
+ * (C) 1991 Linus Torvalds
+ */
+
+/*
+ * NOTE! This file no longer contains the low-level keyboard interrupt:
+ * that is now in kernel/sys_call.S. The reason is that the low-level
+ * interrupt must keep track of stack frames for signals etc.
+ *
+ * Thus it should be very easy to rewrite this in C - I just haven't
+ * bothered.
+ */
+
+/*
+ * Thanks to Alfred Leung for US keyboard patches
+ * Wolfgang Thiel for German keyboard patches
+ * Marc Corsini for the French keyboard
+ * LeBlanc@mcc.ac.uk for the UK keyboard
+ * Tommy Thorn (tthorn@daimi.aau.dk) for Danish keyboard
+ */
+
+/* KBD_FINNISH for Finnish keyboards
+ * KBD_US for US-type
+ * KBD_GR for German keyboards
+ * KBD_FR for Frech keyboard
+ * KBD_UK for British extended keyboard
+ * KBD_DK for Danish keyboard
+ */
+
+.text
+.globl _hard_reset_now
+.globl _do_keyboard_interrupt
+.globl _do_keyboard
+.globl _kapplic
+.globl _kmode
+.globl _kleds
+.globl _set_leds
+.globl _kraw
+.globl _ke0
+
+/*
+ * these are for the keyboard read functions
+ */
+size = 2048 /* must be a power of two ! And MUST be the same
+ as in tty_io.c !!!! */
+head = 4
+tail = 8
+proc_list = 12
+buf = 16
+
+_kapplic: .byte 0
+_kmode: .byte 0 /* caps, alt, ctrl and shift mode */
+_kleds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
+_ke0: .byte 0
+_kraw: .byte 0
+
+/*
+ * do_keyboard is the real interrupt routine that reads the
+ * keyboard scan-code and converts it into the appropriate
+ * ascii character(s).
+ */
+_do_keyboard:
+ xorl %eax,%eax /* %eax is scan code */
+ inb $0x60,%al
+ pushl %eax
+ inb $0x61,%al
+ jmp 1f
+1: jmp 1f
+1: orb $0x80,%al
+ jmp 1f
+1: jmp 1f
+1: outb %al,$0x61
+ jmp 1f
+1: jmp 1f
+1: andb $0x7F,%al
+ outb %al,$0x61
+ jmp 1f
+1: jmp 1f
+1: movb $0x20,%al
+ outb %al,$0x20
+ cmpb $0,_kraw
+ je 1f
+ xorl %ebx,%ebx /* if raw kbd, just put scancode */
+ popl %eax
+ sti
+ call put_queue
+ jmp postkey
+1: popl %eax
+ movl $1,%ebx
+ cmpb $0xE0,%al
+ je end_intr
+ movl $2,%ebx
+ cmpb $0xE1,%al
+ je end_intr
+ sti
+ call key_table(,%eax,4)
+postkey:
+ call _do_keyboard_interrupt
+ movl $0,%ebx
+end_intr:
+ movb %bl,_ke0
+ ret
+
+/*
+ * This routine fills the buffer with max 8 bytes, taken from
+ * %ebx:%eax. (%edx is high). The bytes are written in the
+ * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
+ */
+put_queue:
+ pushl %ecx
+ pushl %edx
+ movl _table_list,%edx # read-queue for console
+ movl head(%edx),%ecx
+1: movb %al,buf(%edx,%ecx)
+ incl %ecx
+ andl $size-1,%ecx
+ cmpl tail(%edx),%ecx # buffer full - discard everything
+ je 3f
+ shrdl $8,%ebx,%eax
+ je 2f
+ shrl $8,%ebx
+ jmp 1b
+2: movl %ecx,head(%edx)
+ movl proc_list(%edx),%ecx
+ testl %ecx,%ecx
+ je 3f
+ movl $0,(%ecx)
+3: popl %edx
+ popl %ecx
+ ret
+
+ctrl: movb $0x04,%al
+ jmp 1f
+alt: movb $0x10,%al
+1: cmpb $0,_ke0
+ je 2f
+ addb %al,%al
+2: orb %al,_kmode
+ ret
+unctrl: movb $0x04,%al
+ jmp 1f
+unalt: movb $0x10,%al
+1: cmpb $0,_ke0
+ je 2f
+ addb %al,%al
+2: notb %al
+ andb %al,_kmode
+ ret
+
+lshift:
+ orb $0x01,_kmode
+ ret
+unlshift:
+ andb $0xfe,_kmode
+ ret
+rshift:
+ orb $0x02,_kmode
+ ret
+unrshift:
+ andb $0xfd,_kmode
+ ret
+
+old_leds:
+ .byte 2
+
+caps: testb $0x80,_kmode
+ jne 1f
+ xorb $4,_kleds
+ xorb $0x40,_kmode
+ orb $0x80,_kmode
+_set_leds:
+ movb _kleds,%al
+ cmpb old_leds,%al
+ je 1f
+ movb %al,old_leds
+ call kb_wait
+ movb $0xed,%al /* set leds command */
+ outb %al,$0x60
+ call kb_wait
+ movb _kleds,%al
+ outb %al,$0x60
+1: ret
+uncaps: andb $0x7f,_kmode
+ ret
+scroll:
+ testb $0x03,_kmode
+ je 1f
+ call _show_mem
+ jmp 2f
+1: call _show_state
+2: xorb $1,_kleds
+ jmp _set_leds
+
+num: cmpb $0x01,_kapplic
+ jne notappl
+ movw $0x0050,%ax
+applkey:
+ shll $16,%eax
+ movw $0x4f1b,%ax
+ xorl %ebx,%ebx
+ jmp put_queue
+
+notappl:
+ xorb $2,_kleds
+ jmp _set_leds
+
+/*
+ * cursor-key/numeric keypad cursor keys are handled here.
+ * checking for numeric keypad etc.
+ */
+cursor:
+ subb $0x47,%al
+ jb 1f
+ cmpb $12,%al
+ ja 1f
+ jne cur2 /* check for ctrl-alt-del */
+ testb $0x0c,_kmode
+ je cur2
+ testb $0x30,_kmode
+ jne _ctrl_alt_del
+cur2: cmpb $0x01,_ke0 /* _ke0 forces cursor movement */
+ je cur
+ testb $0x03,_kmode /* shift forces cursor */
+ jne cur
+ cmpb $0x01,_kapplic
+ jne notcappl
+ movb appl_table(%eax),%al
+ jmp applkey
+notcappl:
+ testb $0x02,_kleds /* not num-lock forces cursor */
+ je cur
+ xorl %ebx,%ebx
+ movb num_table(%eax),%al
+ jmp put_queue
+1: ret
+
+/*
+ * cursor keys send ^[ [ x if normal, ^[ O x if application mode
+ */
+cur: movb cur_table(%eax),%al
+ cmpb $'9,%al
+ ja ok_cur
+ movb $'~,%ah
+ok_cur: shll $16,%eax
+ movw $0x5b1b,%ax
+ xorl %ebx,%ebx
+ cmpb $0x01,_kapplic
+ jne put_queue
+ movb $0x4f,%ah
+ jmp put_queue
+
+#if defined(KBD_FR) /* || defined(KBD_DK) correct, but .. */
+num_table:
+ .ascii "789-456+1230."
+#else
+num_table:
+ .ascii "789-456+1230,"
+#endif
+cur_table:
+ .ascii "HA5-DGC+YB623"
+
+/*
+ Keypad / 35 B7 Q
+ Keypad * (PrtSc) 37 B7 R
+ Keypad NumLock 45 ?? P
+ Keypad 7 (Home) 47 C7 w
+ Keypad 8 (Up arrow) 48 C8 x
+ Keypad 9 (PgUp) 49 C9 y
+ Keypad - 4A CA S
+ Keypad 4 (Left arrow) 4B CB t
+ Keypad 5 4C CC u
+ Keypad 6 (Right arrow) 4D CD v
+ Keypad + 4E CE l
+ Keypad 1 (End) 4F CF q
+ Keypad 2 (Down arrow) 50 D0 r
+ Keypad 3 (PgDn) 51 D1 s
+ Keypad 0 (Ins) 52 D2 p
+ Keypad . (Del) 53 D3 n
+*/
+
+appl_table:
+ .ascii "wxyStuvlqrspn"
+
+/*
+ * this routine handles function keys
+ */
+func:
+ subb $0x3B,%al
+ jb end_func
+ cmpb $9,%al
+ jbe ok_func
+ subb $18,%al
+ cmpb $10,%al
+ jb end_func
+ cmpb $11,%al
+ ja end_func
+ok_func:
+ testb $0x10,_kmode
+ jne alt_func
+ cmpl $4,%ecx /* check that there is enough room */
+ jl end_func
+ movl func_table(,%eax,4),%eax
+ xorl %ebx,%ebx
+ jmp put_queue
+alt_func:
+ pushl %eax
+ call _change_console
+ popl %eax
+end_func:
+ ret
+
+/*
+ * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
+ */
+func_table:
+ .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
+ .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
+ .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
+
+#if defined(KBD_FINNISH)
+key_map:
+ .byte 0,27
+ .ascii "1234567890+'"
+ .byte 127,9
+ .ascii "qwertyuiop}"
+ .byte 0,13,0
+ .ascii "asdfghjkl|{"
+ .byte 0,0
+ .ascii "'zxcvbnm,.-"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '<
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "!\"#$%&/()=?`"
+ .byte 127,9
+ .ascii "QWERTYUIOP]^"
+ .byte 13,0
+ .ascii "ASDFGHJKL\\["
+ .byte 0,0
+ .ascii "*ZXCVBNM;:_"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '>
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0@\243$\0\0{[]}\\\0"
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+#elif defined(KBD_US)
+
+key_map:
+ .byte 0,27
+ .ascii "1234567890-="
+ .byte 127,9
+ .ascii "qwertyuiop[]"
+ .byte 13,0
+ .ascii "asdfghjkl;'"
+ .byte '`,0
+ .ascii "\\zxcvbnm,./"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '<
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "!@#$%^&*()_+"
+ .byte 127,9
+ .ascii "QWERTYUIOP{}"
+ .byte 13,0
+ .ascii "ASDFGHJKL:\""
+ .byte '~,0
+ .ascii "|ZXCVBNM<>?"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '>
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0@\0$\0\0{[]}\\\0"
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+#elif defined(KBD_UK)
+
+key_map:
+ .byte 0,27
+ .ascii "1234567890-="
+ .byte 127,9
+ .ascii "qwertyuiop[]"
+ .byte 13,0
+ .ascii "asdfghjkl;'"
+ .byte '`,0
+ .ascii "#zxcvbnm,./"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .ascii "\\"
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "!\"\243$%^&*()_+"
+ .byte 127,9
+ .ascii "QWERTYUIOP{}"
+ .byte 13,0
+ .ascii "ASDFGHJKL:@"
+ .byte '~,0
+ .ascii "~ZXCVBNM<>?"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0@\0$\0\0{[]}\\\0"
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+#elif defined(KBD_GR)
+
+key_map:
+ .byte 0,27
+ .ascii "1234567890\\'"
+ .byte 127,9
+ .ascii "qwertzuiop@+"
+ .byte 13,0
+ .ascii "asdfghjkl[]^"
+ .byte 0,'#
+ .ascii "yxcvbnm,.-"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '<
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "!\"#$%&/()=?`"
+ .byte 127,9
+ .ascii "QWERTZUIOP\\*"
+ .byte 13,0
+ .ascii "ASDFGHJKL{}~"
+ .byte 0,''
+ .ascii "YXCVBNM;:_"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '>
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0@\0$\0\0{[]}\\\0"
+ .byte 0,0
+ .byte '@,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+#elif defined(KBD_FR)
+
+key_map:
+ .byte 0,27
+ .ascii "&{\"'(-}_/@)="
+ .byte 127,9
+ .ascii "azertyuiop^$"
+ .byte 13,0
+ .ascii "qsdfghjklm|"
+ .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */
+ .ascii "wxcvbn,;:!"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '<
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "1234567890]+"
+ .byte 127,9
+ .ascii "AZERTYUIOP<>"
+ .byte 13,0
+ .ascii "QSDFGHJKLM%"
+ .byte '~,0,'#
+ .ascii "WXCVBN?./\\"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '>
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0~#{[|`\\^@]}"
+ .byte 0,0
+ .byte '@,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '|
+ .fill 10,1,0
+
+#elif defined(KBD_DK)
+
+key_map:
+ .byte 0,27
+ .ascii "1234567890+'"
+ .byte 127,9
+ .ascii "qwertyuiop"
+ .byte 134,0,13,0 /* This is IBM-PC, change it to latin-1 */
+ .ascii "asdfghjkl"
+ .byte 145,155,0,0
+ .ascii "'zxcvbnm,.-"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '<
+ .fill 10,1,0
+
+shift_map:
+ .byte 0,27
+ .ascii "!\"#$%&/()=?`"
+ .byte 127,9
+ .ascii "QWERTYUIOP"
+ .byte 143,94,13,0
+ .ascii "ASDFGHJKL"
+ .byte 146,157,0,0
+ .ascii "*ZXCVBNM;:_"
+ .byte 0,'*,0,32 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte '-,0,0,0,'+ /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .byte '>
+ .fill 10,1,0
+
+alt_map:
+ .byte 0,0
+ .ascii "\0@\0$\0\0{[]}\0"
+ .byte '|,0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte '~,13,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0
+ .byte 0,0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0 /* 36-39 */
+ .fill 16,1,0 /* 3A-49 */
+ .byte 0,0,0,0,0 /* 4A-4E */
+ .byte 0,0,0,0,0,0,0 /* 4F-55 */
+ .ascii "\\"
+ .fill 10,1,0
+
+#else
+#error "KBD-type not defined"
+#endif
+/*
+ * do_self handles "normal" keys, ie keys that don't change meaning
+ * and which have just one character returns.
+ */
+do_self:
+ lea alt_map,%ebx
+ testb $0x20,_kmode /* alt-gr */
+ jne 1f
+ lea shift_map,%ebx
+ testb $0x0f,_kmode
+ jne 1f
+ lea key_map,%ebx
+1: movb (%ebx,%eax),%al
+ orb %al,%al
+ je none
+ testb $0x4c,_kmode /* ctrl or caps */
+ je 2f
+ cmpb $'a,%al
+ jb 2f
+ cmpb $'},%al
+ ja 2f
+ subb $32,%al
+2: testb $0x0c,_kmode /* ctrl */
+ je 3f
+ andb $0x1f,%al
+3: testb $0x10,_kmode /* left alt */
+ je 4f
+ orb $0x80,%al
+4: andl $0xff,%eax
+ xorl %ebx,%ebx
+ call put_queue
+none: ret
+
+/*
+ * slash and star have routines of their own, as a 'E0h' before
+ * the scan code for slash means that the numeric keypad
+ * slash was pushed.
+ */
+slash: cmpb $1,_ke0
+ jne do_self
+ cmpb $1,_kapplic
+ jne notmapplic
+ movw $'Q,%ax
+ jmp applkey
+
+notmapplic:
+ movl $'/,%eax
+ xorl %ebx,%ebx
+ jmp put_queue
+
+star: cmpb $1,_kapplic
+ jne do_self
+ movw $'R,%ax
+ jmp applkey
+
+notsapplic:
+ movl $'*,%eax
+ xorl %ebx,%ebx
+ jmp put_queue
+
+enter: cmpb $1,_ke0
+ jne do_self
+ cmpb $1,_kapplic
+ jne do_self
+ movw $'M,%ax
+ jmp applkey
+
+minus: cmpb $1,_kapplic
+ jne do_self
+ movw $'S,%ax
+ jmp applkey
+
+plus: cmpb $1,_kapplic
+ jne do_self
+ movw $'l,%ax
+ jmp applkey
+
+/*
+ * This table decides which routine to call when a scan-code has been
+ * gotten. Most routines just call do_self, or none, depending if
+ * they are make or break.
+ */
+key_table:
+ .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
+ .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
+ .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
+ .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
+ .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
+ .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
+ .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
+ .long enter,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
+ .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
+ .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
+ .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
+ .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
+ .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
+ .long do_self,slash,rshift,star /* 34-37 . - rshift * */
+ .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
+ .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
+ .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
+ .long func,num,scroll,cursor /* 44-47 f10 num scr home */
+ .long cursor,cursor,minus,cursor /* 48-4B up pgup - left */
+ .long cursor,cursor,plus,cursor /* 4C-4F n5 right + end */
+ .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
+ .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
+ .long func,none,none,none /* 58-5B f12 ? ? ? */
+ .long none,none,none,none /* 5C-5F ? ? ? ? */
+ .long none,none,none,none /* 60-63 ? ? ? ? */
+ .long none,none,none,none /* 64-67 ? ? ? ? */
+ .long none,none,none,none /* 68-6B ? ? ? ? */
+ .long none,none,none,none /* 6C-6F ? ? ? ? */
+ .long none,none,none,none /* 70-73 ? ? ? ? */
+ .long none,none,none,none /* 74-77 ? ? ? ? */
+ .long none,none,none,none /* 78-7B ? ? ? ? */
+ .long none,none,none,none /* 7C-7F ? ? ? ? */
+ .long none,none,none,none /* 80-83 ? br br br */
+ .long none,none,none,none /* 84-87 br br br br */
+ .long none,none,none,none /* 88-8B br br br br */
+ .long none,none,none,none /* 8C-8F br br br br */
+ .long none,none,none,none /* 90-93 br br br br */
+ .long none,none,none,none /* 94-97 br br br br */
+ .long none,none,none,none /* 98-9B br br br br */
+ .long none,unctrl,none,none /* 9C-9F br unctrl br br */
+ .long none,none,none,none /* A0-A3 br br br br */
+ .long none,none,none,none /* A4-A7 br br br br */
+ .long none,none,unlshift,none /* A8-AB br br unlshift br */
+ .long none,none,none,none /* AC-AF br br br br */
+ .long none,none,none,none /* B0-B3 br br br br */
+ .long none,none,unrshift,none /* B4-B7 br br unrshift br */
+ .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
+ .long none,none,none,none /* BC-BF br br br br */
+ .long none,none,none,none /* C0-C3 br br br br */
+ .long none,none,none,none /* C4-C7 br br br br */
+ .long none,none,none,none /* C8-CB br br br br */
+ .long none,none,none,none /* CC-CF br br br br */
+ .long none,none,none,none /* D0-D3 br br br br */
+ .long none,none,none,none /* D4-D7 br br br br */
+ .long none,none,none,none /* D8-DB br ? ? ? */
+ .long none,none,none,none /* DC-DF ? ? ? ? */
+ .long none,none,none,none /* E0-E3 e0 e1 ? ? */
+ .long none,none,none,none /* E4-E7 ? ? ? ? */
+ .long none,none,none,none /* E8-EB ? ? ? ? */
+ .long none,none,none,none /* EC-EF ? ? ? ? */
+ .long none,none,none,none /* F0-F3 ? ? ? ? */
+ .long none,none,none,none /* F4-F7 ? ? ? ? */
+ .long none,none,none,none /* F8-FB ? ? ? ? */
+ .long none,none,none,none /* FC-FF ? ? ? ? */
+
+/*
+ * kb_wait waits for the keyboard controller buffer to empty.
+ */
+kb_wait:
+ pushl %eax
+ pushl %ebx
+ movl $10000,%ebx
+1: inb $0x64,%al
+ testb $0x02,%al
+ je 2f
+ decl %ebx
+ jne 1b
+2: popl %ebx
+ popl %eax
+ ret
+
+no_idt:
+ .long 0,0
+/*
+ * This routine reboots the machine by asking the keyboard
+ * controller to pulse the reset-line low. We try that for a while,
+ * and if it doesn't work, we do some other stupid things.
+ */
+_hard_reset_now:
+ sti
+ movl $100,%ebx
+1: call kb_wait
+ movw $0x1234,0x472 /* don't do memory check */
+ movb $0xfe,%al /* pulse reset low */
+ outb %al,$0x64
+ decl %ebx
+ jne 1b
+ lidt no_idt /* zero-length idt: should triple-fault */
+ jmp _hard_reset_now
+++ /dev/null
-/*
- * linux/kernel/chr_drv/keyboard.c
- *
- * Keyboard driver for Linux v0.96 using Latin-1.
- *
- * Written for linux by Johan Myreen as a translation from
- * the assembly version by Linus (with diacriticals added)
- */
-
-#include <linux/sched.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#define LSHIFT 0x01
-#define RSHIFT 0x02
-#define LCTRL 0x04
-#define RCTRL 0x08
-#define ALT 0x10
-#define ALTGR 0x20
-#define CAPS 0x40
-#define CAPSDOWN 0x80
-
-#define SCRLED 0x01
-#define NUMLED 0x02
-#define CAPSLED 0x04
-
-#define NO_META_BIT 0x80
-
-unsigned char kapplic = 0;
-unsigned char ckmode = 0;
-unsigned char krepeat = 1;
-unsigned char kmode = 0;
-unsigned char kleds = NUMLED;
-unsigned char ke0 = 0;
-unsigned char kraw = 0;
-unsigned char kbd_flags = KBDFLAGS;
-unsigned char lfnlmode = 0;
-
-extern void do_keyboard_interrupt(void);
-extern void ctrl_alt_del(void);
-extern void change_console(unsigned int new_console);
-extern struct tty_queue *table_list[];
-
-typedef void (*fptr)(int);
-
-static unsigned char old_leds = 2;
-static int diacr = -1;
-static int npadch = 0;
-fptr key_table[];
-
-static void put_queue(int);
-void set_leds(void);
-static void applkey(int);
-static void cur(int);
-static void kb_wait(void), kb_ack(void);
-static unsigned int handle_diacr(unsigned int);
-
-void keyboard_interrupt(int cpl)
-{
- static unsigned char rep = 0xff, repke0 = 0;
- unsigned char scancode, x;
- struct tty_struct * tty = TTY_TABLE(0);
-
- scancode=inb_p(0x60);
- x=inb_p(0x61);
- outb_p(x|0x80, 0x61);
- outb_p(x&0x7f, 0x61);
- outb(0x20, 0x20);
- sti();
-
- if (kraw) {
- put_queue(scancode);
- do_keyboard_interrupt();
- return;
- }
- if (scancode == 0xe0) {
- ke0 = 1;
- return;
- }
- if (scancode == 0xe1) {
- ke0 = 2;
- return;
- }
- /*
- * The keyboard maintains its own internal caps lock and num lock
- * statuses. In caps lock mode E0 AA precedes make code and E0 2A
- * follows break code. In num lock mode, E0 2A precedes make
- * code and E0 AA follows break code. We do our own book-keeping,
- * so we will just ignore these.
- */
- if (ke0 == 1 && (scancode == 0x2a || scancode == 0xaa)) {
- ke0 = 0;
- return;
- }
- /*
- * Repeat a key only if the input buffers are empty or the
- * characters get echoed locally. This makes key repeat usable
- * with slow applications and unders heavy loads.
- */
- if (rep == 0xff) {
- if (scancode < 0x80) {
- rep = scancode;
- repke0 = ke0;
- }
- } else if (ke0 == repke0 && (scancode & 0x7f) == rep)
- if (scancode & 0x80)
- rep = 0xff;
- else if (!(krepeat && (L_ECHO(tty) || (EMPTY(tty->secondary) &&
- EMPTY(tty->read_q))))) {
- ke0 = 0;
- return;
- }
- key_table[scancode](scancode);
- do_keyboard_interrupt();
- ke0 = 0;
-}
-
-static void put_queue(int ch)
-{
- register struct tty_queue *qp = table_list[0];
- unsigned long new_head;
-
- qp->buf[qp->head]=ch;
- if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1)) != qp->tail)
- qp->head=new_head;
- wake_up(&qp->proc_list);
-}
-
-static void puts_queue(char *cp)
-{
- register struct tty_queue *qp = table_list[0];
- unsigned long new_head;
- char ch;
-
- while (ch=*cp++) {
- qp->buf[qp->head]=ch;
- if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1))
- != qp->tail)
- qp->head=new_head;
- }
- wake_up(&qp->proc_list);
-}
-
-static void ctrl(int sc)
-{
- if (ke0)
- kmode|=RCTRL;
- else
- kmode|=LCTRL;
-}
-
-static void alt(int sc)
-{
- if (ke0)
- kmode|=ALTGR;
- else
- kmode|=ALT;
-}
-
-static void unctrl(int sc)
-{
- if (ke0)
- kmode&=(~RCTRL);
- else
- kmode&=(~LCTRL);
-}
-
-static void unalt(int sc)
-{
- if (ke0)
- kmode&=(~ALTGR);
- else {
- kmode&=(~ALT);
- if (npadch != 0) {
- put_queue(npadch);
- npadch=0;
- }
- }
-}
-
-static void lshift(int sc)
-{
- kmode|=LSHIFT;
-}
-
-static void unlshift(int sc)
-{
- kmode&=(~LSHIFT);
-}
-
-static void rshift(int sc)
-{
- kmode|=RSHIFT;
-}
-
-static void unrshift(int sc)
-{
- kmode&=(~RSHIFT);
-}
-
-static void caps(int sc)
-{
- if (!(kmode & CAPSDOWN)) {
- kleds ^= CAPSLED;
- kmode ^= CAPS;
- kmode |= CAPSDOWN;
- set_leds();
- }
-}
-
-void set_leds(void)
-{
- if (kleds != old_leds) {
- old_leds = kleds;
- kb_wait();
- outb(0xed, 0x60); /* set leds command */
- kb_ack();
- kb_wait();
- outb(kleds, 0x60);
- kb_ack();
- }
-}
-
-static void uncaps(int sc)
-{
- kmode &= ~CAPSDOWN;
-}
-
-static void scroll(int sc)
-{
- if (kmode & (LSHIFT | RSHIFT))
- show_mem();
- else
- show_state();
- kleds ^= SCRLED;
- set_leds();
-}
-
-static void num(int sc)
-{
- if (kapplic)
- applkey(0x50);
- else {
- kleds ^= NUMLED;
- set_leds();
- }
-}
-
-static void applkey(int key)
-{
- char buf[] = { 0x1b, 0x4f, 0x00, 0x00 };
-
- buf[2] = key;
- puts_queue(buf);
-}
-
-
-#if defined KBD_FINNISH
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '+', '\'', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '}', 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', '|',
- '{', 0, 0, '\'', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', ']', '^', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', '\\',
- '[', 0, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_FINNISH_LATIN1
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '+', 180, 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', 229, 168, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
- 228, 167, 0, '\'', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', 197, '^', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
- 196, 189, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_US
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '-', '=', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '[', ']', 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '/', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '@', '#', '$', '%', '^',
- '&', '*', '(', ')', '_', '+', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', '{', '}', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
- '"', '~', '0', '|', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', '<', '>', '?', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_UK
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '-', '=', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '[', ']', 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', 0, '#', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '/', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '"', 163, '$', '%', '^',
- '&', '*', '(', ')', '_', '+', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', '{', '}', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
- '@', '~', '0', '~', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', '<', '>', '?', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_GR
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\\', '\'', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', '@', '+', 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', '[',
- ']', '^', 0, '#', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', '\\', '*', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', '{',
- '}', '~', 0, '\'', 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_GR_LATIN1
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', 223, 180, 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', 252, '+', 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
- 228, 94, 0, '#', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '"', 167, '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', 220, '*', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
- 196, 176, 0, '\'', 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, 178, 179, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 181, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_FR
-
-static unsigned char key_map[] = {
- 0, 27, '&', '{', '"', '\'', '(', '-',
- '}', '_', '/', '@', ')', '=', 127, 9,
- 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '^', '$', 13, 0, 'q', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
- '|', '`', 0, 42, 'w', 'x', 'c', 'v',
- 'b', 'n', ',', ';', ':', '!', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', ']', '+', 127, 9,
- 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', '<', '>', 13, 0, 'Q', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
- '%', '~', 0, '#', 'W', 'X', 'C', 'V',
- 'B', 'N', '?', '.', '/', '\\', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '~', '#', '{', '[', '|',
- '`', '\\', '^', '@', ']', '}', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_FR_LATIN1
-
-static unsigned char key_map[] = {
- 0, 27, '&', 233, '"', '\'', '(', '-',
- 232, '_', 231, 224, ')', '=', 127, 9,
- 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '^', '$', 13, 0, 'q', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
- 249, 178, 0, 42, 'w', 'x', 'c', 'v',
- 'b', 'n', ',', ';', ':', '!', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', 176, '+', 127, 9,
- 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', 168, 163, 13, 0, 'Q', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
- '%', 0, 0, 181, 'W', 'X', 'C', 'V',
- 'B', 'N', '?', '.', '/', 167, 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '~', '#', '{', '[', '|',
- '`', '\\', '^', '@', ']', '}', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 164, 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_DK
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '+', '\'', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', 229, 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 230,
- 162, 0, 0, '\'', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', 197, '^', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 198,
- 165, 0, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', 0, '|', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_DK_LATIN1
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '+', 180, 127, 9,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', 229, 168, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 230,
- 162, 189, 0, '\'', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '\"', '#', '$', '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', 197, '^', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 198,
- 165, 167, 0, '*', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 163, '$', 0, 0,
- '{', '[', ']', '}', 0, '|', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_DVORAK
-
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\\', '=', 127, 9,
- '\'', ',', '.', 'p', 'y', 'f', 'g', 'c',
- 'r', 'l', '/', ']', 13, 0, 'a', 'o',
- 'e', 'u', 'i', 'd', 'h', 't', 'n', 's',
- '-', '`', 0, '[', ';', 'q', 'j', 'k',
- 'x', 'b', 'm', 'w', 'v', 'z', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char shift_map[] = {
- 0, 27, '!', '@', '#', '$', '%', '^',
- '&', '*', '(', ')', '|', '+', 127, 9,
- '"', '<', '>', 'P', 'Y', 'F', 'G', 'C',
- 'R', 'L', '?', '}', 13, 0, 'A', 'O',
- 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S',
- '_', '~', 0, '{', ':', 'Q', 'J', 'K',
- 'X', 'B', 'M', 'W', 'V', 'Z', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', 0, '$', 0, 0,
- '{', '[', ']', '}', '\\', 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, '~', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '|', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-
-#elif defined KBD_SG
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\'', '^', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', 0, 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0,
- 0, 0, 0, '$', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-static unsigned char shift_map[] = {
- 0, 27, '+', '"', '*', 0, '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', 0, '!', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0,
- 0, 0, 0, 0, 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', '#', 0, 0, 0,
- '|', 0, 0, 0, '\'', '~', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '[', ']', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- '{', 0, 0, '}', 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-#elif defined KBD_SG_LATIN1
-static unsigned char key_map[] = {
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '\'', '^', 127, 9,
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
- 'o', 'p', 252, 0, 13, 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 246,
- 228, 167, 0, '$', 'y', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '-', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '<', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-static unsigned char shift_map[] = {
- 0, 27, '+', '"', '*', 231, '%', '&',
- '/', '(', ')', '=', '?', '`', 127, 9,
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
- 'O', 'P', 220, '!', 13, 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 214,
- 196, 176, 0, 163, 'Y', 'X', 'C', 'V',
- 'B', 'N', 'M', ';', ':', '_', 0, '*',
- 0, 32, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '-', 0, 0, 0, '+', 0,
- 0, 0, 0, 0, 0, 0, '>', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-static unsigned char alt_map[] = {
- 0, 0, 0, '@', '#', 0, 0, 172,
- '|', 162, 0, 0, '\'', '~', 0, 0,
- '@', 0, 0, 0, 0, 0, 0, 0,
- 0, 0, '[', ']', 13, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 233,
- '{', 0, 0, '}', 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, '\\', 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
-#else
-#error "KBD-type not defined"
-#endif
-
-static void do_self(int sc)
-{
- unsigned char ch;
-
- if (kmode & ALTGR)
- ch = alt_map[sc];
- else if (kmode & (LSHIFT | RSHIFT | LCTRL | RCTRL))
- ch = shift_map[sc];
- else
- ch = key_map[sc];
-
- if (ch == 0)
- return;
-
- if ((ch = handle_diacr(ch)) == 0)
- return;
-
- if (kmode & (LCTRL | RCTRL | CAPS)) /* ctrl or caps */
- if ((ch >= 'a' && ch <= 'z') || (ch >= 224 && ch <= 254))
- ch -= 32;
- if (kmode & (LCTRL | RCTRL)) /* ctrl */
- ch &= 0x1f;
-
- if (kmode & ALT)
- if (kbd_flags & NO_META_BIT) {
- put_queue('\033');
- put_queue(ch);
- } else
- put_queue(ch|0x80);
- else
- put_queue(ch);
-}
-
-unsigned char accent_table[5][64] = {
- " \300BCD\310FGH\314JKLMN\322PQRST\331VWXYZ[\\]^_"
- "`\340bcd\350fgh\354jklmn\362pqrst\371vwxyz{|}~", /* accent grave */
-
- " \301BCD\311FGH\315JKLMN\323PQRST\332VWX\335Z[\\]^_"
- "`\341bcd\351fgh\355jklmn\363pqrst\372vwxyz{|}~", /* accent acute */
-
- " \302BCD\312FGH\316JKLMN\324PQRST\333VWXYZ[\\]^_"
- "`\342bcd\352fgh\356jklmn\364pqrst\373vwxyz{|}~", /* circumflex */
-
- " \303BCDEFGHIJKLMN\325PQRSTUVWXYZ[\\]^_"
- "`\343bcdefghijklm\361\365pqrstuvwxyz{|}~", /* tilde */
-
- " \304BCD\313FGH\316JKLMN\326PQRST\334VWXYZ[\\]^_"
- "`\344bcd\353fgh\357jklmn\366pqrst\374vwx\377z{|}~" /* dieresis */
-};
-
-
-/*
- * Check if dead key pressed. If so, check if same key pressed twice;
- * in that case return the char, otherwise store char and return 0.
- * If dead key not pressed, check if accented character pending. If
- * not: return the char, otherwise check if char is a space. If it is
- * a space return the diacritical. Else combine char with diacritical
- * mark and return.
- */
-
-unsigned int handle_diacr(unsigned int ch)
-{
- static unsigned char diacr_table[] =
- {'`', 180, '^', '~', 168, 0}; /* Must end with 0 */
- int i;
-
- for(i=0; diacr_table[i]; i++)
- if (ch==diacr_table[i] && ((1<<i)&kbd_flags)) {
- if (diacr == i) {
- diacr=-1;
- return ch; /* pressed twice */
- } else {
- diacr=i; /* key is dead */
- return 0;
- }
- }
- if (diacr == -1)
- return ch;
- else if (ch == ' ') {
- ch=diacr_table[diacr];
- diacr=-1;
- return ch;
- } else if (ch<64 || ch>122) {
- diacr=-1;
- return ch;
- } else {
- ch=accent_table[diacr][ch-64];
- diacr=-1;
- return ch;
- }
-}
-
-
-#if defined KBD_FR || defined KBD_US || defined KBD_UK
-static unsigned char num_table[] = "789-456+1230.";
-#else
-static unsigned char num_table[] = "789-456+1230,";
-#endif
-
-static unsigned char cur_table[] = "HA5-DGC+YB623";
-static unsigned int pad_table[] = { 7,8,9,0,4,5,6,0,1,2,3,0,0 };
-
-/*
- Keypad / 35 B7 Q
- Keypad * (PrtSc) 37 B7 R
- Keypad NumLock 45 ?? P
- Keypad 7 (Home) 47 C7 w
- Keypad 8 (Up arrow) 48 C8 x
- Keypad 9 (PgUp) 49 C9 y
- Keypad - 4A CA S
- Keypad 4 (Left arrow) 4B CB t
- Keypad 5 4C CC u
- Keypad 6 (Right arrow) 4D CD v
- Keypad + 4E CE l
- Keypad 1 (End) 4F CF q
- Keypad 2 (Down arrow) 50 D0 r
- Keypad 3 (PgDn) 51 D1 s
- Keypad 0 (Ins) 52 D2 p
- Keypad . (Del) 53 D3 n
-*/
-
-static unsigned char appl_table[] = "wxyStuvlqrspn";
-
-static char *func_table[] = {
- "\033[[A", "\033[[B", "\033[[C", "\033[[D",
- "\033[[E", "\033[[F", "\033[[G", "\033[[H",
- "\033[[I", "\033[[J", "\033[[K", "\033[[L"
-};
-
-
-static void cursor(int sc)
-{
- if (sc < 0x47 || sc > 0x53)
- return;
- sc-=0x47;
- if (sc == 12 && (kmode&(LCTRL|RCTRL)) && (kmode&(ALT|ALTGR))) {
- ctrl_alt_del();
- return;
- }
- if (ke0 == 1) {
- cur(sc);
- return;
- }
-
- if ((kmode&ALT) && sc!=12) { /* Alt-numpad */
- npadch=npadch*10+pad_table[sc];
- return;
- }
-
- if (kapplic && !(kmode&(LSHIFT|RSHIFT))) { /* shift forces cursor */
- applkey(appl_table[sc]);
- return;
- }
-
- if (kleds&NUMLED) {
- put_queue(num_table[sc]);
- } else
- cur(sc);
-}
-
-static void cur(int sc)
-{
- char buf[] = { 0x1b, '[', 0, 0, 0 }; /* must not be static */
-
- buf[2]=cur_table[sc];
- if (buf[2] < '9')
- buf[3]='~';
- if ((buf[2] >= 'A' && buf[2] <= 'D') ? ckmode : kapplic)
- buf[1]='O';
- puts_queue(buf);
-}
-
-static void func(int sc)
-{
- if (sc < 0x3b)
- return;
- sc-=0x3b;
- if (sc > 9) {
- sc-=18;
- if (sc < 10 || sc > 11)
- return;
- }
- if (kmode&ALT)
- change_console(sc);
- else
- puts_queue(func_table[sc]);
-}
-
-
-static void slash(int sc)
-{
- if (ke0 != 1)
- do_self(sc);
- else if (kapplic)
- applkey('Q');
- else
- put_queue('/');
-}
-
-static void star(int sc)
-{
- if (kapplic)
- applkey('R');
- else
- do_self(sc);
-}
-
-static void enter(int sc)
-{
- if (ke0 == 1 && kapplic)
- applkey('M');
- else {
- put_queue(13);
- if (lfnlmode)
- put_queue(10);
- }
-}
-
-static void minus(int sc)
-{
- if (kapplic)
- applkey('S');
- else
- do_self(sc);
-}
-
-static void plus(int sc)
-{
- if (kapplic)
- applkey('l');
- else
- do_self(sc);
-}
-
-
-static void none(int sc)
-{
-}
-
-
-/*
- * kb_wait waits for the keyboard controller buffer to empty.
- */
-
-static void kb_wait(void)
-{
- int i;
-
- for (i=0; i<0x10000; i++)
- if ((inb(0x64)&0x02) == 0)
- break;
-}
-
-/*
- * kb_ack waits for 0xfa to appear in port 0x60
- *
- * Suggested by Bruce Evans
- * Added by Niels Skou Olsen [NSO]
- * April 21, 1992
- *
- * Heavily inspired by kb_wait :-)
- * I don't know how much waiting actually is required,
- * but this seems to work
- */
-
-void kb_ack(void)
-{
- int i;
-
- for(i=0; i<0x10000; i++)
- if (inb(0x60) == 0xfa)
- break;
-}
-
-long no_idt[2] = {0, 0};
-
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low. We try that for a while,
- * and if it doesn't work, we do some other stupid things.
- */
-void hard_reset_now(void)
-{
- int i;
-
- sti();
- for (;;) {
- for (i=0; i<100; i++) {
- kb_wait();
- *((unsigned short *)0x472)=0x1234;
- outb(0xfe,0x64); /* pulse reset low */
- }
- __asm__("\tlidt _no_idt"::);
- }
-}
-
-
-static fptr key_table[] = {
- none,do_self,do_self,do_self, /* 00-03 s0 esc 1 2 */
- do_self,do_self,do_self,do_self, /* 04-07 3 4 5 6 */
- do_self,do_self,do_self,do_self, /* 08-0B 7 8 9 0 */
- do_self,do_self,do_self,do_self, /* 0C-0F + ' bs tab */
- do_self,do_self,do_self,do_self, /* 10-13 q w e r */
- do_self,do_self,do_self,do_self, /* 14-17 t y u i */
- do_self,do_self,do_self,do_self, /* 18-1B o p } ^ */
- enter,ctrl,do_self,do_self, /* 1C-1F enter ctrl a s */
- do_self,do_self,do_self,do_self, /* 20-23 d f g h */
- do_self,do_self,do_self,do_self, /* 24-27 j k l | */
- do_self,do_self,lshift,do_self, /* 28-2B { para lshift , */
- do_self,do_self,do_self,do_self, /* 2C-2F z x c v */
- do_self,do_self,do_self,do_self, /* 30-33 b n m , */
- do_self,slash,rshift,star, /* 34-37 . - rshift * */
- alt,do_self,caps,func, /* 38-3B alt sp caps f1 */
- func,func,func,func, /* 3C-3F f2 f3 f4 f5 */
- func,func,func,func, /* 40-43 f6 f7 f8 f9 */
- func,num,scroll,cursor, /* 44-47 f10 num scr home */
- cursor,cursor,minus,cursor, /* 48-4B up pgup - left */
- cursor,cursor,plus,cursor, /* 4C-4F n5 right + end */
- cursor,cursor,cursor,cursor, /* 50-53 dn pgdn ins del */
- none,none,do_self,func, /* 54-57 sysreq ? < f11 */
- func,none,none,none, /* 58-5B f12 ? ? ? */
- none,none,none,none, /* 5C-5F ? ? ? ? */
- none,none,none,none, /* 60-63 ? ? ? ? */
- none,none,none,none, /* 64-67 ? ? ? ? */
- none,none,none,none, /* 68-6B ? ? ? ? */
- none,none,none,none, /* 6C-6F ? ? ? ? */
- none,none,none,none, /* 70-73 ? ? ? ? */
- none,none,none,none, /* 74-77 ? ? ? ? */
- none,none,none,none, /* 78-7B ? ? ? ? */
- none,none,none,none, /* 7C-7F ? ? ? ? */
- none,none,none,none, /* 80-83 ? br br br */
- none,none,none,none, /* 84-87 br br br br */
- none,none,none,none, /* 88-8B br br br br */
- none,none,none,none, /* 8C-8F br br br br */
- none,none,none,none, /* 90-93 br br br br */
- none,none,none,none, /* 94-97 br br br br */
- none,none,none,none, /* 98-9B br br br br */
- none,unctrl,none,none, /* 9C-9F br unctrl br br */
- none,none,none,none, /* A0-A3 br br br br */
- none,none,none,none, /* A4-A7 br br br br */
- none,none,unlshift,none, /* A8-AB br br unlshift br */
- none,none,none,none, /* AC-AF br br br br */
- none,none,none,none, /* B0-B3 br br br br */
- none,none,unrshift,none, /* B4-B7 br br unrshift br */
- unalt,none,uncaps,none, /* B8-BB unalt br uncaps br */
- none,none,none,none, /* BC-BF br br br br */
- none,none,none,none, /* C0-C3 br br br br */
- none,none,none,none, /* C4-C7 br br br br */
- none,none,none,none, /* C8-CB br br br br */
- none,none,none,none, /* CC-CF br br br br */
- none,none,none,none, /* D0-D3 br br br br */
- none,none,none,none, /* D4-D7 br br br br */
- none,none,none,none, /* D8-DB br ? ? ? */
- none,none,none,none, /* DC-DF ? ? ? ? */
- none,none,none,none, /* E0-E3 e0 e1 ? ? */
- none,none,none,none, /* E4-E7 ? ? ? ? */
- none,none,none,none, /* E8-EB ? ? ? ? */
- none,none,none,none, /* EC-EF ? ? ? ? */
- none,none,none,none, /* F0-F3 ? ? ? ? */
- none,none,none,none, /* F4-F7 ? ? ? ? */
- none,none,none,none, /* F8-FB ? ? ? ? */
- none,none,none,none /* FC-FF ? ? ? ? */
-};
unsigned int minor = MINOR(inode->i_rdev);
char c, *temp = buf;
+ if (minor >= LP_NO)
+ return -ENODEV;
+ if ((LP_F(minor) & LP_EXIST) == 0)
+ return -ENODEV;
+ LP_T(minor) = current->pid;
+ LP_F(minor) |= LP_BUSY;
+ LP_R(minor) = count;
temp = buf;
while (count > 0) {
c = get_fs_byte(temp++);
return -EINVAL;
}
-static int lp_open(struct inode * inode, struct file * file)
+static int lp_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
{
- unsigned int minor = MINOR(inode->i_rdev);
-
- if (minor >= LP_NO)
- return -ENODEV;
- if ((LP_F(minor) & LP_EXIST) == 0)
- return -ENODEV;
- if (LP_F(minor) & LP_BUSY)
- return -EBUSY;
- LP_F(minor) |= LP_BUSY;
- return 0;
-}
-
-static void lp_release(struct inode * inode, struct file * file)
-{
- unsigned int minor = MINOR(inode->i_rdev);
-
- LP_F(minor) &= ~LP_BUSY;
+ return -ENOTDIR;
}
static struct file_operations lp_fops = {
lp_lseek,
lp_read,
lp_write,
- NULL, /* lp_readdir */
+ lp_readdir,
+ NULL, /* lp_close */
NULL, /* lp_select */
- NULL, /* lp_ioctl */
- lp_open,
- lp_release
+ NULL /* lp_ioctl */
};
-long lp_init(long kmem_start)
+void lp_init(void)
{
int offset = 0;
unsigned int testvalue = 0;
}
if (count == 0)
printk("lp_init: no lp devices found\n");
- return kmem_start;
}
return tmp-buf;
}
-static int read_zero(struct inode *node,struct file *file,char *buf,int count)
-{
- int left;
-
- for (left = count; left > 0; left--) {
- put_fs_byte(0,buf);
- buf++;
- }
- return count;
-}
-
/*
* The memory devices use the full 32 bits of the offset, and so we cannot
* check against negative addresses: they are ok. The return value is weird,
return 0; /* /dev/null */
case 4:
return read_port(inode,file,buf,count);
- case 5:
- return read_zero(inode,file,buf,count);
default:
return -ENODEV;
}
return count; /* /dev/null */
case 4:
return write_port(inode,file,buf,count);
- case 5:
- return count; /* /dev/zero */
default:
return -ENODEV;
}
}
+static int mem_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
+{
+ return -ENOTDIR;
+}
+
static struct file_operations mem_fops = {
mem_lseek,
mem_read,
mem_write,
- NULL, /* mem_readdir */
+ mem_readdir,
+ NULL, /* mem_close */
NULL, /* mem_select */
- NULL, /* mem_ioctl */
- NULL, /* no special open code */
- NULL /* no special release code */
+ NULL /* mem_ioctl */
};
-long chr_dev_init(long mem_start, long mem_end)
+void chr_dev_init(void)
{
chrdev_fops[1] = &mem_fops;
- mem_start = tty_init(mem_start);
- mem_start = lp_init(mem_start);
- mem_start = mouse_init(mem_start);
- return mem_start;
+ tty_init();
+ lp_init();
}
+++ /dev/null
-/*
- * Logitech Bus Mouse Driver for Linux
- * by James Banks
- *
- * Heavily modified by David Giller
- * changed from queue- to counter- driven
- * hacked out a (probably incorrect) mouse_select
- *
- * Modified again by Nathan Laredo to interface with
- * 0.96c-pl1 IRQ handling changes (13JUL92)
- * didn't bother touching select code.
- *
- * Modified the select() code blindly to conform to the VFS
- * requirements. 92.07.14 - Linus. Somebody should test it out.
- *
- * version 0.1
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mouse.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <signal.h>
-#include <errno.h>
-#include <signal.h>
-
-static struct mouse_status mouse;
-
-static void mouse_interrupt(int cpl)
-{
- char dx, dy, buttons;
-
- MSE_INT_OFF();
-
- outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
- dx = (inb(MSE_DATA_PORT) & 0xf);
-
- outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
- dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
-
- outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
- dy = (inb(MSE_DATA_PORT) & 0xf);
-
- outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
- buttons = inb(MSE_DATA_PORT);
-
- dy |= (buttons & 0xf) << 4;
- buttons = ((buttons >> 5) & 0x07);
-
- mouse.buttons = buttons;
- mouse.latch_buttons |= buttons;
- mouse.dx += dx;
- mouse.dy += dy;
- mouse.ready = 1;
- if (mouse.inode && mouse.inode->i_wait)
- wake_up(&mouse.inode->i_wait);
-
- MSE_INT_ON();
-}
-
-static void release_mouse(struct inode * inode, struct file * file)
-{
- MSE_INT_OFF();
- mouse.active = 0;
- mouse.ready = 0;
- mouse.inode = NULL;
- free_irq(MOUSE_IRQ);
-}
-
-static int open_mouse(struct inode * inode, struct file * file)
-{
- if (mouse.active)
- return -EBUSY;
- if (!mouse.present)
- return -EINVAL;
- if (request_irq(MOUSE_IRQ, mouse_interrupt))
- return -EBUSY;
- mouse.active = 1;
- mouse.ready = 0;
- mouse.inode = inode;
- mouse.dx = 0;
- mouse.dy = 0;
- mouse.buttons = mouse.latch_buttons = 0x80;
- MSE_INT_ON();
- return 0;
-}
-
-static int write_mouse(struct inode * inode, struct file * file, char * buffer, int count)
-{
- return -EINVAL;
-}
-
-static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
-{
- int i;
-
- if (count < 3) return -EINVAL;
- if (!mouse.ready) return -EAGAIN;
-
- MSE_INT_OFF();
-
- put_fs_byte(mouse.latch_buttons | 0x80, buffer);
-
- if (mouse.dx < -127) mouse.dx = -127;
- if (mouse.dx > 127) mouse.dx = 127;
-
- put_fs_byte((char)mouse.dx, buffer + 1);
-
- if (mouse.dy < -127) mouse.dy = -127;
- if (mouse.dy > 127) mouse.dy = 127;
-
- put_fs_byte((char) -mouse.dy, buffer + 2);
-
- for (i = 3; i < count; i++)
- put_fs_byte(0x00, buffer + i);
-
- mouse.dx = 0;
- mouse.dy = 0;
- mouse.latch_buttons = mouse.buttons;
- mouse.ready = 0;
-
- MSE_INT_ON();
- return i;
-}
-
-static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
-{
- if (sel_type != SEL_IN)
- return 0;
- if (mouse.ready)
- return 1;
- select_wait(&inode->i_wait,wait);
- return 0;
-}
-
-static struct file_operations mouse_fops = {
- NULL, /* mouse_seek */
- read_mouse,
- write_mouse,
- NULL, /* mouse_readdir */
- mouse_select, /* mouse_select */
- NULL, /* mouse_ioctl */
- open_mouse,
- release_mouse,
-};
-
-long mouse_init(long kmem_start)
-{
- int i;
-
- outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
- outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
-
- for (i = 0; i < 100000; i++); /* busy loop */
- if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
- printk("No bus mouse detected.\n");
- mouse.present = 0;
- return kmem_start;
- }
- chrdev_fops[10] = &mouse_fops;
- outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
-
- MSE_INT_OFF();
-
- mouse.present = 1;
- mouse.active = 0;
- mouse.ready = 0;
- mouse.buttons = mouse.latch_buttons = 0x80;
- mouse.dx = 0;
- mouse.dy = 0;
- printk("Bus mouse detected and installed.\n");
- return kmem_start;
-}
* void spty_write(struct tty_struct * queue);
*/
-#include <errno.h>
-
#include <linux/sched.h>
#include <linux/tty.h>
-#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/io.h>
-int pty_open(unsigned int dev, struct file * filp)
-{
- struct tty_struct * tty;
-
- tty = tty_table + dev;
- if (!tty->link)
- return -ENODEV;
- wake_up(&tty->read_q->proc_list);
- if (filp->f_flags & O_NDELAY)
- return 0;
- while (!tty->link->count && !(current->signal & ~current->blocked))
- interruptible_sleep_on(&tty->link->read_q->proc_list);
- if (!tty->link->count)
- return -ERESTARTSYS;
- return 0;
-}
-
-void pty_close(unsigned int dev, struct file * filp)
-{
- struct tty_struct * tty;
-
- tty = tty_table + dev;
- wake_up(&tty->read_q->proc_list);
- wake_up(&tty->link->write_q->proc_list);
- if (IS_A_PTY_MASTER(dev)) {
- if (tty->link->pgrp > 0)
- kill_pg(tty->link->pgrp,SIGHUP,1);
- }
-}
-
static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
{
- int c;
+ char c;
while (!from->stopped && !EMPTY(from->write_q)) {
if (FULL(to->read_q)) {
TTY_READ_FLUSH(to);
continue;
}
- c = get_tty_queue(from->write_q);
- put_tty_queue(c,to->read_q);
+ GETCH(from->write_q,c);
+ PUTCH(c,to->read_q);
if (current->signal & ~current->blocked)
break;
}
*/
void mpty_write(struct tty_struct * tty)
{
- if (tty->link)
- pty_copy(tty,tty->link);
+ int nr = tty - tty_table;
+
+ if ((nr >> 6) != 2)
+ printk("bad mpty\n\r");
+ else
+ pty_copy(tty,tty+64);
}
void spty_write(struct tty_struct * tty)
{
- if (tty->link)
- pty_copy(tty,tty->link);
+ int nr = tty - tty_table;
+
+ if ((nr >> 6) != 3)
+ printk("bad spty\n\r");
+ else
+ pty_copy(tty,tty-64);
}
--- /dev/null
+/*
+ * linux/kernel/rs_io.s
+ *
+ * (C) 1991 Linus Torvalds
+ */
+
+/*
+ * rs_io.s
+ *
+ * This module implements the rs232 io interrupts.
+ */
+
+.text
+.globl _rs1_interrupt,_rs2_interrupt
+
+size = 2048 /* must be power of two !
+ and must match the value
+ in tty_io.c!!! */
+
+/* these are the offsets into the read/write buffer structures */
+rs_addr = 0
+head = 4
+tail = 8
+proc_list = 12
+buf = 16
+
+startup = 256 /* chars left in write queue when we restart it */
+
+/*
+ * These are the actual interrupt routines. They look where
+ * the interrupt is coming from, and take appropriate action.
+ *
+ * rs1_interrupt (IRQ 4) takes care of com1 and com3
+ * rs2_interrupt (IRQ 3) takes care of com2 and com4
+ */
+.align 2
+_rs1_interrupt:
+ pushl $_table_list+8
+ pushl $_table_list+24
+ jmp rs_int
+
+.align 2
+_rs2_interrupt:
+ pushl $_table_list+16
+ pushl $_table_list+32
+rs_int: cld
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ push %es
+ push %ds /* as this is an interrupt, we cannot */
+ pushl $0x10 /* know that bs is ok. Load it */
+ pop %ds
+ pushl $0x10
+ pop %es
+ movl 24(%esp),%edx
+ call do_rs_intr
+ movl 28(%esp),%edx
+ call do_rs_intr
+ movb $0x20,%al
+ outb %al,$0x20 /* EOI */
+ pop %ds
+ pop %es
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ addl $8,%esp # jump over the _table_list entries
+ iret
+
+do_rs_intr:
+ pushl %edx
+ movl (%edx),%edx
+ movl rs_addr(%edx),%edx
+ addl $2,%edx /* interrupt ident. reg */
+1: xorl %eax,%eax
+ inb %dx,%al
+ testb $1,%al
+ jne 2f
+ cmpb $6,%al /* this shouldn't happen, but ... */
+ ja 2f
+ movl (%esp),%ecx
+ pushl %edx
+ subl $2,%edx
+ call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
+ popl %edx
+ jmp 1b
+2: popl %edx
+ ret
+
+jmp_table:
+ .long modem_status,write_char,read_char,line_status
+
+.align 2
+modem_status:
+ addl $6,%edx /* clear intr by reading modem status reg */
+ inb %dx,%al
+ ret
+
+.align 2
+line_status:
+ addl $5,%edx /* clear intr by reading line status reg. */
+ inb %dx,%al
+ ret
+
+.align 2
+read_char:
+ inb %dx,%al
+ movl %ecx,%edx
+ subl $_table_list,%edx
+ shrl $3,%edx
+ movl (%ecx),%ecx # read-queue
+ movl head(%ecx),%ebx
+ movb %al,buf(%ecx,%ebx)
+ incl %ebx
+ andl $size-1,%ebx
+ cmpl tail(%ecx),%ebx
+ je 1f
+ movl %ebx,head(%ecx)
+1: movl mask_table(,%edx,4),%edx
+ orl %edx,_timer_active
+ ret
+
+.align 2
+mask_table:
+ .long 0,4,8,16,32
+
+.align 2
+write_char:
+ movl 4(%ecx),%ecx # write-queue
+ movl head(%ecx),%ebx
+ subl tail(%ecx),%ebx
+ andl $size-1,%ebx # nr chars in queue
+ je write_buffer_empty
+ cmpl $startup,%ebx
+ ja 1f
+ movl proc_list(%ecx),%ebx # wake up sleeping process
+ testl %ebx,%ebx # is there any?
+ je 1f
+ movl $0,(%ebx)
+1: movl tail(%ecx),%ebx
+ movb buf(%ecx,%ebx),%al
+ outb %al,%dx
+ incl %ebx
+ andl $size-1,%ebx
+ movl %ebx,tail(%ecx)
+ cmpl head(%ecx),%ebx
+ je write_buffer_empty
+ ret
+
+.align 2
+write_buffer_empty:
+ movl proc_list(%ecx),%ebx # wake up sleeping process
+ testl %ebx,%ebx # is there any?
+ je 1f
+ movl $0,(%ebx)
+1: incl %edx
+ inb %dx,%al
+ jmp 1f
+1: jmp 1f
+1: andb $0xd,%al # disable transmit interrupt
+ outb %al,%dx
+ ret
*
* This module implements the rs232 io functions
* void rs_write(struct tty_struct * queue);
- * long rs_init(long);
+ * void rs_init(void);
* and all interrupts pertaining to serial IO.
*/
-#include <signal.h>
-#include <errno.h>
-
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
-
-#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
-
-struct serial_struct serial_table[NR_SERIALS] = {
- { PORT_UNKNOWN, 0, 0x3F8, 4, NULL},
- { PORT_UNKNOWN, 1, 0x2F8, 3, NULL},
- { PORT_UNKNOWN, 2, 0x3E8, 4, NULL},
- { PORT_UNKNOWN, 3, 0x2E8, 3, NULL},
-};
-
-static void send_intr(struct serial_struct * info);
-
-static void modem_status_intr(struct serial_struct * info)
-{
- unsigned char status = inb(info->port+6);
-
- if (!(info->tty->termios.c_cflag & CLOCAL)) {
- if ((status & 0x88) == 0x08 && info->tty->pgrp > 0)
- kill_pg(info->tty->pgrp,SIGHUP,1);
-
- if (info->tty->termios.c_cflag & CRTSCTS)
- info->tty->stopped = !(status & 0x10);
-
- if (!info->tty->stopped)
- send_intr(info);
- }
-}
-
-void send_break(unsigned int line)
-{
- unsigned short port;
- struct serial_struct * info;
-
- if (line >= NR_SERIALS)
- return;
- info = serial_table + line;
- if (!(port = info->port))
- return;
- port += 3;
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 25;
- outb_p(inb_p(port) | 0x40,port);
- schedule();
- outb_p(inb_p(port) & 0xbf,port);
-}
-
-/*
- * There are several races here: we avoid most of them by disabling timer_active
- * for the crucial part of the process.. That's a good idea anyway.
- *
- * The problem is that we have to output characters /both/ from interrupts
- * and from the normal write: the latter to be sure the interrupts start up
- * again. With serial lines, the interrupts can happen so often that the
- * races actually are noticeable.
- */
-static void send_intr(struct serial_struct * info)
-{
- unsigned short port = info->port;
- unsigned int timer = SER1_TIMEOUT + info->line;
- struct tty_queue * queue = info->tty->write_q;
- int c, i = 0;
-
- if (info->tty->stopped) return;
-
- timer_active &= ~(1 << timer);
- while (inb_p(info->port+5) & 0x20) {
- if (queue->tail == queue->head)
- goto end_send;
- c = queue->buf[queue->tail];
- queue->tail++;
- queue->tail &= TTY_BUF_SIZE-1;
- outb(c,port);
- if ((info->type != PORT_16550A) || (++i >= 14) || info->tty->stopped)
- break;
- }
- timer_table[timer].expires = jiffies + 10;
- timer_active |= 1 << timer;
-end_send:
- if (LEFT(queue) > WAKEUP_CHARS)
- wake_up(&queue->proc_list);
-}
-
-static void receive_intr(struct serial_struct * info)
-{
- unsigned short port = info->port;
- struct tty_queue * queue = info->tty->read_q;
- int head = queue->head;
- int maxhead = (queue->tail-1) & (TTY_BUF_SIZE-1);
-
- timer_active &= ~((1<<SER1_TIMER)<<info->line);
- do {
- queue->buf[head] = inb(port);
- if (head != maxhead) {
- head++;
- head &= TTY_BUF_SIZE-1;
- }
- } while (inb(port+5) & 1);
- queue->head = head;
- timer_active |= (1<<SER1_TIMER)<<info->line;
-}
-
-static void line_status_intr(struct serial_struct * info)
-{
- unsigned char status = inb(info->port+5);
-
-/* printk("line status: %02x\n",status); */
-}
-
-static void (*jmp_table[4])(struct serial_struct *) = {
- modem_status_intr,
- send_intr,
- receive_intr,
- line_status_intr
-};
-
-static void check_tty(struct serial_struct * info)
-{
- unsigned char ident;
-
- if (!info || !info->tty || !info->port)
- return;
- while (1) {
- ident = inb(info->port+2) & 7;
- if (ident & 1)
- return;
- ident >>= 1;
- if (ident > 3)
- return;
- jmp_table[ident](info);
- }
-}
-
-/*
- * Again, we disable interrupts to be sure there aren't any races:
- * see send_intr for details.
- */
-static inline void do_rs_write(struct serial_struct * info)
-{
- if (!info->tty || !info->port)
- return;
- if (!info->tty->write_q || EMPTY(info->tty->write_q))
- return;
- cli();
- send_intr(info);
- sti();
-}
-
-/*
- * IRQ routines: one per line
- */
-static void com1_IRQ(int cpl)
-{
- check_tty(serial_table+0);
-}
-
-static void com2_IRQ(int cpl)
-{
- check_tty(serial_table+1);
-}
-static void com3_IRQ(int cpl)
-{
- check_tty(serial_table+2);
-}
+#define WAKEUP_CHARS (TTY_BUF_SIZE/4)
-static void com4_IRQ(int cpl)
-{
- check_tty(serial_table+3);
-}
+extern void rs1_interrupt(void);
+extern void rs2_interrupt(void);
-/*
- * Receive timer routines: one per line
- */
static void com1_timer(void)
{
TTY_READ_FLUSH(tty_table+64);
TTY_READ_FLUSH(tty_table+67);
}
-/*
- * Send timeout routines: one per line
- */
+static inline void do_rs_write(unsigned int port)
+{
+ char c;
+
+#define TTY (tty_table[64+port].write_q)
+#define TIMER (SER1_TIMEOUT+port)
+ cli();
+ if (!EMPTY(TTY)) {
+ outb_p(inb_p(TTY->data+1)|0x02,TTY->data+1);
+ if (inb(TTY->data+5) & 0x20) {
+ GETCH(TTY,c);
+ outb(c,TTY->data);
+ }
+ timer_table[TIMER].expires = jiffies + 50;
+ timer_active |= 1 << TIMER;
+ } else
+ timer_active &= ~(1 << TIMER);
+ sti();
+#undef TIMER
+#undef TTY
+}
+
static void com1_timeout(void)
{
- do_rs_write(serial_table);
+ do_rs_write(0);
}
static void com2_timeout(void)
{
- do_rs_write(serial_table + 1);
+ do_rs_write(1);
}
static void com3_timeout(void)
{
- do_rs_write(serial_table + 2);
+ do_rs_write(2);
}
static void com4_timeout(void)
{
- do_rs_write(serial_table + 3);
+ do_rs_write(3);
}
-static void init(struct serial_struct * info)
+static void init(int port)
{
- unsigned char status1, status2, scratch;
- unsigned short port = info->port;
-
- if (inb(port+5) == 0xff) {
- info->type = PORT_UNKNOWN;
- return;
- }
-
- scratch = inb(port+7);
- outb_p(0xa5, port+7);
- status1 = inb(port+7);
- outb_p(0x5a, port+7);
- status2 = inb(port+7);
- if (status1 == 0xa5 && status2 == 0x5a) {
- outb_p(scratch, port+7);
- outb_p(0x01, port+2);
- scratch = inb(port+2) >> 6;
- switch (scratch) {
- case 0:
- info->type = PORT_16450;
- break;
- case 1:
- info->type = PORT_UNKNOWN;
- break;
- case 2:
- info->type = PORT_16550;
- outb_p(0x00, port+2);
- break;
- case 3:
- info->type = PORT_16550A;
- outb_p(0xc7, port+2);
- break;
- }
- } else
- info->type = PORT_8250;
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(0x03,port+3); /* reset DLAB */
outb_p(0x00,port+4); /* reset DTR,RTS, OUT_2 */
- outb_p(0x00,port+1); /* disable all intrs */
+ outb_p(0x0d,port+1); /* enable all intrs but writes */
(void)inb(port); /* read data port to reset things (?) */
}
-void serial_close(unsigned line, struct file * filp)
+/*
+ * this routine enables interrupts on 'line', and disables them on
+ * 'line ^ 2', as they share the same IRQ. Braindamaged AT hardware.
+ */
+void serial_open(unsigned int line)
{
- struct serial_struct * info;
- int irq;
+ unsigned short port;
+ unsigned short port2;
- if (line >= NR_SERIALS)
+ if (line>3)
return;
- info = serial_table + line;
- if (!info->port)
+ port = tty_table[64+line].read_q->data;
+ if (!port)
return;
- outb(0x00,info->port+4); /* reset DTR, RTS, */
- irq = info->irq;
- if (irq == 2)
- irq = 9;
- free_irq(irq);
-}
-
-static void startup(unsigned short port)
-{
+ port2 = tty_table[64+(line ^ 2)].read_q->data;
+ cli();
+ if (port2)
+ outb_p(0x00,port2+4);
outb_p(0x03,port+3); /* reset DLAB */
outb_p(0x0f,port+4); /* set DTR,RTS, OUT_2 */
- outb_p(0x0f,port+1); /* enable all intrs */
- inb_p(port+2);
- inb_p(port+6);
- inb_p(port+2);
- inb_p(port+5);
- do { /* drain all of the stuck characters out of the port */
- inb_p(port+0);
- } while (inb_p(port+5) & 1 == 1);
- inb_p(port+2);
+ outb_p(0x0d,port+1); /* enable all intrs but writes */
inb_p(port+5);
-}
-
-void change_speed(unsigned int line)
-{
- struct serial_struct * info;
- unsigned short port,quot;
- unsigned cflag,cval;
- static unsigned short quotient[] = {
- 0, 2304, 1536, 1047, 857,
- 768, 576, 384, 192, 96,
- 64, 48, 24, 12, 6, 3
- };
-
- if (line >= NR_SERIALS)
- return;
- info = serial_table + line;
- cflag = info->tty->termios.c_cflag;
- if (!(port = info->port))
- return;
- quot = quotient[cflag & CBAUD];
- if (!quot)
- outb(0x00,port+4);
- else if (!inb(port+4))
- startup(port);
-/* byte size and parity */
- cval = cflag & (CSIZE | CSTOPB);
- cval >>= 4;
- if (cflag & PARENB)
- cval |= 8;
- if (!(cflag & PARODD))
- cval |= 16;
- cli();
- outb_p(cval | 0x80,port+3); /* set DLAB */
- outb_p(quot & 0xff,port); /* LS of divisor */
- outb_p(quot >> 8,port+1); /* MS of divisor */
- outb(cval,port+3); /* reset DLAB */
- sti();
-}
-
-static void (*serial_handler[NR_SERIALS])(int) = {
- com1_IRQ,com2_IRQ,com3_IRQ,com4_IRQ
-};
-
-/*
- * this routine enables interrupts on 'line', and disables them for any
- * other serial line that shared the same IRQ. Braindamaged AT hardware.
- */
-int serial_open(unsigned line, struct file * filp)
-{
- struct serial_struct * info;
- int irq,retval;
- unsigned short port;
- void (*handler)(int) = serial_handler[line];
-
- if (line >= NR_SERIALS)
- return -ENODEV;
- info = serial_table + line;
- if (!(port = info->port))
- return -ENODEV;
- irq = info->irq;
- if (irq == 2)
- irq = 9;
- if (retval = request_irq(irq,handler))
- return retval;
- startup(port);
- return 0;
-}
-
-int get_serial_info(unsigned int line, struct serial_struct * info)
-{
- if (line >= NR_SERIALS)
- return -ENODEV;
- if (!info)
- return -EFAULT;
- memcpy_tofs(info,serial_table+line,sizeof(*info));
- return 0;
-}
-
-int set_serial_info(unsigned int line, struct serial_struct * info)
-{
- struct serial_struct tmp;
- unsigned new_port;
- unsigned irq,new_irq;
- int retval;
- void (*handler)(int) = serial_handler[line];
-
- if (!suser())
- return -EPERM;
- if (line >= NR_SERIALS)
- return -ENODEV;
- if (!info)
- return -EFAULT;
- memcpy_fromfs(&tmp,info,sizeof(tmp));
- info = serial_table + line;
- if (!(new_port = tmp.port))
- new_port = info->port;
- if (!(new_irq = tmp.irq))
- new_irq = info->irq;
- if (new_irq > 15 || new_port > 0xffff)
- return -EINVAL;
- if (new_irq == 2)
- new_irq = 9;
- irq = info->irq;
- if (irq == 2)
- irq = 9;
- if (irq != new_irq) {
- retval = request_irq(new_irq,handler);
- if (retval)
- return retval;
- info->irq = new_irq;
- free_irq(irq);
- }
- cli();
- if (new_port != info->port) {
- outb(0x00,info->port+4); /* reset DTR, RTS, */
- info->port = new_port;
- init(info);
- startup(new_port);
- }
+ inb_p(port+0);
+ inb(port+6);
+ inb(port+2);
sti();
- return 0;
}
-long rs_init(long kmem_start)
+void rs_init(void)
{
- int i;
- struct serial_struct * info;
-
/* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
timer_table[SER1_TIMER].fn = com1_timer;
timer_table[SER1_TIMER].expires = 0;
timer_table[SER3_TIMEOUT].expires = 0;
timer_table[SER4_TIMEOUT].fn = com4_timeout;
timer_table[SER4_TIMEOUT].expires = 0;
- for (i = 0, info = serial_table; i < NR_SERIALS; i++,info++) {
- info->tty = (tty_table+64) + i;
- init(info);
- if (info->type == PORT_UNKNOWN)
- continue;
- printk("serial port at 0x%04x (irq = %d)",info->port,info->irq);
- switch (info->type) {
- case PORT_8250:
- printk(" is a 8250\n");
- break;
- case PORT_16450:
- printk(" is a 16450\n");
- break;
- case PORT_16550:
- printk(" is a 16550\n");
- break;
- case PORT_16550A:
- printk(" is a 16550A\n");
- break;
- default:
- printk("\n");
- break;
- }
- }
- return kmem_start;
+ set_intr_gate(0x24,rs1_interrupt);
+ set_intr_gate(0x23,rs2_interrupt);
+ init(tty_table[64].read_q->data);
+ init(tty_table[65].read_q->data);
+ init(tty_table[66].read_q->data);
+ init(tty_table[67].read_q->data);
+ outb(inb_p(0x21)&0xE7,0x21);
}
/*
*/
void rs_write(struct tty_struct * tty)
{
- int line = tty - tty_table - 64;
-
- do_rs_write(serial_table+line);
+ cli();
+ if (!EMPTY(tty->write_q))
+ outb_p(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
+ timer_active |= 15 << SER1_TIMEOUT;
+ sti();
}
* Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
*/
+#include <linux/ctype.h>
#include <errno.h>
#include <signal.h>
-
-#include <linux/fcntl.h>
+#include <unistd.h>
+#include <fcntl.h>
#define ALRMMASK (1<<(SIGALRM-1))
#include <linux/sched.h>
#include <linux/tty.h>
-#include <linux/ctype.h>
-#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
-#include <sys/kd.h>
-#include "vt_kern.h"
+int kill_pg(int pgrp, int sig, int priv);
+int is_orphaned_pgrp(int pgrp);
+
+extern void lp_init(void);
+
+#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
+#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
+#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
+
+#define L_CANON(tty) _L_FLAG((tty),ICANON)
+#define L_ISIG(tty) _L_FLAG((tty),ISIG)
+#define L_ECHO(tty) _L_FLAG((tty),ECHO)
+#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
+#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
+#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
+#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
+#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
+#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
+
+#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
+#define I_NLCR(tty) _I_FLAG((tty),INLCR)
+#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
+#define I_NOCR(tty) _I_FLAG((tty),IGNCR)
+#define I_IXON(tty) _I_FLAG((tty),IXON)
+#define I_STRP(tty) _I_FLAG((tty),ISTRIP)
+
+#define O_POST(tty) _O_FLAG((tty),OPOST)
+#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
+#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
+#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
+#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
+
+#define C_SPEED(tty) ((tty)->termios.c_cflag & CBAUD)
+#define C_HUP(tty) (C_SPEED((tty)) == B0)
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-#define QUEUES (3*(NR_CONSOLES+NR_SERIALS+2*NR_PTYS))
-static struct tty_queue * tty_queues;
+#define QUEUES (3*(MAX_CONSOLES+NR_SERIALS+2*NR_PTYS))
+static struct tty_queue tty_queues[QUEUES];
struct tty_struct tty_table[256];
#define con_queues tty_queues
-#define rs_queues ((3*NR_CONSOLES) + tty_queues)
-#define mpty_queues ((3*(NR_CONSOLES+NR_SERIALS)) + tty_queues)
-#define spty_queues ((3*(NR_CONSOLES+NR_SERIALS+NR_PTYS)) + tty_queues)
+#define rs_queues ((3*MAX_CONSOLES) + tty_queues)
+#define mpty_queues ((3*(MAX_CONSOLES+NR_SERIALS)) + tty_queues)
+#define spty_queues ((3*(MAX_CONSOLES+NR_SERIALS+NR_PTYS)) + tty_queues)
#define con_table tty_table
#define rs_table (64+tty_table)
#define mpty_table (128+tty_table)
#define spty_table (192+tty_table)
-/*
- * fg_console is the current virtual console,
- * redirect is the pseudo-tty that console output
- * is redirected to if asked by TIOCCONS.
- */
int fg_console = 0;
-struct tty_struct * redirect = NULL;
/*
* these are the tables used by the machine code handlers.
* you can implement virtual consoles.
*/
-struct tty_queue * table_list[] = { NULL, NULL };
-
-void put_tty_queue(char c, struct tty_queue * queue)
-{
- int head;
- unsigned long flags;
-
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- head = (queue->head + 1) & (TTY_BUF_SIZE-1);
- if (head != queue->tail) {
- queue->buf[queue->head] = c;
- queue->head = head;
- }
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
-}
-
-int get_tty_queue(struct tty_queue * queue)
-{
- int result = -1;
- unsigned long flags;
-
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- if (queue->tail != queue->head) {
- result = 0xff & queue->buf[queue->tail];
- queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
- }
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
- return result;
-}
-
-void tty_write_flush(struct tty_struct * tty)
-{
- if (EMPTY(tty->write_q))
- return;
- if (set_bit(TTY_WRITE_BUSY,&tty->flags))
- return;
- tty->write(tty);
- if (clear_bit(TTY_WRITE_BUSY,&tty->flags))
- printk("tty_write_flush: bit already cleared\n");
-}
-
-void tty_read_flush(struct tty_struct * tty)
-{
- if (EMPTY(tty->read_q))
- return;
- if (set_bit(TTY_READ_BUSY, &tty->flags))
- return;
- copy_to_cooked(tty);
- if (clear_bit(TTY_READ_BUSY, &tty->flags))
- printk("tty_read_flush: bit already cleared\n");
-}
+struct tty_queue * table_list[]={
+ con_queues + 0, con_queues + 1,
+ rs_queues + 0, rs_queues + 1,
+ rs_queues + 3, rs_queues + 4,
+ rs_queues + 6, rs_queues + 7,
+ rs_queues + 9, rs_queues + 10
+ };
void change_console(unsigned int new_console)
{
- if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
- return;
if (new_console == fg_console || new_console >= NR_CONSOLES)
return;
table_list[0] = con_queues + 0 + new_console*3;
sti();
}
+static void sleep_if_full(struct tty_queue * queue)
+{
+ if (!FULL(queue))
+ return;
+ cli();
+ while (!(current->signal & ~current->blocked) && LEFT(queue)<128)
+ interruptible_sleep_on(&queue->proc_list);
+ sti();
+}
+
void wait_for_keypress(void)
{
sleep_if_empty(tty_table[fg_console].secondary);
void copy_to_cooked(struct tty_struct * tty)
{
- int c;
+ unsigned char c;
if (!(tty && tty->write && tty->read_q &&
tty->write_q && tty->secondary)) {
return;
}
while (1) {
- if (FULL(tty->secondary))
+ if (EMPTY(tty->read_q))
break;
- c = get_tty_queue(tty->read_q);
- if (c < 0)
+ if (FULL(tty->secondary)) {
+ if (tty->secondary->proc_list)
+ if (tty->secondary->proc_list != current)
+ current->counter = 0;
break;
+ }
+ GETCH(tty->read_q,c);
if (I_STRP(tty))
c &= 0x7f;
if (c==13) {
if (I_UCLC(tty))
c=tolower(c);
if (L_CANON(tty)) {
- if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((KILL_CHAR(tty) != _POSIX_VDISABLE) &&
(c==KILL_CHAR(tty))) {
/* deal with killing the input line */
while(!(EMPTY(tty->secondary) ||
(c=LAST(tty->secondary))==10 ||
- ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
+ ((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
(c==EOF_CHAR(tty))))) {
if (L_ECHO(tty)) {
- if (c<32) {
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
- }
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
+ if (c<32)
+ PUTCH(127,tty->write_q);
+ PUTCH(127,tty->write_q);
TTY_WRITE_FLUSH(tty);
}
DEC(tty->secondary->head);
}
continue;
}
- if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((ERASE_CHAR(tty) != _POSIX_VDISABLE) &&
(c==ERASE_CHAR(tty))) {
if (EMPTY(tty->secondary) ||
(c=LAST(tty->secondary))==10 ||
- ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
+ ((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
(c==EOF_CHAR(tty))))
continue;
if (L_ECHO(tty)) {
- if (c<32) {
- put_tty_queue(8,tty->write_q);
- put_tty_queue(' ',tty->write_q);
- put_tty_queue(8,tty->write_q);
- }
- put_tty_queue(8,tty->write_q);
- put_tty_queue(32,tty->write_q);
- put_tty_queue(8,tty->write_q);
+ if (c<32)
+ PUTCH(127,tty->write_q);
+ PUTCH(127,tty->write_q);
TTY_WRITE_FLUSH(tty);
}
DEC(tty->secondary->head);
}
}
if (I_IXON(tty)) {
- if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((STOP_CHAR(tty) != _POSIX_VDISABLE) &&
(c==STOP_CHAR(tty))) {
tty->stopped=1;
continue;
}
- if ((START_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((START_CHAR(tty) != _POSIX_VDISABLE) &&
(c==START_CHAR(tty))) {
tty->stopped=0;
TTY_WRITE_FLUSH(tty);
}
}
if (L_ISIG(tty)) {
- if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((INTR_CHAR(tty) != _POSIX_VDISABLE) &&
(c==INTR_CHAR(tty))) {
kill_pg(tty->pgrp, SIGINT, 1);
- flush_input(tty);
continue;
}
- if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((QUIT_CHAR(tty) != _POSIX_VDISABLE) &&
(c==QUIT_CHAR(tty))) {
kill_pg(tty->pgrp, SIGQUIT, 1);
- flush_input(tty);
continue;
}
- if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
+ if ((SUSPEND_CHAR(tty) != _POSIX_VDISABLE) &&
(c==SUSPEND_CHAR(tty))) {
if (!is_orphaned_pgrp(tty->pgrp))
kill_pg(tty->pgrp, SIGTSTP, 1);
continue;
}
}
- if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
+ if (c==10 || (EOF_CHAR(tty) != _POSIX_VDISABLE &&
c==EOF_CHAR(tty)))
tty->secondary->data++;
- if ((L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty))) && (c==10)) {
- put_tty_queue(10,tty->write_q);
- put_tty_queue(13,tty->write_q);
+ if ((L_ECHO(tty) || L_ECHONL(tty)) && (c==10)) {
+ PUTCH(10,tty->write_q);
+ PUTCH(13,tty->write_q);
} else if (L_ECHO(tty)) {
if (c<32 && L_ECHOCTL(tty)) {
- put_tty_queue('^',tty->write_q);
- put_tty_queue(c+64,tty->write_q);
+ PUTCH('^',tty->write_q);
+ PUTCH(c+64,tty->write_q);
} else
- put_tty_queue(c,tty->write_q);
+ PUTCH(c,tty->write_q);
}
- put_tty_queue(c,tty->secondary);
+ PUTCH(c,tty->secondary);
TTY_WRITE_FLUSH(tty);
}
TTY_WRITE_FLUSH(tty);
wake_up(&tty->write_q->proc_list);
}
-int is_ignored(int sig)
-{
- return ((current->blocked & (1<<(sig-1))) ||
- (current->sigaction[sig-1].sa_handler == SIG_IGN));
-}
-
/*
* Called when we need to send a SIGTTIN or SIGTTOU to our process
* group
*/
int tty_signal(int sig, struct tty_struct *tty)
{
+ if (is_orphaned_pgrp(current->pgrp))
+ return -EIO; /* don't stop an orphaned pgrp */
(void) kill_pg(current->pgrp,sig,1);
- return -ERESTARTSYS;
-}
-
-static void wait_for_canon_input(struct tty_struct * tty)
-{
- while (1) {
- TTY_READ_FLUSH(tty);
- if (tty->link)
- if (tty->link->count)
- TTY_WRITE_FLUSH(tty->link);
- else
- return;
- if (current->signal & ~current->blocked)
- return;
- if (FULL(tty->read_q))
- return;
- if (tty->secondary->data)
- return;
- cli();
- if (!tty->secondary->data)
- interruptible_sleep_on(&tty->secondary->proc_list);
- sti();
- }
+ if ((current->blocked & (1<<(sig-1))) ||
+ ((int) current->sigaction[sig-1].sa_handler == 1))
+ return -EIO; /* Our signal will be ignored */
+ else if (current->sigaction[sig-1].sa_handler)
+ return -EINTR; /* We _will_ be interrupted :-) */
+ else
+ return -ERESTARTSYS; /* We _will_ be interrupted :-) */
+ /* (but restart after we continue) */
}
static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
{
struct tty_struct * tty;
- int c;
+ struct tty_struct * other_tty = NULL;
+ unsigned char c;
char * b=buf;
int minimum,time;
tty = TTY_TABLE(channel);
if (!(tty->read_q && tty->secondary))
return -EIO;
- if ((tty->pgrp > 0) &&
- (current->tty == channel) &&
+ if ((tty->pgrp > 0) && (current->tty == channel) &&
(tty->pgrp != current->pgrp))
- if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
- return -EIO;
- else
- return(tty_signal(SIGTTIN, tty));
- if (L_CANON(tty))
- minimum = time = current->timeout = 0;
+ return(tty_signal(SIGTTIN, tty));
+ if (channel & 0x80)
+ other_tty = tty_table + (channel ^ 0x40);
+ time = 10L*tty->termios.c_cc[VTIME];
+ minimum = tty->termios.c_cc[VMIN];
+ if (L_CANON(tty)) {
+ minimum = nr;
+ current->timeout = 0xffffffff;
+ time = 0;
+ } else if (minimum)
+ current->timeout = 0xffffffff;
else {
- time = 10L*tty->termios.c_cc[VTIME];
- minimum = tty->termios.c_cc[VMIN];
- if (minimum)
- current->timeout = 0xffffffff;
- else {
- if (time)
- current->timeout = time + jiffies;
- else
- current->timeout = 0;
- time = 0;
- minimum = 1;
- }
+ minimum = nr;
+ if (time)
+ current->timeout = time + jiffies;
+ time = 0;
}
if (file->f_flags & O_NONBLOCK)
time = current->timeout = 0;
- else if (L_CANON(tty))
- wait_for_canon_input(tty);
if (minimum>nr)
minimum = nr;
+ TTY_READ_FLUSH(tty);
while (nr>0) {
- TTY_READ_FLUSH(tty);
- if (tty->link)
- TTY_WRITE_FLUSH(tty->link);
- while (nr > 0 && ((c = get_tty_queue(tty->secondary)) >= 0)) {
- if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
+ if (other_tty && other_tty->write)
+ TTY_WRITE_FLUSH(other_tty);
+ cli();
+ if (EMPTY(tty->secondary) || (L_CANON(tty) &&
+ !FULL(tty->read_q) && !tty->secondary->data)) {
+ if (!current->timeout)
+ break;
+ if (current->signal & ~current->blocked)
+ break;
+ if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
+ break;
+ interruptible_sleep_on(&tty->secondary->proc_list);
+ sti();
+ TTY_READ_FLUSH(tty);
+ continue;
+ }
+ sti();
+ do {
+ GETCH(tty->secondary,c);
+ if ((EOF_CHAR(tty) != _POSIX_VDISABLE &&
c==EOF_CHAR(tty)) || c==10)
tty->secondary->data--;
- if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
+ if ((EOF_CHAR(tty) != _POSIX_VDISABLE &&
c==EOF_CHAR(tty)) && L_CANON(tty))
break;
- put_fs_byte(c,b++);
- nr--;
- if (time)
- current->timeout = time+jiffies;
+ else {
+ put_fs_byte(c,b++);
+ if (!--nr)
+ break;
+ }
if (c==10 && L_CANON(tty))
break;
- };
+ } while (nr>0 && !EMPTY(tty->secondary));
wake_up(&tty->read_q->proc_list);
- if (b-buf >= minimum || !current->timeout)
- break;
- if (current->signal & ~current->blocked)
+ if (L_CANON(tty) || b-buf >= minimum)
break;
- if (tty->link && !tty->link->count)
- break;
- TTY_READ_FLUSH(tty);
- if (tty->link)
- TTY_WRITE_FLUSH(tty->link);
- cli();
- if (EMPTY(tty->secondary))
- interruptible_sleep_on(&tty->secondary->proc_list);
- sti();
+ if (time)
+ current->timeout = time+jiffies;
}
- TTY_READ_FLUSH(tty);
- if (tty->link && tty->link->write)
- TTY_WRITE_FLUSH(tty->link);
+ sti();
current->timeout = 0;
if (b-buf)
return b-buf;
static int write_chan(unsigned int channel, struct file * file, char * buf, int nr)
{
+ static cr_flag=0;
struct tty_struct * tty;
char c, *b=buf;
if (channel > 255)
return -EIO;
tty = TTY_TABLE(channel);
- if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
- (current->tty == channel) && (tty->pgrp != current->pgrp)) {
- if (is_orphaned_pgrp(tty->pgrp))
- return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
- }
+ if (!(tty->write_q && tty->write))
+ return -EIO;
+ if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
+ (current->tty == channel) && (tty->pgrp != current->pgrp))
+ return(tty_signal(SIGTTOU, tty));
if (nr < 0)
return -EINVAL;
if (!nr)
return 0;
- if (redirect && tty == TTY_TABLE(0))
- tty = redirect;
- if (!(tty->write_q && tty->write))
- return -EIO;
while (nr>0) {
+ sleep_if_full(tty->write_q);
if (current->signal & ~current->blocked)
break;
- if (tty->link && !tty->link->count) {
- send_sig(SIGPIPE,current,0);
- break;
- }
- if (FULL(tty->write_q)) {
- TTY_WRITE_FLUSH(tty);
- cli();
- if (FULL(tty->write_q))
- interruptible_sleep_on(&tty->write_q->proc_list);
- sti();
- continue;
- }
while (nr>0 && !FULL(tty->write_q)) {
c=get_fs_byte(b);
if (O_POST(tty)) {
c='\n';
else if (c=='\n' && O_NLRET(tty))
c='\r';
- if (c=='\n' && O_NLCR(tty) &&
- !set_bit(TTY_CR_PENDING,&tty->flags)) {
- put_tty_queue(13,tty->write_q);
+ if (c=='\n' && !cr_flag && O_NLCR(tty)) {
+ cr_flag = 1;
+ PUTCH(13,tty->write_q);
continue;
}
if (O_LCUC(tty))
c=toupper(c);
}
b++; nr--;
- clear_bit(TTY_CR_PENDING,&tty->flags);
- put_tty_queue(c,tty->write_q);
+ cr_flag = 0;
+ PUTCH(c,tty->write_q);
}
+ TTY_WRITE_FLUSH(tty);
if (nr>0)
schedule();
}
- TTY_WRITE_FLUSH(tty);
if (b-buf)
return b-buf;
- if (tty->link && !tty->link->count)
- return -EPIPE;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
return 0;
static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
{
- int i;
-
- if (MAJOR(file->f_rdev) != 4) {
- printk("tty_read: pseudo-major != 4\n");
- return -EINVAL;
- }
- i = read_chan(MINOR(file->f_rdev),file,buf,count);
- if (i > 0)
- inode->i_atime = CURRENT_TIME;
- return i;
+ return read_chan(current->tty,file,buf,count);
}
-static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
+static int ttyx_read(struct inode * inode, struct file * file, char * buf, int count)
{
- int i;
-
- if (MAJOR(file->f_rdev) != 4) {
- printk("tty_write: pseudo-major != 4\n");
- return -EINVAL;
- }
- i = write_chan(MINOR(file->f_rdev),file,buf,count);
- if (i > 0)
- inode->i_mtime = CURRENT_TIME;
- return i;
+ return read_chan(MINOR(inode->i_rdev),file,buf,count);
}
-static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
{
- return -EBADF;
+ return write_chan(current->tty,file,buf,count);
}
-/*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
- *
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- */
-static int tty_open(struct inode * inode, struct file * filp)
+static int ttyx_write(struct inode * inode, struct file * file, char * buf, int count)
{
- struct tty_struct *tty;
- int dev, retval;
-
- dev = inode->i_rdev;
- if (MAJOR(dev) == 5)
- dev = current->tty;
- else
- dev = MINOR(dev);
- if (dev < 0)
- return -ENODEV;
- filp->f_rdev = 0x0400 | dev;
- tty = TTY_TABLE(dev);
- if (!tty->count && !(tty->link && tty->link->count)) {
- flush_input(tty);
- flush_output(tty);
- tty->stopped = 0;
- }
- if (IS_A_PTY_MASTER(dev)) {
- if (tty->count)
- return -EAGAIN;
- if (tty->link)
- tty->link->count++;
- }
- tty->count++;
- retval = 0;
- if (!(filp->f_flags & O_NOCTTY) &&
- current->leader &&
- current->tty<0 &&
- tty->session==0) {
- current->tty = dev;
- tty->session = current->session;
- tty->pgrp = current->pgrp;
- }
- if (IS_A_SERIAL(dev) && tty->count < 2)
- retval = serial_open(dev-64,filp);
- else if (IS_A_PTY(dev))
- retval = pty_open(dev,filp);
- if (retval) {
- tty->count--;
- if (IS_A_PTY_MASTER(dev) && tty->link)
- tty->link->count--;
- }
- return retval;
+ return write_chan(MINOR(inode->i_rdev),file,buf,count);
}
-/*
- * Note that releasing a pty master also releases the child, so
- * we have to make the redirection checks after that and on both
- * sides of a pty.
- */
-static void tty_release(struct inode * inode, struct file * filp)
+static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
{
- int dev;
- struct tty_struct * tty;
-
- dev = filp->f_rdev;
- if (MAJOR(dev) != 4) {
- printk("tty_close: tty pseudo-major != 4\n");
- return;
- }
- dev = MINOR(filp->f_rdev);
- tty = TTY_TABLE(dev);
- if (IS_A_PTY_MASTER(dev) && tty->link)
- tty->link->count--;
- tty->count--;
- if (tty->count)
- return;
- if (IS_A_SERIAL(dev)) {
- wait_until_sent(tty);
- serial_close(dev-64,filp);
- } else if (IS_A_PTY(dev))
- pty_close(dev,filp);
- if (!tty->count && (tty == redirect))
- redirect = NULL;
- if (tty = tty->link)
- if (!tty->count && (tty == redirect))
- redirect = NULL;
+ return -EBADF;
}
-static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
+static int tty_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
{
- int dev;
- struct tty_struct * tty;
-
- dev = filp->f_rdev;
- if (MAJOR(dev) != 4) {
- printk("tty_select: tty pseudo-major != 4\n");
- return 0;
- }
- dev = MINOR(filp->f_rdev);
- tty = TTY_TABLE(dev);
- switch (sel_type) {
- case SEL_IN:
- if (!EMPTY(tty->secondary))
- return 1;
- if (tty->link && !tty->link->count)
- return 1;
- select_wait(&tty->secondary->proc_list, wait);
- return 0;
- case SEL_OUT:
- if (!FULL(tty->write_q))
- return 1;
- select_wait(&tty->write_q->proc_list, wait);
- return 0;
- case SEL_EX:
- if (tty->link && !tty->link->count)
- return 1;
- return 0;
- }
- return 0;
+ return -ENOTDIR;
}
static struct file_operations tty_fops = {
tty_lseek,
tty_read,
tty_write,
- NULL, /* tty_readdir */
- tty_select,
- tty_ioctl,
- tty_open,
- tty_release
+ tty_readdir,
+ NULL, /* tty_close */
+ NULL, /* tty_select */
+ tty_ioctl /* tty_ioctl */
+};
+
+static struct file_operations ttyx_fops = {
+ tty_lseek,
+ ttyx_read,
+ ttyx_write,
+ tty_readdir,
+ NULL, /* ttyx_close */
+ NULL, /* ttyx_select */
+ tty_ioctl /* ttyx_ioctl */
};
-long tty_init(long kmem_start)
+void tty_init(void)
{
int i;
- tty_queues = (struct tty_queue *) kmem_start;
- kmem_start += QUEUES * (sizeof (struct tty_queue));
- table_list[0] = con_queues + 0;
- table_list[1] = con_queues + 1;
- chrdev_fops[4] = &tty_fops;
+ chrdev_fops[4] = &ttyx_fops;
chrdev_fops[5] = &tty_fops;
for (i=0 ; i < QUEUES ; i++)
tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
+ rs_queues[0] = (struct tty_queue) {0x3f8,0,0,0,""};
+ rs_queues[1] = (struct tty_queue) {0x3f8,0,0,0,""};
+ rs_queues[3] = (struct tty_queue) {0x2f8,0,0,0,""};
+ rs_queues[4] = (struct tty_queue) {0x2f8,0,0,0,""};
+ rs_queues[6] = (struct tty_queue) {0x3e8,0,0,0,""};
+ rs_queues[7] = (struct tty_queue) {0x3e8,0,0,0,""};
+ rs_queues[9] = (struct tty_queue) {0x2e8,0,0,0,""};
+ rs_queues[10] = (struct tty_queue) {0x2e8,0,0,0,""};
for (i=0 ; i<256 ; i++) {
tty_table[i] = (struct tty_struct) {
{0, 0, 0, 0, 0, INIT_C_CC},
- -1, 0, 0, 0, 0, {0,0,0,0},
- NULL, NULL, NULL, NULL, NULL
+ -1, 0, 0, 0, {0,0,0,0},
+ NULL, NULL, NULL, NULL
};
}
- kmem_start = con_init(kmem_start);
+ con_init();
for (i = 0 ; i<NR_CONSOLES ; i++) {
con_table[i] = (struct tty_struct) {
{ICRNL, /* change incoming CR to NL */
-1, /* initial pgrp */
0, /* initial session */
0, /* initial stopped */
- 0, /* initial flags */
- 0, /* initial count */
+ 0, /* initial busy */
{video_num_lines,video_num_columns,0,0},
con_write,
- NULL, /* other-tty */
con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
};
}
0,
0,
0,
- 0,
{25,80,0,0},
rs_write,
- NULL, /* other-tty */
rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3
};
}
0,
0,
0,
- 0,
{25,80,0,0},
mpty_write,
- spty_table+i,
mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
};
spty_table[i] = (struct tty_struct) {
0,
0,
0,
- 0,
{25,80,0,0},
spty_write,
- mpty_table+i,
spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
};
}
- kmem_start = rs_init(kmem_start);
+ rs_init();
printk("%d virtual consoles\n\r",NR_CONSOLES);
printk("%d pty's\n\r",NR_PTYS);
- return kmem_start;
}
extern int session_of_pgrp(int pgrp);
extern int do_screendump(int arg);
extern int kill_pg(int pgrp, int sig, int priv);
+extern int tty_signal(int sig, struct tty_struct *tty);
extern int vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg);
+static unsigned short quotient[] = {
+ 0, 2304, 1536, 1047, 857,
+ 768, 576, 384, 192, 96,
+ 64, 48, 24, 12, 6, 3
+};
+
+static void change_speed(struct tty_struct * tty)
+{
+ unsigned short port,quot;
+
+ if (!(port = tty->read_q->data))
+ return;
+ quot = quotient[tty->termios.c_cflag & CBAUD];
+ cli();
+ outb_p(0x80,port+3); /* set DLAB */
+ outb_p(quot & 0xff,port); /* LS of divisor */
+ outb_p(quot >> 8,port+1); /* MS of divisor */
+ outb(0x03,port+3); /* reset DLAB */
+ sti();
+}
+
static void flush(struct tty_queue * queue)
{
if (queue) {
}
}
-void flush_input(struct tty_struct * tty)
-{
- if (tty->read_q) {
- flush(tty->read_q);
- wake_up(&tty->read_q->proc_list);
- }
- if (tty->secondary) {
- flush(tty->secondary);
- tty->secondary->data = 0;
- }
- if ((tty = tty->link) && tty->write_q) {
- flush(tty->write_q);
- wake_up(&tty->write_q->proc_list);
- }
-}
-
-void flush_output(struct tty_struct * tty)
-{
- if (tty->write_q) {
- flush(tty->write_q);
- wake_up(&tty->write_q->proc_list);
- }
- if (tty = tty->link) {
- if (tty->read_q) {
- flush(tty->read_q);
- wake_up(&tty->read_q->proc_list);
- }
- if (tty->secondary) {
- flush(tty->secondary);
- tty->secondary->data = 0;
- }
- }
-}
-
-void wait_until_sent(struct tty_struct * tty)
+static void wait_until_sent(struct tty_struct * tty)
{
+ cli();
while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
- TTY_WRITE_FLUSH(tty);
current->counter = 0;
- cli();
- if (EMPTY(tty->write_q))
- break;
- else
- interruptible_sleep_on(&tty->write_q->proc_list);
- sti();
+ interruptible_sleep_on(&tty->write_q->proc_list);
}
sti();
}
+static void send_break(struct tty_struct * tty)
+{
+ /* do nothing - not implemented */
+}
+
static int do_get_ps_info(int arg)
{
struct tstruct {
static int set_termios(struct tty_struct * tty, struct termios * termios,
int channel)
{
- int i;
- unsigned short old_cflag = tty->termios.c_cflag;
+ int i, retsig;
/* If we try to set the state of terminal and we're not in the
foreground, send a SIGTTOU. If the signal is blocked or
ignored, go ahead and perform the operation. POSIX 7.2) */
- if ((current->tty == channel) &&
- (tty->pgrp != current->pgrp)) {
- if (is_orphaned_pgrp(current->pgrp))
- return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
+ if ((current->tty == channel) && (tty->pgrp != current->pgrp)) {
+ retsig = tty_signal(SIGTTOU, tty);
+ if (retsig == -ERESTARTSYS || retsig == -EINTR)
+ return retsig;
}
for (i=0 ; i< (sizeof (*termios)) ; i++)
((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
- if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
- change_speed(channel-64);
+ change_speed(tty);
return 0;
}
static int set_termio(struct tty_struct * tty, struct termio * termio,
int channel)
{
- int i;
+ int i, retsig;
struct termio tmp_termio;
- unsigned short old_cflag = tty->termios.c_cflag;
- if ((current->tty == channel) &&
- (tty->pgrp > 0) &&
- (tty->pgrp != current->pgrp)) {
- if (is_orphaned_pgrp(current->pgrp))
- return -EIO;
- if (!is_ignored(SIGTTOU))
- return tty_signal(SIGTTOU, tty);
+ if ((current->tty == channel) && (tty->pgrp != current->pgrp)) {
+ retsig = tty_signal(SIGTTOU, tty);
+ if (retsig == -ERESTARTSYS || retsig == -EINTR)
+ return retsig;
}
for (i=0 ; i< (sizeof (*termio)) ; i++)
((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
tty->termios.c_line = tmp_termio.c_line;
for(i=0 ; i < NCC ; i++)
tty->termios.c_cc[i] = tmp_termio.c_cc[i];
- if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
- change_speed(channel-64);
+ change_speed(tty);
return 0;
}
int pgrp;
int dev;
- if (MAJOR(file->f_rdev) != 4) {
- printk("tty_ioctl: tty pseudo-major != 4\n");
- return -EINVAL;
- }
- dev = MINOR(file->f_rdev);
+ if (MAJOR(inode->i_rdev) == 5) {
+ dev = current->tty;
+ if (dev<0)
+ return -EINVAL;
+ } else
+ dev = MINOR(inode->i_rdev);
tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
if (IS_A_PTY(dev))
case TCGETS:
return get_termios(tty,(struct termios *) arg);
case TCSETSF:
- flush_input(tty);
+ flush(tty->read_q);
+ flush(tty->secondary);
+ if (other_tty)
+ flush(other_tty->write_q);
/* fallthrough */
case TCSETSW:
wait_until_sent(tty);
case TCGETA:
return get_termio(tty,(struct termio *) arg);
case TCSETAF:
- flush_input(tty);
+ flush(tty->read_q);
+ flush(tty->secondary);
+ if (other_tty)
+ flush(other_tty->write_q);
/* fallthrough */
case TCSETAW:
wait_until_sent(tty); /* fallthrough */
case TCSETA:
return set_termio(tty,(struct termio *) arg, dev);
case TCSBRK:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- wait_until_sent(tty);
- if (!arg)
- send_break(dev-64);
+ if (!arg) {
+ wait_until_sent(tty);
+ send_break(tty);
+ }
return 0;
case TCXONC:
switch (arg) {
return 0;
case TCIOFF:
if (STOP_CHAR(tty))
- put_tty_queue(STOP_CHAR(tty),tty->write_q);
+ PUTCH(STOP_CHAR(tty),tty->write_q);
return 0;
case TCION:
if (START_CHAR(tty))
- put_tty_queue(START_CHAR(tty),tty->write_q);
+ PUTCH(START_CHAR(tty),tty->write_q);
return 0;
}
return -EINVAL; /* not implemented */
case TCFLSH:
- if (arg==0)
- flush_input(tty);
- else if (arg==1)
- flush_output(tty);
+ if (arg==0) {
+ flush(tty->read_q);
+ flush(tty->secondary);
+ if (other_tty)
+ flush(other_tty->write_q);
+ } else if (arg==1)
+ flush(tty->write_q);
else if (arg==2) {
- flush_input(tty);
- flush_output(tty);
+ flush(tty->read_q);
+ flush(tty->secondary);
+ flush(tty->write_q);
+ if (other_tty)
+ flush(other_tty->write_q);
} else
return -EINVAL;
return 0;
return 0;
case TIOCINQ:
verify_area((void *) arg,4);
- if (L_CANON(tty) && !tty->secondary->data)
- put_fs_long(0, (unsigned long *) arg);
- else
- put_fs_long(CHARS(tty->secondary),
- (unsigned long *) arg);
+ put_fs_long(CHARS(tty->secondary),
+ (unsigned long *) arg);
return 0;
case TIOCSTI:
return -EINVAL; /* not implemented */
case TIOCGWINSZ:
return get_window_size(tty,(struct winsize *) arg);
case TIOCSWINSZ:
- if (IS_A_PTY_MASTER(dev))
+ if (other_tty)
set_window_size(other_tty,(struct winsize *) arg);
return set_window_size(tty,(struct winsize *) arg);
case TIOCMGET:
default:
return -EINVAL;
}
- case TIOCCONS:
- if (!IS_A_PTY(dev))
- return -EINVAL;
- if (redirect)
- return -EBUSY;
- if (!suser())
- return -EPERM;
- if (IS_A_PTY_MASTER(dev))
- redirect = other_tty;
- else
- redirect = tty;
- return 0;
- case TIOCGSERIAL:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- verify_area((void *) arg,sizeof(struct serial_struct));
- return get_serial_info(dev-64,(struct serial_struct *) arg);
- case TIOCSSERIAL:
- if (!IS_A_SERIAL(dev))
- return -EINVAL;
- return set_serial_info(dev-64,(struct serial_struct *) arg);
default:
return vt_ioctl(tty, dev, cmd, arg);
}
#include <linux/sched.h>
#include <linux/tty.h>
-#include <linux/timer.h>
#include <linux/kernel.h>
#include "vt_kern.h"
* console (vt and kd) routines, as defined by usl svr4 manual
*/
-struct vt_cons vt_cons[NR_CONSOLES];
+struct vt_info vt_info[MAX_CONSOLES];
+extern int NR_CONSOLES;
extern unsigned char kleds;
extern unsigned char kraw;
extern unsigned char ke0;
return 0;
}
-/*
- * all the vt ioctls affect only consoles, so we reject all other ttys.
- * we also have the capability to modify any console, not just the fg_console.
- */
int
vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg)
{
- int console = dev ? dev - 1 : fg_console;
- unsigned char ucval;
-
- if (!IS_A_CONSOLE(dev) || console < 0 || console >= NR_CONSOLES)
- return -EINVAL;
-
switch (cmd) {
case KIOCSOUND:
return kiocsound((unsigned int)arg);
case KDGKBTYPE:
- /*
- * this is naive.
- */
verify_area((void *) arg, sizeof(unsigned char));
put_fs_byte(KB_101, (unsigned char *) arg);
return 0;
case KDENABIO:
case KDDISABIO:
- return sys_ioperm(GPFIRST, GPNUM,
- (cmd == KDENABIO)) ? -ENXIO : 0;
+ return sys_ioperm(GPFIRST, GPNUM, (cmd == KDENABIO)) ? -ENXIO : 0;
case KDSETMODE:
/*
default:
return -EINVAL;
}
- if (vt_cons[console].vt_mode == (unsigned char) arg)
- return 0;
- vt_cons[console].vt_mode = (unsigned char) arg;
- if (console != fg_console)
- return 0;
- if (arg == KD_TEXT)
- unblank_screen();
- else {
- timer_active &= 1<<BLANK_TIMER;
- blank_screen();
- }
+ vt_info[fg_console].mode = arg;
return 0;
case KDGETMODE:
verify_area((void *) arg, sizeof(unsigned long));
- put_fs_long(vt_cons[console].vt_mode, (unsigned long *) arg);
+ put_fs_long(vt_info[fg_console].mode, (unsigned long *) arg);
return 0;
case KDMAPDISP:
case KDSKBMODE:
if (arg == K_RAW) {
- if (console == fg_console) {
- kraw = 1;
- ke0 = 0;
- } else {
- vt_cons[console].vc_kbdraw = 1;
- vt_cons[console].vc_kbde0 = 0;
- }
+ kraw = 1;
+ ke0 = 0;
}
else if (arg == K_XLATE) {
- if (console == fg_console)
- kraw = 0;
- else
- vt_cons[console].vc_kbdraw = 0;
+ kraw = 0;
}
else
return -EINVAL;
- flush_input(tty);
return 0;
case KDGKBMODE:
verify_area((void *) arg, sizeof(unsigned long));
- ucval = (console == fg_console) ? kraw :
- vt_cons[console].vc_kbdraw;
- put_fs_long(ucval ? K_RAW : K_XLATE, (unsigned long *) arg);
+ put_fs_long(kraw ? K_RAW : K_XLATE, (unsigned long *) arg);
return 0;
case KDGETLED:
verify_area((void *) arg, sizeof(unsigned char));
- ucval = (console == fg_console) ? kleds :
- vt_cons[console].vc_kbdleds;
- put_fs_byte((((ucval & 1) ? LED_SCR : 0) |
- ((ucval & 2) ? LED_NUM : 0) |
- ((ucval & 4) ? LED_CAP : 0)),
+ put_fs_byte((((kleds & 1) ? LED_SCR : 0) |
+ ((kleds & 2) ? LED_NUM : 0) |
+ ((kleds & 4) ? LED_CAP : 0)),
(unsigned char *) arg);
return 0;
case KDSETLED:
if (arg & ~7)
return -EINVAL;
- ucval = (((arg & LED_SCR) ? 1 : 0) |
+ kleds = (((arg & LED_SCR) ? 1 : 0) |
((arg & LED_NUM) ? 2 : 0) |
((arg & LED_CAP) ? 4 : 0));
- if (console == fg_console) {
- kleds = ucval;
- set_leds();
- }
- else
- vt_cons[console].vc_kbdleds = ucval;
+ set_leds();
return 0;
default:
return -EINVAL;
}
}
+
+void
+vt_init(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CONSOLES; ++i) {
+ vt_info[i].mode = KD_TEXT;
+ }
+}
#ifndef _VT_KERN_H
#define _VT_KERN_H
-/*
- * this really is an extension of the vc_cons structure in console.c, but
- * with information needed by the vt package
- */
-extern struct vt_cons {
- int vt_mode; /* KD_TEXT, ... */
- unsigned char vc_kbdraw;
- unsigned char vc_kbde0;
- unsigned char vc_kbdleds;
-} vt_cons[NR_CONSOLES];
+extern struct vt_info {
+ int mode; /* KD_TEXT, ... */
+} vt_info[MAX_CONSOLES];
#endif /* _VT_KERN_H */
#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <linux/tty.h>
#include <asm/segment.h>
int sys_close(int fd);
-int send_sig(long sig,struct task_struct * p,int priv)
+inline int send_sig(long sig,struct task_struct * p,int priv)
{
if (!p || (sig < 0) || (sig > 32))
return -EINVAL;
- if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
- (current->euid != p->euid) && (current->uid != p->uid) && !suser())
+ if (!priv && (current->euid!=p->euid) && !suser())
return -EPERM;
if (!sig)
return 0;
/* save the signal number for wait. */
p->exit_code = sig;
- /* we have to make sure the parent process is awake. */
+ /* we have to make sure the parent is awake. */
if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
p->p_pptr->state = TASK_RUNNING;
for (i=1 ; i<NR_TASKS ; i++)
if (task[i] == p) {
task[i] = NULL;
- REMOVE_LINKS(p);
+ /* Update links */
+ if (p->p_osptr)
+ p->p_osptr->p_ysptr = p->p_ysptr;
+ if (p->p_ysptr)
+ p->p_ysptr->p_osptr = p->p_osptr;
+ else
+ p->p_pptr->p_cptr = p->p_osptr;
free_page((long) p);
return;
}
}
#endif /* DEBUG_PROC_TREE */
-/*
- * This checks not only the pgrp, but falls back on the pid if no
- * satisfactory prgp is found. I dunno - gdb doesn't work correctly
- * without this...
- */
int session_of_pgrp(int pgrp)
{
struct task_struct **p;
- int fallback;
- fallback = -1;
- for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
- if (!*p || (*p)->session <= 0)
- continue;
+ for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if ((*p)->pgrp == pgrp)
- return (*p)->session;
- if ((*p)->pid == pgrp)
- fallback = (*p)->session;
- }
- return fallback;
+ return((*p)->session);
+ return -1;
}
int kill_pg(int pgrp, int sig, int priv)
if (sig<0 || sig>32 || pgrp<=0)
return -EINVAL;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
- if (*p && (*p)->pgrp == pgrp) {
+ if ((*p)->pgrp == pgrp) {
if (sig && (err = send_sig(sig,*p,priv)))
retval = err;
else
if (sig<0 || sig>32)
return -EINVAL;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
- if (*p && (*p)->pid == pid)
+ if ((*p)->pid == pid)
return(sig ? send_sig(sig,*p,priv) : 0);
return(-ESRCH);
}
return(kill_pg(current->pgrp,sig,0));
if (pid == -1) {
while (--p > &FIRST_TASK)
- if (*p && (*p)->pid > 1 && *p != current) {
+ if ((*p)->pid > 1 && *p != current) {
++count;
if ((err = send_sig(sig,*p,0)) != -EPERM)
retval = err;
struct task_struct ** p;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
- if (!*p || (*p)->pgrp != pgrp)
+ if ((*p)->pgrp != pgrp)
continue;
if ((*p)->state == TASK_STOPPED)
return(1);
return(0);
}
-static void forget_original_parent(struct task_struct * father)
-{
- struct task_struct ** p;
-
- for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
- if (*p && (*p)->p_opptr == father)
- if (task[1])
- (*p)->p_opptr = task[1];
- else
- (*p)->p_opptr = task[0];
-}
-
volatile void do_exit(long code)
{
struct task_struct *p;
int i;
-fake_volatile:
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i])
sys_close(i);
- forget_original_parent(current);
iput(current->pwd);
current->pwd = NULL;
iput(current->root);
current->root = NULL;
iput(current->executable);
current->executable = NULL;
- for (i=0; i < current->numlibraries; i++) {
+ for (i=0; i<current->numlibraries; i++) {
iput(current->libraries[i].library);
current->libraries[i].library = NULL;
}
* A. Make init inherit all the child processes
* B. Check to see if any process groups have become orphaned
* as a result of our exiting, and if they have any stopped
- * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
+ * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
while (p = current->p_cptr) {
current->p_cptr = p->p_osptr;
p->p_ysptr = NULL;
- p->flags &= ~PF_PTRACED;
- if (task[1])
- p->p_pptr = task[1];
- else
- p->p_pptr = task[0];
- p->p_osptr = p->p_pptr->p_cptr;
- p->p_osptr->p_ysptr = p;
- p->p_pptr->p_cptr = p;
+ p->flags &= ~PF_PTRACED;
+ p->p_pptr = task[1];
+ p->p_osptr = task[1]->p_cptr;
+ task[1]->p_cptr->p_ysptr = p;
+ task[1]->p_cptr = p;
if (p->state == TASK_ZOMBIE)
- send_sig(SIGCHLD,p->p_pptr,1);
+ task[1]->signal |= (1<<(SIGCHLD-1));
/*
* process group orphan check
* Case ii: Our child is in a different pgrp
tty->session = 0;
}
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
- if (*p && (*p)->session == current->session)
+ if ((*p)->session == current->session)
(*p)->tty = -1;
}
if (last_task_used_math == current)
audit_ptree();
#endif
schedule();
-/*
- * In order to get rid of the "volatile function does return" message
- * I did this little loop that confuses gcc to think do_exit really
- * is volatile. In fact it's schedule() that is volatile in some
- * circumstances: when current->state = ZOMBIE, schedule() never
- * returns.
- *
- * In fact the natural way to do all this is to have the label and the
- * goto right after each other, but I put the fake_volatile label at
- * the start of the function just in case something /really/ bad
- * happens, and the schedule returns. This way we can try again. I'm
- * not paranoid: it's just that everybody is out to get me.
- */
- goto fake_volatile;
}
int sys_exit(int error_code)
if (stat_addr)
verify_area(stat_addr,4);
repeat:
- current->signal &= ~(1<<(SIGCHLD-1));
flag=0;
- for (p = current->p_cptr ; p ; p = p->p_osptr) {
+ for (p = current->p_cptr ; p ; p = p->p_osptr) {
if (pid>0) {
if (p->pid != pid)
continue;
}
switch (p->state) {
case TASK_STOPPED:
- if (!p->exit_code)
- continue;
- if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
+ if (!(options & WUNTRACED) ||
+ !p->exit_code)
continue;
if (stat_addr)
put_fs_long((p->exit_code << 8) | 0x7f,
flag = p->pid;
if (stat_addr)
put_fs_long(p->exit_code, stat_addr);
- if (p->p_opptr != p->p_pptr) {
- REMOVE_LINKS(p);
- p->p_pptr = p->p_opptr;
- SET_LINKS(p);
- send_sig(SIGCHLD,p->p_pptr,1);
- } else
- release(p);
+ release(p);
#ifdef DEBUG_PROC_TREE
audit_ptree();
#endif
}
return -ECHILD;
}
+
+
#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <asm/segment.h>
#include <asm/system.h>
+extern void write_verify(unsigned long address);
+
long last_pid=0;
void verify_area(void * addr,int size)
static int find_empty_process(void)
{
- int i, task_nr;
+ int i;
repeat:
- if ((++last_pid) & 0xffff0000)
- last_pid=1;
+ if ((++last_pid)<0) last_pid=1;
for(i=0 ; i<NR_TASKS ; i++)
if (task[i] && ((task[i]->pid == last_pid) ||
(task[i]->pgrp == last_pid)))
goto repeat;
-/* Only the super-user can fill the last available slot */
- task_nr = 0;
for(i=1 ; i<NR_TASKS ; i++)
if (!task[i])
- if (task_nr)
- return task_nr;
- else
- task_nr = i;
- if (task_nr && suser())
- return task_nr;
+ return i;
return -EAGAIN;
}
}
task[nr] = p;
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
- p->wait.task = p;
- p->wait.next = NULL;
p->state = TASK_UNINTERRUPTIBLE;
- p->flags &= ~PF_PTRACED;
p->pid = last_pid;
- p->p_pptr = p->p_opptr = current;
+ p->p_pptr = current;
p->p_cptr = NULL;
- SET_LINKS(p);
+ p->p_ysptr = NULL;
+ if (p->p_osptr = current->p_cptr)
+ p->p_osptr->p_ysptr = p;
+ current->p_cptr = p;
p->counter = p->priority;
p->signal = 0;
- p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
- p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
+ p->alarm = 0;
p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
p->tss.eip = eip;
- p->tss.eflags = eflags & 0xffffcfff; /* iopl is always 0 for a new process */
+ p->tss.eflags = eflags;
p->tss.eax = 0;
p->tss.ecx = ecx;
p->tss.edx = edx;
__asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) {
task[nr] = NULL;
- REMOVE_LINKS(p);
+ if (p->p_pptr->p_cptr == p)
+ p->p_pptr->p_cptr = p->p_osptr;
+ if (p->p_osptr)
+ p->p_osptr->p_ysptr = p->p_ysptr;
+ if (p->p_ysptr)
+ p->p_ysptr->p_osptr = p->p_osptr;
free_page((long) p);
return -EAGAIN;
}
}
return 0;
}
-
-unsigned int *stack;
-
-/*
- * sys_iopl has to be used when you want to access the IO ports
- * beyond the 0x3ff range: to get the full 65536 ports bitmapped
- * you'd need 8kB of bitmaps/process, which is a bit excessive.
- *
- * Here we just change the eflags value on the stack: we allow
- * only the super-user to do it. This depends on the stack-layout
- * on system-call entry - see also fork() and the signal handling
- * code.
- */
-int sys_iopl(long ebx,long ecx,long edx,
- long esi, long edi, long ebp, long eax, long ds,
- long es, long fs, long gs, long orig_eax,
- long eip,long cs,long eflags,long esp,long ss)
-{
- unsigned int level = ebx;
-
- if (level > 3)
- return -EINVAL;
- if (!suser())
- return -EPERM;
- *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
- return 0;
-}
+++ /dev/null
-/*
- * linux/kernel/irq.c
- *
- * (C) 1992 Linus Torvalds
- *
- * This file contains the code used by various IRQ handling routines:
- * asking for different IRQ's should be done through these routines
- * instead of just grabbing them. Thus setups with different IRQ numbers
- * shouldn't result in any weird surprises, and installing new handlers
- * should be easier.
- */
-
-/*
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- * The same sigaction struct is used, and with similar semantics (ie there
- * is a SA_INTERRUPT flag etc). Naturally it's not a 1:1 relation, but there
- * are similarities.
- *
- * sa_handler(int irq_NR) is the default function called.
- * sa_mask is 0 if nothing uses this IRQ
- * sa_flags contains various info: SA_INTERRUPT etc
- * sa_restorer is the unused
- */
-
-#include <signal.h>
-#include <errno.h>
-
-#include <sys/ptrace.h>
-
-#include <linux/sched.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-struct sigaction irq_sigaction[16] = {
- { NULL, 0, 0, NULL },
-};
-
-void irq13(void);
-
-/*
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that do all
- * the operations that are needed to keep the AT interrupt-controller
- * happy. They are also written to be fast - and to disable interrupts
- * as little as humanly possible.
- */
-BUILD_IRQ(FIRST,0,0x01)
-BUILD_IRQ(FIRST,1,0x02)
-BUILD_IRQ(FIRST,2,0x04)
-BUILD_IRQ(FIRST,3,0x08)
-BUILD_IRQ(FIRST,4,0x10)
-BUILD_IRQ(FIRST,5,0x20)
-BUILD_IRQ(FIRST,6,0x40)
-BUILD_IRQ(FIRST,7,0x80)
-BUILD_IRQ(SECOND,8,0x01)
-BUILD_IRQ(SECOND,9,0x02)
-BUILD_IRQ(SECOND,10,0x04)
-BUILD_IRQ(SECOND,11,0x08)
-BUILD_IRQ(SECOND,12,0x10)
-BUILD_IRQ(SECOND,13,0x20)
-BUILD_IRQ(SECOND,14,0x40)
-BUILD_IRQ(SECOND,15,0x80)
-
-/*
- * This routine gets called at every IRQ request. Interrupts
- * are enabled, the interrupt has been accnowledged and this
- * particular interrupt is disabled when this is called.
- *
- * The routine has to call the appropriate handler (disabling
- * interrupts if needed first). If no handler exists, we return
- * an error value, telling the low-level IRQ routines not to
- * re-enable this IRQ line.
- *
- * Note similarities on a very low level between this and the
- * do_signal() function. Naturally this is simplified, but they
- * get similar arguments, use them similarly etc... Note that
- * unlike the signal-handlers, the IRQ-handlers don't get the IRQ
- * (signal) number as argument, but the cpl value at the time of
- * the interrupt.
- */
-int do_IRQ(int irq, struct pt_regs * regs)
-{
- struct sigaction * sa = irq + irq_sigaction;
- void (*handler)(int);
- unsigned int esp;
-
- if (!(handler = sa->sa_handler))
- return -1; /* the irq isn't re-enabled */
- __asm__ __volatile__("movl %%esp,%0":"=r" (esp));
- if (esp < 200+(unsigned long)(current+1)) {
- printk("Stack overflow on IRQ%d: shutting down\n",irq);
- return -1;
- }
- if (sa->sa_flags & SA_INTERRUPT)
- cli();
- handler(regs->cs & 3);
- sti();
- return 0; /* re-enable the irq when returning */
-}
-
-int irqaction(unsigned int irq, struct sigaction * new)
-{
- struct sigaction * sa;
- unsigned long flags;
-
- if (irq > 15)
- return -EINVAL;
- if (irq == 2)
- irq = 9;
- sa = irq + irq_sigaction;
- if (sa->sa_mask)
- return -EBUSY;
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- *sa = *new;
- sa->sa_mask = 1;
- if (irq < 8)
- outb(inb_p(0x21) & ~(1<<irq),0x21);
- else
- outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
- return 0;
-}
-
-int request_irq(unsigned int irq, void (*handler)(int))
-{
- struct sigaction sa;
-
- sa.sa_handler = handler;
- sa.sa_flags = 0;
- sa.sa_mask = 0;
- sa.sa_restorer = NULL;
- return irqaction(irq,&sa);
-}
-
-void free_irq(unsigned int irq)
-{
- struct sigaction * sa = irq + irq_sigaction;
- unsigned long flags;
-
- if (irq > 15) {
- printk("Trying to free IRQ%d\n",irq);
- return;
- }
- if (!sa->sa_mask) {
- printk("Trying to free free IRQ%d\n",irq);
- return;
- }
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- if (irq < 8)
- outb(inb_p(0x21) | (1<<irq),0x21);
- else
- outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
- sa->sa_handler = NULL;
- sa->sa_flags = 0;
- sa->sa_mask = 0;
- sa->sa_restorer = NULL;
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
-}
-
-extern void math_error(void);
-
-static void math_error_irq(int cpl)
-{
- outb(0,0xF0);
- math_error();
-}
-
-void init_IRQ(void)
-{
- set_trap_gate(0x20,IRQ0_interrupt);
- set_trap_gate(0x21,IRQ1_interrupt);
- set_trap_gate(0x22,IRQ2_interrupt);
- set_trap_gate(0x23,IRQ3_interrupt);
- set_trap_gate(0x24,IRQ4_interrupt);
- set_trap_gate(0x25,IRQ5_interrupt);
- set_trap_gate(0x26,IRQ6_interrupt);
- set_trap_gate(0x27,IRQ7_interrupt);
- set_trap_gate(0x28,IRQ8_interrupt);
- set_trap_gate(0x29,IRQ9_interrupt);
- set_trap_gate(0x2a,IRQ10_interrupt);
- set_trap_gate(0x2b,IRQ11_interrupt);
- set_trap_gate(0x2c,IRQ12_interrupt);
- set_trap_gate(0x2d,IRQ13_interrupt);
- set_trap_gate(0x2e,IRQ14_interrupt);
- set_trap_gate(0x2f,IRQ15_interrupt);
- if (request_irq(13,math_error_irq))
- printk("Unable to get IRQ13 for math-error handler\n");
-}
+++ /dev/null
-/*
- * linux/kernel/itimer.c
- *
- * (C) 1992 Darren Senn
- */
-
-/* These are all the functions necessary to implement itimers */
-
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <asm/segment.h>
-
-#include <signal.h>
-#include <sys/time.h>
-#include <errno.h>
-
-static unsigned long tvtojiffies(struct timeval *value)
-{
- return((unsigned long )value->tv_sec * HZ +
- (unsigned long )(value->tv_usec + (1000000 / HZ - 1)) /
- (1000000 / HZ));
-}
-
-static void jiffiestotv(unsigned long jiffies, struct timeval *value)
-{
- value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
- value->tv_sec = jiffies / HZ;
- return;
-}
-
-int _getitimer(int which, struct itimerval *value)
-{
- register unsigned long val, interval;
-
- switch (which) {
- case ITIMER_REAL:
- val = current->it_real_value;
- interval = current->it_real_incr;
- break;
- case ITIMER_VIRTUAL:
- val = current->it_virt_value;
- interval = current->it_virt_incr;
- break;
- case ITIMER_PROF:
- val = current->it_prof_value;
- interval = current->it_prof_incr;
- break;
- default:
- return(-EINVAL);
- }
- jiffiestotv(val, &value->it_value);
- jiffiestotv(interval, &value->it_interval);
- return(0);
-}
-
-int sys_getitimer(int which, struct itimerval *value)
-{
- struct itimerval get_buffer;
- int k;
-
- if (!value)
- return -EFAULT;
- k = _getitimer(which, &get_buffer);
- if (k < 0)
- return k;
- verify_area(value, sizeof(struct itimerval));
- memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
- return 0;
-}
-
-int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
-{
- register unsigned long i, j;
- int k;
-
- i = tvtojiffies(&value->it_interval);
- j = tvtojiffies(&value->it_value);
- if (ovalue && (k = _getitimer(which, ovalue)) < 0)
- return k;
- switch (which) {
- case ITIMER_REAL:
- current->it_real_value = j;
- current->it_real_incr = i;
- break;
- case ITIMER_VIRTUAL:
- current->it_virt_value = j;
- current->it_virt_incr = i;
- break;
- case ITIMER_PROF:
- current->it_prof_value = j;
- current->it_prof_incr = i;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
-{
- struct itimerval set_buffer, get_buffer;
- int k;
-
- if (!value)
- memset((char *) &set_buffer, 0, sizeof(set_buffer));
- else
- memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
- k = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
- if (k < 0 || !ovalue)
- return k;
- verify_area(ovalue, sizeof(struct itimerval));
- memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
- return 0;
-}
# unless it's something special (ie not a .c file).
#
+AR =ar
+AS =as
+LD =ld
+LDFLAGS =-s -x
+CC =gcc -nostdinc -I../../include
+CPP =cpp -nostdinc -I../../include
+
.c.s:
- $(CC) $(CFLAGS) $(MATH_EMULATION) -S $<
+ $(CC) $(CFLAGS) $(MATH_EMULATION) \
+ -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) $(MATH_EMULATION) -c $<
+ $(CC) $(CFLAGS) $(MATH_EMULATION) \
+ -c -o $*.o $<
OBJS = emulate.o error.o convert.o ea.o get_put.o \
- add.o mul.o div.o compare.o sqrt.o
+ add.o mul.o div.o compare.o
math.a: $(OBJS)
$(AR) rcs math.a $(OBJS)
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+ $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
-add.o : add.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-compare.o : compare.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-convert.o : convert.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-div.o : div.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-ea.o : ea.c /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/math_emu.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h
-emulate.o : emulate.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h
-error.o : error.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h
-get_put.o : get_put.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h
-mul.o : mul.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-sqrt.o : sqrt.c /usr/src/linux/include/linux/math_emu.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
+add.s add.o : add.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h
+compare.s compare.o : compare.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h
+convert.s convert.o : convert.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h
+div.s div.o : div.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h
+ea.s ea.o : ea.c ../../include/stddef.h ../../include/linux/math_emu.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h ../../include/asm/segment.h
+emulate.s emulate.o : emulate.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h
+error.s error.o : error.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/sched.h \
+ ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h
+get_put.s get_put.o : get_put.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/math_emu.h \
+ ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+ ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+ ../../include/asm/segment.h
+mul.s mul.o : mul.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+ ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+ ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+ ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ ../../include/sys/resource.h
char * ea(struct info * info, unsigned short code)
{
unsigned char mod,rm;
- long * tmp;
+ long * tmp = &EAX;
int offset = 0;
mod = (code >> 6) & 3;
EIP += 4;
break;
case 3:
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
}
I387.foo = offset;
I387.fos = 0x17;
return;
case 0x1d1: case 0x1d2: case 0x1d3:
case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0x1e0:
ST(0).exponent ^= 0x8000;
return;
ST(0).exponent &= 0x7fff;
return;
case 0x1e2: case 0x1e3:
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0x1e4:
ftst(PST(0));
return;
case 0x1e5:
printk("fxam not implemented\n\r");
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0x1e6: case 0x1e7:
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0x1e8:
fpush();
ST(0) = CONST1;
ST(0) = CONSTZ;
return;
case 0x1ef:
- math_abort(info,SIGILL);
- case 0x1fa:
- fsqrt(PST(0),&tmp);
- real_to_real(&tmp,&ST(0));
- return;
+ math_abort(info,1<<(SIGILL-1));
case 0x1f0: case 0x1f1: case 0x1f2: case 0x1f3:
case 0x1f4: case 0x1f5: case 0x1f6: case 0x1f7:
- case 0x1f8: case 0x1f9: case 0x1fb: case 0x1fd:
- case 0x1fe: case 0x1ff:
+ case 0x1f8: case 0x1f9: case 0x1fa: case 0x1fb:
+ case 0x1fd: case 0x1fe: case 0x1ff:
printk("%04x fxxx not implemented\n\r",code + 0xd800);
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0x1fc:
frndint(PST(0),&tmp);
real_to_real(&tmp,&ST(0));
return;
case 0xb8:
printk("ffree not implemented\n\r");
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
case 0xb9:
fxchg(&ST(0),&ST(code & 7));
return;
return;
case 0xf8:
printk("ffree not implemented\n\r");
- math_abort(info,SIGILL);
+ math_abort(info,1<<(SIGILL-1));
fpop();
return;
case 0xf9:
return;
}
printk("Unknown math-insns: %04x:%08x %04x\n\r",CS,EIP,code);
- math_abort(info,SIGFPE);
+ math_abort(info,1<<(SIGFPE-1));
}
void math_emulate(long ___false)
void __math_abort(struct info * info, unsigned int signal)
{
EIP = ORIG_EIP;
- send_sig(signal,current,1);
+ current->signal |= signal;
__asm__("movl %0,%%esp ; ret"::"g" (((long) info)-4));
}
void math_emulate(long ___false)
{
- send_sig(SIGFPE,current,1);
+ current->signal |= 1<<(SIGFPE-1);
schedule();
}
void math_error(void)
{
if (last_task_used_math)
- send_sig(SIGFPE,last_task_used_math,1);
+ last_task_used_math->signal |= 1<<(SIGFPE-1);
__asm__("fnclex");
}
+++ /dev/null
-/*
- * linux/kernel/math/sqrt.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-/*
- * simple and stupid temporary real fsqrt() routine
- *
- * There are probably better ways to do this, but this should work ok.
- */
-
-#include <linux/math_emu.h>
-#include <linux/sched.h>
-
-static void shift_right(int * c)
-{
- __asm__("shrl $1,12(%0) ; rcrl $1,8(%0) ; rcrl $1,4(%0) ; rcrl $1,(%0)"
- ::"r" ((long) c));
-}
-
-static int sqr64(unsigned long * a, unsigned long * b)
-{
- unsigned long tmp[4];
-
- __asm__("movl (%0),%%eax ; mull %%eax\n\t"
- "movl %%eax,(%1) ; movl %%edx,4(%1)\n\t"
- "movl 4(%0),%%eax ; mull %%eax\n\t"
- "movl %%eax,8(%1) ; movl %%edx,12(%1)\n\t"
- "movl (%0),%%eax ; mull 4(%0)\n\t"
- "addl %%eax,%%eax ; adcl %%edx,%%edx\n\t"
- "adcl $0,12(%1) ; addl %%eax,4(%1)\n\t"
- "adcl %%edx,8(%1) ; adcl $0,12(%1)"
- ::"b" ((long) a),"c" ((long) tmp)
- :"ax","bx","cx","dx");
- if (tmp[3] > b[3] ||
- (tmp[3] == b[3] && (tmp[2] > b[2] ||
- (tmp[2] == b[2] && (tmp[1] > b[1] ||
- (tmp[1] == b[1] && tmp[0] > b[0]))))))
- return 0;
- return 1;
-}
-
-void fsqrt(const temp_real * s, temp_real * d)
-{
- unsigned long src[4];
- unsigned long res[2];
- int exponent;
- unsigned long mask, *c;
- int i;
-
- exponent = s->exponent;
- src[0] = src[1] = 0;
- src[2] = s->a;
- src[3] = s->b;
- d->exponent = 0;
- d->a = d->b = 0;
- if (!exponent) /* fsqrt(0.0) = 0.0 */
- return;
- if (!src[2] && !src[3])
- return;
- if (exponent & 0x8000) {
- send_sig(SIGFPE,current,0);
- return;
- }
- if (exponent & 1) {
- shift_right(src);
- exponent++;
- }
- exponent >>= 1;
- exponent += 0x1fff;
- c = res + 2;
- mask = 0;
- for (i = 64 ; i > 0 ; i--) {
- if (!(mask >>= 1)) {
- c--;
- mask = 0x80000000;
- }
- res[0] = d->a; res[1] = d->b;
- *c |= mask;
- if (sqr64(res,src)) {
- d->a = res[0];
- d->b = res[1];
- }
- }
- if (!d->a && !d->b)
- return;
- while (!(d->b & 0x80000000)) {
- __asm__("addl %%eax,%%eax ; adcl %%edx,%%edx"
- :"=a" (d->a),"=d" (d->b)
- :"0" (d->a),"1" (d->b));
- exponent--;
- }
- d->exponent = exponent;
-}
* (C) 1991 Linus Torvalds
*/
+/*
+ * When in kernel-mode, we cannot use printf, as fs is liable to
+ * point to 'interesting' things. Make a printf with fs-saving, and
+ * all is well.
+ */
#include <stdarg.h>
#include <stddef.h>
-#include <errno.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/sched.h>
#include <linux/kernel.h>
static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args);
-extern void console_print(const char *);
-
-static unsigned long log_page = 0;
-static unsigned long log_start = 0;
-static unsigned long log_size = 0;
-static struct wait_queue * log_wait = NULL;
-
-int sys_syslog(int type, char * buf, int len)
-{
- unsigned long i;
- char c;
-
- if (!suser())
- return -EPERM;
- switch (type) {
- case 0:
- i = log_page;
- log_page = 0;
- free_page(i);
- wake_up(&log_wait);
- return 0;
- case 1:
- i = get_free_page();
- if (log_page) {
- free_page(i);
- return 0;
- } else if (log_page = i) {
- log_start = log_size = 0;
- return 0;
- }
- return -ENOMEM;
- case 2:
- if (!buf || len < 0)
- return -EINVAL;
- if (!len)
- return 0;
- verify_area(buf,len);
- while (!log_size) {
- if (!log_page)
- return -EIO;
- if (current->signal & ~current->blocked)
- return -ERESTARTSYS;
- cli();
- if (!log_size)
- interruptible_sleep_on(&log_wait);
- sti();
- }
- i = 0;
- while (log_size && len) {
- c = *((char *) log_page+log_start);
- log_start++;
- log_size--;
- log_start &= 4095;
- put_fs_byte(c,buf);
- buf++;
- i++;
- }
- return i;
- }
- return -EINVAL;
-}
-
int printk(const char *fmt, ...)
{
va_list args;
- int i,j;
- char * p;
+ int i;
va_start(args, fmt);
i=vsprintf(buf,fmt,args);
va_end(args);
- for (j = 0; j < i && log_page ; j++) {
- p = (char *) log_page + (4095 & (log_start+log_size));
- *p = buf[j];
- if (log_size < 4096)
- log_size++;
- else
- log_start++;
- }
- if (log_page)
- wake_up(&log_wait);
console_print(buf);
return i;
}
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
-
+#include <errno.h>
#include <asm/segment.h>
#include <asm/system.h>
-
-#include <errno.h>
#include <sys/ptrace.h>
/*
*/
#define MAGICNUMBER 68
-void do_no_page(unsigned long, unsigned long, struct task_struct *, unsigned long);
+void do_no_page(unsigned long, unsigned long, struct task_struct *);
void write_verify(unsigned long);
/* change a pid into a task struct. */
-static inline struct task_struct * get_task(int pid)
+static inline int get_task(int pid)
{
int i;
- for (i = 1; i < NR_TASKS; i++) {
+ for (i = 0; i < NR_TASKS; i++) {
if (task[i] != NULL && (task[i]->pid == pid))
- return task[i];
+ return i;
}
- return NULL;
+ return -1;
}
/*
page = *((unsigned long *) page);
}
if (!(page & PAGE_PRESENT)) {
- do_no_page(0,addr,tsk,0);
+ do_no_page(0,addr,tsk);
goto repeat;
}
page &= 0xfffff000;
page = *((unsigned long *) page);
}
if (!(page & PAGE_PRESENT)) {
- do_no_page(0,addr,tsk,0);
+ do_no_page(0,addr,tsk);
goto repeat;
}
if (!(page & PAGE_RW)) {
int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
+ int childno;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->flags & PF_PTRACED)
- return -EPERM;
+ if (request == 0) {
/* set the ptrace bit in the proccess flags. */
current->flags |= PF_PTRACED;
return 0;
}
- if (!(child = get_task(pid)))
- return -ESRCH;
- if (request == PTRACE_ATTACH) {
- long tmp;
-
- if (child == current)
- return -EPERM;
- if ((!child->dumpable || (current->uid != child->euid) ||
- (current->gid != child->egid)) && !suser())
- return -EPERM;
- /* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
- return -EPERM;
- child->flags |= PF_PTRACED;
- if (child->p_pptr != current) {
- REMOVE_LINKS(child);
- child->p_pptr = current;
- SET_LINKS(child);
- }
- tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
- put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- if (child->state == TASK_INTERRUPTIBLE ||
- child->state == TASK_STOPPED)
- child->state = TASK_RUNNING;
- child->signal = 0;
- return 0;
- }
- if (!(child->flags & PF_PTRACED) || child->state != TASK_STOPPED)
+
+ childno = get_task(pid);
+
+ if (childno < 0)
return -ESRCH;
- if (child->p_pptr != current)
+ else
+ child = task[childno];
+
+ if (child->p_pptr != current || !(child->flags & PF_PTRACED) ||
+ child->state != TASK_STOPPED)
return -ESRCH;
switch (request) {
/* when I and D space are seperate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
+ case 1: /* read word at location addr. */
+ case 2: {
int tmp,res;
- res = read_long(child, addr, &tmp);
+ res = read_long(task[childno], addr, &tmp);
if (res < 0)
return res;
verify_area((void *) data, 4);
}
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
+ case 3: {
int tmp;
addr = addr >> 2; /* temporary hack. */
if (addr < 0 || addr >= 17)
}
/* when I and D space are seperate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- return write_long(child,addr,data);
+ case 4: /* write the word at location addr. */
+ case 5:
+ return write_long(task[childno],addr,data);
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ case 6: /* write the word at location addr in the USER area */
addr = addr >> 2; /* temproary hack. */
if (addr < 0 || addr >= 17)
return -EIO;
return -EIO;
return 0;
- case PTRACE_CONT: { /* restart after signal. */
+ case 7: { /* restart after signal. */
long tmp;
- child->signal = 0;
+ child->signal=0;
if (data > 0 && data <= NSIG)
child->signal = 1<<(data-1);
- child->state = TASK_RUNNING;
+ child->state = 0;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
* perhaps it should be put in the status that it want's to
* exit.
*/
- case PTRACE_KILL: {
+ case 8: {
long tmp;
- child->state = TASK_RUNNING;
+ child->state = 0;
child->signal = 1 << (SIGKILL-1);
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
return 0;
}
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ case 9: { /* set the trap flag. */
long tmp;
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- child->state = TASK_RUNNING;
+ child->state = 0;
child->signal = 0;
- if (data > 0 && data <= NSIG)
+ if (data > 0 && data <NSIG)
child->signal= 1<<(data-1);
/* give it a chance to run. */
return 0;
}
- case PTRACE_DETACH: { /* detach a process that was attached. */
- long tmp;
-
- child->flags &= ~PF_PTRACED;
- child->signal=0;
- child->state = 0;
- REMOVE_LINKS(child);
- child->p_pptr = child->p_opptr;
- SET_LINKS(child);
- /* make sure the single step bit is not set. */
- tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- return 0;
- }
-
default:
return -EIO;
}
* call functions (type getpid(), which just extracts a field from
* current-task
*/
-
-#define TIMER_IRQ 0
-
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
-#include <sys/time.h>
#include <signal.h>
#include <errno.h>
-int need_resched = 0;
-
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-static 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);
- printk("%d: pid=%d, state=%d, father=%d, child=%d, ",(p == current)?-nr:nr,p->pid,
+ printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
i=0;
while (i<j && !((char *)(p+1))[i])
char stack[PAGE_SIZE];
};
-static union task_union init_task = {INIT_TASK, };
+static union task_union init_task = {INIT_TASK,};
unsigned long volatile jiffies=0;
unsigned long startup_time=0;
/* check alarm, wake up any interruptible tasks that have got a signal */
- need_resched = 0;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) {
if ((*p)->timeout && (*p)->timeout < jiffies)
if ((*p)->state == TASK_INTERRUPTIBLE) {
(*p)->timeout = 0;
- wake_one_task(*p);
+ (*p)->state = TASK_RUNNING;
}
+ if ((*p)->alarm && (*p)->alarm < jiffies) {
+ (*p)->signal |= (1<<(SIGALRM-1));
+ (*p)->alarm = 0;
+ }
if (((*p)->signal & ~(*p)->blocked) &&
- (*p)->state==TASK_INTERRUPTIBLE)
- wake_one_task(*p);
+ (*p)->state==TASK_INTERRUPTIBLE)
+ (*p)->state=TASK_RUNNING;
}
/* this is the scheduler proper: */
return -EINTR;
}
-void wake_one_task(struct task_struct * p)
-{
- p->state = TASK_RUNNING;
- if (p->counter > current->counter)
- need_resched = 1;
-}
-
-/*
- * wake_up doesn't wake up stopped processes - they have to be awakened
- * with signals or similar.
- */
-void wake_up(struct wait_queue **q)
+void wake_up(struct task_struct **p)
{
- struct wait_queue *tmp, *next;
- struct task_struct * p;
- unsigned long flags;
-
- if (!q || !(next = *q))
- return;
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
- do {
- tmp = next;
- next = tmp->next;
- if (p = tmp->task) {
- if (p->state == TASK_ZOMBIE)
+ struct task_struct * wakeup_ptr, * tmp;
+
+ if (p && *p) {
+ wakeup_ptr = *p;
+ *p = NULL;
+ while (wakeup_ptr && wakeup_ptr != task[0]) {
+ if (wakeup_ptr->state == TASK_STOPPED)
+ printk("wake_up: TASK_STOPPED\n");
+ else if (wakeup_ptr->state == TASK_ZOMBIE)
printk("wake_up: TASK_ZOMBIE\n");
- else if (p->state != TASK_STOPPED) {
- p->state = TASK_RUNNING;
- if (p->counter > current->counter)
- need_resched = 1;
- }
+ else
+ wakeup_ptr->state = TASK_RUNNING;
+ tmp = wakeup_ptr->next_wait;
+ wakeup_ptr->next_wait = task[0];
+ wakeup_ptr = tmp;
}
- tmp->next = NULL;
- } while (next && next != *q);
- __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
+ }
}
-static inline void __sleep_on(struct wait_queue **p, int state)
+static inline void __sleep_on(struct task_struct **p, int state)
{
- unsigned long flags;
+ unsigned int flags;
if (!p)
return;
if (current == task[0])
panic("task[0] trying to sleep");
- if (current->wait.next)
- printk("__sleep_on: wait->next exists\n");
- __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
+ __asm__("pushfl ; popl %0":"=r" (flags));
+ current->next_wait = *p;
+ task[0]->next_wait = NULL;
+ *p = current;
current->state = state;
- add_wait_queue(p,¤t->wait);
sti();
schedule();
- remove_wait_queue(p,¤t->wait);
+ if (current->next_wait != task[0])
+ wake_up(p);
+ current->next_wait = NULL;
__asm__("pushl %0 ; popfl"::"r" (flags));
}
-void interruptible_sleep_on(struct wait_queue **p)
+void interruptible_sleep_on(struct task_struct **p)
{
__sleep_on(p,TASK_INTERRUPTIBLE);
}
-void sleep_on(struct wait_queue **p)
+void sleep_on(struct task_struct **p)
{
__sleep_on(p,TASK_UNINTERRUPTIBLE);
}
* proper. They are here because the floppy needs a timer, and this
* was the easiest way of doing it.
*/
-static struct wait_queue * 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 moff_timer[4]={0,0,0,0};
unsigned char current_DOR = 0x0C;
sti();
}
-#define FSHIFT 11
-#define FSCALE (1<<FSHIFT)
-/*
- * Constants for averages over 1, 5, and 15 minutes
- * when sampling at 5 second intervals.
- */
-static unsigned long cexp[3] = {
- 1884, /* 0.9200444146293232 * FSCALE, exp(-1/12) */
- 2014, /* 0.9834714538216174 * FSCALE, exp(-1/60) */
- 2037, /* 0.9944598480048967 * FSCALE, exp(-1/180) */
-};
-unsigned long averunnable[3] = { 0, }; /* fixed point numbers */
-
-void update_avg(void)
-{
- int i, n=0;
- struct task_struct **p;
-
- for(p = &LAST_TASK; p > &FIRST_TASK; --p)
- if (*p && ((*p)->state == TASK_RUNNING ||
- (*p)->state == TASK_UNINTERRUPTIBLE))
- ++n;
-
- for (i = 0; i < 3; ++i)
- averunnable[i] = (cexp[i] * averunnable[i] +
- n * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
-}
-
unsigned long timer_active = 0;
struct timer_struct timer_table[32];
-static void do_timer(int cpl)
+void do_timer(long cpl)
{
unsigned long mask;
struct timer_struct *tp = timer_table+0;
- struct task_struct ** task_p;
- static int avg_cnt = 0;
- jiffies++;
- if (!cpl)
- current->stime++;
- else
- current->utime++;
- if (--avg_cnt < 0) {
- avg_cnt = 500;
- update_avg();
- }
- if ((--current->counter)<=0) {
- current->counter=0;
- need_resched = 1;
- }
- /* Update ITIMER_REAL for every task */
- for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
- if (*task_p && (*task_p)->it_real_value
- && !(--(*task_p)->it_real_value)) {
- send_sig(SIGALRM,*task_p,1);
- (*task_p)->it_real_value = (*task_p)->it_real_incr;
- need_resched = 1;
- }
- /* Update ITIMER_PROF for the current task */
- if (current->it_prof_value && !(--current->it_prof_value)) {
- current->it_prof_value = current->it_prof_incr;
- send_sig(SIGPROF,current,1);
- }
- /* Update ITIMER_VIRT for current task if not in a system call */
- if (current->it_virt_value && !(--current->it_virt_value)) {
- current->it_virt_value = current->it_virt_incr;
- send_sig(SIGVTALRM,current,1);
- }
for (mask = 1 ; mask ; tp++,mask += mask) {
if (mask > timer_active)
break;
continue;
timer_active &= ~mask;
tp->fn();
- sti();
}
+
+ if (cpl)
+ current->utime++;
+ else
+ current->stime++;
+
if (next_timer) {
next_timer->jiffies--;
while (next_timer && next_timer->jiffies <= 0) {
}
if (current_DOR & 0xf0)
do_floppy_timer();
+ if ((--current->counter)>0) return;
+ current->counter=0;
+ if (!cpl) return;
+ schedule();
}
int sys_alarm(long seconds)
{
- extern int _setitimer(int, struct itimerval *, struct itimerval *);
- struct itimerval new, old;
-
- new.it_interval.tv_sec = new.it_interval.tv_usec = 0;
- new.it_value.tv_sec = seconds;
- new.it_value.tv_usec = 0;
- _setitimer(ITIMER_REAL, &new, &old);
- return(old.it_value.tv_sec + (old.it_value.tv_usec / 1000000));
+ int old = current->alarm;
+
+ if (old)
+ old = (old - jiffies) / HZ;
+ current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
+ return (old);
}
int sys_getpid(void)
{
if (increment < 0 && !suser())
return -EPERM;
- if (increment >= current->priority)
+ if (increment > current->priority)
increment = current->priority-1;
current->priority -= increment;
return 0;
panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
- set_system_gate(0x80,&system_call);
p = gdt+2+FIRST_TSS_ENTRY;
for(i=1 ; i<NR_TASKS ; i++) {
task[i] = NULL;
outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- request_irq(TIMER_IRQ,do_timer);
+ set_intr_gate(0x20,&timer_interrupt);
+ outb(inb_p(0x21)&~0x01,0x21);
+ set_system_gate(0x80,&system_call);
}
#include <signal.h>
#include <sys/wait.h>
-#include <sys/ptrace.h>
#include <errno.h>
-
-extern int core_dump(long signr,struct pt_regs * regs);
-
+
+int send_sig (int, struct task_struct *, int);
+
int sys_sgetmask()
{
return current->blocked;
return -EINVAL;
tmp.sa_handler = (void (*)(int)) handler;
tmp.sa_mask = 0;
- tmp.sa_flags = SA_ONESHOT | SA_NOMASK | SA_INTERRUPT;
+ tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer = (void (*)(void)) restorer;
handler = (long) current->sigaction[signum-1].sa_handler;
current->sigaction[signum-1] = tmp;
return 0;
}
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently not implemented.
+ */
+int core_dump(long signr)
+{
+ return(0); /* We didn't do a dump */
+}
+
extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
-int do_signal(long signr,struct pt_regs * regs)
+int do_signal(long signr,long ebx, long ecx, long edx,
+ long esi, long edi, long ebp, long eax,
+ long ds, long es, long fs, long gs,
+ long orig_eax,
+ long eip, long cs, long eflags,
+ unsigned long * esp, long ss)
{
unsigned long sa_handler;
- long old_eip = regs->eip;
+ long old_eip=eip;
struct sigaction * sa = current->sigaction + signr - 1;
int longs;
+
unsigned long * tmp_esp;
#ifdef notdef
printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
- current->pid, signr, regs->eax, regs->orig_eax,
+ current->pid, signr, eax, orig_eax,
sa->sa_flags & SA_INTERRUPT);
#endif
- sa_handler = (unsigned long) sa->sa_handler;
- if ((regs->orig_eax != -1) &&
- ((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
- if ((sa_handler > 1) && (regs->eax == -ERESTARTSYS) &&
- (sa->sa_flags & SA_INTERRUPT))
- regs->eax = -EINTR;
+ if ((orig_eax != -1) &&
+ ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {
+ if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
+ signr < SIGCONT || signr > SIGTTOU))
+ *(&eax) = -EINTR;
else {
- regs->eax = regs->orig_eax;
- regs->eip = old_eip -= 2;
+ *(&eax) = orig_eax;
+ *(&eip) = old_eip -= 2;
}
}
+ sa_handler = (unsigned long) sa->sa_handler;
if (sa_handler==1) {
/* check for SIGCHLD: it's special */
if (signr == SIGCHLD)
current->exit_code = signr;
if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- send_sig(SIGCHLD, current->p_pptr, 1);
+ send_sig(SIGCHLD, current->p_pptr, 1);
+/* current->p_pptr->signal |= (1<<(SIGCHLD-1));*/
+
return(1); /* Reschedule another event */
case SIGQUIT:
case SIGIOT:
case SIGFPE:
case SIGSEGV:
- if (core_dump(signr,regs))
+ if (core_dump(signr))
do_exit(signr|0x80);
/* fall through */
default:
*/
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- regs->eip = sa_handler;
- longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
- regs->esp -= longs;
- tmp_esp = (unsigned long *) regs->esp;
- verify_area(tmp_esp,longs);
+ *(&eip) = sa_handler;
+ longs = (sa->sa_flags & SA_NOMASK)?7:8;
+ *(&esp) -= longs;
+ verify_area(esp,longs*4);
+ tmp_esp=esp;
put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++);
- put_fs_long(regs->eax,tmp_esp++);
- put_fs_long(regs->ecx,tmp_esp++);
- put_fs_long(regs->edx,tmp_esp++);
- put_fs_long(regs->eflags,tmp_esp++);
+ put_fs_long(eax,tmp_esp++);
+ put_fs_long(ecx,tmp_esp++);
+ put_fs_long(edx,tmp_esp++);
+ put_fs_long(eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask;
/* force a supervisor-mode page-in of the signal handler to reduce races */
#include <linux/config.h>
#include <asm/segment.h>
#include <sys/times.h>
-#include <linux/utsname.h>
+#include <sys/utsname.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <linux/string.h>
extern int session_of_pgrp(int pgrp);
-#define PZERO 15
-
-static int proc_sel(struct task_struct *p, int which, int who)
-{
- switch (which) {
- case PRIO_PROCESS:
- if (!who && p == current)
- return 1;
- return(p->pid == who);
- case PRIO_PGRP:
- if (!who)
- who = current->pgrp;
- return(p->pgrp == who);
- case PRIO_USER:
- if (!who)
- who = current->uid;
- return(p->uid == who);
- }
- return 0;
-}
-
-int sys_setpriority(int which, int who, int niceval)
+int sys_getpriority()
{
- struct task_struct **p;
- int error = ESRCH;
- int priority;
-
- if (which > 2 || which < 0)
- return -EINVAL;
-
- if ((priority = PZERO - niceval) <= 0)
- priority = 1;
-
- for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
- if (!*p || !proc_sel(*p, which, who))
- continue;
- if ((*p)->uid != current->euid &&
- (*p)->uid != current->uid && !suser()) {
- error = EPERM;
- continue;
- }
- if (error == ESRCH)
- error = 0;
- if (priority > (*p)->priority && !suser())
- error = EACCES;
- else
- (*p)->priority = priority;
- }
- return -error;
+ return -ENOSYS;
}
-int sys_getpriority(int which, int who)
+int sys_setpriority()
{
- struct task_struct **p;
- int max_prio = 0;
-
- if (which > 2 || which < 0)
- return -EINVAL;
-
- for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
- if (!*p || !proc_sel(*p, which, who))
- continue;
- if ((*p)->priority > max_prio)
- max_prio = (*p)->priority;
- }
- return(max_prio ? max_prio : -ESRCH);
+ return -ENOSYS;
}
int sys_profil()
{
if (C_A_D)
hard_reset_now();
- else
- if (task[1])
- send_sig(SIGINT,task[1],1);
}
*/
int sys_setregid(int rgid, int egid)
{
- if (rgid >= 0) {
+ if (rgid>0) {
if ((current->gid == rgid) ||
suser())
current->gid = rgid;
else
return(-EPERM);
}
- if (egid >= 0) {
+ if (egid>0) {
if ((current->gid == egid) ||
(current->egid == egid) ||
suser()) {
{
int old_ruid = current->uid;
- if (ruid >= 0) {
+ if (ruid>0) {
if ((current->euid==ruid) ||
- (old_ruid == ruid) ||
+ (old_ruid == ruid) ||
suser())
current->uid = ruid;
else
return(-EPERM);
}
- if (euid >= 0) {
+ if (euid>0) {
if ((old_ruid == euid) ||
- (current->euid == euid) ||
+ (current->euid == euid) ||
suser()) {
current->euid = euid;
current->suid = euid;
return 0;
}
-static struct new_utsname thisname = {
+static struct utsname thisname = {
UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, UTS_MACHINE
};
-int sys_newuname(struct new_utsname * name)
+int sys_uname(struct utsname * name)
{
- if (!name)
- return -EFAULT;
- verify_area(name, sizeof *name);
- memcpy_tofs(name,&thisname,sizeof *name);
- return 0;
-}
+ int i;
-int sys_uname(struct old_utsname * name)
-{
if (!name)
return -EINVAL;
verify_area(name,sizeof *name);
- memcpy_tofs(&name->sysname,&thisname.sysname,__OLD_UTS_LEN);
- put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
- memcpy_tofs(&name->nodename,&thisname.nodename,__OLD_UTS_LEN);
- put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
- memcpy_tofs(&name->release,&thisname.release,__OLD_UTS_LEN);
- put_fs_byte(0,name->release+__OLD_UTS_LEN);
- memcpy_tofs(&name->version,&thisname.version,__OLD_UTS_LEN);
- put_fs_byte(0,name->version+__OLD_UTS_LEN);
- memcpy_tofs(&name->machine,&thisname.machine,__OLD_UTS_LEN);
- put_fs_byte(0,name->machine+__OLD_UTS_LEN);
+ for(i=0;i<sizeof *name;i++)
+ put_fs_byte(((char *) &thisname)[i],i+(char *) name);
return 0;
}
if (!suser())
return -EPERM;
- if (len > __NEW_UTS_LEN)
+ if (len > MAXHOSTNAMELEN)
return -EINVAL;
for (i=0; i < len; i++) {
if ((thisname.nodename[i] = get_fs_byte(name+i)) == 0)
- return 0;
+ break;
+ }
+ if (thisname.nodename[i]) {
+ thisname.nodename[i>MAXHOSTNAMELEN ? MAXHOSTNAMELEN : i] = 0;
}
- thisname.nodename[i] = 0;
return 0;
}
* 40(%esp) - %oldss
*/
+SIG_CHLD = 17
+
EBX = 0x00
ECX = 0x04
EDX = 0x08
* Ok, I get parallel printer interrupts while using the floppy for some
* strange reason. Urgel. Now I just ignore them.
*/
-.globl _system_call,_sys_execve
+.globl _system_call,_timer_interrupt,_sys_execve
.globl _device_not_available, _coprocessor_error
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
-.globl _general_protection,_reserved
+.globl _general_protection,_irq13,_reserved
.globl _alignment_check,_page_fault
-.globl ret_from_sys_call
+.globl _keyboard_interrupt
#define SAVE_ALL \
cld; \
movl $0x17,%edx; \
mov %dx,%fs
+#define ACK_FIRST(mask) \
+ inb $0x21,%al; \
+ jmp 1f; \
+1: jmp 1f; \
+1: orb $(mask),%al; \
+ outb %al,$0x21; \
+ jmp 1f; \
+1: jmp 1f; \
+1: movb $0x20,%al; \
+ outb %al,$0x20
+
+#define ACK_SECOND(mask) \
+ inb $0xA1,%al; \
+ jmp 1f; \
+1: jmp 1f; \
+1: orb $mask,%al; \
+ outb %al,$0xA1; \
+ jmp 1f; \
+1: jmp 1f; \
+1: movb $0x20,%al; \
+ outb %al,$0x20
+ jmp 1f; \
+1: jmp 1f; \
+1: outb %al,$0xA0
+
+#define UNBLK_FIRST(mask) \
+ inb $0x21,%al; \
+ jmp 1f; \
+1: jmp 1f; \
+1: andb $~(mask),%al; \
+ outb %al,$0x21
+
+#define UNBLK_SECOND(mask) \
+ inb $0xA1,%al; \
+ jmp 1f; \
+1: jmp 1f; \
+1: andb $~(mask),%al; \
+ outb %al,$0xA1
+
+.align 2
+bad_sys_call:
+ movl $-ENOSYS,EAX(%esp)
+ jmp ret_from_sys_call
.align 2
reschedule:
pushl $ret_from_sys_call
jmp _schedule
.align 2
_system_call:
- pushl %eax # save orig_eax
+ pushl %eax # save orig_eax
SAVE_ALL
- movl $-ENOSYS,EAX(%esp)
cmpl _NR_syscalls,%eax
- jae ret_from_sys_call
+ jae bad_sys_call
call _sys_call_table(,%eax,4)
movl %eax,EAX(%esp) # save the return value
ret_from_sys_call:
jne 2f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 2f
-1: cmpl $0,_need_resched
- jne reschedule
- movl _current,%eax
+1: movl _current,%eax
+ cmpl _task,%eax # task[0] cannot have signals
+ je 2f
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
- movl $1,_need_resched
- cmpl _task,%eax # task[0] cannot have signals
- je 2f
- movl $0,_need_resched
movl signal(%eax),%ebx
movl blocked(%eax),%ecx
notl %ecx
je 2f
btrl %ecx,%ebx
movl %ebx,signal(%eax)
- movl %esp,%ebx
- pushl %ebx
incl %ecx
pushl %ecx
call _do_signal
popl %ecx
- popl %ebx
testl %eax, %eax
jne 1b # see if we need to switch tasks, or do more signals
2: popl %ebx
iret
.align 2
+_irq13:
+ pushl %eax
+ xorb %al,%al
+ outb %al,$0xF0
+ movb $0x20,%al
+ outb %al,$0x20
+ jmp 1f
+1: jmp 1f
+1: outb %al,$0xA0
+ popl %eax
_coprocessor_error:
pushl $-1 # mark this as an int.
SAVE_ALL
addl $4,%esp
ret
+.align 2
+_keyboard_interrupt:
+ pushl $-1
+ SAVE_ALL
+ ACK_FIRST(2)
+ sti
+ call _do_keyboard
+ cli
+ UNBLK_FIRST(2)
+ jmp ret_from_sys_call
+
+.align 2
+_timer_interrupt:
+ pushl $-1 # mark this as an int
+ SAVE_ALL
+ incl _jiffies
+ movb $0x20,%al # EOI to interrupt controller #1
+ outb %al,$0x20
+ movl CS(%esp),%eax
+ andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
+ pushl %eax
+ call _do_timer # 'do_timer(long CPL)' does everything from
+ addl $4,%esp # task switching to accounting ...
+ jmp ret_from_sys_call
+
.align 2
_sys_execve:
lea (EIP+4)(%esp),%eax # don't forget about the return address.
void page_fault(void);
void coprocessor_error(void);
void reserved(void);
+void parallel_interrupt(void);
+void irq13(void);
void alignment_check(void);
+int send_sig(long, struct task_struct *, int);
static void die(char * str,long esp_ptr,long nr)
{
for(i=0;i<10;i++)
printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
printk("\n\r");
- if ((0xffff & esp[1]) == 0xf)
- send_sig(SIGSEGV, current, 0);
- else
- do_exit(SIGSEGV);
+ do_exit(11); /* play segment exception */
}
void do_double_fault(long esp, long error_code)
void do_alignment_check(long esp, long error_code)
{
- die("alignment check",esp,error_code);
+ die("alignment check",esp,error_code);
}
void do_divide_error(long esp, long error_code)
void do_nmi(long esp, long error_code)
{
- printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+ die("nmi",esp,error_code);
}
void do_debug(long esp, long error_code)
{
- send_sig(SIGTRAP, current, 0);
+ send_sig(SIGTRAP, current, 0);
}
void do_overflow(long esp, long error_code)
set_trap_gate(17,&alignment_check);
for (i=18;i<48;i++)
set_trap_gate(i,&reserved);
+ set_trap_gate(45,&irq13);
+ outb_p(inb_p(0x21)&0xfb,0x21);
+ outb(inb_p(0xA1)&0xdf,0xA1);
+ set_trap_gate(39,¶llel_interrupt);
}
# unless it's something special (ie not a .c file).
#
+AR =ar
+AS =as
+LD =ld
+LDFLAGS =-s -x
+CC =gcc -nostdinc -I../include
+CPP =gcc -E -nostdinc -I../include
+
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) \
+ -c -o $*.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
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+ (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
+ $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
-_exit.o : _exit.c /usr/src/linux/include/linux/unistd.h
-close.o : close.c /usr/src/linux/include/linux/unistd.h
-ctype.o : ctype.c /usr/src/linux/include/linux/ctype.h
-dup.o : dup.c /usr/src/linux/include/linux/unistd.h
-errno.o : errno.c
-execve.o : execve.c /usr/src/linux/include/linux/unistd.h
-malloc.o : malloc.c /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/asm/system.h
-open.o : open.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/stdarg.h
-setsid.o : setsid.c /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
- /usr/src/linux/include/linux/unistd.h
-string.o : string.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h
-wait.o : wait.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/sys/wait.h \
- /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h
-write.o : write.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h
+_exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
+close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
+ctype.s ctype.o : ctype.c ../include/linux/ctype.h
+dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
+errno.s errno.o : errno.c
+execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
+malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h ../include/linux/fs.h \
+ ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/signal.h \
+ ../include/asm/system.h
+open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h ../include/stdarg.h
+setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
+string.s string.o : string.c ../include/linux/string.h
+wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h ../include/sys/wait.h
+write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+ ../include/sys/param.h ../include/sys/resource.h ../include/utime.h
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
volatile void _exit(int exit_code)
{
-fake_volatile:
__asm__("movl %1,%%ebx\n\t"
"int $0x80"::"a" (__NR_exit),"g" (exit_code));
- goto fake_volatile;
}
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
_syscall1(int,close,int,fd)
-
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
_syscall1(int,dup,int,fd)
-
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
_syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-
+++ /dev/null
-/*
- * linux/lib/itimer.c
- *
- * (C) 1992 Darren Senn
- */
-
-#define __LIBRARY__
-#include <linux/unistd.h>
-#include <sys/time.h>
-
-_syscall2(int,getitimer,int,which,struct itimerval *,value)
-_syscall3(int,setitimer,int,which,struct itimerval *,value,struct itimerval *,ovalue)
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
#include <stdarg.h>
int open(const char * filename, int flag, ...)
*/
#define __LIBRARY__
-#include <sys/types.h>
-#include <linux/unistd.h>
+#include <unistd.h>
_syscall0(pid_t,setsid)
-
*/
#define __LIBRARY__
-#include <linux/unistd.h>
+#include <unistd.h>
#include <sys/wait.h>
_syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
{
return waitpid(-1,wait_stat,0);
}
-
*/
#define __LIBRARY__
-#include <linux/unistd.h>
-#include <sys/types.h>
+#include <unistd.h>
_syscall3(int,write,int,fd,const char *,buf,off_t,count)
-
#
# Note 2! The CFLAGS definition is now in the main makefile...
+AS =as
+AR =ar
+LD =ld
+CC =gcc -nostdinc -I../include
+CPP =cpp -nostdinc -I../include
+
.c.o:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) \
+ -c -o $*.o $<
.s.o:
$(AS) -o $*.o $<
.c.s:
- $(CC) $(CFLAGS) -S $<
+ $(CC) $(CFLAGS) \
+ -S -o $*.s $<
OBJS = memory.o swap.o mmap.o
dep:
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
### Dependencies:
-memory.o : memory.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h
-mmap.o : mmap.c /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
- /usr/src/linux/include/signal.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/mman.h
-swap.o : swap.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h \
- /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
- /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
- /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
- /usr/src/linux/include/sys/resource.h
+memory.o : memory.c ../include/signal.h ../include/sys/types.h ../include/asm/system.h \
+ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+ ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h
+mmap.o : mmap.c ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+ ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
+ ../include/asm/system.h ../include/errno.h ../include/sys/mman.h
+swap.o : swap.c ../include/errno.h ../include/sys/stat.h ../include/sys/types.h \
+ ../include/linux/mm.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+ ../include/linux/kernel.h ../include/signal.h ../include/linux/string.h ../include/linux/sched.h \
+ ../include/linux/head.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+ ../include/sys/resource.h
* a more complete version of free_page_tables which performs with page
* granularity.
*/
-int unmap_page_range(unsigned long from, unsigned long size)
+int
+unmap_page_range(unsigned long from, unsigned long size)
{
unsigned long page, page_dir;
unsigned long *page_table, *dir;
* write/copy: yes/copy copy/copy
* exec: yes yes
*/
-int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
+int
+remap_page_range(unsigned long from, unsigned long to, unsigned long size,
int permiss)
{
unsigned long *page_table, *dir;
return 0;
}
if (mem_map[(page-LOW_MEM)>>12] != 1) {
- printk("put_page: mem_map disagrees with %p at %p\n",page,address);
+ printk("mem_map disagrees with %p at %p\n",page,address);
return 0;
}
page_table = (unsigned long *) ((address>>20) & 0xffc);
return;
}
-static void get_empty_page(unsigned long address)
+void get_empty_page(unsigned long address)
{
unsigned long tmp;
struct task_struct ** p;
int i;
- if (!inode || inode->i_count < 2)
+ if (inode->i_count < 2 || !inode)
return 0;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
if (!*p)
return 0;
}
-/*
- * fill in an empty page or directory if none exists
- */
-static unsigned long get_empty(unsigned long * p)
-{
- unsigned long page = 0;
-
-repeat:
- if (1 & *p) {
- free_page(page);
- return *p;
- }
- if (*p) {
- printk("get_empty: bad page entry \n");
- *p = 0;
- }
- if (page) {
- *p = page | 7;
- return *p;
- }
- if (!(page = get_free_page()))
- oom();
- goto repeat;
-}
-
void do_no_page(unsigned long error_code, unsigned long address,
- struct task_struct *tsk, unsigned long user_esp)
+ struct task_struct *tsk)
{
static unsigned int last_checked = 0;
int nr[4];
unsigned long tmp;
unsigned long page;
- unsigned int block,i;
+ int block,i;
struct inode * inode;
/* Thrashing ? Make it interruptible, but don't penalize otherwise */
printk("Bad things happen: nonexistent page error in do_no_page\n\r");
do_exit(SIGSEGV);
}
- page = get_empty((unsigned long *) ((address >> 20) & 0xffc));
- page &= 0xfffff000;
- page += (address >> 10) & 0xffc;
- tmp = *(unsigned long *) page;
- if (tmp & 1) {
- printk("bogus do_no_page\n");
- return;
- }
++tsk->rss;
- if (tmp) {
- ++tsk->maj_flt;
- swap_in((unsigned long *) page);
- return;
+ page = *(unsigned long *) ((address >> 20) & 0xffc);
+/* check the page directory: make a page dir entry if no such exists */
+ if (page & 1) {
+ page &= 0xfffff000;
+ page += (address >> 10) & 0xffc;
+ tmp = *(unsigned long *) page;
+ if (tmp && !(1 & tmp)) {
+ ++tsk->maj_flt;
+ swap_in((unsigned long *) page);
+ return;
+ }
+ } else {
+ if (page)
+ printk("do_no_page: bad page directory\n");
+ if (!(page = get_free_page()))
+ oom();
+ page |= 7;
+ *(unsigned long *) ((address >> 20) & 0xffc) = page;
}
address &= 0xfffff000;
tmp = address - tsk->start_code;
- inode = NULL;
- block = 0;
- if (tmp < tsk->end_data) {
- inode = tsk->executable;
- block = 1 + tmp / BLOCK_SIZE;
- } else {
+ if (tmp >= LIBRARY_OFFSET ) {
+ inode = NULL;
+ block = 1;
i = tsk->numlibraries;
while (i-- > 0) {
- if (tmp < tsk->libraries[i].start)
- continue;
- block = tmp - tsk->libraries[i].start;
- if (block >= tsk->libraries[i].length)
- continue;
- inode = tsk->libraries[i].library;
- block = 1 + block / BLOCK_SIZE;
- break;
+ if (tmp < (tsk->libraries[i].start +
+ tsk->libraries[i].length)) {
+ inode = tsk->libraries[i].library;
+ block = 1 + (tmp - tsk->libraries[i].start) /
+ BLOCK_SIZE;
+ break;
+ }
}
+ } else if (tmp < tsk->end_data) {
+ inode = tsk->executable;
+ block = 1 + tmp / BLOCK_SIZE;
+ } else {
+ inode = NULL;
+ block = 0;
}
if (!inode) {
++tsk->min_flt;
+ if (tmp < LIBRARY_OFFSET && tmp > tsk->brk && tsk == current &&
+ LIBRARY_OFFSET - tmp > tsk->rlim[RLIMIT_STACK].rlim_max)
+ do_exit(SIGSEGV);
get_empty_page(address);
- if (tsk != current)
- return;
- if (tmp >= LIBRARY_OFFSET || tmp < tsk->brk)
- return;
- if (tmp+8192 >= (user_esp & 0xfffff000))
- return;
- send_sig(SIGSEGV,tsk,1);
return;
}
if (tsk == current)
++tsk->maj_flt;
if (!(page = get_free_page()))
oom();
+/* remember that 1 block is used for header */
for (i=0 ; i<4 ; block++,i++)
nr[i] = bmap(inode,block);
bread_page(page,inode->i_dev,nr);
if (i>4095)
i = 0;
tmp = page + 4096;
- while (i--) {
+ while (i-- > 0) {
tmp--;
*(char *)tmp = 0;
}
{
int i;
- end_mem &= 0xfffff000;
- start_mem += 0xfff;
- start_mem &= 0xfffff000;
swap_device = 0;
swap_file = NULL;
HIGH_MEMORY = end_mem;
void do_page_fault(unsigned long *esp, unsigned long error_code)
{
unsigned long address;
- unsigned long user_esp;
-
- if ((0xffff & esp[1]) == 0xf)
- user_esp = esp[3];
- else
- user_esp = 0;
/* get the address */
+
__asm__("movl %%cr2,%0":"=r" (address));
if (!(error_code & 1)) {
- do_no_page(error_code, address, current, user_esp);
+ do_no_page(error_code, address, current);
return;
} else {
do_wp_page(error_code, address);
*
* Written by obz.
*/
-#include <linux/stat.h>
+#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <errno.h>
#define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
current->start_code + current->end_code)
+extern int remap_page_range(unsigned long from, unsigned long to,
+ unsigned long size, int permiss);
+extern int unmap_page_range(unsigned long from, unsigned long size);
+
static caddr_t
mmap_chr(unsigned long addr, size_t len, int prot, int flags,
struct inode *inode, unsigned long off)
{
int major, minor;
+ extern unsigned long HIGH_MEMORY;
major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
*/
#include <errno.h>
+#include <sys/stat.h>
-#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/sched.h>
*
* The swapon system call
*/
+
int sys_swapon(const char * specialfile)
{
struct inode * swap_inode;
- char * tmp;
int i,j;
if (!suser())
iput(swap_inode);
return -EINVAL;
}
- tmp = (char *) get_free_page();
- if (!tmp) {
+ swap_bitmap = (char *) get_free_page();
+ if (!swap_bitmap) {
iput(swap_file);
swap_device = 0;
swap_file = NULL;
printk("Unable to start swapping: out of memory :-)\n");
return -ENOMEM;
}
- read_swap_page(0,tmp);
- if (strncmp("SWAP-SPACE",tmp+4086,10)) {
+ read_swap_page(0,swap_bitmap);
+ if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {
printk("Unable to find swap-space signature\n\r");
- free_page((long) tmp);
+ free_page((long) swap_bitmap);
iput(swap_file);
swap_device = 0;
swap_file = NULL;
swap_bitmap = NULL;
return -EINVAL;
}
- memset(tmp+4086,0,10);
+ memset(swap_bitmap+4086,0,10);
j = 0;
for (i = 1 ; i < SWAP_BITS ; i++)
- if (bit(tmp,i))
+ if (bit(swap_bitmap,i))
j++;
if (!j) {
printk("Empty swap-file\n");
- free_page((long) tmp);
+ free_page((long) swap_bitmap);
iput(swap_file);
swap_device = 0;
swap_file = NULL;
swap_bitmap = NULL;
return -EINVAL;
}
- swap_bitmap = tmp;
printk("Adding Swap: %d pages (%d bytes) swap-space\n\r",j,j*4096);
return 0;
}
+++ /dev/null
-#
-# Makefile for the linux networking.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-.c.o:
- $(CC) $(CFLAGS) -c $<
-.s.o:
- $(AS) -o $*.o $<
-.c.s:
- $(CC) $(CFLAGS) -S $<
-
-OBJS = socket.o unix.o
-
-net.o: $(OBJS)
- $(LD) -r -o net.o $(OBJS)
-
-clean:
- rm -f core *.o *.a tmp_make
- for i in *.c;do rm -f `basename $$i .c`.s;done
-
-dep:
- sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
- for i in *.c;do $(CPP) -M $$i;done >> tmp_make
- cp tmp_make Makefile
-
-### Dependencies:
-socket.o : socket.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/linux/sched.h \
- /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/dirent.h \
- /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/mm.h \
- /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h \
- /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/stat.h \
- /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/socket.h \
- /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/termios.h kern_sock.h \
- socketcall.h
-unix.o : unix.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
- /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/linux/string.h \
- /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
- /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
- /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h \
- /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
- /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
- /usr/src/linux/include/sys/socket.h /usr/src/linux/include/sys/un.h /usr/src/linux/include/linux/fcntl.h \
- /usr/src/linux/include/termios.h kern_sock.h
+++ /dev/null
-#ifndef _KERN_SOCK_H
-#define _KERN_SOCK_H
-
-#define NSOCKETS 128 /* should be dynamic, later... */
-
-typedef enum {
- SS_FREE = 0, /* not allocated */
- SS_UNCONNECTED, /* unconnected to any socket */
- SS_CONNECTING, /* in process of connecting */
- SS_CONNECTED, /* connected to socket */
- SS_DISCONNECTING, /* in process of disconnecting */
-} socket_state;
-
-#define SO_ACCEPTCON (1<<16) /* performed a listen */
-
-/*
- * internel representation of a socket. not all the fields are used by
- * all configurations:
- *
- * server client
- * conn client connected to server connected to
- * iconn list of clients -unused-
- * awaiting connections
- * wait sleep for clients, sleep for connection,
- * sleep for i/o sleep for i/o
- */
-struct socket {
- short type; /* SOCK_STREAM, ... */
- socket_state state;
- long flags;
- struct proto_ops *ops; /* protocols do most everything */
- char *data; /* protocol data */
- struct socket *conn; /* server socket connected to */
- struct socket *iconn; /* incomplete client connections */
- struct socket *next;
- struct wait_queue **wait; /* ptr to place to wait on */
- void *dummy;
-};
-
-struct proto_ops {
- int (*init)(void);
- int (*create)(struct socket *sock, int protocol);
- int (*dup)(struct socket *newsock, struct socket *oldsock);
- int (*release)(struct socket *sock, struct socket *peer);
- int (*bind)(struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
- int (*connect)(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len);
- int (*socketpair)(struct socket *sock1, struct socket *sock2);
- int (*accept)(struct socket *sock, struct socket *newsock);
- int (*getname)(struct socket *sock, struct sockaddr *uaddr,
- int *usockaddr_len, int peer);
- int (*read)(struct socket *sock, char *ubuf, int size, int nonblock);
- int (*write)(struct socket *sock, char *ubuf, int size, int nonblock);
- int (*select)(struct socket *sock, int sel_type, select_table * wait);
- int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg);
-};
-
-extern int sock_awaitconn(struct socket *mysock, struct socket *servsock);
-
-#ifdef SOCK_DEBUG
-#define PRINTK printk
-#else
-#define PRINTK (void)
-#endif
-
-#endif /* _KERN_SOCK_H */
+++ /dev/null
-#include <signal.h>
-#include <errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <sys/socket.h>
-#include <linux/fcntl.h>
-#include <termios.h>
-#include "kern_sock.h"
-#include "socketcall.h"
-
-extern int sys_close(int fd);
-
-extern struct proto_ops unix_proto_ops;
-
-static struct {
- short family;
- char *name;
- struct proto_ops *ops;
-} proto_table[] = {
- AF_UNIX, "AF_UNIX", &unix_proto_ops
-};
-#define NPROTO (sizeof(proto_table) / sizeof(proto_table[0]))
-
-static char *
-family_name(int family)
-{
- int i;
-
- for (i = 0; i < NPROTO; ++i)
- if (proto_table[i].family == family)
- return proto_table[i].name;
- return "UNKNOWN";
-}
-
-static int sock_lseek(struct inode *inode, struct file *file, off_t offset,
- int whence);
-static int sock_read(struct inode *inode, struct file *file, char *buf,
- int size);
-static int sock_write(struct inode *inode, struct file *file, char *buf,
- int size);
-static int sock_readdir(struct inode *inode, struct file *file,
- struct dirent *dirent, int count);
-static void sock_close(struct inode *inode, struct file *file);
-static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
-static int sock_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned int arg);
-
-static struct file_operations socket_file_ops = {
- sock_lseek,
- sock_read,
- sock_write,
- sock_readdir,
- sock_select, /* not in vfs yet */
- sock_ioctl,
- NULL, /* no special open code... */
- sock_close
-};
-
-#define SOCK_INODE(S) ((struct inode *)(S)->dummy)
-
-static struct socket sockets[NSOCKETS];
-#define last_socket (sockets + NSOCKETS - 1)
-static struct wait_queue *socket_wait_free = NULL;
-
-/*
- * obtains the first available file descriptor and sets it up for use
- */
-static int
-get_fd(struct inode *inode)
-{
- int fd, i;
- struct file *file;
-
- /*
- * find a file descriptor suitable for return to the user.
- */
- for (fd = 0; fd < NR_OPEN; ++fd)
- if (!current->filp[fd])
- break;
- if (fd == NR_OPEN)
- return -1;
- current->close_on_exec &= ~(1 << fd);
- for (file = file_table, i = 0; i < NR_FILE; ++i, ++file)
- if (!file->f_count)
- break;
- if (i == NR_FILE)
- return -1;
- current->filp[fd] = file;
- file->f_op = &socket_file_ops;
- file->f_mode = 3;
- file->f_flags = 0;
- file->f_count = 1;
- file->f_inode = inode;
- file->f_pos = 0;
- return fd;
-}
-
-/*
- * reverses the action of get_fd() by releasing the file. it closes the
- * descriptor, but makes sure it does nothing more. called when an incomplete
- * socket must be closed, along with sock_release().
- */
-static inline void
-toss_fd(int fd)
-{
- current->filp[fd]->f_inode = NULL; /* safe from iput */
- sys_close(fd);
-}
-
-static inline struct socket *
-socki_lookup(struct inode *inode)
-{
- struct socket *sock;
-
- for (sock = sockets; sock <= last_socket; ++sock)
- if (sock->state != SS_FREE && SOCK_INODE(sock) == inode)
- return sock;
- return NULL;
-}
-
-static inline struct socket *
-sockfd_lookup(int fd, struct file **pfile)
-{
- struct file *file;
-
- if (fd < 0 || fd >= NR_OPEN || !(file = current->filp[fd]))
- return NULL;
- if (pfile)
- *pfile = file;
- return socki_lookup(file->f_inode);
-}
-
-static struct socket *
-sock_alloc(int wait)
-{
- struct socket *sock;
-
- while (1) {
- cli();
- for (sock = sockets; sock <= last_socket; ++sock)
- if (sock->state == SS_FREE) {
- sock->state = SS_UNCONNECTED;
- sti();
- sock->flags = 0;
- sock->ops = NULL;
- sock->data = NULL;
- sock->conn = NULL;
- sock->iconn = NULL;
- /*
- * this really shouldn't be necessary, but
- * everything else depends on inodes, so we
- * grab it.
- * sleeps are also done on the i_wait member
- * of this inode.
- * the close system call will iput this inode
- * for us.
- */
- if (!(SOCK_INODE(sock) = get_empty_inode())) {
- printk("sock_alloc: no more inodes\n");
- sock->state = SS_FREE;
- return NULL;
- }
- SOCK_INODE(sock)->i_mode = S_IFSOCK;
- sock->wait = &SOCK_INODE(sock)->i_wait;
- PRINTK("sock_alloc: socket 0x%x, inode 0x%x\n",
- sock, SOCK_INODE(sock));
- return sock;
- }
- sti();
- if (!wait)
- return NULL;
- PRINTK("sock_alloc: no free sockets, sleeping...\n");
- interruptible_sleep_on(&socket_wait_free);
- if (current->signal & ~current->blocked) {
- PRINTK("sock_alloc: sleep was interrupted\n");
- return NULL;
- }
- PRINTK("sock_alloc: wakeup... trying again...\n");
- }
-}
-
-static inline void
-sock_release_peer(struct socket *peer)
-{
- peer->state = SS_DISCONNECTING;
- wake_up(peer->wait);
-}
-
-static void
-sock_release(struct socket *sock)
-{
- int oldstate;
- struct socket *peersock, *nextsock;
-
- PRINTK("sock_release: socket 0x%x, inode 0x%x\n", sock,
- SOCK_INODE(sock));
- if ((oldstate = sock->state) != SS_UNCONNECTED)
- sock->state = SS_DISCONNECTING;
- /*
- * wake up anyone waiting for connections
- */
- for (peersock = sock->iconn; peersock; peersock = nextsock) {
- nextsock = peersock->next;
- sock_release_peer(peersock);
- }
- /*
- * wake up anyone we're connected to. first, we release the
- * protocol, to give it a chance to flush data, etc.
- */
- peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL;
- if (sock->ops)
- sock->ops->release(sock, peersock);
- if (peersock)
- sock_release_peer(peersock);
- sock->state = SS_FREE; /* this really releases us */
- wake_up(&socket_wait_free);
-}
-
-static int
-sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence)
-{
- PRINTK("sock_lseek: huh?\n");
- return -EBADF;
-}
-
-static int
-sock_read(struct inode *inode, struct file *file, char *ubuf, int size)
-{
- struct socket *sock;
-
- PRINTK("sock_read: buf=0x%x, size=%d\n", ubuf, size);
- if (!(sock = socki_lookup(inode))) {
- printk("sock_read: can't find socket for inode!\n");
- return -EBADF;
- }
- if (sock->flags & SO_ACCEPTCON)
- return -EINVAL;
- return sock->ops->read(sock, ubuf, size, (file->f_flags & O_NONBLOCK));
-}
-
-static int
-sock_write(struct inode *inode, struct file *file, char *ubuf, int size)
-{
- struct socket *sock;
-
- PRINTK("sock_write: buf=0x%x, size=%d\n", ubuf, size);
- if (!(sock = socki_lookup(inode))) {
- printk("sock_write: can't find socket for inode!\n");
- return -EBADF;
- }
- if (sock->flags & SO_ACCEPTCON)
- return -EINVAL;
- return sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK));
-}
-
-static int
-sock_readdir(struct inode *inode, struct file *file, struct dirent *dirent,
- int count)
-{
- PRINTK("sock_readdir: huh?\n");
- return -EBADF;
-}
-
-int
-sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned int arg)
-{
- struct socket *sock;
-
- PRINTK("sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n", inode, cmd, arg);
- if (!(sock = socki_lookup(inode))) {
- printk("sock_ioctl: can't find socket for inode!\n");
- return -EBADF;
- }
- switch (cmd) {
- case TIOCINQ:
- case TIOCOUTQ:
- if (sock->flags & SO_ACCEPTCON)
- return -EINVAL;
- break;
-
- default:
- return -EINVAL;
- }
- return sock->ops->ioctl(sock, cmd, arg);
-}
-
-static int
-sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
-{
- struct socket *sock;
-
- PRINTK("sock_select: inode = 0x%x, kind = %s\n", inode,
- (sel_type == SEL_IN) ? "in" :
- (sel_type == SEL_OUT) ? "out" : "ex");
- if (!(sock = socki_lookup(inode))) {
- printk("sock_select: can't find socket for inode!\n");
- return 0;
- }
-
- /*
- * handle server sockets specially
- */
- if (sock->flags & SO_ACCEPTCON) {
- if (sel_type == SEL_IN) {
- PRINTK("sock_select: %sconnections pending\n",
- sock->iconn ? "" : "no ");
- if (sock->iconn)
- return 1;
- select_wait(&inode->i_wait, wait);
- return sock->iconn ? 1 : 0;
- }
- PRINTK("sock_select: nothing else for server socket\n");
- select_wait(&inode->i_wait, wait);
- return 0;
- }
- /*
- * we can't return errors to select, so its either yes or no.
- */
- if (sock->ops && sock->ops->select)
- return sock->ops->select(sock, sel_type, wait);
- return 0;
-}
-
-void
-sock_close(struct inode *inode, struct file *file)
-{
- struct socket *sock;
-
- PRINTK("sock_close: inode=0x%x (cnt=%d)\n", inode, inode->i_count);
- /*
- * it's possible the inode is NULL if we're closing an unfinished
- * socket.
- */
- if (!inode)
- return;
- if (!(sock = socki_lookup(inode))) {
- printk("sock_close: can't find socket for inode!\n");
- return;
- }
- sock_release(sock);
-}
-
-int
-sock_awaitconn(struct socket *mysock, struct socket *servsock)
-{
- struct socket *last;
-
- PRINTK("sock_awaitconn: trying to connect socket 0x%x to 0x%x\n",
- mysock, servsock);
- if (!(servsock->flags & SO_ACCEPTCON)) {
- PRINTK("sock_awaitconn: server not accepting connections\n");
- return -EINVAL;
- }
-
- /*
- * put ourselves on the server's incomplete connection queue.
- */
- mysock->next = NULL;
- cli();
- if (!(last = servsock->iconn))
- servsock->iconn = mysock;
- else {
- while (last->next)
- last = last->next;
- last->next = mysock;
- }
- mysock->state = SS_CONNECTING;
- mysock->conn = servsock;
- sti();
-
- /*
- * wake up server, then await connection. server will set state to
- * SS_CONNECTED if we're connected.
- */
- wake_up(servsock->wait);
- if (mysock->state != SS_CONNECTED) {
- interruptible_sleep_on(mysock->wait);
- if (mysock->state != SS_CONNECTED) {
- /*
- * if we're not connected we could have been
- * 1) interrupted, so we need to remove ourselves
- * from the server list
- * 2) rejected (mysock->conn == NULL), and have
- * already been removed from the list
- */
- if (mysock->conn == servsock) {
- cli();
- if ((last = servsock->iconn) == mysock)
- servsock->iconn = mysock->next;
- else {
- while (last->next != mysock)
- last = last->next;
- last->next = mysock->next;
- }
- sti();
- }
- return mysock->conn ? -EINTR : -EACCES;
- }
- }
- return 0;
-}
-
-/*
- * perform the socket system call. we locate the appropriate family, then
- * create a fresh socket.
- */
-static int
-sock_socket(int family, int type, int protocol)
-{
- int i, fd;
- struct socket *sock;
- struct proto_ops *ops;
-
- PRINTK("sys_socket: family = %d (%s), type = %d, protocol = %d\n",
- family, family_name(family), type, protocol);
-
- /*
- * locate the correct protocol family
- */
- for (i = 0; i < NPROTO; ++i)
- if (proto_table[i].family == family)
- break;
- if (i == NPROTO) {
- PRINTK("sys_socket: family not found\n");
- return -EINVAL;
- }
- ops = proto_table[i].ops;
-
- /*
- * check that this is a type that we know how to manipulate and
- * the protocol makes sense here. the family can still reject the
- * protocol later.
- */
- if ((type != SOCK_STREAM &&
- type != SOCK_DGRAM &&
- type != SOCK_SEQPACKET &&
- type != SOCK_RAW) ||
- protocol < 0)
- return -EINVAL;
-
- /*
- * allocate the socket and allow the family to set things up. if
- * the protocol is 0, the family is instructed to select an appropriate
- * default.
- */
- if (!(sock = sock_alloc(1))) {
- printk("sys_socket: no more sockets\n");
- return -EAGAIN;
- }
- sock->type = type;
- sock->ops = ops;
- if ((i = sock->ops->create(sock, protocol)) < 0) {
- sock_release(sock);
- return i;
- }
-
- if ((fd = get_fd(SOCK_INODE(sock))) < 0) {
- sock_release(sock);
- return -EINVAL;
- }
-
- return fd;
-}
-
-static int
-sock_socketpair(int family, int type, int protocol, int usockvec[2])
-{
- int fd1, fd2, i;
- struct socket *sock1, *sock2;
-
- PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n",
- family, type, protocol);
-
- /*
- * obtain the first socket and check if the underlying protocol
- * supports the socketpair call
- */
- if ((fd1 = sock_socket(family, type, protocol)) < 0)
- return fd1;
- sock1 = sockfd_lookup(fd1, NULL);
- if (!sock1->ops->socketpair) {
- sys_close(fd1);
- return -EINVAL;
- }
-
- /*
- * now grab another socket and try to connect the two together
- */
- if ((fd2 = sock_socket(family, type, protocol)) < 0) {
- sys_close(fd1);
- return -EINVAL;
- }
- sock2 = sockfd_lookup(fd2, NULL);
- if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
- sys_close(fd1);
- sys_close(fd2);
- return i;
- }
- sock1->conn = sock2;
- sock2->conn = sock1;
- sock1->state = SS_CONNECTED;
- sock2->state = SS_CONNECTED;
-
- verify_area(usockvec, 2 * sizeof(int));
- put_fs_long(fd1, &usockvec[0]);
- put_fs_long(fd2, &usockvec[1]);
-
- return 0;
-}
-
-/*
- * binds a name to a socket. nothing much to do here since its the
- * protocol's responsibility to handle the local address
- */
-static int
-sock_bind(int fd, struct sockaddr *umyaddr, int addrlen)
-{
- struct socket *sock;
- int i;
-
- PRINTK("sys_bind: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
- return -EBADF;
- if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) {
- PRINTK("sys_bind: bind failed\n");
- return i;
- }
- return 0;
-}
-
-/*
- * perform a listen. basically, we allow the protocol to do anything
- * necessary for a listen, and if that works, we mark the socket as
- * ready for listening.
- */
-static int
-sock_listen(int fd, int backlog)
-{
- struct socket *sock;
-
- PRINTK("sys_listen: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
- return -EBADF;
- if (sock->state != SS_UNCONNECTED) {
- PRINTK("sys_listen: socket isn't unconnected\n");
- return -EINVAL;
- }
- if (sock->flags & SO_ACCEPTCON) {
- PRINTK("sys_listen: socket already accepting connections!\n");
- return -EINVAL;
- }
- sock->flags |= SO_ACCEPTCON;
- return 0;
-}
-
-/*
- * for accept, we attempt to create a new socket, set up the link with the
- * client, wake up the client, then return the new connected fd.
- */
-static int
-sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
-{
- struct file *file;
- struct socket *sock, *clientsock, *newsock;
- int i;
-
- PRINTK("sys_accept: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, &file)))
- return -EBADF;
- if (sock->state != SS_UNCONNECTED) {
- PRINTK("sys_accept: socket isn't unconnected\n");
- return -EINVAL;
- }
- if (!(sock->flags & SO_ACCEPTCON)) {
- PRINTK("sys_accept: socket not accepting connections!\n");
- return -EINVAL;
- }
-
- /*
- * if there aren't any sockets awaiting connection, then wait for
- * one, unless nonblocking
- */
- while (!(clientsock = sock->iconn)) {
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- interruptible_sleep_on(sock->wait);
- if (current->signal & ~current->blocked) {
- PRINTK("sys_accept: sleep was interrupted\n");
- return -ERESTARTSYS;
- }
- }
-
- if (!(newsock = sock_alloc(0))) {
- printk("sys_accept: no more sockets\n");
- return -EINVAL;
- }
- newsock->type = sock->type;
- newsock->ops = sock->ops;
- if ((i = sock->ops->dup(newsock, sock)) < 0) {
- sock_release(newsock);
- return i;
- }
-
- if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {
- sock_release(newsock);
- return -EINVAL;
- }
-
- /*
- * great. finish the connection relative to server and client,
- * wake up the client and return the new fd to the server
- */
- sock->iconn = clientsock->next;
- clientsock->next = NULL;
- newsock->conn = clientsock;
- clientsock->conn = newsock;
- clientsock->state = SS_CONNECTED;
- newsock->state = SS_CONNECTED;
- newsock->ops->accept(sock, newsock);
- PRINTK("sys_accept: connected socket 0x%x via 0x%x to 0x%x\n",
- sock, newsock, clientsock);
- if (upeer_sockaddr)
- newsock->ops->getname(newsock, upeer_sockaddr,
- upeer_addrlen, 1);
- wake_up(clientsock->wait);
-
- return fd;
-}
-
-/*
- * attempt to connect to a socket with the server address.
- */
-static int
-sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
-{
- struct socket *sock;
- int i;
-
- PRINTK("sys_connect: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
- return -EBADF;
- if (sock->state != SS_UNCONNECTED) {
- PRINTK("sys_connect: socket not unconnected\n");
- return -EINVAL;
- }
- if ((i = sock->ops->connect(sock, uservaddr, addrlen)) < 0) {
- PRINTK("sys_connect: connect failed\n");
- return i;
- }
- return 0;
-}
-
-static int
-sock_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
-{
- struct socket *sock;
-
- PRINTK("sys_getsockname: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
- return -EBADF;
- return sock->ops->getname(sock, usockaddr, usockaddr_len, 0);
-}
-
-static int
-sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
-{
- struct socket *sock;
-
- PRINTK("sys_getpeername: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
- return -EBADF;
- return sock->ops->getname(sock, usockaddr, usockaddr_len, 1);
-}
-
-/*
- * system call vectors. since i want to rewrite sockets as streams, we have
- * this level of indirection. not a lot of overhead, since more of the work is
- * done via read/write/select directly
- */
-int
-sys_socketcall(int call, unsigned long *args)
-{
- switch (call) {
- case SYS_SOCKET:
- verify_area(args, 3 * sizeof(long));
- return sock_socket(get_fs_long(args+0),
- get_fs_long(args+1),
- get_fs_long(args+2));
-
- case SYS_BIND:
- verify_area(args, 3 * sizeof(long));
- return sock_bind(get_fs_long(args+0),
- (struct sockaddr *)get_fs_long(args+1),
- get_fs_long(args+2));
-
- case SYS_CONNECT:
- verify_area(args, 3 * sizeof(long));
- return sock_connect(get_fs_long(args+0),
- (struct sockaddr *)get_fs_long(args+1),
- get_fs_long(args+2));
-
- case SYS_LISTEN:
- verify_area(args, 2 * sizeof(long));
- return sock_listen(get_fs_long(args+0),
- get_fs_long(args+1));
-
- case SYS_ACCEPT:
- verify_area(args, 3 * sizeof(long));
- return sock_accept(get_fs_long(args+0),
- (struct sockaddr *)get_fs_long(args+1),
- (int *)get_fs_long(args+2));
-
- case SYS_GETSOCKNAME:
- verify_area(args, 3 * sizeof(long));
- return sock_getsockname(get_fs_long(args+0),
- (struct sockaddr *)get_fs_long(args+1),
- (int *)get_fs_long(args+2));
-
- case SYS_GETPEERNAME:
- verify_area(args, 3 * sizeof(long));
- return sock_getpeername(get_fs_long(args+0),
- (struct sockaddr *)get_fs_long(args+1),
- (int *)get_fs_long(args+2));
-
- case SYS_SOCKETPAIR:
- verify_area(args, 4 * sizeof(long));
- return sock_socketpair(get_fs_long(args+0),
- get_fs_long(args+1),
- get_fs_long(args+2),
- (int *)get_fs_long(args+3));
-
- default:
- return -EINVAL;
- }
-}
-
-void
-sock_init(void)
-{
- struct socket *sock;
- int i, ok;
-
- for (sock = sockets; sock <= last_socket; ++sock)
- sock->state = SS_FREE;
- for (i = ok = 0; i < NPROTO; ++i) {
- printk("sock_init: initializing family %d (%s)\n",
- proto_table[i].family, proto_table[i].name);
- if ((*proto_table[i].ops->init)() < 0) {
- printk("sock_init: init failed.\n",
- proto_table[i].family);
- proto_table[i].family = -1;
- }
- else
- ++ok;
- }
- if (!ok)
- printk("sock_init: warning: no protocols initialized\n");
- return;
-}
-
+++ /dev/null
-#ifndef _SOCKETCALL_
-#define _SOCKETCALL_
-
-#define SYS_SOCKET 1
-#define SYS_BIND 2
-#define SYS_CONNECT 3
-#define SYS_LISTEN 4
-#define SYS_ACCEPT 5
-#define SYS_GETSOCKNAME 6
-#define SYS_GETPEERNAME 7
-#define SYS_SOCKETPAIR 8
-
-#endif _SOCKETCALL_
+++ /dev/null
-#include <signal.h>
-#include <errno.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <linux/fcntl.h>
-#include <termios.h>
-#include "kern_sock.h"
-
-static struct unix_proto_data {
- int refcnt; /* cnt of reference 0=free */
- struct socket *socket; /* socket we're bound to */
- int protocol;
- struct sockaddr_un sockaddr_un;
- short sockaddr_len; /* >0 if name bound */
- char *buf;
- int bp_head, bp_tail;
- struct inode *inode;
- struct unix_proto_data *peerupd;
-} unix_datas[NSOCKETS];
-#define last_unix_data (unix_datas + NSOCKETS - 1)
-
-#define UN_DATA(SOCK) ((struct unix_proto_data *)(SOCK)->data)
-#define UN_PATH_OFFSET ((unsigned long)((struct sockaddr_un *)0)->sun_path)
-
-/*
- * buffer size must be power of 2. buffer mgmt inspired by pipe code.
- * note that buffer contents can wraparound, and we can write one byte less
- * than full size to discern full vs empty.
- */
-#define BUF_SIZE PAGE_SIZE
-#define UN_BUF_AVAIL(UPD) (((UPD)->bp_head - (UPD)->bp_tail) & (BUF_SIZE-1))
-#define UN_BUF_SPACE(UPD) ((BUF_SIZE-1) - UN_BUF_AVAIL(UPD))
-
-static int unix_proto_init(void);
-static int unix_proto_create(struct socket *sock, int protocol);
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
-static int unix_proto_release(struct socket *sock, struct socket *peer);
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len);
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
-static int unix_proto_accept(struct socket *sock, struct socket *newsock);
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
- int *usockaddr_len, int peer);
-static int unix_proto_read(struct socket *sock, char *ubuf, int size,
- int nonblock);
-static int unix_proto_write(struct socket *sock, char *ubuf, int size,
- int nonblock);
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg);
-
-struct proto_ops unix_proto_ops = {
- unix_proto_init,
- unix_proto_create,
- unix_proto_dup,
- unix_proto_release,
- unix_proto_bind,
- unix_proto_connect,
- unix_proto_socketpair,
- unix_proto_accept,
- unix_proto_getname,
- unix_proto_read,
- unix_proto_write,
- unix_proto_select,
- unix_proto_ioctl
-};
-
-#ifdef SOCK_DEBUG
-void
-sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
-{
- char buf[sizeof(sockun->sun_path) + 1];
-
- sockaddr_len -= UN_PATH_OFFSET;
- if (sockun->sun_family != AF_UNIX)
- printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family);
- else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1)
- printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len);
- else {
- memcpy(buf, sockun->sun_path, sockaddr_len);
- buf[sockaddr_len] = '\0';
- printk("sockaddr_un: '%s'[%d]\n", buf,
- sockaddr_len + UN_PATH_OFFSET);
- }
-}
-#endif
-
-static struct unix_proto_data *
-unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
-{
- struct unix_proto_data *upd;
-
- for (upd = unix_datas; upd <= last_unix_data; ++upd) {
- if (upd->refcnt && upd->socket &&
- upd->sockaddr_len == sockaddr_len &&
- memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
- return upd;
- }
- return NULL;
-}
-
-static struct unix_proto_data *
-unix_data_alloc(void)
-{
- struct unix_proto_data *upd;
-
- cli();
- for (upd = unix_datas; upd <= last_unix_data; ++upd) {
- if (!upd->refcnt) {
- upd->refcnt = 1;
- sti();
- upd->socket = NULL;
- upd->sockaddr_len = 0;
- upd->buf = NULL;
- upd->bp_head = upd->bp_tail = 0;
- upd->inode = NULL;
- upd->peerupd = NULL;
- return upd;
- }
- }
- sti();
- return NULL;
-}
-
-static inline void
-unix_data_ref(struct unix_proto_data *upd)
-{
- ++upd->refcnt;
- PRINTK("unix_data_ref: refing data 0x%x (%d)\n", upd, upd->refcnt);
-}
-
-static void
-unix_data_deref(struct unix_proto_data *upd)
-{
- if (upd->refcnt == 1) {
- PRINTK("unix_data_deref: releasing data 0x%x\n", upd);
- if (upd->buf) {
- free_page((unsigned long)upd->buf);
- upd->buf = NULL;
- upd->bp_head = upd->bp_tail = 0;
- }
- }
- --upd->refcnt;
-}
-
-/*
- * upon a create, we allocate an empty protocol data, and grab a page to
- * buffer writes
- */
-static int
-unix_proto_create(struct socket *sock, int protocol)
-{
- struct unix_proto_data *upd;
-
- PRINTK("unix_proto_create: socket 0x%x, proto %d\n", sock, protocol);
- if (protocol != 0) {
- PRINTK("unix_proto_create: protocol != 0\n");
- return -EINVAL;
- }
- if (!(upd = unix_data_alloc())) {
- printk("unix_proto_create: can't allocate buffer\n");
- return -ENOMEM;
- }
- if (!(upd->buf = (char *)get_free_page())) {
- printk("unix_proto_create: can't get page!\n");
- unix_data_deref(upd);
- return -ENOMEM;
- }
- upd->protocol = protocol;
- upd->socket = sock;
- UN_DATA(sock) = upd;
- PRINTK("unix_proto_create: allocated data 0x%x\n", upd);
- return 0;
-}
-
-static int
-unix_proto_dup(struct socket *newsock, struct socket *oldsock)
-{
- struct unix_proto_data *upd = UN_DATA(oldsock);
-
- return unix_proto_create(newsock, upd->protocol);
-}
-
-static int
-unix_proto_release(struct socket *sock, struct socket *peer)
-{
- struct unix_proto_data *upd = UN_DATA(sock);
-
- PRINTK("unix_proto_release: socket 0x%x, unix_data 0x%x\n",
- sock, upd);
- if (!upd)
- return 0;
- if (upd->socket != sock) {
- printk("unix_proto_release: socket link mismatch!\n");
- return -EINVAL;
- }
- if (upd->inode) {
- PRINTK("unix_proto_release: releasing inode 0x%x\n",
- upd->inode);
- iput(upd->inode);
- upd->inode = NULL;
- }
- UN_DATA(sock) = NULL;
- upd->socket = NULL;
- if (upd->peerupd)
- unix_data_deref(upd->peerupd);
- unix_data_deref(upd);
- return 0;
-}
-
-/*
- * bind a name to a socket. this is where much of the work is done. we
- * allocate a fresh page for the buffer, grab the appropriate inode and
- * set things up.
- *
- * XXX what should we do if an address is already bound? here we return
- * EINVAL, but it may be necessary to re-bind. i think thats what bsd does
- * in the case of datagram sockets
- */
-static int
-unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len)
-{
- struct unix_proto_data *upd = UN_DATA(sock);
- char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
- int i;
- unsigned long old_fs;
-
- PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
- sockaddr_len);
- if (sockaddr_len <= UN_PATH_OFFSET ||
- sockaddr_len >= sizeof(struct sockaddr_un)) {
- PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
- return -EINVAL;
- }
- if (upd->sockaddr_len || upd->inode) {
- printk("unix_proto_bind: already bound!\n");
- return -EINVAL;
- }
- verify_area(umyaddr, sockaddr_len);
- memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
- if (upd->sockaddr_un.sun_family != AF_UNIX) {
- PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
- upd->sockaddr_un.sun_family, AF_UNIX);
- return -EINVAL;
- }
-
- memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
- fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
- old_fs = get_fs();
- set_fs(get_ds());
- i = do_mknod(fname, S_IFSOCK | 0777, 0);
- if (i == 0)
- i = open_namei(fname, 0, S_IFSOCK, &upd->inode);
- set_fs(old_fs);
- if (i < 0) {
- printk("unix_proto_bind: can't open socket %s\n", fname);
- return i;
- }
-
- upd->sockaddr_len = sockaddr_len; /* now its legal */
- PRINTK("unix_proto_bind: bound socket address: ");
-#ifdef SOCK_DEBUG
- sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
-#endif
- return 0;
-}
-
-/*
- * perform a connection. we can only connect to unix sockets (i can't for
- * the life of me find an application where that wouldn't be the case!)
- */
-static int
-unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len)
-{
- int i;
- struct unix_proto_data *serv_upd;
- struct sockaddr_un sockun;
-
- PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
- sockaddr_len);
- if (sockaddr_len <= UN_PATH_OFFSET ||
- sockaddr_len >= sizeof(struct sockaddr_un)) {
- PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
- return -EINVAL;
- }
- verify_area(uservaddr, sockaddr_len);
- memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
- if (sockun.sun_family != AF_UNIX) {
- PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
- sockun.sun_family, AF_UNIX);
- return -EINVAL;
- }
- if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
- PRINTK("unix_proto_connect: can't locate peer\n");
- return -EINVAL;
- }
- if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
- PRINTK("unix_proto_connect: can't await connection\n");
- return i;
- }
- unix_data_ref(UN_DATA(sock->conn));
- UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
- return 0;
-}
-
-/*
- * to do a socketpair, we make just connect the two datas, easy! since we
- * always wait on the socket inode, they're no contention for a wait area,
- * and deadlock prevention in the case of a process writing to itself is,
- * ignored, in true unix fashion!
- */
-static int
-unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
-{
- struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
-
- unix_data_ref(upd1);
- unix_data_ref(upd2);
- upd1->peerupd = upd2;
- upd2->peerupd = upd1;
- return 0;
-}
-
-/*
- * on accept, we ref the peer's data for safe writes
- */
-static int
-unix_proto_accept(struct socket *sock, struct socket *newsock)
-{
- PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
- sock, newsock);
- unix_data_ref(UN_DATA(newsock->conn));
- UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
- return 0;
-}
-
-/*
- * gets the current name or the name of the connected socket.
- */
-static int
-unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
- int *usockaddr_len, int peer)
-{
- struct unix_proto_data *upd;
- int len;
-
- PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
- peer ? "peer" : "self");
- if (peer) {
- if (sock->state != SS_CONNECTED) {
- PRINTK("unix_proto_getname: socket not connected\n");
- return -EINVAL;
- }
- upd = UN_DATA(sock->conn);
- }
- else
- upd = UN_DATA(sock);
- verify_area(usockaddr_len, sizeof(*usockaddr_len));
- if ((len = get_fs_long(usockaddr_len)) <= 0)
- return -EINVAL;
- if (len > upd->sockaddr_len)
- len = upd->sockaddr_len;
- if (len) {
- verify_area(usockaddr, len);
- memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
- }
- put_fs_long(len, usockaddr_len);
- return 0;
-}
-
-/*
- * we read from our own buf.
- */
-static int
-unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
-{
- struct unix_proto_data *upd;
- int todo, avail;
-
- if ((todo = size) <= 0)
- return 0;
- upd = UN_DATA(sock);
- while (!(avail = UN_BUF_AVAIL(upd))) {
- if (sock->state != SS_CONNECTED) {
- PRINTK("unix_proto_read: socket not connected\n");
- return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
- }
- PRINTK("unix_proto_read: no data available...\n");
- if (nonblock)
- return -EAGAIN;
- interruptible_sleep_on(sock->wait);
- if (current->signal & ~current->blocked) {
- PRINTK("unix_proto_read: interrupted\n");
- return -ERESTARTSYS;
- }
- if (sock->state == SS_DISCONNECTING) {
- PRINTK("unix_proto_read: disconnected\n");
- return 0;
- }
- }
-
- /*
- * copy from the read buffer into the user's buffer, watching for
- * wraparound. then we wake up the writer
- */
- do {
- int part, cando;
-
- if (avail <= 0) {
- PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
- send_sig(SIGKILL,current,1);
- return -EINTR;
- }
-
- if ((cando = todo) > avail)
- cando = avail;
- if (cando > (part = BUF_SIZE - upd->bp_tail))
- cando = part;
- PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
- avail, todo, cando);
- verify_area(ubuf, cando);
- memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
- upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
- ubuf += cando;
- todo -= cando;
- if (sock->state == SS_CONNECTED)
- wake_up(sock->conn->wait);
- avail = UN_BUF_AVAIL(upd);
- } while (todo && avail);
- return size - todo;
-}
-
-/*
- * we write to our peer's buf. when we connected we ref'd this peer so we
- * are safe that the buffer remains, even after the peer has disconnected,
- * which we check other ways.
- */
-static int
-unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
-{
- struct unix_proto_data *pupd;
- int todo, space;
-
- if ((todo = size) <= 0)
- return 0;
- if (sock->state != SS_CONNECTED) {
- PRINTK("unix_proto_write: socket not connected\n");
- if (sock->state == SS_DISCONNECTING) {
- send_sig(SIGPIPE,current,1);
- return -EINTR;
- }
- return -EINVAL;
- }
- pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */
-
- while (!(space = UN_BUF_SPACE(pupd))) {
- PRINTK("unix_proto_write: no space left...\n");
- if (nonblock)
- return -EAGAIN;
- interruptible_sleep_on(sock->wait);
- if (current->signal & ~current->blocked) {
- PRINTK("unix_proto_write: interrupted\n");
- return -ERESTARTSYS;
- }
- if (sock->state == SS_DISCONNECTING) {
- PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
- send_sig(SIGPIPE,current,1);
- return -EINTR;
- }
- }
-
- /*
- * copy from the user's buffer to the write buffer, watching for
- * wraparound. then we wake up the reader
- */
- do {
- int part, cando;
-
- if (space <= 0) {
- PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
- send_sig(SIGKILL,current,1);
- return -EINTR;
- }
-
- /*
- * we may become disconnected inside this loop, so watch
- * for it (peerupd is safe until we close)
- */
- if (sock->state == SS_DISCONNECTING) {
- send_sig(SIGPIPE,current,1);
- return -EINTR;
- }
- if ((cando = todo) > space)
- cando = space;
- if (cando > (part = BUF_SIZE - pupd->bp_head))
- cando = part;
- PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
- space, todo, cando);
- verify_area(ubuf, cando);
- memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
- pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
- ubuf += cando;
- todo -= cando;
- if (sock->state == SS_CONNECTED)
- wake_up(sock->conn->wait);
- space = UN_BUF_SPACE(pupd);
- } while (todo && space);
- return size - todo;
-}
-
-static int
-unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
-{
- struct unix_proto_data *upd, *peerupd;
-
- if (sel_type == SEL_IN) {
- upd = UN_DATA(sock);
- PRINTK("unix_proto_select: there is%s data available\n",
- UN_BUF_AVAIL(upd) ? "" : " no");
- if (UN_BUF_AVAIL(upd)) /* even if disconnected */
- return 1;
- else if (sock->state != SS_CONNECTED) {
- PRINTK("unix_proto_select: socket not connected (read EOF)\n");
- return 1;
- }
- select_wait(sock->wait,wait);
- return 0;
- }
- if (sel_type == SEL_OUT) {
- if (sock->state != SS_CONNECTED) {
- PRINTK("unix_proto_select: socket not connected (write EOF)\n");
- return 1;
- }
- peerupd = UN_DATA(sock->conn);
- PRINTK("unix_proto_select: there is%s space available\n",
- UN_BUF_SPACE(peerupd) ? "" : " no");
- if (UN_BUF_SPACE(peerupd) > 0)
- return 1;
- select_wait(sock->wait,wait);
- return 0;
- }
- /* SEL_EX */
- PRINTK("unix_proto_select: there are no exceptions here?!\n");
- return 0;
-}
-
-static int
-unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct unix_proto_data *upd, *peerupd;
-
- upd = UN_DATA(sock);
- peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
-
- switch (cmd) {
- case TIOCINQ:
- verify_area((void *)arg, sizeof(unsigned long));
- if (UN_BUF_AVAIL(upd) || peerupd)
- put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
- else
- put_fs_long(1, (unsigned long *)arg); /* read EOF */
- break;
-
- case TIOCOUTQ:
- verify_area((void *)arg, sizeof(unsigned long));
- if (peerupd)
- put_fs_long(UN_BUF_SPACE(peerupd),
- (unsigned long *)arg);
- else
- put_fs_long(0, (unsigned long *)arg);
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int
-unix_proto_init(void)
-{
- struct unix_proto_data *upd;
-
- PRINTK("unix_proto_init: initializing...\n");
- for (upd = unix_datas; upd <= last_unix_data; ++upd)
- upd->refcnt = 0;
- return 0;
-}
#define MINIX_HEADER 32
#define GCC_HEADER 1024
-#define SYS_SIZE 0x5000
+#define SYS_SIZE 0x4000
#define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0
}
fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
if ((major_root != 2) && (major_root != 3) &&
- (major_root != 8) && (major_root != 0)) {
+ (major_root != 0)) {
fprintf(stderr, "Illegal root device (major = %d)\n",
major_root);
die("Bad root device --- major #");