]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.95a (March 17, 1992) 0.95a
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:00 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:00 +0000 (15:09 -0500)
Oops.  I had forgotten to change the kernel version number in 0.95 (so
it showed as 0.12).

 - 80x50 console on standard VGA
 - do "memcpy_fromfs()" and "memcpy_tofs()" rather than byte-at-a-time
   to improve performance (inspired by some earlier patches by Keith White)
 - allow select() on many more file descriptors
 - support up to 4 serial ports (and increase buffering size)
 - Branko Lankester helped make extended partitions work and implemented
   DM partition table support

The big deal in the release notes is actually that the root diskette
maintainership had been moved over to Jim Winstead Jr.

33 files changed:
Makefile
boot/setup.S
fs/block_dev.c
fs/buffer.c
fs/fasterdisk.pat [new file with mode: 0644]
fs/inode.c
fs/minix/file_dev.c
fs/minix/truncate.c
fs/select.c
include/asm/io.h
include/asm/segment.h
include/linux/config.h
include/linux/fs.h
include/linux/sched.h
include/linux/timer.h
include/linux/tty.h
include/termios.h
init/main.c
kernel/blk_drv/blk.h
kernel/blk_drv/floppy.c
kernel/blk_drv/hd.c
kernel/chr_drv/console.c
kernel/chr_drv/keyboard.S
kernel/chr_drv/rs_io.s
kernel/chr_drv/serial.c
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c
kernel/exit.c
kernel/ptrace.c
kernel/sched.c
mm/Makefile
mm/memory.c
mm/swap.c

index 8bedb81b8ebf11abc0a4eac148da4354578f7971..e397dab0ffc2725af8928e1ee25f3b9a4f30db7e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -61,28 +61,28 @@ tools/system:       boot/head.o init/main.o \
        $(LIBS) \
        -o tools/system > System.map
 
-kernel/math/math.a:
+kernel/math/math.a: dummy
        (cd kernel/math; make)
 
-kernel/blk_drv/blk_drv.a:
+kernel/blk_drv/blk_drv.a: dummy
        (cd kernel/blk_drv; make)
 
-kernel/chr_drv/chr_drv.a:
+kernel/chr_drv/chr_drv.a: dummy
        (cd kernel/chr_drv; make)
 
-kernel/kernel.o:
+kernel/kernel.o: dummy
        (cd kernel; make)
 
-mm/mm.o:
+mm/mm.o: dummy
        (cd mm; make)
 
-fs/fs.o:
+fs/fs.o: dummy
        (cd fs; make)
 
-fs/minix/minix.o:
+fs/minix/minix.o: dummy
        (cd fs/minix; make)
 
-lib/lib.a:
+lib/lib.a: dummy
        (cd lib; make)
 
 boot/setup: boot/setup.s
@@ -120,6 +120,8 @@ dep:
        (cd kernel; make dep)
        (cd mm; make dep)
 
+dummy:
+
 ### Dependencies:
 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 \
index 1befd14f13113f467bec1f625934e0eeda0028ee..7e9d1327dbff680a06c9524a6572b2593fefc121 100644 (file)
@@ -43,6 +43,12 @@ start:
        int     0x15
        mov     [2],ax
 
+! set the keyboard repeat rate to the max
+
+       mov     ax,#0x0305
+       mov     bx,#0x0000
+       int     0x16
+
 ! check for EGA/VGA and some config parameters
 
        mov     ah,#0x12
@@ -498,8 +504,25 @@ nozero:    sub     al,#0x80
        lodsw
        pop     ds
        ret
-novid7:        pop     ds      ! Here could be code to support standard 80x50,80x30
-       mov     ax,#0x5019      
+novid7:
+       mov     ax,#0x1112
+       mov     bl,#0
+       int     0x10            ! use 8x8 font set (50 lines on VGA)
+
+       mov     ax,#0x1200
+       mov     bl,#0x20
+       int     0x10            ! use alternate print screen
+
+       mov     ax,#0x1201
+       mov     bl,#0x34
+       int     0x10            ! turn off cursor emulation
+
+       mov     ah,#0x01
+       mov     cx,#0x0607
+       int     0x10            ! turn on cursor (scan lines 6 to 7)
+
+       pop     ds
+       mov     ax,#0x5032      ! return 80x50
        ret
 
 ! Routine that 'tabs' to next col.
index e4a4e9ed6f2d2494f408c6dd4eac89b80633f58e..cca44d36266146bc81a13e404b6db7e0d4a06a91 100644 (file)
@@ -47,8 +47,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
                filp->f_pos += chars;
                written += chars;
                count -= chars;
-               while (chars-->0)
-                       *(p++) = get_fs_byte(buf++);
+               memcpy_fromfs(p,buf,chars);
+               p += chars;
+               buf += chars;
                bh->b_dirt = 1;
                brelse(bh);
        }
@@ -85,8 +86,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
                filp->f_pos += chars;
                read += chars;
                count -= chars;
-               while (chars-->0)
-                       put_fs_byte(*(p++),buf++);
+               memcpy_tofs(buf,p,chars);
+               p += chars;
+               buf += chars;
                brelse(bh);
        }
        return read;
index 2ece7792b2409edf931666ed702857d6a58236c7..d4aaa06da5c329df9538ff5aa4fbdfa268162d73 100644 (file)
@@ -109,10 +109,15 @@ void inline invalidate_buffers(int dev)
 void check_disk_change(int dev)
 {
        int i;
+       struct buffer_head * bh;
 
        if (MAJOR(dev) != 2)
                return;
-       if (!floppy_change(dev & 0x03))
+       if (!(bh = getblk(dev,0)))
+               return;
+       i = floppy_change(bh);
+       brelse(bh);
+       if (!i)
                return;
        for (i=0 ; i<NR_SUPER ; i++)
                if (super_block[i].s_dev == dev)
diff --git a/fs/fasterdisk.pat b/fs/fasterdisk.pat
new file mode 100644 (file)
index 0000000..2e4b1fd
--- /dev/null
@@ -0,0 +1,153 @@
+From kwhite@csi.uottawa.ca Sun Mar 15 20:01:06 1992
+Received: from klaava.Helsinki.FI by kruuna.helsinki.fi with SMTP id AA04345
+  (5.65c/IDA-1.4.4 for <torvalds@klaava.Helsinki.FI>); Sun, 15 Mar 1992 20:00:45 +0200
+Received: from csi.UOttawa.CA (csi0.csi.uottawa.ca) by klaava.Helsinki.FI (4.1/SMI-4.1)
+       id AA21712; Sun, 15 Mar 92 20:00:40 +0200
+Received: by csi.UOttawa.CA id AA00608
+  (5.65+/IDA-1.3.5 for torvalds@klaava.helsinki.fi); Sun, 15 Mar 92 12:57:47 -0500
+From: Keith White <kwhite@csi.uottawa.ca>
+Message-Id: <9203151757.AA00608@csi.UOttawa.CA>
+Subject: reset-floppy fixed, double your disk speed (linux 0.95)
+To: torvalds@cc.helsinki.fi (Linus Torvalds)
+Date: Sun, 15 Mar 92 12:57:46 EST
+X-Mailer: ELM [version 2.3 PL11]
+Status: OR
+
+A couple of things.
+
+1) I must be one of those lucky few who's been able to use linux0.95.
+However I was surprised to see that hard disk speed was slower.  This
+was until I remembered that I had patched fs/block_dev.c and
+include/asm/segment.h to support block moves to and from the fs
+segment.  These patches (very minimal it must be admitted) give a
+reasonable increase in speed for 'fsck':
+       original:       42.62 elapsed
+       patched:        22.06 elapsed
+These patches have no effect on sequential disk access (dd if=/dev/hda
+...)  since most time is spent waiting for those small 2 sector
+transfers anyway.  The patches are included below.
+
+2) I don't run DOS so a floppy disk format program is sort of
+essential.  Lawrence Foard's (sp?) formatting routines have a few
+problems (nits).
+       a) The inter-sector gap should be larger for a format than it
+is for a read or write.
+       b) An interleave is not required (at least on my machine, a
+bottom of the line 386SX-16).
+
+3) I seem to have fixed the dreaded "reset-floppy called" problem --
+at least it works for me.  The posted fix does not work in my case.
+I'd send you these patches as well, but I only have diffs that include
+all the mods I did for the floppy format stuff.  The key point (I
+think) was to only reset twice during an error loop.  If a track was
+bad, the recalibrate would fail and call reset which would call
+recalibrate ...  If you're interested, I could try to separate the
+formatting stuff and all my debugging "printks" from the reset fix
+stuff and send the diffs.
+
+...keith (kwhite@csi.uottawa.ca)
+
+---cut here---
+*** 1.1        1992/03/14 16:33:21
+--- include/asm/segment.h      1992/03/15 17:10:14
+***************
+*** 63,65 ****
+--- 63,109 ----
+       __asm__("mov %0,%%fs"::"r" ((unsigned short) val));
+  }
+  
++ /*
++  * these routines are added to use the movs instruction with data
++  * in the fs segment.  No optimizations are done with regards to using
++  * movsw or movsd 
++  *
++  * kwhite@csi.uottawa.ca
++  */
++ 
++ #define memcpy_fromfs(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; movl %%ax,%%ds\n\
++      cld; rep; movsb\n\
++      mov %%es,%%ax; mov %%ax,%%ds" \
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
++ #define memcpy_fromfs_w(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; movl %%ax,%%ds\n\
++      cld; rep; movsw\n\
++      mov %%es,%%ax; mov %%ax,%%ds" \
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
++ #define memcpy_fromfs_l(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; movl %%ax,%%ds\n\
++      cld; rep; movsl\n\
++      mov %%es,%%ax; mov %%ax,%%ds" \
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
++ #define memcpy_tofs(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; mov %%ax,%%es\n\
++      cld; rep; movsb\n\
++      mov %%ds,%%ax; mov %%ax,%%es" \
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
++ #define memcpy_tofs_w(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; mov %%ax,%%es\n\
++      cld; rep; movsw\n\
++      mov %%ds,%%ax; mov %%ax,%%es" \
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
++ #define memcpy_tofs_l(dest,src,n) __asm__ (\
++      "mov %%fs,%%ax; mov %%ax,%%es\n\
++      cld; rep; movsl\n\
++      mov %%ds,%%ax; mov %%ax,%%es"\
++      ::"D" ((long)(dest)), "S" ((long)(src)), "c" ((long) (n)) \
++      :"di", "si", "cx", "ax");
+*** 1.1        1992/03/14 16:37:10
+--- fs/block_dev.c     1992/03/14 16:38:26
+***************
+*** 47,54 ****
+--- 47,64 ----
+               filp->f_pos += chars;
+               written += chars;
+               count -= chars;
++ #ifdef notdef
+               while (chars-->0)
+                       *(p++) = get_fs_byte(buf++);
++ #else
++              if ((chars&1) || ((long)p&1) || ((long)buf&1)) {
++                      memcpy_fromfs(p, buf, chars);
++              }
++              else {
++                      memcpy_fromfs_w(p, buf, chars>>1);
++              }
++              p += chars; buf += chars; chars = 0;
++ #endif
+               bh->b_dirt = 1;
+               brelse(bh);
+       }
+***************
+*** 85,92 ****
+--- 95,112 ----
+               filp->f_pos += chars;
+               read += chars;
+               count -= chars;
++ #ifdef notdef
+               while (chars-->0)
+                       put_fs_byte(*(p++),buf++);
++ #else
++              if ((chars&1) || ((long)buf&1) || ((long)p&1)) {
++                      memcpy_tofs(buf, p, chars);
++              }
++              else {
++                      memcpy_tofs_w(buf, p, chars>>1);
++              }
++              p += chars; buf += chars; chars = 0;
++ #endif
+               brelse(bh);
+       }
+       return read;
+---cut here---
+
+-- 
+BITNET:                kwhite@uotcsi2.bitnet (being phased out)
+UUCP:          {...,nrcaer,cunews}!uotcsi2!kwhite
+INTERNET:      kwhite@csi.uottawa.ca
+
index dd68b1d29d909aadd11acbc10f5dd4b0f7bc44af..7173e2371d10a6ab8d8e99db63f53ea5db9b1bf2 100644 (file)
@@ -73,8 +73,10 @@ void invalidate_inodes(int dev)
        for(i=0 ; i<NR_INODE ; i++,inode++) {
                wait_on_inode(inode);
                if (inode->i_dev == dev) {
-                       if (inode->i_count)
+                       if (inode->i_count) {
                                printk("inode in use on removed disk\n\r");
+                               continue;
+                       }
                        inode->i_dev = inode->i_dirt = 0;
                }
        }
