From 0ddfb7468beaf052932e032381cb9e6f11fe4ccc Mon Sep 17 00:00:00 2001 From: hinus Date: Thu, 12 Aug 2021 21:31:40 +0800 Subject: [PATCH] Title: ioctl, tty_ioctl Issue: https://gitee.com/hinus/linux_kernel_011/issues/I431WK Description: To support tty_ioctl for ioctl. --- fs/Makefile | 2 +- fs/ioctl.c | 5 +- fs/read_write.c | 1 + include/asm/segment.h | 48 +++-------- include/termios.h | 59 ++++++++++++- kernel/Makefile | 8 +- kernel/chr_drv/Makefile | 7 +- kernel/chr_drv/kboard.c | 8 +- kernel/chr_drv/tty_io.c | 17 +++- kernel/chr_drv/tty_ioctl.c | 168 +++++++++++++++++++++++++++++++++++++ kernel/segment.c | 38 +++++++++ kernel/sys_call.S | 9 ++ 12 files changed, 318 insertions(+), 52 deletions(-) create mode 100644 kernel/chr_drv/tty_ioctl.c create mode 100644 kernel/segment.c diff --git a/fs/Makefile b/fs/Makefile index 28fa41a..dffd2a8 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -1,6 +1,6 @@ GCC := gcc LD := ld -CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno-stack-protector -fno-pic -c -m32 +CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno-stack-protector -fno-pic -c -m32 LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include OBJS := read_write.o buffer.o super.o open.o file_table.o inode.o namei.o fcntl.o char_dev.o \ diff --git a/fs/ioctl.c b/fs/ioctl.c index 076a29a..df570f5 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -4,7 +4,7 @@ #include -int tty_ioctl(int dev, int cmd, int arg); +extern int tty_ioctl(int dev, int cmd, int arg); extern int pipe_ioctl(struct m_inode *pino, int cmd, int arg); typedef int (*ioctl_ptr)(int dev,int cmd,int arg); @@ -20,9 +20,6 @@ static ioctl_ptr ioctl_table[]={ NULL, /* /dev/lp */ NULL}; /* named pipes */ -int tty_ioctl(int dev, int cmd, int arg) { - return 0; -} int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; diff --git a/fs/read_write.c b/fs/read_write.c index 004c982..632b292 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -4,6 +4,7 @@ #include #include +#include extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); extern int read_pipe(struct m_inode * inode, char * buf, int count); diff --git a/include/asm/segment.h b/include/asm/segment.h index 8d51e34..faf0d1b 100644 --- a/include/asm/segment.h +++ b/include/asm/segment.h @@ -1,41 +1,19 @@ #ifndef _SEGMENT_H #define _SEGMENT_H -static inline unsigned char get_fs_byte(const char * addr) { - unsigned register char _v; - __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); - return _v; -} - -static inline void put_fs_byte(char val,char *addr) { - __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); -} - -extern inline unsigned long get_fs_long(const unsigned long *addr) { - unsigned long _v; - __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); - return _v; -} - -extern inline void put_fs_long(unsigned long val,unsigned long * addr) { - __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr)); -} - -extern inline unsigned long get_fs() { - unsigned short _v; - __asm__("mov %%fs,%%ax":"=a" (_v):); - return _v; -} - -extern inline unsigned long get_ds() { - unsigned short _v; - __asm__("mov %%ds,%%ax":"=a" (_v):); - return _v; -} - -extern inline void set_fs(unsigned long val) { - __asm__("mov %0,%%fs"::"a" ((unsigned short) val)); -} +inline unsigned char get_fs_byte(const char * addr); + +inline void put_fs_byte(char val,char *addr); + +inline unsigned long get_fs_long(const unsigned long *addr) ; + +inline void put_fs_long(unsigned long val,unsigned long * addr) ; + +inline unsigned long get_fs(); + +inline unsigned long get_ds(); + +inline void set_fs(unsigned long val); #endif diff --git a/include/termios.h b/include/termios.h index 1490605..6079df2 100644 --- a/include/termios.h +++ b/include/termios.h @@ -3,6 +3,16 @@ #define TTY_BUF_SIZE 1024 +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + #define NCCS 17 struct termios { unsigned short c_iflag; @@ -13,16 +23,53 @@ struct termios { unsigned char c_cc[NCCS]; }; - +#define VINTR 0 +#define VQUIT 1 #define VERASE 2 #define VKILL 3 #define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 #define VSTART 8 #define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 -#define FIONREAD 0x541B -#define TIOCINQ FIONREAD +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD // iflag #define IGNBRK 0000001 @@ -66,4 +113,10 @@ struct termios { #define PENDIN 0040000 #define IEXTEN 0100000 +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + #endif diff --git a/kernel/Makefile b/kernel/Makefile index 2d048e0..0f25438 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -3,8 +3,9 @@ CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno- LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include OBJS := head.o main.o sys_call.o asm.o sched.o printk.o vsprintf.o mktime.o \ - traps.o fork.o panic.o sys.o signal.o exit.o \ - chr_drv/chr_drv.a blk_drv/blk_drv.a ../mm/mm.o ../lib/lib.a ../fs/fs.o + traps.o fork.o panic.o sys.o signal.o exit.o segment.o \ + ../fs/fs.o ../mm/mm.o \ + chr_drv/chr_drv.a blk_drv/blk_drv.a ../lib/lib.a system: $(OBJS) $(LD) $(LDFLAG) -M -e startup_32 -o $@ $^ > System.map @@ -51,6 +52,9 @@ signal.o : signal.c exit.o : exit.c $(GCC) $(CCFLAG) -o $@ $< +segment.o : segment.c + $(GCC) $(CCFLAG) -o $@ $< + chr_drv/chr_drv.a: chr_drv/*.c cd chr_drv; make chr_drv.a; cd .. diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile index 7fbf851..4839d77 100644 --- a/kernel/chr_drv/Makefile +++ b/kernel/chr_drv/Makefile @@ -1,8 +1,8 @@ AR := ar LD := ld GCC := gcc -CCFLAG := -m32 -I../../include -nostdinc -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c -std=gnu11 -OBJS := tty_io.o console.o keyboard.o kboard.o +CCFLAG := -m32 -I../../include -nostdinc -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c +OBJS := tty_io.o console.o keyboard.o kboard.o tty_ioctl.o chr_drv.a : $(OBJS) $(AR) rcs $@ $^ @@ -20,6 +20,9 @@ keyboard.o : keyboard.S console.o : console.c $(GCC) $(CCFLAG) -o $@ $< +tty_ioctl.o : tty_ioctl.c + $(GCC) $(CCFLAG) -o $@ $< + clean : -rm *.o -rm chr_drv.a diff --git a/kernel/chr_drv/kboard.c b/kernel/chr_drv/kboard.c index 04883bc..d67272b 100644 --- a/kernel/chr_drv/kboard.c +++ b/kernel/chr_drv/kboard.c @@ -100,7 +100,7 @@ static char key_map[0x7f] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 127, 9, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', - 13, 0, + 10, 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', @@ -112,11 +112,11 @@ static char key_map[0x7f] = { 0,0,0,0,0,0,0,0,0,0}; static char shift_map[0x7f] = { - 0,27, - '!', '@', '#', '$', '%', '^', '&', '*','(',')','_','+', + 0,27, + '!', '@', '#', '$', '%', '^', '&', '*','(',')','_','+', 127,9, 'Q','W','E','R','T','Y','U','I','O','P','{','}', - 13,0, + 10,0, 'A','S','D','F','G','H','J','K','L',':','\"', '~',0, '|','Z','X','C','V','B','N','M','<','>','?', diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c index 9c3b7e9..99918aa 100644 --- a/kernel/chr_drv/tty_io.c +++ b/kernel/chr_drv/tty_io.c @@ -73,6 +73,22 @@ static void sleep_if_full(struct tty_queue * queue) { sti(); } +int tty_signal(int sig, struct tty_struct *tty) { + if (is_orphaned_pgrp(current->pgrp)) + return -EIO; + + (void) kill_pg(current->pgrp,sig,1); + if ((current->blocked & (1<<(sig-1))) || + ((int) current->sigaction[sig-1].sa_handler == 1)) + return -EIO; + + else if (current->sigaction[sig-1].sa_handler) + return -EINTR; + + else + return -ERESTARTSYS; +} + int tty_read(unsigned channel, char * buf, int nr) { struct tty_struct * tty; char c, * b=buf; @@ -99,7 +115,6 @@ int tty_read(unsigned channel, char * buf, int nr) { return (b - buf); } else { -// printk("tty_read:%c\n", c); put_fs_byte(c,b++); if (!--nr) break; diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c new file mode 100644 index 0000000..7e0c8b0 --- /dev/null +++ b/kernel/chr_drv/tty_ioctl.c @@ -0,0 +1,168 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include + +extern int tty_signal(int sig, struct tty_struct *tty); + +static void flush(struct tty_queue * queue) { + cli(); + queue->head = queue->tail; + sti(); +} + +static void wait_until_sent(struct tty_struct * tty) { +} + +static void send_break(struct tty_struct * tty) { +} + +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 ((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); + 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; +} + +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]; + return 0; +} + +int tty_ioctl(int dev, int cmd, int arg) { + struct tty_struct * tty; + + if (MAJOR(dev) == 5) { + dev=current->tty; + if (dev<0) + panic("tty_ioctl: dev<0"); + } else + dev=MINOR(dev); + + tty = tty_table + dev; + + 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; + 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; + 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; + default: + return -EINVAL; + } +} + diff --git a/kernel/segment.c b/kernel/segment.c new file mode 100644 index 0000000..35b9414 --- /dev/null +++ b/kernel/segment.c @@ -0,0 +1,38 @@ +#include + +inline unsigned char get_fs_byte(const char * addr) { + unsigned register char _v; + __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +inline void put_fs_byte(char val,char *addr) { + __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +inline unsigned long get_fs_long(const unsigned long *addr) { + unsigned long _v; + __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +inline void put_fs_long(unsigned long val,unsigned long * addr) { + __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr)); +} + +inline unsigned long get_fs() { + unsigned short _v; + __asm__("mov %%fs,%%ax":"=a" (_v):); + return _v; +} + +inline unsigned long get_ds() { + unsigned short _v; + __asm__("mov %%ds,%%ax":"=a" (_v):); + return _v; +} + +inline void set_fs(unsigned long val) { + __asm__("mov %0,%%fs"::"a" ((unsigned short) val)); +} + diff --git a/kernel/sys_call.S b/kernel/sys_call.S index f885360..8285c48 100644 --- a/kernel/sys_call.S +++ b/kernel/sys_call.S @@ -32,6 +32,9 @@ sa_restorer = 12 int_msg: .asciz "In kernel interrupt\n\r" +show_ind: + .asciz "sys call %d\n\r" + .align 4 reschedule: pushl $ret_from_sys_call @@ -52,6 +55,12 @@ system_call: movl $0x17, %edx movw %dx, %fs + pushl %eax + pushl $show_ind + call printk + popl %eax + popl %eax + call *sys_call_table(, %eax, 4) pushl %eax -- Gitee