initial version
This commit is contained in:
88
Book-Lite/linux-0.12/kernel/chr_drv/Makefile
Normal file
88
Book-Lite/linux-0.12/kernel/chr_drv/Makefile
Normal file
@@ -0,0 +1,88 @@
|
||||
#
|
||||
# Makefile for the FREAX-kernel character 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).
|
||||
#
|
||||
|
||||
AR =gar
|
||||
AS =gas
|
||||
LD =gld
|
||||
LDFLAGS =-s -x
|
||||
CC =gcc
|
||||
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
|
||||
-finline-functions -mstring-insns -nostdinc -I../../include
|
||||
CPP =gcc -E -nostdinc -I../../include
|
||||
|
||||
.c.s:
|
||||
$(CC) $(CFLAGS) \
|
||||
-S -o $*.s $<
|
||||
.s.o:
|
||||
$(AS) -c -o $*.o $<
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) \
|
||||
-c -o $*.o $<
|
||||
|
||||
OBJS = tty_io.o console.o keyboard.o serial.o rs_io.o \
|
||||
tty_ioctl.o pty.o
|
||||
|
||||
chr_drv.a: $(OBJS)
|
||||
$(AR) rcs chr_drv.a $(OBJS)
|
||||
sync
|
||||
|
||||
keyboard.s: keyboard.S
|
||||
$(CPP) -traditional keyboard.S -o keyboard.s
|
||||
|
||||
clean:
|
||||
rm -f core *.o *.a tmp_make keyboard.s
|
||||
for i in *.c;do rm -f `basename $$i .c`.s;done
|
||||
|
||||
dep:
|
||||
sed '/\#\#\# Dependencies/q' < Makefile > 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.s console.o : console.c ../../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/tty.h \
|
||||
../../include/termios.h ../../include/linux/config.h ../../include/asm/io.h \
|
||||
../../include/asm/system.h ../../include/asm/segment.h \
|
||||
../../include/string.h ../../include/errno.h
|
||||
pty.s pty.o : pty.c ../../include/linux/tty.h ../../include/termios.h \
|
||||
../../include/sys/types.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/asm/system.h ../../include/asm/io.h
|
||||
serial.s serial.o : serial.c ../../include/linux/tty.h ../../include/termios.h \
|
||||
../../include/sys/types.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/asm/system.h ../../include/asm/io.h
|
||||
tty_io.s tty_io.o : tty_io.c ../../include/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/linux/sched.h \
|
||||
../../include/linux/head.h ../../include/linux/fs.h \
|
||||
../../include/linux/mm.h ../../include/linux/kernel.h \
|
||||
../../include/linux/tty.h ../../include/termios.h \
|
||||
../../include/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/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
|
||||
1025
Book-Lite/linux-0.12/kernel/chr_drv/console.c
Normal file
1025
Book-Lite/linux-0.12/kernel/chr_drv/console.c
Normal file
File diff suppressed because it is too large
Load Diff
599
Book-Lite/linux-0.12/kernel/chr_drv/keyboard.S
Normal file
599
Book-Lite/linux-0.12/kernel/chr_drv/keyboard.S
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* linux/kernel/keyboard.S
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to Alfred Leung for US keyboard patches
|
||||
* Wolfgang Thiel for German keyboard patches
|
||||
* Marc Corsini for the French keyboard
|
||||
*/
|
||||
|
||||
/* KBD_FINNISH for Finnish keyboards
|
||||
* KBD_US for US-type
|
||||
* KBD_GR for German keyboards
|
||||
* KBD_FR for Frech keyboard
|
||||
*/
|
||||
#define KBD_FINNISH
|
||||
|
||||
.text
|
||||
.globl _keyboard_interrupt
|
||||
|
||||
/*
|
||||
* these are for the keyboard read functions
|
||||
*/
|
||||
size = 1024 /* 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
|
||||
|
||||
mode: .byte 0 /* caps, alt, ctrl and shift mode */
|
||||
leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
|
||||
e0: .byte 0
|
||||
|
||||
/*
|
||||
* con_int is the real interrupt routine that reads the
|
||||
* keyboard scan-code and converts it into the appropriate
|
||||
* ascii character(s).
|
||||
*/
|
||||
_keyboard_interrupt:
|
||||
pushl %eax
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
push %ds
|
||||
push %es
|
||||
movl $0x10,%eax
|
||||
mov %ax,%ds
|
||||
mov %ax,%es
|
||||
movl _blankinterval,%eax
|
||||
movl %eax,_blankcount
|
||||
xorl %eax,%eax /* %eax is scan code */
|
||||
inb $0x60,%al
|
||||
cmpb $0xe0,%al
|
||||
je set_e0
|
||||
cmpb $0xe1,%al
|
||||
je set_e1
|
||||
call key_table(,%eax,4)
|
||||
movb $0,e0
|
||||
e0_e1: 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
|
||||
movb $0x20,%al
|
||||
outb %al,$0x20
|
||||
pushl $0
|
||||
call _do_tty_interrupt
|
||||
addl $4,%esp
|
||||
pop %es
|
||||
pop %ds
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
popl %eax
|
||||
iret
|
||||
set_e0: movb $1,e0
|
||||
jmp e0_e1
|
||||
set_e1: movb $2,e0
|
||||
jmp e0_e1
|
||||
|
||||
/*
|
||||
* 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,e0
|
||||
je 2f
|
||||
addb %al,%al
|
||||
2: orb %al,mode
|
||||
ret
|
||||
unctrl: movb $0x04,%al
|
||||
jmp 1f
|
||||
unalt: movb $0x10,%al
|
||||
1: cmpb $0,e0
|
||||
je 2f
|
||||
addb %al,%al
|
||||
2: notb %al
|
||||
andb %al,mode
|
||||
ret
|
||||
|
||||
lshift:
|
||||
orb $0x01,mode
|
||||
ret
|
||||
unlshift:
|
||||
andb $0xfe,mode
|
||||
ret
|
||||
rshift:
|
||||
orb $0x02,mode
|
||||
ret
|
||||
unrshift:
|
||||
andb $0xfd,mode
|
||||
ret
|
||||
|
||||
caps: testb $0x80,mode
|
||||
jne 1f
|
||||
xorb $4,leds
|
||||
xorb $0x40,mode
|
||||
orb $0x80,mode
|
||||
set_leds:
|
||||
call kb_wait
|
||||
movb $0xed,%al /* set leds command */
|
||||
outb %al,$0x60
|
||||
call kb_wait
|
||||
movb leds,%al
|
||||
outb %al,$0x60
|
||||
ret
|
||||
uncaps: andb $0x7f,mode
|
||||
ret
|
||||
scroll:
|
||||
testb $0x03,mode
|
||||
je 1f
|
||||
call _show_mem
|
||||
jmp 2f
|
||||
1: call _show_state
|
||||
2: xorb $1,leds
|
||||
jmp set_leds
|
||||
num: xorb $2,leds
|
||||
jmp set_leds
|
||||
|
||||
/*
|
||||
* curosr-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,mode
|
||||
je cur2
|
||||
testb $0x30,mode
|
||||
jne reboot
|
||||
cur2: cmpb $0x01,e0 /* e0 forces cursor movement */
|
||||
je cur
|
||||
testb $0x02,leds /* not num-lock forces cursor */
|
||||
je cur
|
||||
testb $0x03,mode /* shift forces cursor */
|
||||
jne cur
|
||||
xorl %ebx,%ebx
|
||||
movb num_table(%eax),%al
|
||||
jmp put_queue
|
||||
1: ret
|
||||
|
||||
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
|
||||
jmp put_queue
|
||||
|
||||
#if defined(KBD_FR)
|
||||
num_table:
|
||||
.ascii "789 456 1230."
|
||||
#else
|
||||
num_table:
|
||||
.ascii "789 456 1230,"
|
||||
#endif
|
||||
cur_table:
|
||||
.ascii "HA5 DGC YB623"
|
||||
|
||||
/*
|
||||
* 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,mode
|
||||
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@\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_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_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
|
||||
|
||||
#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,mode /* alt-gr */
|
||||
jne 1f
|
||||
lea shift_map,%ebx
|
||||
testb $0x03,mode
|
||||
jne 1f
|
||||
lea key_map,%ebx
|
||||
1: movb (%ebx,%eax),%al
|
||||
orb %al,%al
|
||||
je none
|
||||
testb $0x4c,mode /* ctrl or caps */
|
||||
je 2f
|
||||
cmpb $'a,%al
|
||||
jb 2f
|
||||
cmpb $'},%al
|
||||
ja 2f
|
||||
subb $32,%al
|
||||
2: testb $0x0c,mode /* ctrl */
|
||||
je 3f
|
||||
cmpb $64,%al
|
||||
jb 3f
|
||||
cmpb $64+32,%al
|
||||
jae 3f
|
||||
subb $64,%al
|
||||
3: testb $0x10,mode /* left alt */
|
||||
je 4f
|
||||
orb $0x80,%al
|
||||
4: andl $0xff,%eax
|
||||
xorl %ebx,%ebx
|
||||
call put_queue
|
||||
none: ret
|
||||
|
||||
/*
|
||||
* minus has a routine of it's own, as a 'E0h' before
|
||||
* the scan code for minus means that the numeric keypad
|
||||
* slash was pushed.
|
||||
*/
|
||||
minus: cmpb $1,e0
|
||||
jne do_self
|
||||
movl $'/,%eax
|
||||
xorl %ebx,%ebx
|
||||
jmp put_queue
|
||||
|
||||
/*
|
||||
* 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 do_self,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,minus,rshift,do_self /* 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,do_self,cursor /* 48-4B up pgup - left */
|
||||
.long cursor,cursor,do_self,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.
|
||||
* there is no timeout - if the buffer doesn't empty, we hang.
|
||||
*/
|
||||
kb_wait:
|
||||
pushl %eax
|
||||
1: inb $0x64,%al
|
||||
testb $0x02,%al
|
||||
jne 1b
|
||||
popl %eax
|
||||
ret
|
||||
/*
|
||||
* This routine reboots the machine by asking the keyboard
|
||||
* controller to pulse the reset-line low.
|
||||
*/
|
||||
reboot:
|
||||
call kb_wait
|
||||
movw $0x1234,0x472 /* don't do memory check */
|
||||
movb $0xfc,%al /* pulse reset and A20 low */
|
||||
outb %al,$0x64
|
||||
die: jmp die
|
||||
63
Book-Lite/linux-0.12/kernel/chr_drv/pty.c
Normal file
63
Book-Lite/linux-0.12/kernel/chr_drv/pty.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* linux/kernel/chr_drv/pty.c
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* pty.c
|
||||
*
|
||||
* This module implements the pty functions
|
||||
* void mpty_write(struct tty_struct * queue);
|
||||
* void spty_write(struct tty_struct * queue);
|
||||
*/
|
||||
|
||||
#include <linux/tty.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (!from->stopped && !EMPTY(from->write_q)) {
|
||||
if (FULL(to->read_q)) {
|
||||
if (FULL(to->secondary))
|
||||
break;
|
||||
copy_to_cooked(to);
|
||||
continue;
|
||||
}
|
||||
GETCH(from->write_q,c);
|
||||
PUTCH(c,to->read_q);
|
||||
if (current->signal & ~current->blocked)
|
||||
break;
|
||||
}
|
||||
copy_to_cooked(to);
|
||||
wake_up(&from->write_q->proc_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine gets called when tty_write has put something into
|
||||
* the write_queue. It copies the input to the output-queue of it's
|
||||
* slave.
|
||||
*/
|
||||
void mpty_write(struct tty_struct * tty)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int nr = tty - tty_table;
|
||||
|
||||
if ((nr >> 6) != 3)
|
||||
printk("bad spty\n\r");
|
||||
else
|
||||
pty_copy(tty,tty-64);
|
||||
}
|
||||
148
Book-Lite/linux-0.12/kernel/chr_drv/rs_io.s
Normal file
148
Book-Lite/linux-0.12/kernel/chr_drv/rs_io.s
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 = 1024 /* 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.
|
||||
*/
|
||||
.align 2
|
||||
_rs1_interrupt:
|
||||
pushl $_table_list+8
|
||||
jmp rs_int
|
||||
.align 2
|
||||
_rs2_interrupt:
|
||||
pushl $_table_list+16
|
||||
rs_int:
|
||||
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
|
||||
movl (%edx),%edx
|
||||
movl rs_addr(%edx),%edx
|
||||
addl $2,%edx /* interrupt ident. reg */
|
||||
rep_int:
|
||||
xorl %eax,%eax
|
||||
inb %dx,%al
|
||||
testb $1,%al
|
||||
jne end
|
||||
cmpb $6,%al /* this shouldn't happen, but ... */
|
||||
ja end
|
||||
movl 24(%esp),%ecx
|
||||
pushl %edx
|
||||
subl $2,%edx
|
||||
call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
|
||||
popl %edx
|
||||
jmp rep_int
|
||||
end: movb $0x20,%al
|
||||
outb %al,$0x20 /* EOI */
|
||||
pop %ds
|
||||
pop %es
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
addl $4,%esp # jump over _table_list entry
|
||||
iret
|
||||
|
||||
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: addl $63,%edx
|
||||
pushl %edx
|
||||
call _do_tty_interrupt
|
||||
addl $4,%esp
|
||||
ret
|
||||
|
||||
.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
|
||||
59
Book-Lite/linux-0.12/kernel/chr_drv/serial.c
Normal file
59
Book-Lite/linux-0.12/kernel/chr_drv/serial.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* linux/kernel/serial.c
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* serial.c
|
||||
*
|
||||
* This module implements the rs232 io functions
|
||||
* void rs_write(struct tty_struct * queue);
|
||||
* void rs_init(void);
|
||||
* and all interrupts pertaining to serial IO.
|
||||
*/
|
||||
|
||||
#include <linux/tty.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define WAKEUP_CHARS (TTY_BUF_SIZE/4)
|
||||
|
||||
extern void rs1_interrupt(void);
|
||||
extern void rs2_interrupt(void);
|
||||
|
||||
static void init(int port)
|
||||
{
|
||||
outb_p(0x80,port+3); /* set DLAB of line control reg */
|
||||
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(0x0b,port+4); /* set DTR,RTS, OUT_2 */
|
||||
outb_p(0x0d,port+1); /* enable all intrs but writes */
|
||||
(void)inb(port); /* read data port to reset things (?) */
|
||||
}
|
||||
|
||||
void rs_init(void)
|
||||
{
|
||||
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);
|
||||
outb(inb_p(0x21)&0xE7,0x21);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine gets called when tty_write has put something into
|
||||
* the write_queue. It must check wheter the queue is empty, and
|
||||
* set the interrupt register accordingly
|
||||
*
|
||||
* void _rs_write(struct tty_struct * tty);
|
||||
*/
|
||||
void rs_write(struct tty_struct * tty)
|
||||
{
|
||||
cli();
|
||||
if (!EMPTY(tty->write_q))
|
||||
outb(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
|
||||
sti();
|
||||
}
|
||||
484
Book-Lite/linux-0.12/kernel/chr_drv/tty_io.c
Normal file
484
Book-Lite/linux-0.12/kernel/chr_drv/tty_io.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* linux/kernel/tty_io.c
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
|
||||
* or rs-channels. It also implements echoing, cooked mode etc.
|
||||
*
|
||||
* Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ALRMMASK (1<<(SIGALRM-1))
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/tty.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
int kill_pg(int pgrp, int sig, int priv);
|
||||
int is_orphaned_pgrp(int pgrp);
|
||||
|
||||
#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_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 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*(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*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)
|
||||
|
||||
int fg_console = 0;
|
||||
|
||||
/*
|
||||
* these are the tables used by the machine code handlers.
|
||||
* you can implement virtual consoles.
|
||||
*/
|
||||
struct tty_queue * table_list[]={
|
||||
con_queues + 0, con_queues + 1,
|
||||
rs_queues + 0, rs_queues + 1,
|
||||
rs_queues + 3, rs_queues + 4
|
||||
};
|
||||
|
||||
void change_console(unsigned int new_console)
|
||||
{
|
||||
if (new_console == fg_console || new_console >= NR_CONSOLES)
|
||||
return;
|
||||
fg_console = new_console;
|
||||
table_list[0] = con_queues + 0 + fg_console*3;
|
||||
table_list[1] = con_queues + 1 + fg_console*3;
|
||||
update_screen();
|
||||
}
|
||||
|
||||
static void sleep_if_empty(struct tty_queue * queue)
|
||||
{
|
||||
cli();
|
||||
while (!(current->signal & ~current->blocked) && EMPTY(queue))
|
||||
interruptible_sleep_on(&queue->proc_list);
|
||||
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)
|
||||
{
|
||||
signed char c;
|
||||
|
||||
if (!(tty->read_q || tty->write_q || tty->secondary)) {
|
||||
printk("copy_to_cooked: missing queues\n\r");
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
if (EMPTY(tty->read_q))
|
||||
break;
|
||||
if (FULL(tty->secondary))
|
||||
break;
|
||||
GETCH(tty->read_q,c);
|
||||
if (c==13) {
|
||||
if (I_CRNL(tty))
|
||||
c=10;
|
||||
else if (I_NOCR(tty))
|
||||
continue;
|
||||
} else if (c==10 && I_NLCR(tty))
|
||||
c=13;
|
||||
if (I_UCLC(tty))
|
||||
c=tolower(c);
|
||||
if (L_CANON(tty)) {
|
||||
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) != _POSIX_VDISABLE) &&
|
||||
(c==EOF_CHAR(tty))))) {
|
||||
if (L_ECHO(tty)) {
|
||||
if (c<32)
|
||||
PUTCH(127,tty->write_q);
|
||||
PUTCH(127,tty->write_q);
|
||||
tty->write(tty);
|
||||
}
|
||||
DEC(tty->secondary->head);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((ERASE_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==ERASE_CHAR(tty))) {
|
||||
if (EMPTY(tty->secondary) ||
|
||||
(c=LAST(tty->secondary))==10 ||
|
||||
((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==EOF_CHAR(tty))))
|
||||
continue;
|
||||
if (L_ECHO(tty)) {
|
||||
if (c<32)
|
||||
PUTCH(127,tty->write_q);
|
||||
PUTCH(127,tty->write_q);
|
||||
tty->write(tty);
|
||||
}
|
||||
DEC(tty->secondary->head);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (I_IXON(tty)) {
|
||||
if ((STOP_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==STOP_CHAR(tty))) {
|
||||
tty->stopped=1;
|
||||
tty->write(tty);
|
||||
continue;
|
||||
}
|
||||
if ((START_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==START_CHAR(tty))) {
|
||||
tty->stopped=0;
|
||||
tty->write(tty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (L_ISIG(tty)) {
|
||||
if ((INTR_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==INTR_CHAR(tty))) {
|
||||
kill_pg(tty->pgrp, SIGINT, 1);
|
||||
continue;
|
||||
}
|
||||
if ((QUIT_CHAR(tty) != _POSIX_VDISABLE) &&
|
||||
(c==QUIT_CHAR(tty))) {
|
||||
kill_pg(tty->pgrp, SIGQUIT, 1);
|
||||
continue;
|
||||
}
|
||||
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) != _POSIX_VDISABLE &&
|
||||
c==EOF_CHAR(tty)))
|
||||
tty->secondary->data++;
|
||||
if (L_ECHO(tty)) {
|
||||
if (c==10) {
|
||||
PUTCH(10,tty->write_q);
|
||||
PUTCH(13,tty->write_q);
|
||||
} else if (c<32) {
|
||||
if (L_ECHOCTL(tty)) {
|
||||
PUTCH('^',tty->write_q);
|
||||
PUTCH(c+64,tty->write_q);
|
||||
}
|
||||
} else
|
||||
PUTCH(c,tty->write_q);
|
||||
tty->write(tty);
|
||||
}
|
||||
PUTCH(c,tty->secondary);
|
||||
}
|
||||
wake_up(&tty->secondary->proc_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we need to send a SIGTTIN or SIGTTOU to our process
|
||||
* group
|
||||
*
|
||||
* We only request that a system call be restarted if there was if the
|
||||
* default signal handler is being used. The reason for this is that if
|
||||
* a job is catching SIGTTIN or SIGTTOU, the signal handler may not want
|
||||
* the system call to be restarted blindly. If there is no way to reset the
|
||||
* terminal pgrp back to the current pgrp (perhaps because the controlling
|
||||
* tty has been released on logout), we don't want to be in an infinite loop
|
||||
* while restarting the system call, and have it always generate a SIGTTIN
|
||||
* or SIGTTOU. The default signal handler will cause the process to stop
|
||||
* thus avoiding the infinite loop problem. Presumably the job-control
|
||||
* cognizant parent will fix things up before continuging its child process.
|
||||
*/
|
||||
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);
|
||||
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) */
|
||||
}
|
||||
|
||||
int tty_read(unsigned channel, char * buf, int nr)
|
||||
{
|
||||
struct tty_struct * tty;
|
||||
struct tty_struct * other_tty = NULL;
|
||||
char c, * b=buf;
|
||||
int minimum,time;
|
||||
|
||||
if (channel > 255)
|
||||
return -EIO;
|
||||
tty = TTY_TABLE(channel);
|
||||
if (!(tty->write_q || tty->read_q || tty->secondary))
|
||||
return -EIO;
|
||||
if ((current->tty == channel) && (tty->pgrp != current->pgrp))
|
||||
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 {
|
||||
minimum = nr;
|
||||
if (time)
|
||||
current->timeout = time + jiffies;
|
||||
time = 0;
|
||||
}
|
||||
if (minimum>nr)
|
||||
minimum = nr;
|
||||
while (nr>0) {
|
||||
if (other_tty)
|
||||
other_tty->write(other_tty);
|
||||
cli();
|
||||
if (EMPTY(tty->secondary) || (L_CANON(tty) &&
|
||||
!FULL(tty->read_q) && !tty->secondary->data)) {
|
||||
if (!current->timeout ||
|
||||
(current->signal & ~current->blocked)) {
|
||||
sti();
|
||||
break;
|
||||
}
|
||||
if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
|
||||
break;
|
||||
interruptible_sleep_on(&tty->secondary->proc_list);
|
||||
sti();
|
||||
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) != _POSIX_VDISABLE &&
|
||||
c==EOF_CHAR(tty)) && L_CANON(tty))
|
||||
break;
|
||||
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 (time)
|
||||
current->timeout = time+jiffies;
|
||||
if (L_CANON(tty) || b-buf >= minimum)
|
||||
break;
|
||||
}
|
||||
current->timeout = 0;
|
||||
if ((current->signal & ~current->blocked) && !(b-buf))
|
||||
return -ERESTARTSYS;
|
||||
return (b-buf);
|
||||
}
|
||||
|
||||
int tty_write(unsigned channel, 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 (!(tty->write_q || tty->read_q || tty->secondary))
|
||||
return -EIO;
|
||||
if (L_TOSTOP(tty) &&
|
||||
(current->tty == channel) && (tty->pgrp != current->pgrp))
|
||||
return(tty_signal(SIGTTOU, tty));
|
||||
while (nr>0) {
|
||||
sleep_if_full(tty->write_q);
|
||||
if (current->signal & ~current->blocked)
|
||||
break;
|
||||
while (nr>0 && !FULL(tty->write_q)) {
|
||||
c=get_fs_byte(b);
|
||||
if (O_POST(tty)) {
|
||||
if (c=='\r' && O_CRNL(tty))
|
||||
c='\n';
|
||||
else if (c=='\n' && O_NLRET(tty))
|
||||
c='\r';
|
||||
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--;
|
||||
cr_flag = 0;
|
||||
PUTCH(c,tty->write_q);
|
||||
}
|
||||
tty->write(tty);
|
||||
if (nr>0)
|
||||
schedule();
|
||||
}
|
||||
return (b-buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jeh, sometimes I really like the 386.
|
||||
* This routine is called from an interrupt,
|
||||
* and there should be absolutely no problem
|
||||
* with sleeping even in an interrupt (I hope).
|
||||
* Of course, if somebody proves me wrong, I'll
|
||||
* hate intel for all time :-). We'll have to
|
||||
* be careful and see to reinstating the interrupt
|
||||
* chips before calling this, though.
|
||||
*
|
||||
* I don't think we sleep here under normal circumstances
|
||||
* anyway, which is good, as the task sleeping might be
|
||||
* totally innocent.
|
||||
*/
|
||||
void do_tty_interrupt(int tty)
|
||||
{
|
||||
copy_to_cooked(TTY_TABLE(tty));
|
||||
}
|
||||
|
||||
void chr_dev_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tty_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
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,""};
|
||||
for (i=0 ; i<256 ; i++) {
|
||||
tty_table[i] = (struct tty_struct) {
|
||||
{0, 0, 0, 0, 0, INIT_C_CC},
|
||||
0, 0, 0, NULL, NULL, NULL, NULL
|
||||
};
|
||||
}
|
||||
con_init();
|
||||
for (i = 0 ; i<NR_CONSOLES ; i++) {
|
||||
con_table[i] = (struct tty_struct) {
|
||||
{ICRNL, /* change incoming CR to NL */
|
||||
OPOST|ONLCR, /* change outgoing NL to CRNL */
|
||||
0,
|
||||
IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
|
||||
0, /* console termio */
|
||||
INIT_C_CC},
|
||||
0, /* initial pgrp */
|
||||
0, /* initial session */
|
||||
0, /* initial stopped */
|
||||
con_write,
|
||||
con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
|
||||
};
|
||||
}
|
||||
for (i = 0 ; i<NR_SERIALS ; i++) {
|
||||
rs_table[i] = (struct tty_struct) {
|
||||
{0, /* no translation */
|
||||
0, /* no translation */
|
||||
B2400 | CS8,
|
||||
0,
|
||||
0,
|
||||
INIT_C_CC},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
rs_write,
|
||||
rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3
|
||||
};
|
||||
}
|
||||
for (i = 0 ; i<NR_PTYS ; i++) {
|
||||
mpty_table[i] = (struct tty_struct) {
|
||||
{0, /* no translation */
|
||||
0, /* no translation */
|
||||
B9600 | CS8,
|
||||
0,
|
||||
0,
|
||||
INIT_C_CC},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
mpty_write,
|
||||
mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
|
||||
};
|
||||
spty_table[i] = (struct tty_struct) {
|
||||
{0, /* no translation */
|
||||
0, /* no translation */
|
||||
B9600 | CS8,
|
||||
IXON | ISIG | ICANON,
|
||||
0,
|
||||
INIT_C_CC},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
spty_write,
|
||||
spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
|
||||
};
|
||||
}
|
||||
rs_init();
|
||||
printk("%d virtual consoles\n\r",NR_CONSOLES);
|
||||
printk("%d pty's\n\r",NR_PTYS);
|
||||
}
|
||||
251
Book-Lite/linux-0.12/kernel/chr_drv/tty_ioctl.c
Normal file
251
Book-Lite/linux-0.12/kernel/chr_drv/tty_ioctl.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* linux/kernel/chr_drv/tty_ioctl.c
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
extern int session_of_pgrp(int pgrp);
|
||||
extern int tty_signal(int sig, struct tty_struct *tty);
|
||||
|
||||
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)
|
||||
{
|
||||
cli();
|
||||
queue->head = queue->tail;
|
||||
sti();
|
||||
}
|
||||
|
||||
static void wait_until_sent(struct tty_struct * tty)
|
||||
{
|
||||
/* do nothing - not implemented */
|
||||
}
|
||||
|
||||
static void send_break(struct tty_struct * tty)
|
||||
{
|
||||
/* do nothing - not implemented */
|
||||
}
|
||||
|
||||
static int get_termios(struct tty_struct * tty, struct termios * termios)
|
||||
{
|
||||
int i;
|
||||
|
||||
verify_area(termios, sizeof (*termios));
|
||||
for (i=0 ; i< (sizeof (*termios)) ; i++)
|
||||
put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_termios(struct tty_struct * tty, struct termios * termios,
|
||||
int channel)
|
||||
{
|
||||
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)) {
|
||||
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);
|
||||
change_speed(tty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_termio(struct tty_struct * tty, struct termio * termio)
|
||||
{
|
||||
int i;
|
||||
struct termio tmp_termio;
|
||||
|
||||
verify_area(termio, sizeof (*termio));
|
||||
tmp_termio.c_iflag = tty->termios.c_iflag;
|
||||
tmp_termio.c_oflag = tty->termios.c_oflag;
|
||||
tmp_termio.c_cflag = tty->termios.c_cflag;
|
||||
tmp_termio.c_lflag = tty->termios.c_lflag;
|
||||
tmp_termio.c_line = tty->termios.c_line;
|
||||
for(i=0 ; i < NCC ; i++)
|
||||
tmp_termio.c_cc[i] = tty->termios.c_cc[i];
|
||||
for (i=0 ; i< (sizeof (*termio)) ; i++)
|
||||
put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This only works as the 386 is low-byt-first
|
||||
*/
|
||||
static int set_termio(struct tty_struct * tty, struct termio * termio,
|
||||
int channel)
|
||||
{
|
||||
int i, retsig;
|
||||
struct termio tmp_termio;
|
||||
|
||||
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);
|
||||
*(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
|
||||
*(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
|
||||
*(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
|
||||
*(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
|
||||
tty->termios.c_line = tmp_termio.c_line;
|
||||
for(i=0 ; i < NCC ; i++)
|
||||
tty->termios.c_cc[i] = tmp_termio.c_cc[i];
|
||||
change_speed(tty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tty_ioctl(int dev, int cmd, int arg)
|
||||
{
|
||||
struct tty_struct * tty;
|
||||
int pgrp;
|
||||
|
||||
if (MAJOR(dev) == 5) {
|
||||
dev=current->tty;
|
||||
if (dev<0)
|
||||
panic("tty_ioctl: dev<0");
|
||||
} else
|
||||
dev=MINOR(dev);
|
||||
tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
|
||||
switch (cmd) {
|
||||
case TCGETS:
|
||||
return get_termios(tty,(struct termios *) arg);
|
||||
case TCSETSF:
|
||||
flush(tty->read_q); /* fallthrough */
|
||||
case TCSETSW:
|
||||
wait_until_sent(tty); /* fallthrough */
|
||||
case TCSETS:
|
||||
return set_termios(tty,(struct termios *) arg, dev);
|
||||
case TCGETA:
|
||||
return get_termio(tty,(struct termio *) arg);
|
||||
case TCSETAF:
|
||||
flush(tty->read_q); /* fallthrough */
|
||||
case TCSETAW:
|
||||
wait_until_sent(tty); /* fallthrough */
|
||||
case TCSETA:
|
||||
return set_termio(tty,(struct termio *) arg, dev);
|
||||
case TCSBRK:
|
||||
if (!arg) {
|
||||
wait_until_sent(tty);
|
||||
send_break(tty);
|
||||
}
|
||||
return 0;
|
||||
case TCXONC:
|
||||
switch (arg) {
|
||||
case TCOOFF:
|
||||
tty->stopped = 1;
|
||||
tty->write(tty);
|
||||
return 0;
|
||||
case TCOON:
|
||||
tty->stopped = 0;
|
||||
tty->write(tty);
|
||||
return 0;
|
||||
case TCIOFF:
|
||||
if (STOP_CHAR(tty))
|
||||
PUTCH(STOP_CHAR(tty),tty->write_q);
|
||||
return 0;
|
||||
case TCION:
|
||||
if (START_CHAR(tty))
|
||||
PUTCH(START_CHAR(tty),tty->write_q);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL; /* not implemented */
|
||||
case TCFLSH:
|
||||
if (arg==0)
|
||||
flush(tty->read_q);
|
||||
else if (arg==1)
|
||||
flush(tty->write_q);
|
||||
else if (arg==2) {
|
||||
flush(tty->read_q);
|
||||
flush(tty->write_q);
|
||||
} else
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
case TIOCEXCL:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCNXCL:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCSCTTY:
|
||||
return -EINVAL; /* set controlling term NI */
|
||||
case TIOCGPGRP:
|
||||
verify_area((void *) arg,4);
|
||||
put_fs_long(tty->pgrp,(unsigned long *) arg);
|
||||
return 0;
|
||||
case TIOCSPGRP:
|
||||
if ((current->tty < 0) ||
|
||||
(current->tty != dev) ||
|
||||
(tty->session != current->session))
|
||||
return -ENOTTY;
|
||||
pgrp=get_fs_long((unsigned long *) arg);
|
||||
if (pgrp < 0)
|
||||
return -EINVAL;
|
||||
if (session_of_pgrp(pgrp) != current->session)
|
||||
return -EPERM;
|
||||
tty->pgrp = pgrp;
|
||||
return 0;
|
||||
case TIOCOUTQ:
|
||||
verify_area((void *) arg,4);
|
||||
put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
|
||||
return 0;
|
||||
case TIOCINQ:
|
||||
verify_area((void *) arg,4);
|
||||
put_fs_long(CHARS(tty->secondary),
|
||||
(unsigned long *) arg);
|
||||
return 0;
|
||||
case TIOCSTI:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCGWINSZ:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCSWINSZ:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCMGET:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCMBIS:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCMBIC:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCMSET:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCGSOFTCAR:
|
||||
return -EINVAL; /* not implemented */
|
||||
case TIOCSSOFTCAR:
|
||||
return -EINVAL; /* not implemented */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user