index 646ba0e24d0a5da0c469da8da21be829b77fec57..d9d1fb907e57555a7be2417bfbe212f7ea590091 100644 (file)
@@ -39,9 +39,8 @@ int minix_file_read(struct inode * inode, struct file * filp, char * buf, int co
                left -= chars;
                read += chars;
                if (bh) {
-                       char * p = nr + bh->b_data;
-                       while (chars-->0)
-                               put_fs_byte(*(p++),buf++);
+                       memcpy_tofs(buf,nr+bh->b_data,chars);
+                       buf += chars;
                        brelse(bh);
                } else {
                        while (chars-->0)
@@ -81,7 +80,6 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
                }
                c = pos % BLOCK_SIZE;
                p = c + bh->b_data;
-               bh->b_dirt = 1;
                c = BLOCK_SIZE-c;
                if (c > count-written)
                        c = count-written;
@@ -91,8 +89,9 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
                        inode->i_dirt = 1;
                }
                written += c;
-               while (c-->0)
-                       *(p++) = get_fs_byte(buf++);
+               memcpy_fromfs(p,buf,c);
+               buf += c;
+               bh->b_dirt = 1;
                brelse(bh);
        }
        inode->i_mtime = CURRENT_TIME;
index 4f163bd170d9dc4229f2d20702a2c4b7fa44d6c8..ab72736b5d43e3b0b6c66e39ad97d9f9db7ab203 100644 (file)
@@ -135,6 +135,8 @@ static int check_char_dev(struct inode * inode, struct file * filp)
                        tty->session= current->session;
                        tty->pgrp = current->pgrp;
                }
+               if (IS_A_SERIAL(min))
+                       serial_open(min-64);
        }
        return 0;
 }
index 053b1ab3f3c1af1d1b38441123f71fda9c429992..e5d14396bc6f8e4226f263f438337d2315cfc1d0 100644 (file)
@@ -39,11 +39,15 @@ typedef struct {
        struct task_struct ** wait_address;
 } wait_entry;
 
-typedef struct {
-       int nr;
+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;
 
+static select_table * sel_tables = NULL;
+
 static void add_wait(struct task_struct ** wait_address, select_table * p)
 {
        int i;
@@ -53,32 +57,52 @@ static void add_wait(struct task_struct ** wait_address, select_table * p)
        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;
+       p->entry[p->nr].old_task = *wait_address;
        *wait_address = current;
        p->nr++;
 }
 
-static void free_wait(select_table * p)
+/*
+ * 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++) {
-               tpp = p->entry[i].wait_address;
-               while (*tpp && *tpp != current) {
-                       (*tpp)->state = 0;
-                       current->state = TASK_UNINTERRUPTIBLE;
-                       schedule();
-               }
-               if (!*tpp)
-                       printk("free_wait: NULL");
-               if (*tpp = p->entry[i].old_task)
-                       (**tpp).state = 0;
+               wake_up(p->entry[i].wait_address);
+               wake_up(&p->entry[i].old_task);
        }
        p->nr = 0;
 }
 
+static void free_wait(select_table * p)
+{
+       select_table * tmp;
+
+       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;
@@ -177,6 +201,10 @@ int do_select(fd_set in, fd_set out, fd_set ex,
        }
 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;
        mask = 1;
@@ -200,7 +228,9 @@ repeat:
        if (!(current->signal & ~current->blocked) &&
            current->timeout && !count) {
                current->state = TASK_INTERRUPTIBLE;
+               sti();
                schedule();
+               cli();
                free_wait(&wait_table);
                goto repeat;
        }
@@ -276,7 +306,9 @@ int sys_select( unsigned long *buffer )
                timeout *= (1000000/HZ);
                put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
        }
-       if (!i && (current->signal & ~current->blocked))
+       if (i)
+               return i;
+       if (current->signal & ~current->blocked)
                return -EINTR;
-       return i;
+       return 0;
 }
index 118249acbf239868172d7119ec0baaf4387aea19..9886d7bda81b9e0f9a9fdec25dcffd0e4a15efdf 100644 (file)
@@ -1,27 +1,37 @@
 static void inline outb(char value, unsigned short port)
 {
-__asm__ volatile ("outb %0,%1"::"a" (value),"d" (port));
+__asm__ volatile ("outb %0,%1"
+               ::"a" ((char) value),"d" ((unsigned short) port));
 }
 
 static void inline outb_p(char value, unsigned short port)
 {
-__asm__ volatile ("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"
-       ::"a" (value),"d" (port));
+__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));
 }
 
 static unsigned char inline inb(unsigned short port)
 {
        unsigned char _v;
-       __asm__ volatile ("inb %1,%0":"=a" (_v):"d" (port));
+__asm__ volatile ("inb %1,%0"
+               :"=a" (_v):"d" ((unsigned short) port));
        return _v;
 }
 
 static unsigned char inb_p(unsigned short port)
 {
        unsigned char _v;
-       __asm__ volatile ("inb %1,%0\n"
-               "\tjmp 1f\n"
+__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));
+               "1:"
+               :"=a" (_v):"d" ((unsigned short) port));
        return _v;
 }
index 5efc9e7b3e87e31360153b43f957034ca8e48407..cf2890c27e044a370f5d02440652ffeffb18d438 100644 (file)
@@ -37,6 +37,40 @@ extern inline void put_fs_long(unsigned long val,unsigned long * addr)
 __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
 }
 
+extern inline void memcpy_tofs(void * to, void * from, unsigned long n)
+{
+__asm__("cld\n\t"
+       "push %%es\n\t"
+       "push %%fs\n\t"
+       "pop %%es\n\t"
+       "testb $1,%%cl\n\t"
+       "je 1f\n\t"
+       "movsb\n"
+       "1:\ttestb $2,%%cl\n\t"
+       "je 2f\n\t"
+       "movsw\n"
+       "2:\tshrl $2,%%ecx\n\t"
+       "rep ; movsl\n\t"
+       "pop %%es"
+       ::"c" (n),"D" ((long) to),"S" ((long) from)
+       :"cx","di","si");
+}
+
+extern inline void memcpy_fromfs(void * to, void * from, unsigned long n)
+{
+__asm__("cld\n\t"
+       "testb $1,%%cl\n\t"
+       "je 1f\n\t"
+       "fs ; movsb\n"
+       "1:\ttestb $2,%%cl\n\t"
+       "je 2f\n\t"
+       "fs ; movsw\n"
+       "2:\tshrl $2,%%ecx\n\t"
+       "rep ; fs ; movsl"
+       ::"c" (n),"D" ((long) to),"S" ((long) from)
+       :"cx","di","si");
+}
+
 /*
  * Someone who knows GNU asm better than I should double check the followig.
  * It seems to work, but I don't know if I'm doing something subtly wrong.
index ca364b629122c2ac880374d0b0e6ee301d79e4e5..fc2ce17daf9551d75252c8bf016687708a0767e0 100644 (file)
@@ -16,7 +16,7 @@
 #define UTS_SYSNAME "Linux"
 #define UTS_NODENAME "(none)"  /* set by sethostname() */
 #define UTS_RELEASE "0"                /* patchlevel */
-#define UTS_VERSION "0.12"
+#define UTS_VERSION "0.95a"
 #define UTS_MACHINE "i386"     /* hardware type */
 
 /* Don't touch these, unless you really know what your doing. */
index 0c7b2e9b10bdf2aa2ca5f6efa7cc6f096f26b3a9..885164658c5cec20f07c52f3c0d2807ae57334bf 100644 (file)
@@ -165,7 +165,7 @@ extern struct buffer_head * start_buffer;
 extern int nr_buffers;
 
 extern void check_disk_change(int dev);
-extern int floppy_change(unsigned int nr);
+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);
index d903e2daf671ca6402d9d4dda330d9d7eee6fc83..99f919b644161be6b5bb90cffd8dcfc0bef8f1ec 100644 (file)
@@ -120,7 +120,11 @@ struct task_struct {
         * older sibling, respectively.  (p->father can be replaced with 
         * p->p_pptr->pid)
         */
-       struct task_struct      *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+       struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+       /*
+        * sleep makes a singly linked list with this.
+        */
+       struct task_struct *next_wait;
        unsigned short uid,euid,suid;
        unsigned short gid,egid,sgid;
        unsigned long timeout,alarm;
@@ -164,7 +168,7 @@ struct task_struct {
 /* ec,brk... */        0,0,0,0,0,0, \
 /* pid etc.. */        0,0,0,0, \
 /* suppl grps*/ {NOGROUP,}, \
-/* proc links*/ &init_task.task,0,0,0, \
+/* 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, \
 /* rlimits */   { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff},  \
index 295738e64f2bd81153479211a24422ea9db1d593..ab3c74ed3be1bc06ba2290c0c358e2811e4de1dc 100644 (file)
 
 #define BLANK_TIMER    0
 #define BEEP_TIMER     1
+
 #define SER1_TIMER     2
 #define SER2_TIMER     3
+#define SER3_TIMER     4
+#define SER4_TIMER     5
 
 #define SER1_TIMEOUT   8
 #define SER2_TIMEOUT   9
+#define SER3_TIMEOUT   10
+#define SER4_TIMEOUT   11
 
 #define HD_TIMER       16
 #define FLOPPY_TIMER   17
index 4812f85aff080c20c1e54d7691d3171a6e20ee3f..805894dedca26febec9e66088a81683d77209db7 100644 (file)
 #define _TTY_H
 
 #define MAX_CONSOLES   8
-#define NR_SERIALS     2
+#define NR_SERIALS     4
 #define NR_PTYS                4
 
 extern int NR_CONSOLES;
 
 #include <termios.h>
 
-#define TTY_BUF_SIZE 1024
+#define TTY_BUF_SIZE 2048
 
 struct tty_queue {
        unsigned long data;
@@ -60,6 +60,7 @@ struct tty_struct {
        int pgrp;
        int session;
        int stopped;
+       int busy;
        struct winsize winsize;
        void (*write)(struct tty_struct * tty);
        struct tty_queue *read_q;
@@ -67,6 +68,18 @@ struct tty_struct {
        struct tty_queue *secondary;
        };
 
+#define TTY_WRITE(tty) \
+do { \
+       cli(); \
+       if (!(tty)->busy) { \
+               (tty)->busy = 1; \
+               sti(); \
+               (tty)->write((tty)); \
+               (tty)->busy = 0; \
+       } else \
+               sti(); \
+} while (0)
+
 extern struct tty_struct tty_table[];
 extern int fg_console;
 extern unsigned long video_num_columns;
@@ -96,6 +109,8 @@ void rs_write(struct tty_struct * tty);
 void mpty_write(struct tty_struct * tty);
 void spty_write(struct tty_struct * tty);
 
+extern void serial_open(unsigned int line);
+
 void copy_to_cooked(struct tty_struct * tty);
 
 void update_screen(int new_console);
index faa6e53ef01d98e968a5e320a111a67cf9d2cf5e..b04a0e9928ecb212c19da1dd2ac0bde95f1ddfbf 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <sys/types.h>
 
-#define TTY_BUF_SIZE 1024
-
 /* 0x54 is just a magic number to make these relatively uniqe ('T') */
 
 #define TCGETS         0x5401
index 1739de5de754dbbeea68b4955351b3e78f056a96..d53e00f4061ae162468420b49a79f1519d2e8ece 100644 (file)
@@ -203,6 +203,7 @@ void init(void)
                NR_BUFFERS*BLOCK_SIZE);
        printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
 
+       execve("/etc/init",argv_init,envp_init);
        execve("/bin/init",argv_init,envp_init);
        /* if this fails, fall through to original stuff */
 
index 28e37d573fbf694f1e9b2134e018db791c9582f3..c159025d558e018bfb2a3165cd1adad1d0d3be51 100644 (file)
@@ -100,11 +100,16 @@ extern int * blk_size[NR_BLK_DEV];
 void (*DEVICE_INTR)(void) = NULL;
 #endif
 #ifdef DEVICE_TIMEOUT
-#define SET_INTR(x) (DEVICE_INTR = (x), \
-       timer_table[DEVICE_TIMEOUT].expires = jiffies + 200, \
-       timer_active |= 1<<DEVICE_TIMEOUT)
+
+#define SET_INTR(x) if (DEVICE_INTR = (x)) { \
+timer_table[DEVICE_TIMEOUT].expires = jiffies + 200; \
+timer_active |= 1<<DEVICE_TIMEOUT; \
+} else timer_active &= ~(1<<DEVICE_TIMEOUT)
+
 #else
+
 #define SET_INTR(x) (DEVICE_INTR = (x))
+
 #endif
 static void (DEVICE_REQUEST)(void);
 
@@ -134,23 +139,16 @@ extern inline void end_request(int uptodate)
        CURRENT = CURRENT->next;
 }
 
-#ifdef DEVICE_TIMEOUT
-#define CLEAR_DEVICE_TIMEOUT timer_active &= ~(1<<DEVICE_TIMEOUT);
-#else
-#define CLEAR_DEVICE_TIMEOUT
-#endif
-
 #ifdef DEVICE_INTR
-#define CLEAR_DEVICE_INTR DEVICE_INTR = 0;
+#define CLEAR_INTR SET_INTR(NULL)
 #else
-#define CLEAR_DEVICE_INTR
+#define CLEAR_INTR
 #endif
 
 #define INIT_REQUEST \
 repeat: \
        if (!CURRENT) {\
-               CLEAR_DEVICE_INTR \
-               CLEAR_DEVICE_TIMEOUT \
+               CLEAR_INTR; \
                return; \
        } \
        if (MAJOR(CURRENT->dev) != MAJOR_NR) \
index 92881e5bffc04a33e15458811c5ad4b1a1ce1ad4..a97bff665a0a8e9a18c063dd2194eb00e0380e0b 100644 (file)
@@ -43,6 +43,8 @@
 #define MAJOR_NR 2
 #include "blk.h"
 
+unsigned int changed_floppies = 0;
+
 static int recalibrate = 0;
 static int reset = 0;
 static int seek = 0;
@@ -56,8 +58,8 @@ __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
 #define DRIVE(x) ((x)&0x03)
 /*
  * Note that MAX_ERRORS=X doesn't imply that we retry every bad read
- * max X times - some types of errors increase the errorcount by 2,
- * so we might actually retry only X/2 times before giving up.
+ * max X times - some types of errors increase the errorcount by 2 or
+ * even 3, so we might actually retry only X/2 times before giving up.
  */
 #define MAX_ERRORS 12
 
@@ -115,18 +117,20 @@ extern char floppy_track_buffer[512*2*18];
  * information to interrupts. They are the data used for the current
  * request.
  */
+#define NO_TRACK 255
+
 static int read_track = 0;     /* flag to indicate if we want to read all track */
 static int buffer_track = -1;
 static int buffer_drive = -1;
 static int cur_spec1 = -1;
 static int cur_rate = -1;
 static struct floppy_struct * floppy = floppy_type;
-static unsigned char current_drive = 0;
+static unsigned char current_drive = 255;
 static unsigned char sector = 0;
 static unsigned char head = 0;
 static unsigned char track = 0;
 static unsigned char seek_track = 0;
-static unsigned char current_track = 255;
+static unsigned char current_track = NO_TRACK;
 static unsigned char command = 0;
 unsigned char selected = 0;
 struct task_struct * wait_on_floppy_select = NULL;
@@ -145,20 +149,37 @@ void floppy_deselect(unsigned int nr)
  * to the desired drive, but it will probably not survive the sleep if
  * several floppies are used at the same time: thus the loop.
  */
-int floppy_change(unsigned int nr)
+int floppy_change(struct buffer_head * bh)
 {
-repeat:
-       floppy_on(nr);
-       while ((current_DOR & 3) != nr && selected)
-               sleep_on(&wait_on_floppy_select);
-       if ((current_DOR & 3) != nr)
-               goto repeat;
-       if (inb(FD_DIR) & 0x80) {
-               floppy_off(nr);
-               buffer_track = -1;
+       unsigned int mask = 1 << (bh->b_dev & 0x03);
+
+       if (MAJOR(bh->b_dev) != 2) {
+               printk("floppy_changed: not a floppy\n");
+               return 0;
+       }
+       if (changed_floppies & mask) {
+               changed_floppies &= ~mask;
+               recalibrate = 1;
                return 1;
        }
-       floppy_off(nr);
+       if (!bh)
+               return 0;
+       if (bh->b_dirt)
+               ll_rw_block(WRITE,bh);
+       else {
+               buffer_track = -1;
+               bh->b_uptodate = 0;
+               ll_rw_block(READ,bh);
+       }
+       cli();
+       while (bh->b_lock)
+               sleep_on(&bh->b_wait);
+       sti();
+       if (changed_floppies & mask) {
+               changed_floppies &= ~mask;
+               recalibrate = 1;
+               return 1;
+       }       
        return 0;
 }
 
@@ -223,6 +244,7 @@ static void output_byte(char byte)
                        return;
                }
        }
+       current_track = NO_TRACK;
        reset = 1;
        printk("Unable to send byte to FDC\n\r");
 }
@@ -244,13 +266,14 @@ static int result(void)
                }
        }
        reset = 1;
+       current_track = NO_TRACK;
        printk("Getstatus times out\n\r");
        return -1;
 }
 
 static void bad_flp_intr(void)
 {
-       current_track = -1;
+       current_track = NO_TRACK;
        CURRENT->errors++;
        if (CURRENT->errors > MAX_ERRORS) {
                floppy_deselect(current_drive);
@@ -258,6 +281,8 @@ static void bad_flp_intr(void)
        }
        if (CURRENT->errors > MAX_ERRORS/2)
                reset = 1;
+       else
+               recalibrate = 1;
 }      
 
 /*
@@ -383,15 +408,15 @@ static void transfer(void)
 static void recal_interrupt(void)
 {
        output_byte(FD_SENSEI);
+       current_track = NO_TRACK;
        if (result()!=2 || (ST0 & 0xE0) == 0x60)
                reset = 1;
-       else
-               recalibrate = 0;
        do_fd_request();
 }
 
 void unexpected_floppy_interrupt(void)
 {
+       current_track = NO_TRACK;
        output_byte(FD_SENSEI);
        if (result()!=2 || (ST0 & 0xE0) == 0x60)
                reset = 1;
@@ -427,15 +452,16 @@ static void reset_floppy(void)
 {
        int i;
 
+       do_floppy = reset_interrupt;
        reset = 0;
+       current_track = NO_TRACK;
        cur_spec1 = -1;
        cur_rate = -1;
        recalibrate = 1;
        printk("Reset-floppy called\n\r");
        cli();
-       do_floppy = reset_interrupt;
        outb_p(current_DOR & ~0x04,FD_DOR);
-       for (i=0 ; i<100 ; i++)
+       for (i=0 ; i<1000 ; i++)
                __asm__("nop");
        outb(current_DOR,FD_DOR);
        sti();
@@ -443,6 +469,18 @@ static void reset_floppy(void)
 
 static void floppy_on_interrupt(void)
 {
+       if (inb(FD_DIR) & 0x80) {
+               changed_floppies |= 1<<current_drive;
+               buffer_track = -1;
+       }
+       if (reset) {
+               reset_floppy();
+               return;
+       }
+       if (recalibrate) {
+               recalibrate_floppy();
+               return;
+       }
 /* We cannot do a floppy-select, as that might sleep. We just force it */
        selected = 1;
        if (current_drive != (current_DOR & 3)) {
@@ -459,19 +497,11 @@ void do_fd_request(void)
        unsigned int block;
        char * buffer_area;
 
-       seek = 0;
-       if (reset) {
-               reset_floppy();
-               return;
-       }
-       if (recalibrate) {
-               recalibrate_floppy();
-               return;
-       }
        INIT_REQUEST;
+       seek = 0;
        floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
        if (current_drive != CURRENT_DEV)
-               seek = 1;
+               current_track = NO_TRACK;
        current_drive = CURRENT_DEV;
        block = CURRENT->sector;
        if (block+2 > floppy->size) {
index b75b17655cfd9811002df73e8962cdd6a476efcd..e3a6ca57407e106fa9bb196a10913049fd05c49d 100644 (file)
@@ -11,6 +11,9 @@
  * sleep. Special care is recommended.
  * 
  *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
  */
 
 #include <linux/config.h>
 #define MAJOR_NR 3
 #include "blk.h"
 
-#define CMOS_READ(addr) ({ \
-outb_p(0x80|addr,0x70); \
-inb_p(0x71); \
-})
+static inline unsigned char CMOS_READ(unsigned char addr)
+{
+       outb_p(0x80|addr,0x70);
+       return inb_p(0x71);
+}
 
 /* Max read/write errors/sector */
 #define MAX_ERRORS     7
@@ -39,7 +43,7 @@ static void recal_intr(void);
 static void bad_rw_intr(void);
 
 static int recalibrate = 0;
-static int reset = 0;
+static int reset = 1;
 
 /*
  *  This struct defines the HD's and their types.
@@ -87,12 +91,30 @@ static void check_partition(unsigned int dev)
        if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
                p = 0x1BE + (void *)bh->b_data;
                for (i=0 ; i<4 ; i++,p++) {
+                       if (!(hd[i+minor].nr_sects = p->nr_sects))
+                               continue;
                        hd[i+minor].start_sect = p->start_sect;
-                       hd[i+minor].nr_sects = p->nr_sects;
+                       if ((current_minor & 0x3f) >= 60)
+                               continue;
+                       if (p->sys_ind == EXTENDED_PARTITION) {
+                               current_minor += 4;
+                               check_partition(0x0300 | (i+minor));
+                       }
                }
-               if (p->nr_sects && p->sys_ind == EXTENDED_PARTITION) {
-                       current_minor += 4;
-                       check_partition(i+minor);
+               /*
+                * check for Disk Manager partition table
+                */
+               if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
+                       p = 0x1BE + (void *)bh->b_data;
+                       for (i=4; i<16; i++) {
+                               p--;
+                               if ((current_minor & 0x3f) >= 60)
+                                       break;
+                               if (!(hd[current_minor+4].start_sect = p->start_sect))
+                                       continue;
+                               hd[current_minor+4].nr_sects = p->nr_sects;
+                               current_minor++;
+                       }
                }
        } else
                printk("Bad partition table on dev %04x\n",dev);
@@ -196,7 +218,8 @@ static int win_result(void)
        if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
                == (READY_STAT | SEEK_STAT))
                return(0); /* ok */
-       if (i&1) i=inb(HD_ERROR);
+       if (i&1)
+               i=inb(HD_ERROR);
        return (1);
 }
 
@@ -289,11 +312,15 @@ static void bad_rw_intr(void)
                end_request(0);
        if (CURRENT->errors > MAX_ERRORS/2)
                reset = 1;
+       else
+               recalibrate = 1;
 }
 
 static void read_intr(void)
 {
+       SET_INTR(&read_intr);
        if (win_result()) {
+               SET_INTR(NULL);
                bad_rw_intr();
                do_hd_request();
                return;
@@ -302,10 +329,9 @@ static void read_intr(void)
        CURRENT->errors = 0;
        CURRENT->buffer += 512;
        CURRENT->sector++;
-       if (--CURRENT->nr_sectors) {
-               SET_INTR(&read_intr);
+       if (--CURRENT->nr_sectors)
                return;
-       }
+       SET_INTR(NULL);
        end_request(1);
        do_hd_request();
 }
@@ -336,14 +362,14 @@ static void recal_intr(void)
 }
 
 static void hd_times_out(void)
-{
+{      
+       do_hd = NULL;
+       reset = 1;
        if (!CURRENT)
                return;
        printk("HD timeout");
        if (++CURRENT->errors >= MAX_ERRORS)
                end_request(0);
-       SET_INTR(NULL);
-       reset = 1;
        do_hd_request();
 }
 
@@ -357,7 +383,8 @@ void do_hd_request(void)
        INIT_REQUEST;
        dev = MINOR(CURRENT->dev);
        block = CURRENT->sector;
-       if (dev >= (NR_HD<<6) || block+2 > hd[dev].nr_sects) {
+       nsect = CURRENT->nr_sectors;
+       if (dev >= (NR_HD<<6) || block+nsect > hd[dev].nr_sects) {
                end_request(0);
                goto repeat;
        }
@@ -368,7 +395,6 @@ void do_hd_request(void)
        head = block % hd_info[dev].head;
        cyl = block / hd_info[dev].head;
        sec++;
-       nsect = CURRENT->nr_sectors;
        if (reset) {
                recalibrate = 1;
                reset_hd();
@@ -376,7 +402,7 @@ void do_hd_request(void)
        }
        if (recalibrate) {
                recalibrate = 0;
-               hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
+               hd_out(dev,hd_info[dev].sect,0,0,0,
                        WIN_RESTORE,&recal_intr);
                if (reset)
                        goto repeat;
@@ -404,7 +430,7 @@ void do_hd_request(void)
 void hd_init(void)
 {
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       set_trap_gate(0x2E,&hd_interrupt);
+       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;
index 3de86488e64fff3164fb4106ced9779671e8400f..f506c4c63070eb442accca65c2d42a8a3233110f 100644 (file)
@@ -187,7 +187,7 @@ static char * translations[] = {
 #define GRAF_TRANS (translations[1])
 
 /* NOTE! gotoxy thinks x==video_num_columns is ok */
-static inline void gotoxy(int currcons, int new_x,unsigned int new_y)
+static inline void gotoxy(int currcons, unsigned int new_x,unsigned int new_y)
 {
        if (new_x > video_num_columns || new_y >= video_num_lines)
                return;
@@ -210,75 +210,46 @@ static inline void set_origin(int currcons)
        sti();
 }
 
-static void scrup(int currcons)
+static void scrup(int currcons, unsigned int t, unsigned int b)
 {
-       unsigned int oldbottom, oldtop;
-
-       oldbottom = bottom;
-       oldtop = top;
-       if (y < top) {
-               top = 0;
-               bottom = y + 1;
-       } else if (y > bottom) {
-               bottom = video_num_lines;
-               top = y;
-       }
-       if (top > video_num_lines)
-               top = 0;
-       if (bottom > video_num_lines)
-               bottom = video_num_lines;
-       if (bottom <= top) {
-               bottom = oldbottom;
-               top = oldtop;
+       int hardscroll = 1;
+
+       if (b > video_num_lines || t >= b)
                return;
-       }
-       if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
-       {
-               if (!top && bottom == video_num_lines) {
-                       origin += video_size_row;
-                       pos += video_size_row;
-                       scr_end += video_size_row;
-                       if (scr_end > video_mem_end) {
-                               __asm__("cld\n\t"
-                                       "rep\n\t"
-                                       "movsl\n\t"
-                                       "movl _video_num_columns,%1\n\t"
-                                       "rep\n\t"
-                                       "stosw"
-                                       ::"a" (video_erase_char),
-                                       "c" ((video_num_lines-1)*video_num_columns>>1),
-                                       "D" (video_mem_start),
-                                       "S" (origin)
-                                       :"cx","di","si");
-                               scr_end -= origin-video_mem_start;
-                               pos -= origin-video_mem_start;
-                               origin = video_mem_start;
-                       } else {
-                               __asm__("cld\n\t"
-                                       "rep\n\t"
-                                       "stosw"
-                                       ::"a" (video_erase_char),
-                                       "c" (video_num_columns),
-                                       "D" (scr_end-video_size_row)
-                                       :"cx","di");
-                       }
-                       set_origin(currcons);
-               } else {
+       if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
+               hardscroll = 0;
+       else if (t || b != video_num_lines)
+               hardscroll = 0;
+       if (hardscroll) {
+               origin += video_size_row;
+               pos += video_size_row;
+               scr_end += video_size_row;
+               if (scr_end > video_mem_end) {
                        __asm__("cld\n\t"
                                "rep\n\t"
                                "movsl\n\t"
-                               "movl _video_num_columns,%%ecx\n\t"
+                               "movl _video_num_columns,%1\n\t"
                                "rep\n\t"
                                "stosw"
                                ::"a" (video_erase_char),
-                               "c" ((bottom-top-1)*video_num_columns>>1),
-                               "D" (origin+video_size_row*top),
-                               "S" (origin+video_size_row*(top+1))
+                               "c" ((video_num_lines-1)*video_num_columns>>1),
+                               "D" (video_mem_start),
+                               "S" (origin)
                                :"cx","di","si");
+                       scr_end -= origin-video_mem_start;
+                       pos -= origin-video_mem_start;
+                       origin = video_mem_start;
+               } else {
+                       __asm__("cld\n\t"
+                               "rep\n\t"
+                               "stosw"
+                               ::"a" (video_erase_char),
+                               "c" (video_num_columns),
+                               "D" (scr_end-video_size_row)
+                               :"cx","di");
                }
-       }
-       else            /* Not EGA/VGA */
-       {
+               set_origin(currcons);
+       } else {
                __asm__("cld\n\t"
                        "rep\n\t"
                        "movsl\n\t"
@@ -286,37 +257,17 @@ static void scrup(int currcons)
                        "rep\n\t"
                        "stosw"
                        ::"a" (video_erase_char),
-                       "c" ((bottom-top-1)*video_num_columns>>1),
-                       "D" (origin+video_size_row*top),
-                       "S" (origin+video_size_row*(top+1))
+                       "c" ((b-t-1)*video_num_columns>>1),
+                       "D" (origin+video_size_row*t),
+                       "S" (origin+video_size_row*(t+1))
                        :"cx","di","si");
        }
-       bottom = oldbottom;
-       top = oldtop;
 }
 
-static void scrdown(int currcons)
+static void scrdown(int currcons, unsigned int t, unsigned int b)
 {
-       unsigned int oldbottom, oldtop;
-
-       oldbottom = bottom;
-       oldtop = top;
-       if (y < top) {
-               top = 0;
-               bottom = y + 1;
-       } else if (y > bottom) {
-               bottom = video_num_lines;
-               top = y;
-       }
-       if (top > video_num_lines)
-               top = 0;
-       if (bottom > video_num_lines)
-               bottom = video_num_lines;
-       if (bottom<=top) {
-               bottom = oldbottom;
-               top = oldtop;
+       if (b > video_num_lines || t >= b)
                return;
-       }
        __asm__("std\n\t"
                "rep\n\t"
                "movsl\n\t"
@@ -326,12 +277,10 @@ static void scrdown(int currcons)
                "stosw\n\t"
                "cld"
                ::"a" (video_erase_char),
-               "c" ((bottom-top-1)*video_num_columns>>1),
-               "D" (origin+video_size_row*bottom-4),
-               "S" (origin+video_size_row*(bottom-1)-4)
+               "c" ((b-t-1)*video_num_columns>>1),
+               "D" (origin+video_size_row*b-4),
+               "S" (origin+video_size_row*(b-1)-4)
                :"ax","cx","di","si");
-       bottom = oldbottom;
-       top = oldtop;
 }
 
 static void lf(int currcons)
@@ -341,7 +290,7 @@ static void lf(int currcons)
                pos += video_size_row;
                return;
        } else 
-               scrup(currcons);
+               scrup(currcons,top,bottom);
 }
 
 static void ri(int currcons)
@@ -351,7 +300,7 @@ static void ri(int currcons)
                pos -= video_size_row;
                return;
        } else
-               scrdown(currcons);
+               scrdown(currcons,top,bottom);
 }
 
 static void cr(int currcons)
@@ -371,8 +320,8 @@ static void del(int currcons)
 
 static void csi_J(int currcons, int vpar)
 {
-       long count;
-       long start;
+       unsigned long count;
+       unsigned long start;
 
        switch (vpar) {
                case 0: /* erase from cursor to end of display */
@@ -429,7 +378,7 @@ static void csi_K(int currcons, int vpar)
                :"cx","di");
 }
 
-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 };
@@ -455,22 +404,23 @@ void csi_m(int currcons )
                          }
                          break;
                        case 5: attr=attr|0x80;break;  /* blinking */
-                       case 7: attr=(attr<<4)|(attr>>4);break;  /* negative */
+                       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 & 0xf0)|(def_attr & 0x0f); break;
-                       case 49: attr=(attr & 0x0f)|(def_attr & 0xf0); break;
+                       case 39: attr=(attr & 0xf8)|(def_attr & 0x07); break;
+                       case 49: attr=(attr & 0x8f)|(def_attr & 0x70); break;
                        default:
                          if (!can_do_colour)
                            break;
                          iscolor = 1;
                          if ((par[i]>=30) && (par[i]<=37))
-                           attr = (attr & 0xf0) | conv_table[par[i]-30];
+                           attr = (attr & 0xf8) | conv_table[par[i]-30];
                          else  /* Background color */
                            if ((par[i]>=40) && (par[i]<=47))
-                             attr = (attr & 0x0f) | (conv_table[par[i]-40]<<4);
+                             attr = (attr & 0x8f) | (conv_table[par[i]-40]<<4);
                            else
                                break;
                }
@@ -511,39 +461,30 @@ static void respond(int currcons, struct tty_struct * tty)
 
 static void insert_char(int currcons)
 {
-       int i=x;
+       unsigned int i = x;
        unsigned short tmp, old = video_erase_char;
        unsigned short * p = (unsigned short *) pos;
 
-       while (i++<video_num_columns) {
-               tmp=*p;
-               *p=old;
-               old=tmp;
+       while (i++ < video_num_columns) {
+               tmp = *p;
+               *p = old;
+               old = tmp;
                p++;
        }
 }
 
 static void insert_line(int currcons)
 {
-       int oldtop,oldbottom;
-
-       oldtop=top;
-       oldbottom=bottom;
-       top=y;
-       bottom = video_num_lines;
-       scrdown(currcons);
-       top=oldtop;
-       bottom=oldbottom;
+       scrdown(currcons,y,bottom);
 }
 
 static void delete_char(int currcons)
 {
-       int i;
+       unsigned int i = x;
        unsigned short * p = (unsigned short *) pos;
 
-       if (x>=video_num_columns)
+       if (x >= video_num_columns)
                return;
-       i = x;
        while (++i < video_num_columns) {
                *p = *(p+1);
                p++;
@@ -553,15 +494,7 @@ static void delete_char(int currcons)
 
 static void delete_line(int currcons)
 {
-       int oldtop,oldbottom;
-
-       oldtop=top;
-       oldbottom=bottom;
-       top=y;
-       bottom = video_num_lines;
-       scrup(currcons);
-       top=oldtop;
-       bottom=oldbottom;
+       scrup(currcons,y,bottom);
 }
 
 static void csi_at(int currcons, unsigned int nr)
@@ -606,13 +539,13 @@ static void csi_M(int currcons, unsigned int nr)
 
 static void save_cur(int currcons)
 {
-       saved_x=x;
-       saved_y=y;
+       saved_x = x;
+       saved_y = y;
 }
 
 static void restore_cur(int currcons)
 {
-       gotoxy(currcons,saved_x, saved_y);
+       gotoxy(currcons, saved_x, saved_y);
 }
 
 
@@ -621,18 +554,16 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
 
 void con_write(struct tty_struct * tty)
 {
-       int nr;
-       char c;
-       int currcons;
+       unsigned char c;
+       unsigned int currcons;
 
        wake_up(&tty->write_q->proc_list);
        currcons = tty - tty_table;
-       if ((currcons>=MAX_CONSOLES) || (currcons<0)) {
+       if (currcons >= MAX_CONSOLES) {
                printk("con_write: illegal tty\n\r");
                return;
        }
-       nr = CHARS(tty->write_q);
-       while (nr--) {
+       while (!EMPTY(tty->write_q)) {
                if (tty->stopped)
                        break;
                GETCH(tty->write_q,c);
@@ -640,41 +571,40 @@ void con_write(struct tty_struct * tty)
                        state = ESnormal;
                switch(state) {
                        case ESnormal:
-                               if (c>31 && c<127) {
-                                       if (x>=video_num_columns) {
+                               if (c > 31 && c < 127) {
+                                       while (x >= video_num_columns) {
                                                x -= video_num_columns;
                                                pos -= video_size_row;
                                                lf(currcons);
                                        }
                                        *(char *) pos = translate[c-32];
-                                       pos++;
-                                       *(char *) pos = attr;
-                                       pos++;
+                                       *(char *) (pos+1) = attr;
+                                       pos += 2;
                                        x++;
-                               } else if (c==27)
+                               } else if (c == 27)
                                        state = ESesc;
-                               else if (c==10 || c==11 || c==12)
+                               else if (c == 10 || c == 11 || c == 12)
                                        lf(currcons);
-                               else if (c==13)
+                               else if (c == 13)
                                        cr(currcons);
-                               else if (c==127)
+                               else if (c == 127)
                                        del(currcons);
-                               else if (c==8) {
+                               else if (c == 8) {
                                        if (x) {
                                                x--;
                                                pos -= 2;
                                        }
-                               } else if (c==9) {
+                               } else if (c == 9) {
                                        c = 8-(x&7);
                                        x += c;
                                        pos += c<<1;
-                                       if (x>video_num_columns) {
+                                       if (x > video_num_columns) {
                                                x -= video_num_columns;
                                                pos -= video_size_row;
                                                lf(currcons);
                                        }
-                                       c=9;
-                               } else if (c==7)
+                                       c = 9;
+                               } else if (c == 7)
                                        sysbeep();
                                else if (c == 14) {
                                        checkin = 1;
@@ -740,7 +670,7 @@ void con_write(struct tty_struct * tty)
                                break;
                        case ESsquare:
                                for(npar = 0 ; npar < NPAR ; npar++)
-                                       par[npar]=0;
+                                       par[npar] = 0;
                                npar = 0;
                                state = ESgetpars;
                                if (c == '[') { /* Function key */
@@ -754,7 +684,8 @@ void con_write(struct tty_struct * tty)
                                        npar++;
                                        break;
                                } else if (c>='0' && c<='9') {
-                                       par[npar]=10*par[npar]+c-'0';
+                                       par[npar] *= 10;
+                                       par[npar] += c-'0';
                                        break;
                                } else state=ESgotpars;
                        case ESgotpars:
@@ -823,8 +754,10 @@ void con_write(struct tty_struct * tty)
                                                csi_m(currcons);
                                                break;
                                        case 'r':
-                                               if (par[0]) par[0]--;
-                                               if (!par[1]) par[1] = video_num_lines;
+                                               if (par[0])
+                                                       par[0]--;
+                                               if (!par[1])
+                                                       par[1] = video_num_lines;
                                                if (par[0] < par[1] &&
                                                    par[1] <= video_num_lines) {
                                                        top=par[0];
@@ -839,7 +772,7 @@ void con_write(struct tty_struct * tty)
                                                break;
                                        case 'l': /* blank interval */
                                        case 'b': /* bold attribute */
-                                                 if (!((npar >= 2) &&
+                                               if (!((npar >= 2) &&
                                                  ((par[1]-13) == par[0]) && 
                                                  ((par[2]-17) == par[0]))) 
                                                    break;
@@ -1072,9 +1005,7 @@ static void get_scrmem(int currcons)
        video_mem_start = (unsigned long)vc_scrbuf[fg_console];
        origin  = video_mem_start;
        scr_end = video_mem_end = video_mem_start+screen_size;
-       top = 0;
        pos = origin + y*video_size_row + (x<<1);
-       bottom  = video_num_lines;
 }
 
 static void set_scrmem(int currcons)
@@ -1083,8 +1014,6 @@ static void set_scrmem(int currcons)
        video_mem_end = video_mem_term;
        origin  = video_mem_start;
        scr_end = video_mem_start + screen_size;
-       top     = 0;
-       bottom  = video_num_lines; 
        pos = origin + y*video_size_row + (x<<1);
        memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
 }
@@ -1185,15 +1114,14 @@ void console_print(const char * b)
                        cr(currcons);
                        continue;
                }
-               if (x>=video_num_columns) {
+               while (x >= video_num_columns) {
                        x -= video_num_columns;
                        pos -= video_size_row;
                        lf(currcons);
                }
                *(char *) pos = c;
-               pos++;
-               *(char *) pos = attr;
-               pos++;
+               *(char *) (pos+1) = attr;
+               pos += 2;
                x++;
        }
        set_cursor(currcons);
index 0177e0680b78b8f24103f7bc769d420d4a427e3a..6a26867c69fb5ff4569dd8dc75f4d8e40a0039b4 100644 (file)
@@ -32,7 +32,7 @@
 /*
  * these are for the keyboard read functions
  */
-size   = 1024          /* must be a power of two ! And MUST be the same
+size   = 2048          /* must be a power of two ! And MUST be the same
                           as in tty_io.c !!!! */
 head = 4
 tail = 8
@@ -434,7 +434,7 @@ key_map:
 
 shift_map:
        .byte 0,27
-       .ascii "!\"#$%%&*()_+"
+       .ascii "!\"#$%^&*()_+"
        .byte 127,9
        .ascii "QWERTYUIOP{}"
        .byte 13,0
@@ -626,7 +626,7 @@ do_self:
        testb $0x20,_kmode              /* alt-gr */
        jne 1f
        lea shift_map,%ebx
-       testb $0x03,_kmode
+       testb $0x0f,_kmode
        jne 1f
        lea key_map,%ebx
 1:     movb (%ebx,%eax),%al
@@ -641,11 +641,7 @@ do_self:
        subb $32,%al
 2:     testb $0x0c,_kmode              /* ctrl */
        je 3f
-       cmpb $64,%al
-       jb 3f
-       cmpb $64+32,%al
-       jae 3f
-       subb $64,%al
+       andb $0x1f,%al
 3:     testb $0x10,_kmode              /* left alt */
        je 4f
        orb $0x80,%al
index f147cecb082b78d88925052a12b9d3d0ef59de4f..e74dcd3f329c635f7bb65fbb0342c8263a6699bc 100644 (file)
@@ -13,7 +13,7 @@
 .text
 .globl _rs1_interrupt,_rs2_interrupt
 
-size   = 1024                          /* must be power of two !
+size   = 2048                          /* must be power of two !
                                           and must match the value
                                           in tty_io.c!!! */
 
@@ -29,16 +29,21 @@ 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
-rs_int:
-       cld
+       pushl $_table_list+32
+rs_int:        cld
        pushl %edx
        pushl %ecx
        pushl %ebx
@@ -50,32 +55,39 @@ rs_int:
        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 */
-rep_int:
-       xorl %eax,%eax
+1:     xorl %eax,%eax
        inb %dx,%al
        testb $1,%al
-       jne end
+       jne 2f
        cmpb $6,%al             /* this shouldn't happen, but ... */
-       ja end
-       movl 24(%esp),%ecx
+       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 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 1b
+2:     popl %edx
+       ret
 
 jmp_table:
        .long modem_status,write_char,read_char,line_status
@@ -112,7 +124,7 @@ read_char:
 
 .align 2
 mask_table:
-       .long 0,4,8
+       .long 0,4,8,16,32
 
 .align 2
 write_char:
@@ -136,6 +148,7 @@ write_char:
        cmpl head(%ecx),%ebx
        je write_buffer_empty
        ret
+
 .align 2
 write_buffer_empty:
        movl proc_list(%ecx),%ebx       # wake up sleeping process
@@ -146,6 +159,6 @@ write_buffer_empty:
        inb %dx,%al
        jmp 1f
 1:     jmp 1f
-1:     andb $0xd,%al           /* disable transmit interrupt */
+1:     andb $0xd,%al                   # disable transmit interrupt
        outb %al,%dx
        ret
index 2334e50a3322f24946b144ae20ca97bd3041a65d..741cc435f863600d28720eddbe9b6e0b0b093ad4 100644 (file)
@@ -34,6 +34,16 @@ static void com2_timer(void)
        copy_to_cooked(tty_table+65);
 }
 
+static void com3_timer(void)
+{
+       copy_to_cooked(tty_table+66);
+}
+
+static void com4_timer(void)
+{
+       copy_to_cooked(tty_table+67);
+}
+
 static inline void do_rs_write(unsigned int port)
 {
        char c;
@@ -66,17 +76,55 @@ static void com2_timeout(void)
        do_rs_write(1);
 }
 
+static void com3_timeout(void)
+{
+       do_rs_write(2);
+}
+
+static void com4_timeout(void)
+{
+       do_rs_write(3);
+}
+
 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(0x00,port+4);    /* reset DTR,RTS, OUT_2 */
        outb_p(0x0d,port+1);    /* enable all intrs but writes */
        (void)inb(port);        /* read data port to reset things (?) */
 }
 
+/*
+ * 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)
+{
+       unsigned short port;
+       unsigned short port2;
+
+       if (line>3)
+               return;
+       port = tty_table[64+line].read_q->data;
+       if (!port)
+               return;
+       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(0x0d,port+1);    /* enable all intrs but writes */
+       inb_p(port+5);
+       inb_p(port+0);
+       inb(port+6);
+       inb(port+2);
+       sti();
+}
+
 void rs_init(void)
 {
 /* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
@@ -84,15 +132,25 @@ void rs_init(void)
        timer_table[SER1_TIMER].expires = 0;
        timer_table[SER2_TIMER].fn = com2_timer;
        timer_table[SER2_TIMER].expires = 0;
+       timer_table[SER3_TIMER].fn = com3_timer;
+       timer_table[SER3_TIMER].expires = 0;
+       timer_table[SER4_TIMER].fn = com4_timer;
+       timer_table[SER4_TIMER].expires = 0;
 /* SERx_TIMEOUT timers are used for writing: prevent serial lockups */
        timer_table[SER1_TIMEOUT].fn = com1_timeout;
        timer_table[SER1_TIMEOUT].expires = 0;
        timer_table[SER2_TIMEOUT].fn = com2_timeout;
        timer_table[SER2_TIMEOUT].expires = 0;
+       timer_table[SER3_TIMEOUT].fn = com3_timeout;
+       timer_table[SER3_TIMEOUT].expires = 0;
+       timer_table[SER4_TIMEOUT].fn = com4_timeout;
+       timer_table[SER4_TIMEOUT].expires = 0;
        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);
 }
 
@@ -108,6 +166,6 @@ void rs_write(struct tty_struct * tty)
        cli();
        if (!EMPTY(tty->write_q))
                outb_p(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
-       timer_active |= 3 << SER1_TIMEOUT;
+       timer_active |= 15 << SER1_TIMEOUT;
        sti();
 }
index 18ea261528aed9c56bedc00b7649435dff84a311..12c64799f65e8e3853329a971b9f9f3fa41b09bc 100644 (file)
@@ -83,7 +83,9 @@ int fg_console = 0;
 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 + 3, rs_queues + 4,
+       rs_queues + 6, rs_queues + 7,
+       rs_queues + 9, rs_queues + 10
        };
 
 void change_console(unsigned int new_console)
@@ -122,15 +124,27 @@ void copy_to_cooked(struct tty_struct * tty)
 {
        unsigned char c;
 
-       if (!(tty->read_q || tty->write_q || tty->secondary)) {
+       if (!(tty && tty->write && tty->read_q &&
+           tty->write_q && tty->secondary)) {
                printk("copy_to_cooked: missing queues\n\r");
                return;
        }
+       cli();
+       if (tty->busy) {
+               sti();
+               return;
+       }
+       tty->busy = 1;
+       sti();
        while (1) {
                if (EMPTY(tty->read_q))
                        break;
-               if (FULL(tty->secondary))
+               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 (c==13) {
                        if (I_CRNL(tty))
@@ -153,7 +167,6 @@ void copy_to_cooked(struct tty_struct * tty)
                                                if (c<32)
                                                        PUTCH(127,tty->write_q);
                                                PUTCH(127,tty->write_q);
-                                               tty->write(tty);
                                        }
                                        DEC(tty->secondary->head);
                                }
@@ -170,7 +183,6 @@ void copy_to_cooked(struct tty_struct * tty)
                                        if (c<32)
                                                PUTCH(127,tty->write_q);
                                        PUTCH(127,tty->write_q);
-                                       tty->write(tty);
                                }
                                DEC(tty->secondary->head);
                                continue;
@@ -180,13 +192,11 @@ void copy_to_cooked(struct tty_struct * 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;
                        }
                }
@@ -221,10 +231,12 @@ void copy_to_cooked(struct tty_struct * tty)
                        } else
                                PUTCH(c,tty->write_q);
                }
-               tty->write(tty);
                PUTCH(c,tty->secondary);
        }
-       wake_up(&tty->secondary->proc_list);
+       tty->write(tty);
+       tty->busy = 0;
+       if (!EMPTY(tty->secondary))
+               wake_up(&tty->secondary->proc_list);
 }
 
 /*
@@ -270,7 +282,8 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
        tty = TTY_TABLE(channel);
        if (!(tty->read_q && tty->secondary))
                return -EIO;
-       if ((current->tty == channel) && (tty->pgrp != current->pgrp)) 
+       if ((tty->pgrp > 0) && (current->tty == channel) &&
+           (tty->pgrp != current->pgrp))
                return(tty_signal(SIGTTIN, tty));
        if (channel & 0x80)
                other_tty = tty_table + (channel ^ 0x40);
@@ -295,15 +308,14 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
        copy_to_cooked(tty);
        while (nr>0) {
                if (other_tty && other_tty->write)
-                       other_tty->write(other_tty);
+                       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();
+                       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);
@@ -329,11 +341,12 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
                                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;
+               if (time)
+                       current->timeout = time+jiffies;
        }
+       sti();
        current->timeout = 0;
        if (b-buf)
                return b-buf;
@@ -355,9 +368,13 @@ int tty_write(unsigned channel, char * buf, int nr)
        tty = TTY_TABLE(channel);
        if (!(tty->write_q && tty->write))
                return -EIO;
-       if (L_TOSTOP(tty) && 
+       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;
        while (nr>0) {
                sleep_if_full(tty->write_q);
                if (current->signal & ~current->blocked)
@@ -381,11 +398,15 @@ int tty_write(unsigned channel, char * buf, int nr)
                        cr_flag = 0;
                        PUTCH(c,tty->write_q);
                }
-               tty->write(tty);
+               TTY_WRITE(tty);
                if (nr>0)
                        schedule();
        }
-       return (b-buf);
+       if (b-buf)
+               return b-buf;
+       if (current->signal & ~current->blocked)
+               return -ERESTARTSYS;
+       return 0;
 }
 
 void chr_dev_init(void)
@@ -402,10 +423,14 @@ void tty_init(void)
        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},
-                       0, 0, 0, {0,0,0,0},
+                       -1, 0, 0, 0, {0,0,0,0},
                        NULL, NULL, NULL, NULL
                };
        }
@@ -418,9 +443,10 @@ void tty_init(void)
                        IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
                        0,              /* console termio */
                        INIT_C_CC},
-                       0,                      /* initial pgrp */
+                       -1,             /* initial pgrp */
                        0,                      /* initial session */
                        0,                      /* initial stopped */
+                       0,                      /* initial busy */
                        {video_num_lines,video_num_columns,0,0},
                        con_write,
                        con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
@@ -434,6 +460,7 @@ void tty_init(void)
                        0,
                        0,
                        INIT_C_CC},
+                       -1,
                        0,
                        0,
                        0,
@@ -450,6 +477,7 @@ void tty_init(void)
                        0,
                        0,
                        INIT_C_CC},
+                       -1,
                        0,
                        0,
                        0,
@@ -464,6 +492,7 @@ void tty_init(void)
                        IXON | ISIG | ICANON,
                        0,
                        INIT_C_CC},
+                       -1,
                        0,
                        0,
                        0,
index a4250d3ca73b8346e362f00a2f6bb96a55e93f11..eabfbed1b2ca83be88de8ad79df1d00618956be7 100644 (file)
@@ -53,7 +53,12 @@ static void flush(struct tty_queue * queue)
 
 static void wait_until_sent(struct tty_struct * tty)
 {
-       /* do nothing - not implemented */
+       cli();
+       while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
+               current->counter = 0;
+               interruptible_sleep_on(&tty->write_q->proc_list);
+       }
+       sti();
 }
 
 static void send_break(struct tty_struct * tty)
@@ -137,7 +142,7 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
 }
 
 /*
- * This only works as the 386 is low-byt-first
+ * This only works as the 386 is low-byte-first
  */
 static int set_termio(struct tty_struct * tty, struct termio * termio,
                        int channel)
@@ -255,11 +260,11 @@ int tty_ioctl(int dev, int cmd, int arg)
                        switch (arg) {
                        case TCOOFF:
                                tty->stopped = 1;
-                               tty->write(tty);
+                               TTY_WRITE(tty);
                                return 0;
                        case TCOON:
                                tty->stopped = 0;
-                               tty->write(tty);
+                               TTY_WRITE(tty);
                                return 0;
                        case TCIOFF:
                                if (STOP_CHAR(tty))
index e81319a920d32418639ac2f21c7d11cb6ba6ff64..be284bd3543e263e5f45a79d0736a9ca6b04ff8a 100644 (file)
@@ -359,9 +359,9 @@ volatile void do_exit(long code)
 
                if (current->tty >= 0) {
                        tty = TTY_TABLE(current->tty);
-                       if (tty->pgrp>0)
+                       if (tty->pgrp > 0)
                                kill_pg(tty->pgrp, SIGHUP, 1);
-                       tty->pgrp = 0;
+                       tty->pgrp = -1;
                        tty->session = 0;
                }
                for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
index 1dab26141c31a8f311bb28fc51ea7a0fe8d94dc8..6722ef7233ad5a97629b663d4f59080868c74924 100644 (file)
@@ -9,8 +9,11 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <sys/ptrace.h>
-/* does not yet catch signals sent when the child dies. in
-   exit.c or in signal.c. */
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
 
 /* determines which flags the user has access to. */
 /* 1 = access 0 = no access */
 /* check's for granularity. */
 #define GRANULARITY 0x00800000
 
-/* this is the number to subtract from the top of the stack. To find
-   the local frame. */
-
+/*
+ * this is the number to subtract from the top of the stack. To find
+ * the local frame.
+ */
 #define MAGICNUMBER 68
 
-void do_no_page (unsigned long, unsigned long, struct task_struct *);
-void write_verify (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 int get_task(int pid)
 {
-  int i;
-  for (i =0; i < NR_TASKS; i++)
-    {
-      if (task[i] != NULL && (task[i]->pid == pid)) return (i);
-    }
-  return (-1);
+       int i;
+
+       for (i = 0; i < NR_TASKS; i++) {
+               if (task[i] != NULL && (task[i]->pid == pid))
+                       return i;
+       }
+       return -1;
 }
 
-/* this routine will get a word off of the processes priviledged stack. 
-   the offset is how far from the base addr as stored in the TSS.  
-   this routine assumes that all the priviledged stacks are in our
-   data space. */
+/*
+ * this routine will get a word off of the processes priviledged stack. 
+ * the offset is how far from the base addr as stored in the TSS.  
+ * this routine assumes that all the priviledged stacks are in our
+ * data space.
+ */
    
-static inline int
-get_stack_long(struct task_struct *task, int offset)
+static inline int get_stack_long(struct task_struct *task, int offset)
 {
-  unsigned char *stack;
-  stack = (unsigned char *)task->tss.esp0;
-  stack += offset;
-  return (*((int *)stack));
+       unsigned char *stack;
 
+       stack = (unsigned char *)task->tss.esp0;
+       stack += offset;
+       return (*((int *)stack));
 }
 
-/* this routine will put a word on the processes priviledged stack. 
-   the offset is how far from the base addr as stored in the TSS.  
-   this routine assumes that all the priviledged stacks are in our
-   data space. */
-   
-static inline int
-put_stack_long(struct task_struct *task, int offset, unsigned short data)
+/*
+ * this routine will put a word on the processes priviledged stack. 
+ * the offset is how far from the base addr as stored in the TSS.  
+ * this routine assumes that all the priviledged stacks are in our
+ * data space.
+ */
+static inline int put_stack_long(struct task_struct *task, int offset,
+       unsigned short data)
 {
-  unsigned char *stack;
-  stack = (unsigned char *)task->tss.esp0;
-  stack += offset;
-  *(int *)stack = data;
-  return (0);
+       unsigned char * stack;
 
+       stack = (unsigned char *) task->tss.esp0;
+       stack += offset;
+       *(int *) stack = data;
+       return 0;
 }
 
-/* this routine will get a word out of an arbitrary 
-   tasks data space.  It likes to have the task number
-   rather than the task pointer.  Perhaps the number
-   should be included in the pointer. */
+/*
+ * this routine will get a word out of an arbitrary 
+ * tasks data space.  It likes to have the task number
+ * rather than the task pointer.  Perhaps the number
+ * should be included in the pointer.
+ */
 /* seg = 0 if I space */
-static inline int get_long (int tsk, long addr, unsigned seg, int *data)
+static inline int get_long(int tsk, long addr, unsigned seg, int *data)
 {
-  int i;
-  int limit;
-  int cur;
-  unsigned long address;
-  unsigned long page;
-  unsigned oldfs;
+       int i;
+       int limit;
+       int cur;
+       unsigned long address;
+       unsigned long page;
+       unsigned oldfs;
+
   /* find the task number of the current task. */
-  for (i = 0; i < NR_TASKS ; i ++)
-    {
-      if (task[i] == current) break;
-    }
-  if (i == NR_TASKS) 
-    {
-      panic ("PTRACE: Can't find current task\n");
-    }
-  cur = i;
-
-  /* we will need to check the redaability of the segment
+       for (i = 0; i < NR_TASKS ; i ++) {
+               if (task[i] == current) break;
+       }
+       if (i == NR_TASKS) {
+               printk("PTRACE: Can't find current task\n");
+               do_exit(SIGSEGV);
+       }
+       cur = i;
+
+  /* we will need to check the readability of the segment
      and then the byte in order to avoid segment violations. */
-  seg++;
-  limit=(task[tsk]->ldt[seg].a) & 0xffff;
+       seg++;
+       limit = (task[tsk]->ldt[seg].a) & 0xffff;
   /* this should be constant amound all of our segments, but we
      had better check anyway. */
-  if (task[tsk]->ldt[seg].b & GRANULARITY) limit = limit << 12;
+       if (task[tsk]->ldt[seg].b & GRANULARITY)
+               limit = limit << 12;
 
-  if (limit <= addr+4) return (-EIO);
+       if (limit <= addr+4)
+               return -EIO;
 
   /* Now compute the address, and make sure that it is present. */
-  address = ((task[tsk]->ldt[seg].a & 0xffff000) >> 8) |
-            ((task[tsk]->ldt[seg].b & 0xff) << 16 ) |
-           (task[tsk]->ldt[seg].b & 0xff000000);
+       address = task[tsk]->start_code + addr;
 
-  page = *((unsigned long*) ((address >> 20) & 0xffc));
+       page = *((unsigned long*) ((address >> 20) & 0xffc));
   /* see if it is present. */
-  if (! (page & PAGE_PRESENT))
-    {
-      do_no_page (0, address, task[tsk]);
-    }
+       if (!(page & PAGE_PRESENT)) {
+               do_no_page(0, address, task[tsk]);
+       }
 
-  oldfs=get_fs();
+       oldfs = get_fs();
   /* now convert seg to the right format. */
-  seg = seg << 3 | 0x4;
+       seg = (seg << 3) | 0x4;
 
-  cli(); /* we are about to change our ldt, we better do it
+       cli(); /* we are about to change our ldt, we better do it
            with interrupts off.  Perhaps we should call schedule
            first so that we won't be taking too much extra time. */
-  lldt(tsk);
-  set_fs(seg);
-  *data = get_fs_long((void *)addr); /* we are assuming kernel space
-                                       is in the gdt here. */
-  lldt(cur);
-  set_fs(oldfs);
-  sti();
-  return (0);
+       lldt(tsk);
+       set_fs(seg);
+       *data = get_fs_long((void *)addr); /* we are assuming kernel space
+                                               is in the gdt here. */
+       lldt(cur);
+       set_fs(oldfs);
+       sti();
+       return 0;
 }
 
-/* this routine will get a word out of an arbitrary 
-   tasks data space.  It likes to have the task number
-   rather than the task pointer.  Perhaps the number
-   should be included in the pointer. */
+/*
+ * this routine will get a word out of an arbitrary 
+ * tasks data space.  It likes to have the task number
+ * rather than the task pointer.  Perhaps the number
+ * should be included in the pointer.
+ */
 /* seg = 0 if I space */
-static inline int put_long (int tsk, long addr, int data, unsigned seg)
+static inline int put_long(int tsk, long addr, int data, unsigned seg)
 {
-  int i;
-  int limit;
-  unsigned oldfs;
-  unsigned long address;
-  unsigned long page;
-  int cur;
+       int i;
+       int limit;
+       unsigned oldfs;
+       unsigned long address;
+       unsigned long page;
+       int cur;
+
   /* find the task number of the current task. */
-  for (i = 0; i < NR_TASKS ; i ++)
-    {
-      if (task[i] == current) break;
-    }
-  if (i == NR_TASKS) 
-    {
-      panic ("PTRACE: Can't find current task\n");
-    }
-  cur = i;
+       for (i = 0; i < NR_TASKS ; i++) {
+               if (task[i] == current) break;
+       }
+       if (i == NR_TASKS) {
+               printk("PTRACE: Can't find current task\n");
+               do_exit(SIGSEGV);
+       }
+       cur = i;
 
   /* we will need to check the readability of the segment
      and then the byte in order to avoid segment violations. */
-  seg++;
-  limit=(task[tsk]->ldt[seg].a) & 0xffff;
+       seg++;
+       limit = (task[tsk]->ldt[seg].a) & 0xffff;
   /* this should be constant amound all of our segments, but we
      had better check anyway. */
-  if (task[tsk]->ldt[seg].b & GRANULARITY) limit = limit << 12;
+       if (task[tsk]->ldt[seg].b & GRANULARITY)
+               limit = limit << 12;
 
-  if (limit <= addr+4) return (-EIO);
+       if (limit <= addr+4)
+               return -EIO;
 
   /* Now compute the address, and make sure that it is present. */
-  address = ((task[tsk]->ldt[seg].a & 0xffff000) >> 8) |
-            ((task[tsk]->ldt[seg].b & 0xff) << 16 ) |
-           (task[tsk]->ldt[seg].b & 0xff000000);
+       address = task[tsk]->start_code + addr;
 
-  page = *((unsigned long*) ((address >> 20) & 0xffc));
+       page = *((unsigned long*) ((address >> 20) & 0xffc));
   /* see if it is present. */
-  if (! (page & PAGE_PRESENT))
-    {
-      do_no_page (0, address, task[tsk]);
-    }
-  write_verify (address);
+       if (!(page & PAGE_PRESENT)) {
+               do_no_page(0, address, task[tsk]);
+       }
+       write_verify(address);
 
-  oldfs=get_fs();
+       oldfs=get_fs();
   /* now convert seg to the right format. */
-  seg = seg << 3 | 0x4;
+       seg = (seg << 3) | 0x4;
 
-  cli(); /* we are about to change our ldt, we better do it
+       cli(); /* we are about to change our ldt, we better do it
            with interrupts off.  Perhaps we should call schedule
            first so that we won't be taking too much extra time. */
-  lldt(tsk);
-  set_fs(seg);
-  put_fs_long(data,(void *)addr);
-  lldt(cur);
-  set_fs(oldfs);
-  sti();
-  return (0);
+       lldt(tsk);
+       set_fs(seg);
+       put_fs_long(data,(void *)addr);
+       lldt(cur);
+       set_fs(oldfs);
+       sti();
+       return 0;
 }
 
 
-int
-sys_ptrace( unsigned long *buffer)
 /* Perform ptrace(request, pid, addr, data) syscall */
+int sys_ptrace(unsigned long *buffer)
 {
-  long request, pid, data;
-  long addr;
-  struct task_struct *child;
-  int childno;
-
-  request = get_fs_long(buffer++);
-  pid = get_fs_long(buffer++);
-  addr = get_fs_long(buffer++); /* assume long = void * */
-  data = get_fs_long(buffer++);
-
-  if (request == 0)
-    {
-      /* set the ptrace bit in the proccess flags. */
-      current->flags |= PF_PTRACED;
-      return (0);
-    }
-
-  childno=get_task(pid);
-
-  if (childno < 0)
-    return (-ESRCH);
-  else
-    child = task[childno];
-
-  if (child->p_pptr != current ||
-      !(child->flags & PF_PTRACED) || child->state != TASK_STOPPED)
-    return (-ESRCH);
-
-  switch (request)
-    {
+       long request, pid, data;
+       long addr;
+       struct task_struct *child;
+       int childno;
+
+       request = get_fs_long(buffer++);
+       pid = get_fs_long(buffer++);
+       addr = get_fs_long(buffer++); /* assume long = void * */
+       data = get_fs_long(buffer++);
+
+       if (request == 0) {
+               /* set the ptrace bit in the proccess flags. */
+               current->flags |= PF_PTRACED;
+               return 0;
+       }
+
+       childno = get_task(pid);
+
+       if (childno < 0)
+               return -ESRCH;
+       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 1: /* read word at location addr. */ 
-    case 2: {
-       int tmp;
-       int res;
-       res = get_long(childno, addr, 1, &tmp);
-       if (res < 0)
-               return res;
-       verify_area(data, 4);
-       put_fs_long( tmp, (unsigned long *)data);
-       return 0;
-    }
-
-    case 3: /* read the word at location addr in the USER area. */
-      {
-       int tmp;
-       addr = addr >> 2; /* temporary hack. */
-       if (addr < 0 || addr >= 17)
-               return (-EIO);
-       verify_area(data, 4);
-       tmp = get_stack_long (child, 4*addr-MAGICNUMBER);
-       put_fs_long(tmp,(unsigned long *)data);
-       return (0);
-      }
-    case 4: /* write the word at location addr. */
-    case 5:
+               case 1: /* read word at location addr. */ 
+               case 2: {
+                       int tmp,res;
+
+                       res = get_long(childno, addr, 1, &tmp);
+                       if (res < 0)
+                               return res;
+                       verify_area((void *) data, 4);
+                       put_fs_long(tmp,(unsigned long *) data);
+                       return 0;
+               }
+
+       /* read the word at location addr in the USER area. */
+               case 3: {
+                       int tmp;
+                       addr = addr >> 2; /* temporary hack. */
+                       if (addr < 0 || addr >= 17)
+                               return -EIO;
+                       verify_area((void *) data, 4);
+                       tmp = get_stack_long(child, 4*addr - MAGICNUMBER);
+                       put_fs_long(tmp,(unsigned long *) data);
+                       return 0;
+               }
+
       /* when I and D space are seperate, this will have to be fixed. */
-      if (put_long(childno, addr, data, 1)) return (-EIO);
-      return (0);
-      
-    case 6: /* write the word at location addr in the USER area */
-      addr = addr >> 2; /* temproary hack. */
-      if (addr < 0 || addr >= 17) return (-EIO);
-      if (addr == ORIG_EAX) return (-EIO);
-      if (addr == EFL)   /* flags. */
-       {
-         data &= FLAG_MASK;
-         data |= get_stack_long(child, EFL*4-MAGICNUMBER)  & ~FLAG_MASK;
-       }
-      
-      if (put_stack_long(child, 4*addr-MAGICNUMBER, data)) return (-EIO);
-      return (0);
-      
-    case 7: /* restart after signal. */
-      {
-       long tmp;
-       child->signal=0;
-       if (data > 0 && data <= NSIG)
-         child->signal = 1<<(data-1);
-       child->state = 0;
+               case 4: /* write the word at location addr. */
+               case 5:
+                       if (put_long(childno, addr, data, 1))
+                               return -EIO;
+                       return 0;
+
+               case 6: /* write the word at location addr in the USER area */
+                       addr = addr >> 2; /* temproary hack. */
+                       if (addr < 0 || addr >= 17)
+                                       return -EIO;
+                       if (addr == ORIG_EAX)
+                               return -EIO;
+                       if (addr == EFL) {   /* flags. */
+                               data &= FLAG_MASK;
+                               data |= get_stack_long(child, EFL*4-MAGICNUMBER)  & ~FLAG_MASK;
+                       }
+
+                       if (put_stack_long(child, 4*addr-MAGICNUMBER, data))
+                               return -EIO;
+                       return 0;
+
+               case 7: { /* restart after signal. */
+                       long tmp;
+
+                       child->signal=0;
+                       if (data > 0 && data <= NSIG)
+                               child->signal = 1<<(data-1);
+                       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);
-       return (0);
-      }
-
-    case 8: /* make the child exit.  Best I can do is send it a sigkill. 
-              perhaps it should be put in the status that it want's to 
-              exit. */
-      {
-       long tmp;
-       child->state = 0;
-       child->signal = 1 << (SIGKILL -1 );
+                       tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
+                       put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+                       return 0;
+               }
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it want's to 
+ * exit.
+ */
+               case 8: {
+                       long tmp;
+
+                       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;
-       put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
-       return (0);
-      }
-      
-    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 = 0;
-       child->signal=0;
-       if (data > 0 && data <NSIG)
-         child->signal= 1<<(data-1);
+                       tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
+                       put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+                       return 0;
+               }
+
+               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 = 0;
+                       child->signal = 0;
+                       if (data > 0 && data <NSIG)
+                               child->signal= 1<<(data-1);
        /* give it a chance to run. */
-       return (0);
-      }
-
-    default:
-      return (-EIO);
-    }
+                       return 0;
+               }
 
+               default:
+                       return -EIO;
+       }
 }
index 335551d6e3ef2fbab8771734bc354bf242a8001e..2c8a845efee65c5cad5940a91102359e81dbf42d 100644 (file)
@@ -126,11 +126,11 @@ void schedule(void)
 
        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                if (*p) {
-                       if ((*p)->timeout && (*p)->timeout < jiffies) {
-                               (*p)->timeout = 0;
-                               if ((*p)->state == TASK_INTERRUPTIBLE)
+                       if ((*p)->timeout && (*p)->timeout < jiffies)
+                               if ((*p)->state == TASK_INTERRUPTIBLE) {
+                                       (*p)->timeout = 0;
                                        (*p)->state = TASK_RUNNING;
-                       }
+                               }
                        if ((*p)->alarm && (*p)->alarm < jiffies) {
                                (*p)->signal |= (1<<(SIGALRM-1));
                                (*p)->alarm = 0;
@@ -178,29 +178,45 @@ int sys_pause(void)
        return -EINTR;
 }
 
+void wake_up(struct task_struct **p)
+{
+       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
+                               wakeup_ptr->state = TASK_RUNNING;
+                       tmp = wakeup_ptr->next_wait;
+                       wakeup_ptr->next_wait = task[0];
+                       wakeup_ptr = tmp;
+               }
+       }
+}
+
 static inline void __sleep_on(struct task_struct **p, int state)
 {
-       struct task_struct *tmp;
        unsigned int flags;
 
        if (!p)
                return;
-       if (current == &(init_task.task))
+       if (current == task[0])
                panic("task[0] trying to sleep");
        __asm__("pushfl ; popl %0":"=r" (flags));
-       tmp = *p;
+       current->next_wait = *p;
+       task[0]->next_wait = NULL;
        *p = current;
        current->state = state;
-/* make sure interrupts are enabled: there should be no more races here */
        sti();
-repeat:        schedule();
-       if (*p && *p != current) {
-               current->state = TASK_UNINTERRUPTIBLE;
-               (**p).state = 0;
-               goto repeat;
-       }
-       if (*p = tmp)
-               tmp->state=0;
+       schedule();
+       if (current->next_wait != task[0])
+               wake_up(p);
+       current->next_wait = NULL;
        __asm__("pushl %0 ; popfl"::"r" (flags));
 }
 
@@ -214,17 +230,6 @@ void sleep_on(struct task_struct **p)
        __sleep_on(p,TASK_UNINTERRUPTIBLE);
 }
 
-void wake_up(struct task_struct **p)
-{
-       if (p && *p) {
-               if ((**p).state == TASK_STOPPED)
-                       printk("wake_up: TASK_STOPPED");
-               if ((**p).state == TASK_ZOMBIE)
-                       printk("wake_up: TASK_ZOMBIE");
-               (**p).state=0;
-       }
-}
-
 /*
  * OK, here are some floppy things that shouldn't be in the kernel
  * proper. They are here because the floppy needs a timer, and this
@@ -261,14 +266,6 @@ int ticks_to_floppy_on(unsigned int nr)
        return mon_timer[nr];
 }
 
-void floppy_on(unsigned int nr)
-{
-       cli();
-       while (ticks_to_floppy_on(nr))
-               sleep_on(nr+wait_motor);
-       sti();
-}
-
 void floppy_off(unsigned int nr)
 {
        moff_timer[nr]=3*HZ;
index 44c38abbde9cfb01e450891754877e96f3b1dc0b..cc6e20965fe68dc93e62363262020b8f05718447 100644 (file)
@@ -17,8 +17,6 @@ CPP   =gcc -E -nostdinc -I../include
 
 OBJS   = memory.o swap.o
 
-all: mm.o
-
 mm.o: $(OBJS)
        $(LD) -r -o mm.o $(OBJS)
 
index a77f26f675f397469498397197907b9441b53fd6..574f28152b07b3b79d60fe592bb029d142fbdfda 100644 (file)
@@ -213,7 +213,13 @@ static unsigned long put_page(unsigned long page,unsigned long address)
                *page_table = tmp | 7;
                page_table = (unsigned long *) tmp;
        }
-       page_table[(address>>12) & 0x3ff] = page | 7;
+       page_table += (address>>12) & 0x3ff;
+       if (*page_table) {
+               printk("put_page: page already exists\n");
+               *page_table = 0;
+               invalidate();
+       }
+       *page_table = page | 7;
 /* no need for invalidate */
        return page;
 }
@@ -243,7 +249,13 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address)
                *page_table = tmp|7;
                page_table = (unsigned long *) tmp;
        }
-       page_table[(address>>12) & 0x3ff] = page | (PAGE_DIRTY | 7);
+       page_table += (address>>12) & 0x3ff;
+       if (*page_table) {
+               printk("put_dirty_page: page already exists\n");
+               *page_table = 0;
+               invalidate();
+       }
+       *page_table = page | (PAGE_DIRTY | 7);
 /* no need for invalidate */
        return page;
 }
@@ -296,8 +308,10 @@ repeat:
  */
 void do_wp_page(unsigned long error_code,unsigned long address)
 {
-       if (address < TASK_SIZE)
+       if (address < TASK_SIZE) {
                printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
+               do_exit(SIGSEGV);
+       }
        if (address - current->start_code >= TASK_SIZE) {
                printk("Bad things happen: page error in do_wp_page\n\r");
                do_exit(SIGSEGV);
@@ -305,7 +319,6 @@ void do_wp_page(unsigned long error_code,unsigned long address)
        un_wp_page((unsigned long *)
                (((address>>10) & 0xffc) + (0xfffff000 &
                *((unsigned long *) ((address>>20) &0xffc)))));
-
 }
 
 void write_verify(unsigned long address)
@@ -436,8 +449,10 @@ void do_no_page(unsigned long error_code,
        if (last_checked >= CHECK_LAST_NR)
                last_checked = 0;
        last_pages[last_checked] = address & 0xfffff000;
-       if (address < TASK_SIZE)
+       if (address < TASK_SIZE) {
                printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
+               do_exit(SIGSEGV);
+       }
        if (address - tsk->start_code >= TASK_SIZE) {
                printk("Bad things happen: nonexistent page error in do_no_page\n\r");
                do_exit(SIGSEGV);
@@ -567,12 +582,12 @@ void show_mem(void)
 /* This routine handles page faults.  It determines the address,
    and the problem then passes it off to one of the appropriate
    routines. */
-void do_page_fault (unsigned long *esp, unsigned long error_code)
+void do_page_fault(unsigned long *esp, unsigned long error_code)
 {
        unsigned long address;
        /* get the address */
 
-       __asm__ ("movl %%cr2,%0":"=r" (address));
+       __asm__("movl %%cr2,%0":"=r" (address));
        if (!(error_code & 1)) {
                do_no_page(error_code, address, current);
                return;
index 4c621d0123bbcacb13eceea6f69fca654aea3da5..5c7e883a3c841dc9012a5a98ee27c5a19ede4fc9 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -155,37 +155,38 @@ int swap_out(void)
        static int dir_entry = 1024;
        static int page_entry = -1;
        int counter = VM_PAGES;
-       int pg_table = 0;
+       int pg_table;
 
-repeat:
-       while (counter > 0) {
+check_dir:
+       if (counter < 0)
+               goto no_swap;
+       if (dir_entry >= 1024)
+               dir_entry = FIRST_VM_PAGE>>10;
+       if (!(1 & (pg_table = pg_dir[dir_entry]))) {
+               if (pg_table) {
+                       printk("bad page-table at pg_dir[%d]: %08x\n\r",
+                               dir_entry,pg_table);
+                       pg_dir[dir_entry] = 0;
+               }
                counter -= 1024;
                dir_entry++;
-               if (dir_entry >= 1024)
-                       dir_entry = FIRST_VM_PAGE>>10;
-               if (pg_table = pg_dir[dir_entry])
-                       break;
-       }
-       if (counter <= 0) {
-               printk("Out of swap-memory\n");
-               return 0;
-       }
-       if (!(pg_table & 1)) {
-               printk("bad page-table at pg_dir[%d]: %08x\n\r",dir_entry,
-                       pg_table);
-               return 0;
+               goto check_dir;
        }
        pg_table &= 0xfffff000;
-       while (counter > 0) {
-               counter--;
-               page_entry++;
-               if (page_entry >= 1024) {
-                       page_entry = -1;
-                       goto repeat;
-               }
-               if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
-                       return 1;
+check_table:
+       if (counter < 0)
+               goto no_swap;
+       counter--;
+       page_entry++;
+       if (page_entry >= 1024) {
+               page_entry = -1;
+               dir_entry++;
+               goto check_dir;
        }
+       if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
+               return 1;
+       goto check_table;
+no_swap:
        printk("Out of swap-memory\n\r");
        return 0;
 }