Commit e4f54503 authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.95a (March 17, 1992)

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.
parent e6c7a63f
...@@ -61,28 +61,28 @@ tools/system: boot/head.o init/main.o \ ...@@ -61,28 +61,28 @@ tools/system: boot/head.o init/main.o \
$(LIBS) \ $(LIBS) \
-o tools/system > System.map -o tools/system > System.map
kernel/math/math.a: kernel/math/math.a: dummy
(cd kernel/math; make) (cd kernel/math; make)
kernel/blk_drv/blk_drv.a: kernel/blk_drv/blk_drv.a: dummy
(cd kernel/blk_drv; make) (cd kernel/blk_drv; make)
kernel/chr_drv/chr_drv.a: kernel/chr_drv/chr_drv.a: dummy
(cd kernel/chr_drv; make) (cd kernel/chr_drv; make)
kernel/kernel.o: kernel/kernel.o: dummy
(cd kernel; make) (cd kernel; make)
mm/mm.o: mm/mm.o: dummy
(cd mm; make) (cd mm; make)
fs/fs.o: fs/fs.o: dummy
(cd fs; make) (cd fs; make)
fs/minix/minix.o: fs/minix/minix.o: dummy
(cd fs/minix; make) (cd fs/minix; make)
lib/lib.a: lib/lib.a: dummy
(cd lib; make) (cd lib; make)
boot/setup: boot/setup.s boot/setup: boot/setup.s
...@@ -120,6 +120,8 @@ dep: ...@@ -120,6 +120,8 @@ dep:
(cd kernel; make dep) (cd kernel; make dep)
(cd mm; make dep) (cd mm; make dep)
dummy:
### Dependencies: ### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \ init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \ include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \
......
...@@ -43,6 +43,12 @@ start: ...@@ -43,6 +43,12 @@ start:
int 0x15 int 0x15
mov [2],ax 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 ! check for EGA/VGA and some config parameters
mov ah,#0x12 mov ah,#0x12
...@@ -498,8 +504,25 @@ nozero: sub al,#0x80 ...@@ -498,8 +504,25 @@ nozero: sub al,#0x80
lodsw lodsw
pop ds pop ds
ret ret
novid7: pop ds ! Here could be code to support standard 80x50,80x30 novid7:
mov ax,#0x5019 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 ret
! Routine that 'tabs' to next col. ! Routine that 'tabs' to next col.
......
...@@ -47,8 +47,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -47,8 +47,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
filp->f_pos += chars; filp->f_pos += chars;
written += chars; written += chars;
count -= chars; count -= chars;
while (chars-->0) memcpy_fromfs(p,buf,chars);
*(p++) = get_fs_byte(buf++); p += chars;
buf += chars;
bh->b_dirt = 1; bh->b_dirt = 1;
brelse(bh); brelse(bh);
} }
...@@ -85,8 +86,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -85,8 +86,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
filp->f_pos += chars; filp->f_pos += chars;
read += chars; read += chars;
count -= chars; count -= chars;
while (chars-->0) memcpy_tofs(buf,p,chars);
put_fs_byte(*(p++),buf++); p += chars;
buf += chars;
brelse(bh); brelse(bh);
} }
return read; return read;
......
...@@ -109,10 +109,15 @@ void inline invalidate_buffers(int dev) ...@@ -109,10 +109,15 @@ void inline invalidate_buffers(int dev)
void check_disk_change(int dev) void check_disk_change(int dev)
{ {
int i; int i;
struct buffer_head * bh;
if (MAJOR(dev) != 2) if (MAJOR(dev) != 2)
return; return;
if (!floppy_change(dev & 0x03)) if (!(bh = getblk(dev,0)))
return;
i = floppy_change(bh);
brelse(bh);
if (!i)
return; return;
for (i=0 ; i<NR_SUPER ; i++) for (i=0 ; i<NR_SUPER ; i++)
if (super_block[i].s_dev == dev) if (super_block[i].s_dev == dev)
......
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
...@@ -73,8 +73,10 @@ void invalidate_inodes(int dev) ...@@ -73,8 +73,10 @@ void invalidate_inodes(int dev)
for(i=0 ; i<NR_INODE ; i++,inode++) { for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode); wait_on_inode(inode);
if (inode->i_dev == dev) { if (inode->i_dev == dev) {
if (inode->i_count) if (inode->i_count) {
printk("inode in use on removed disk\n\r"); printk("inode in use on removed disk\n\r");
continue;
}
inode->i_dev = inode->i_dirt = 0; inode->i_dev = inode->i_dirt = 0;
} }
} }
......
...@@ -39,9 +39,8 @@ int minix_file_read(struct inode * inode, struct file * filp, char * buf, int co ...@@ -39,9 +39,8 @@ int minix_file_read(struct inode * inode, struct file * filp, char * buf, int co
left -= chars; left -= chars;
read += chars; read += chars;
if (bh) { if (bh) {
char * p = nr + bh->b_data; memcpy_tofs(buf,nr+bh->b_data,chars);
while (chars-->0) buf += chars;
put_fs_byte(*(p++),buf++);
brelse(bh); brelse(bh);
} else { } else {
while (chars-->0) while (chars-->0)
...@@ -81,7 +80,6 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c ...@@ -81,7 +80,6 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
} }
c = pos % BLOCK_SIZE; c = pos % BLOCK_SIZE;
p = c + bh->b_data; p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c; c = BLOCK_SIZE-c;
if (c > count-written) if (c > count-written)
c = count-written; c = count-written;
...@@ -91,8 +89,9 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c ...@@ -91,8 +89,9 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
inode->i_dirt = 1; inode->i_dirt = 1;
} }
written += c; written += c;
while (c-->0) memcpy_fromfs(p,buf,c);
*(p++) = get_fs_byte(buf++); buf += c;
bh->b_dirt = 1;
brelse(bh); brelse(bh);
} }
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
......
...@@ -135,6 +135,8 @@ static int check_char_dev(struct inode * inode, struct file * filp) ...@@ -135,6 +135,8 @@ static int check_char_dev(struct inode * inode, struct file * filp)
tty->session= current->session; tty->session= current->session;
tty->pgrp = current->pgrp; tty->pgrp = current->pgrp;
} }
if (IS_A_SERIAL(min))
serial_open(min-64);
} }
return 0; return 0;
} }
......
...@@ -39,11 +39,15 @@ typedef struct { ...@@ -39,11 +39,15 @@ typedef struct {
struct task_struct ** wait_address; struct task_struct ** wait_address;
} wait_entry; } wait_entry;
typedef struct { typedef struct select_table_struct {
int nr; int nr, woken;
struct task_struct * current;
struct select_table_struct * next_table;
wait_entry entry[NR_OPEN*3]; wait_entry entry[NR_OPEN*3];
} select_table; } select_table;
static select_table * sel_tables = NULL;
static void add_wait(struct task_struct ** wait_address, select_table * p) static void add_wait(struct task_struct ** wait_address, select_table * p)
{ {
int i; int i;
...@@ -53,32 +57,52 @@ static void add_wait(struct task_struct ** wait_address, select_table * p) ...@@ -53,32 +57,52 @@ static void add_wait(struct task_struct ** wait_address, select_table * p)
for (i = 0 ; i < p->nr ; i++) for (i = 0 ; i < p->nr ; i++)
if (p->entry[i].wait_address == wait_address) if (p->entry[i].wait_address == wait_address)
return; return;
current->next_wait = NULL;
p->entry[p->nr].wait_address = wait_address; 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; *wait_address = current;
p->nr++; 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; int i;
struct task_struct ** tpp; 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++) { for (i = 0; i < p->nr ; i++) {
tpp = p->entry[i].wait_address; wake_up(p->entry[i].wait_address);
while (*tpp && *tpp != current) { wake_up(&p->entry[i].old_task);
(*tpp)->state = 0;
current->state = TASK_UNINTERRUPTIBLE;
schedule();
}
if (!*tpp)
printk("free_wait: NULL");
if (*tpp = p->entry[i].old_task)
(**tpp).state = 0;
} }
p->nr = 0; 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) static struct tty_struct * get_tty(struct inode * inode)
{ {
int major, minor; int major, minor;
...@@ -177,6 +201,10 @@ int do_select(fd_set in, fd_set out, fd_set ex, ...@@ -177,6 +201,10 @@ int do_select(fd_set in, fd_set out, fd_set ex,
} }
repeat: repeat:
wait_table.nr = 0; 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; *inp = *outp = *exp = 0;
count = 0; count = 0;
mask = 1; mask = 1;
...@@ -200,7 +228,9 @@ int do_select(fd_set in, fd_set out, fd_set ex, ...@@ -200,7 +228,9 @@ int do_select(fd_set in, fd_set out, fd_set ex,
if (!(current->signal & ~current->blocked) && if (!(current->signal & ~current->blocked) &&
current->timeout && !count) { current->timeout && !count) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
sti();
schedule(); schedule();
cli();
free_wait(&wait_table); free_wait(&wait_table);
goto repeat; goto repeat;
} }
...@@ -276,7 +306,9 @@ int sys_select( unsigned long *buffer ) ...@@ -276,7 +306,9 @@ int sys_select( unsigned long *buffer )
timeout *= (1000000/HZ); timeout *= (1000000/HZ);
put_fs_long(timeout, (unsigned long *) &tvp->tv_usec); put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
} }
if (!i && (current->signal & ~current->blocked)) if (i)
return -EINTR;
return i; return i;
if (current->signal & ~current->blocked)
return -EINTR;
return 0;
} }
static void inline outb(char value, unsigned short port) 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) static void inline outb_p(char value, unsigned short port)
{ {
__asm__ volatile ("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:" __asm__ volatile ("outb %0,%1\n"
::"a" (value),"d" (port)); "\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) static unsigned char inline inb(unsigned short port)
{ {
unsigned char _v; 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; return _v;
} }
static unsigned char inb_p(unsigned short port) static unsigned char inb_p(unsigned short port)
{ {
unsigned char _v; unsigned char _v;
__asm__ volatile ("inb %1,%0\n" __asm__ volatile ("inb %1,%0\n"
"\tjmp 1f\n" "\tjmp 1f\n"
"1:\tjmp 1f\n" "1:\tjmp 1f\n"
"1:":"=a" (_v):"d" ((unsigned short) port)); "1:\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:"
:"=a" (_v):"d" ((unsigned short) port));
return _v; return _v;
} }
...@@ -37,6 +37,40 @@ extern inline void put_fs_long(unsigned long val,unsigned long * addr) ...@@ -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)); __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. * Someone who knows GNU asm better than I should double check the followig.
* It seems to work, but I don't know if I'm doing something subtly wrong. * It seems to work, but I don't know if I'm doing something subtly wrong.
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#define UTS_SYSNAME "Linux" #define UTS_SYSNAME "Linux"
#define UTS_NODENAME "(none)" /* set by sethostname() */ #define UTS_NODENAME "(none)" /* set by sethostname() */
#define UTS_RELEASE "0" /* patchlevel */ #define UTS_RELEASE "0" /* patchlevel */
#define UTS_VERSION "0.12" #define UTS_VERSION "0.95a"
#define UTS_MACHINE "i386" /* hardware type */ #define UTS_MACHINE "i386" /* hardware type */
/* Don't touch these, unless you really know what your doing. */ /* Don't touch these, unless you really know what your doing. */
......
...@@ -165,7 +165,7 @@ extern struct buffer_head * start_buffer; ...@@ -165,7 +165,7 @@ extern struct buffer_head * start_buffer;
extern int nr_buffers; extern int nr_buffers;
extern void check_disk_change(int dev); extern void check_disk_change(int dev);
extern int floppy_change(unsigned int nr); extern int floppy_change(struct buffer_head * first_block);
extern int ticks_to_floppy_on(unsigned int dev); extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev); extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev); extern void floppy_off(unsigned int dev);
......
...@@ -121,6 +121,10 @@ struct task_struct { ...@@ -121,6 +121,10 @@ struct task_struct {
* p->p_pptr->pid) * 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 uid,euid,suid;
unsigned short gid,egid,sgid; unsigned short gid,egid,sgid;
unsigned long timeout,alarm; unsigned long timeout,alarm;
...@@ -164,7 +168,7 @@ struct task_struct { ...@@ -164,7 +168,7 @@ struct task_struct {
/* ec,brk... */ 0,0,0,0,0,0, \ /* ec,brk... */ 0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \ /* 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, \ /* uid etc */ 0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0, \ /* timeout */ 0,0,0,0,0,0,0, \
/* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \ /* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
......
...@@ -24,11 +24,16 @@ ...@@ -24,11 +24,16 @@
#define BLANK_TIMER 0 #define BLANK_TIMER 0
#define BEEP_TIMER 1 #define BEEP_TIMER 1
#define SER1_TIMER 2 #define SER1_TIMER 2
#define SER2_TIMER 3 #define SER2_TIMER 3
#define SER3_TIMER 4
#define SER4_TIMER 5
#define SER1_TIMEOUT 8 #define SER1_TIMEOUT 8
#define SER2_TIMEOUT 9 #define SER2_TIMEOUT 9
#define SER3_TIMEOUT 10
#define SER4_TIMEOUT 11
#define HD_TIMER 16 #define HD_TIMER 16
#define FLOPPY_TIMER 17 #define FLOPPY_TIMER 17
......
...@@ -10,14 +10,14 @@ ...@@ -10,14 +10,14 @@
#define _TTY_H #define _TTY_H
#define MAX_CONSOLES 8 #define MAX_CONSOLES 8
#define NR_SERIALS 2 #define NR_SERIALS 4
#define NR_PTYS 4 #define NR_PTYS 4
extern int NR_CONSOLES; extern int NR_CONSOLES;
#include <termios.h> #include <termios.h>
#define TTY_BUF_SIZE 1024 #define TTY_BUF_SIZE 2048
struct tty_queue { struct tty_queue {
unsigned long data; unsigned long data;
...@@ -60,6 +60,7 @@ struct tty_struct { ...@@ -60,6 +60,7 @@ struct tty_struct {
int pgrp; int pgrp;
int session; int session;
int stopped; int stopped;
int busy;
struct winsize winsize; struct winsize winsize;
void (*write)(struct tty_struct * tty); void (*write)(struct tty_struct * tty);
struct tty_queue *read_q; struct tty_queue *read_q;
...@@ -67,6 +68,18 @@ struct tty_struct { ...@@ -67,6 +68,18 @@ struct tty_struct {
struct tty_queue *secondary; 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 struct tty_struct tty_table[];
extern int fg_console; extern int fg_console;
extern unsigned long video_num_columns; extern unsigned long video_num_columns;
...@@ -96,6 +109,8 @@ void rs_write(struct tty_struct * tty); ...@@ -96,6 +109,8 @@ void rs_write(struct tty_struct * tty);
void mpty_write(struct tty_struct * tty); void mpty_write(struct tty_struct * tty);
void spty_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 copy_to_cooked(struct tty_struct * tty);
void update_screen(int new_console); void update_screen(int new_console);
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
#include <sys/types.h> #include <sys/types.h>
#define TTY_BUF_SIZE 1024
/* 0x54 is just a magic number to make these relatively uniqe ('T') */ /* 0x54 is just a magic number to make these relatively uniqe ('T') */
#define TCGETS 0x5401 #define TCGETS 0x5401
......
...@@ -203,6 +203,7 @@ void init(void) ...@@ -203,6 +203,7 @@ void init(void)
NR_BUFFERS*BLOCK_SIZE); NR_BUFFERS*BLOCK_SIZE);
printf("Free mem: %d bytes\n\r",memory_end-main_memory_start); printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init);
/* if this fails, fall through to original stuff */ /* if this fails, fall through to original stuff */
......
...@@ -100,11 +100,16 @@ extern int * blk_size[NR_BLK_DEV]; ...@@ -100,11 +100,16 @@ extern int * blk_size[NR_BLK_DEV];
void (*DEVICE_INTR)(void) = NULL; void (*DEVICE_INTR)(void) = NULL;
#endif #endif
#ifdef DEVICE_TIMEOUT #ifdef DEVICE_TIMEOUT
#define SET_INTR(x) (DEVICE_INTR = (x), \
timer_table[DEVICE_TIMEOUT].expires = jiffies + 200, \ #define SET_INTR(x) if (DEVICE_INTR = (x)) { \
timer_active |= 1<<DEVICE_TIMEOUT) timer_table[DEVICE_TIMEOUT].expires = jiffies + 200; \
timer_active |= 1<<DEVICE_TIMEOUT; \
} else timer_active &= ~(1<<DEVICE_TIMEOUT)
#else #else
#define SET_INTR(x) (DEVICE_INTR = (x)) #define SET_INTR(x) (DEVICE_INTR = (x))
#endif #endif
static void (DEVICE_REQUEST)(void); static void (DEVICE_REQUEST)(void);
...@@ -134,23 +139,16 @@ extern inline void end_request(int uptodate) ...@@ -134,23 +139,16 @@ extern inline void end_request(int uptodate)
CURRENT = CURRENT->next; CURRENT = CURRENT->next;
} }
#ifdef DEVICE_TIMEOUT
#define CLEAR_DEVICE_TIMEOUT timer_active &= ~(1<<DEVICE_TIMEOUT);
#else
#define CLEAR_DEVICE_TIMEOUT
#endif
#ifdef DEVICE_INTR #ifdef DEVICE_INTR
#define CLEAR_DEVICE_INTR DEVICE_INTR = 0; #define CLEAR_INTR SET_INTR(NULL)
#else #else
#define CLEAR_DEVICE_INTR #define CLEAR_INTR
#endif #endif
#define INIT_REQUEST \ #define INIT_REQUEST \
repeat: \ repeat: \
if (!CURRENT) {\ if (!CURRENT) {\
CLEAR_DEVICE_INTR \ CLEAR_INTR; \
CLEAR_DEVICE_TIMEOUT \
return; \ return; \
} \ } \
if (MAJOR(CURRENT->dev) != MAJOR_NR) \ if (MAJOR(CURRENT->dev) != MAJOR_NR) \
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#define MAJOR_NR 2 #define MAJOR_NR 2
#include "blk.h" #include "blk.h"
unsigned int changed_floppies = 0;
static int recalibrate = 0; static int recalibrate = 0;
static int reset = 0; static int reset = 0;
static int seek = 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)) ...@@ -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) #define DRIVE(x) ((x)&0x03)
/* /*
* Note that MAX_ERRORS=X doesn't imply that we retry every bad read * 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, * max X times - some types of errors increase the errorcount by 2 or
* so we might actually retry only X/2 times before giving up. * even 3, so we might actually retry only X/2 times before giving up.
*/ */
#define MAX_ERRORS 12 #define MAX_ERRORS 12
...@@ -115,18 +117,20 @@ extern char floppy_track_buffer[512*2*18]; ...@@ -115,18 +117,20 @@ extern char floppy_track_buffer[512*2*18];
* information to interrupts. They are the data used for the current * information to interrupts. They are the data used for the current
* request. * request.
*/ */
#define NO_TRACK 255
static int read_track = 0; /* flag to indicate if we want to read all track */ static int read_track = 0; /* flag to indicate if we want to read all track */
static int buffer_track = -1; static int buffer_track = -1;
static int buffer_drive = -1; static int buffer_drive = -1;
static int cur_spec1 = -1; static int cur_spec1 = -1;
static int cur_rate = -1; static int cur_rate = -1;
static struct floppy_struct * floppy = floppy_type; static struct floppy_struct * floppy = floppy_type;
static unsigned char current_drive = 0; static unsigned char current_drive = 255;
static unsigned char sector = 0; static unsigned char sector = 0;
static unsigned char head = 0; static unsigned char head = 0;
static unsigned char track = 0; static unsigned char track = 0;
static unsigned char seek_track = 0; static unsigned char seek_track = 0;
static unsigned char current_track = 255; static unsigned char current_track = NO_TRACK;
static unsigned char command = 0; static unsigned char command = 0;
unsigned char selected = 0; unsigned char selected = 0;
struct task_struct * wait_on_floppy_select = NULL; struct task_struct * wait_on_floppy_select = NULL;
...@@ -145,20 +149,37 @@ void floppy_deselect(unsigned int nr) ...@@ -145,20 +149,37 @@ void floppy_deselect(unsigned int nr)
* to the desired drive, but it will probably not survive the sleep if * to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop. * several floppies are used at the same time: thus the loop.
*/ */
int floppy_change(unsigned int nr) int floppy_change(struct buffer_head * bh)
{ {
repeat: unsigned int mask = 1 << (bh->b_dev & 0x03);
floppy_on(nr);
while ((current_DOR & 3) != nr && selected) if (MAJOR(bh->b_dev) != 2) {
sleep_on(&wait_on_floppy_select); printk("floppy_changed: not a floppy\n");
if ((current_DOR & 3) != nr) return 0;
goto repeat; }
if (inb(FD_DIR) & 0x80) { if (changed_floppies & mask) {
floppy_off(nr); changed_floppies &= ~mask;
recalibrate = 1;
return 1;
}
if (!bh)
return 0;
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
else {
buffer_track = -1; 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 1;
} }
floppy_off(nr);
return 0; return 0;
} }
...@@ -223,6 +244,7 @@ static void output_byte(char byte) ...@@ -223,6 +244,7 @@ static void output_byte(char byte)
return; return;
} }
} }
current_track = NO_TRACK;
reset = 1; reset = 1;
printk("Unable to send byte to FDC\n\r"); printk("Unable to send byte to FDC\n\r");
} }
...@@ -244,13 +266,14 @@ static int result(void) ...@@ -244,13 +266,14 @@ static int result(void)
} }
} }
reset = 1; reset = 1;
current_track = NO_TRACK;
printk("Getstatus times out\n\r"); printk("Getstatus times out\n\r");
return -1; return -1;
} }
static void bad_flp_intr(void) static void bad_flp_intr(void)
{ {
current_track = -1; current_track = NO_TRACK;
CURRENT->errors++; CURRENT->errors++;
if (CURRENT->errors > MAX_ERRORS) { if (CURRENT->errors > MAX_ERRORS) {
floppy_deselect(current_drive); floppy_deselect(current_drive);
...@@ -258,6 +281,8 @@ static void bad_flp_intr(void) ...@@ -258,6 +281,8 @@ static void bad_flp_intr(void)
} }
if (CURRENT->errors > MAX_ERRORS/2) if (CURRENT->errors > MAX_ERRORS/2)
reset = 1; reset = 1;
else
recalibrate = 1;
} }
/* /*
...@@ -383,15 +408,15 @@ static void transfer(void) ...@@ -383,15 +408,15 @@ static void transfer(void)
static void recal_interrupt(void) static void recal_interrupt(void)
{ {
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
current_track = NO_TRACK;
if (result()!=2 || (ST0 & 0xE0) == 0x60) if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1; reset = 1;
else
recalibrate = 0;
do_fd_request(); do_fd_request();
} }
void unexpected_floppy_interrupt(void) void unexpected_floppy_interrupt(void)
{ {
current_track = NO_TRACK;
output_byte(FD_SENSEI); output_byte(FD_SENSEI);
if (result()!=2 || (ST0 & 0xE0) == 0x60) if (result()!=2 || (ST0 & 0xE0) == 0x60)
reset = 1; reset = 1;
...@@ -427,15 +452,16 @@ static void reset_floppy(void) ...@@ -427,15 +452,16 @@ static void reset_floppy(void)
{ {
int i; int i;
do_floppy = reset_interrupt;
reset = 0; reset = 0;
current_track = NO_TRACK;
cur_spec1 = -1; cur_spec1 = -1;
cur_rate = -1; cur_rate = -1;
recalibrate = 1; recalibrate = 1;
printk("Reset-floppy called\n\r"); printk("Reset-floppy called\n\r");
cli(); cli();
do_floppy = reset_interrupt;
outb_p(current_DOR & ~0x04,FD_DOR); outb_p(current_DOR & ~0x04,FD_DOR);
for (i=0 ; i<100 ; i++) for (i=0 ; i<1000 ; i++)
__asm__("nop"); __asm__("nop");
outb(current_DOR,FD_DOR); outb(current_DOR,FD_DOR);
sti(); sti();
...@@ -443,6 +469,18 @@ static void reset_floppy(void) ...@@ -443,6 +469,18 @@ static void reset_floppy(void)
static void floppy_on_interrupt(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 */ /* We cannot do a floppy-select, as that might sleep. We just force it */
selected = 1; selected = 1;
if (current_drive != (current_DOR & 3)) { if (current_drive != (current_DOR & 3)) {
...@@ -459,19 +497,11 @@ void do_fd_request(void) ...@@ -459,19 +497,11 @@ void do_fd_request(void)
unsigned int block; unsigned int block;
char * buffer_area; char * buffer_area;
seek = 0;
if (reset) {
reset_floppy();
return;
}
if (recalibrate) {
recalibrate_floppy();
return;
}
INIT_REQUEST; INIT_REQUEST;
seek = 0;
floppy = (MINOR(CURRENT->dev)>>2) + floppy_type; floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
if (current_drive != CURRENT_DEV) if (current_drive != CURRENT_DEV)
seek = 1; current_track = NO_TRACK;
current_drive = CURRENT_DEV; current_drive = CURRENT_DEV;
block = CURRENT->sector; block = CURRENT->sector;
if (block+2 > floppy->size) { if (block+2 > floppy->size) {
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
* sleep. Special care is recommended. * sleep. Special care is recommended.
* *
* modified by Drew Eckhardt to check nr of hd's from the CMOS. * modified by Drew Eckhardt to check nr of hd's from the CMOS.
*
* 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> #include <linux/config.h>
...@@ -26,10 +29,11 @@ ...@@ -26,10 +29,11 @@
#define MAJOR_NR 3 #define MAJOR_NR 3
#include "blk.h" #include "blk.h"
#define CMOS_READ(addr) ({ \ static inline unsigned char CMOS_READ(unsigned char addr)
outb_p(0x80|addr,0x70); \ {
inb_p(0x71); \ outb_p(0x80|addr,0x70);
}) return inb_p(0x71);
}
/* Max read/write errors/sector */ /* Max read/write errors/sector */
#define MAX_ERRORS 7 #define MAX_ERRORS 7
...@@ -39,7 +43,7 @@ static void recal_intr(void); ...@@ -39,7 +43,7 @@ static void recal_intr(void);
static void bad_rw_intr(void); static void bad_rw_intr(void);
static int recalibrate = 0; static int recalibrate = 0;
static int reset = 0; static int reset = 1;
/* /*
* This struct defines the HD's and their types. * This struct defines the HD's and their types.
...@@ -87,12 +91,30 @@ static void check_partition(unsigned int dev) ...@@ -87,12 +91,30 @@ static void check_partition(unsigned int dev)
if (*(unsigned short *) (bh->b_data+510) == 0xAA55) { if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
p = 0x1BE + (void *)bh->b_data; p = 0x1BE + (void *)bh->b_data;
for (i=0 ; i<4 ; i++,p++) { 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].start_sect = p->start_sect;
hd[i+minor].nr_sects = p->nr_sects; if ((current_minor & 0x3f) >= 60)
} continue;
if (p->nr_sects && p->sys_ind == EXTENDED_PARTITION) { if (p->sys_ind == EXTENDED_PARTITION) {
current_minor += 4; current_minor += 4;
check_partition(i+minor); check_partition(0x0300 | (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 } else
printk("Bad partition table on dev %04x\n",dev); printk("Bad partition table on dev %04x\n",dev);
...@@ -196,7 +218,8 @@ static int win_result(void) ...@@ -196,7 +218,8 @@ static int win_result(void)
if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)) if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
== (READY_STAT | SEEK_STAT)) == (READY_STAT | SEEK_STAT))
return(0); /* ok */ return(0); /* ok */
if (i&1) i=inb(HD_ERROR); if (i&1)
i=inb(HD_ERROR);
return (1); return (1);
} }
...@@ -289,11 +312,15 @@ static void bad_rw_intr(void) ...@@ -289,11 +312,15 @@ static void bad_rw_intr(void)
end_request(0); end_request(0);
if (CURRENT->errors > MAX_ERRORS/2) if (CURRENT->errors > MAX_ERRORS/2)
reset = 1; reset = 1;
else
recalibrate = 1;
} }
static void read_intr(void) static void read_intr(void)
{ {
SET_INTR(&read_intr);
if (win_result()) { if (win_result()) {
SET_INTR(NULL);
bad_rw_intr(); bad_rw_intr();
do_hd_request(); do_hd_request();
return; return;
...@@ -302,10 +329,9 @@ static void read_intr(void) ...@@ -302,10 +329,9 @@ static void read_intr(void)
CURRENT->errors = 0; CURRENT->errors = 0;
CURRENT->buffer += 512; CURRENT->buffer += 512;
CURRENT->sector++; CURRENT->sector++;
if (--CURRENT->nr_sectors) { if (--CURRENT->nr_sectors)
SET_INTR(&read_intr);
return; return;
} SET_INTR(NULL);
end_request(1); end_request(1);
do_hd_request(); do_hd_request();
} }
...@@ -337,13 +363,13 @@ static void recal_intr(void) ...@@ -337,13 +363,13 @@ static void recal_intr(void)
static void hd_times_out(void) static void hd_times_out(void)
{ {
do_hd = NULL;
reset = 1;
if (!CURRENT) if (!CURRENT)
return; return;
printk("HD timeout"); printk("HD timeout");
if (++CURRENT->errors >= MAX_ERRORS) if (++CURRENT->errors >= MAX_ERRORS)
end_request(0); end_request(0);
SET_INTR(NULL);
reset = 1;
do_hd_request(); do_hd_request();
} }
...@@ -357,7 +383,8 @@ void do_hd_request(void) ...@@ -357,7 +383,8 @@ void do_hd_request(void)
INIT_REQUEST; INIT_REQUEST;
dev = MINOR(CURRENT->dev); dev = MINOR(CURRENT->dev);
block = CURRENT->sector; 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); end_request(0);
goto repeat; goto repeat;
} }
...@@ -368,7 +395,6 @@ void do_hd_request(void) ...@@ -368,7 +395,6 @@ void do_hd_request(void)
head = block % hd_info[dev].head; head = block % hd_info[dev].head;
cyl = block / hd_info[dev].head; cyl = block / hd_info[dev].head;
sec++; sec++;
nsect = CURRENT->nr_sectors;
if (reset) { if (reset) {
recalibrate = 1; recalibrate = 1;
reset_hd(); reset_hd();
...@@ -376,7 +402,7 @@ void do_hd_request(void) ...@@ -376,7 +402,7 @@ void do_hd_request(void)
} }
if (recalibrate) { if (recalibrate) {
recalibrate = 0; 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); WIN_RESTORE,&recal_intr);
if (reset) if (reset)
goto repeat; goto repeat;
...@@ -404,7 +430,7 @@ void do_hd_request(void) ...@@ -404,7 +430,7 @@ void do_hd_request(void)
void hd_init(void) void hd_init(void)
{ {
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
set_trap_gate(0x2E,&hd_interrupt); set_intr_gate(0x2E,&hd_interrupt);
outb_p(inb_p(0x21)&0xfb,0x21); outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1); outb(inb_p(0xA1)&0xbf,0xA1);
timer_table[HD_TIMER].fn = hd_times_out; timer_table[HD_TIMER].fn = hd_times_out;
......
This diff is collapsed.
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
/* /*
* these are for the keyboard read functions * 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 !!!! */ as in tty_io.c !!!! */
head = 4 head = 4
tail = 8 tail = 8
...@@ -434,7 +434,7 @@ key_map: ...@@ -434,7 +434,7 @@ key_map:
shift_map: shift_map:
.byte 0,27 .byte 0,27
.ascii "!\"#$%%&*()_+" .ascii "!\"#$%^&*()_+"
.byte 127,9 .byte 127,9
.ascii "QWERTYUIOP{}" .ascii "QWERTYUIOP{}"
.byte 13,0 .byte 13,0
...@@ -626,7 +626,7 @@ do_self: ...@@ -626,7 +626,7 @@ do_self:
testb $0x20,_kmode /* alt-gr */ testb $0x20,_kmode /* alt-gr */
jne 1f jne 1f
lea shift_map,%ebx lea shift_map,%ebx
testb $0x03,_kmode testb $0x0f,_kmode
jne 1f jne 1f
lea key_map,%ebx lea key_map,%ebx
1: movb (%ebx,%eax),%al 1: movb (%ebx,%eax),%al
...@@ -641,11 +641,7 @@ do_self: ...@@ -641,11 +641,7 @@ do_self:
subb $32,%al subb $32,%al
2: testb $0x0c,_kmode /* ctrl */ 2: testb $0x0c,_kmode /* ctrl */
je 3f je 3f
cmpb $64,%al andb $0x1f,%al
jb 3f
cmpb $64+32,%al
jae 3f
subb $64,%al
3: testb $0x10,_kmode /* left alt */ 3: testb $0x10,_kmode /* left alt */
je 4f je 4f
orb $0x80,%al orb $0x80,%al
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
.text .text
.globl _rs1_interrupt,_rs2_interrupt .globl _rs1_interrupt,_rs2_interrupt
size = 1024 /* must be power of two ! size = 2048 /* must be power of two !
and must match the value and must match the value
in tty_io.c!!! */ in tty_io.c!!! */
...@@ -29,16 +29,21 @@ startup = 256 /* chars left in write queue when we restart it */ ...@@ -29,16 +29,21 @@ startup = 256 /* chars left in write queue when we restart it */
/* /*
* These are the actual interrupt routines. They look where * These are the actual interrupt routines. They look where
* the interrupt is coming from, and take appropriate action. * the interrupt is coming from, and take appropriate action.
*
* rs1_interrupt (IRQ 4) takes care of com1 and com3
* rs2_interrupt (IRQ 3) takes care of com2 and com4
*/ */
.align 2 .align 2
_rs1_interrupt: _rs1_interrupt:
pushl $_table_list+8 pushl $_table_list+8
pushl $_table_list+24
jmp rs_int jmp rs_int
.align 2 .align 2
_rs2_interrupt: _rs2_interrupt:
pushl $_table_list+16 pushl $_table_list+16
rs_int: pushl $_table_list+32
cld rs_int: cld
pushl %edx pushl %edx
pushl %ecx pushl %ecx
pushl %ebx pushl %ebx
...@@ -50,32 +55,39 @@ rs_int: ...@@ -50,32 +55,39 @@ rs_int:
pushl $0x10 pushl $0x10
pop %es pop %es
movl 24(%esp),%edx 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 (%edx),%edx
movl rs_addr(%edx),%edx movl rs_addr(%edx),%edx
addl $2,%edx /* interrupt ident. reg */ addl $2,%edx /* interrupt ident. reg */
rep_int: 1: xorl %eax,%eax
xorl %eax,%eax
inb %dx,%al inb %dx,%al
testb $1,%al testb $1,%al
jne end jne 2f
cmpb $6,%al /* this shouldn't happen, but ... */ cmpb $6,%al /* this shouldn't happen, but ... */
ja end ja 2f
movl 24(%esp),%ecx movl (%esp),%ecx
pushl %edx pushl %edx
subl $2,%edx subl $2,%edx
call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */ call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
popl %edx popl %edx
jmp rep_int jmp 1b
end: movb $0x20,%al 2: popl %edx
outb %al,$0x20 /* EOI */ ret
pop %ds
pop %es
popl %eax
popl %ebx
popl %ecx
popl %edx
addl $4,%esp # jump over _table_list entry
iret
jmp_table: jmp_table:
.long modem_status,write_char,read_char,line_status .long modem_status,write_char,read_char,line_status
...@@ -112,7 +124,7 @@ read_char: ...@@ -112,7 +124,7 @@ read_char:
.align 2 .align 2
mask_table: mask_table:
.long 0,4,8 .long 0,4,8,16,32
.align 2 .align 2
write_char: write_char:
...@@ -136,6 +148,7 @@ write_char: ...@@ -136,6 +148,7 @@ write_char:
cmpl head(%ecx),%ebx cmpl head(%ecx),%ebx
je write_buffer_empty je write_buffer_empty
ret ret
.align 2 .align 2
write_buffer_empty: write_buffer_empty:
movl proc_list(%ecx),%ebx # wake up sleeping process movl proc_list(%ecx),%ebx # wake up sleeping process
...@@ -146,6 +159,6 @@ write_buffer_empty: ...@@ -146,6 +159,6 @@ write_buffer_empty:
inb %dx,%al inb %dx,%al
jmp 1f jmp 1f
1: jmp 1f 1: jmp 1f
1: andb $0xd,%al /* disable transmit interrupt */ 1: andb $0xd,%al # disable transmit interrupt
outb %al,%dx outb %al,%dx
ret ret
...@@ -34,6 +34,16 @@ static void com2_timer(void) ...@@ -34,6 +34,16 @@ static void com2_timer(void)
copy_to_cooked(tty_table+65); 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) static inline void do_rs_write(unsigned int port)
{ {
char c; char c;
...@@ -66,17 +76,55 @@ static void com2_timeout(void) ...@@ -66,17 +76,55 @@ static void com2_timeout(void)
do_rs_write(1); 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) static void init(int port)
{ {
outb_p(0x80,port+3); /* set DLAB of line control reg */ outb_p(0x80,port+3); /* set DLAB of line control reg */
outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */ outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */
outb_p(0x00,port+1); /* MS of divisor */ outb_p(0x00,port+1); /* MS of divisor */
outb_p(0x03,port+3); /* reset DLAB */ outb_p(0x03,port+3); /* reset DLAB */
outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */ outb_p(0x00,port+4); /* reset DTR,RTS, OUT_2 */
outb_p(0x0d,port+1); /* enable all intrs but writes */ outb_p(0x0d,port+1); /* enable all intrs but writes */
(void)inb(port); /* read data port to reset things (?) */ (void)inb(port); /* read data port to reset things (?) */
} }
/*
* 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) void rs_init(void)
{ {
/* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */ /* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
...@@ -84,15 +132,25 @@ void rs_init(void) ...@@ -84,15 +132,25 @@ void rs_init(void)
timer_table[SER1_TIMER].expires = 0; timer_table[SER1_TIMER].expires = 0;
timer_table[SER2_TIMER].fn = com2_timer; timer_table[SER2_TIMER].fn = com2_timer;
timer_table[SER2_TIMER].expires = 0; 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 */ /* SERx_TIMEOUT timers are used for writing: prevent serial lockups */
timer_table[SER1_TIMEOUT].fn = com1_timeout; timer_table[SER1_TIMEOUT].fn = com1_timeout;
timer_table[SER1_TIMEOUT].expires = 0; timer_table[SER1_TIMEOUT].expires = 0;
timer_table[SER2_TIMEOUT].fn = com2_timeout; timer_table[SER2_TIMEOUT].fn = com2_timeout;
timer_table[SER2_TIMEOUT].expires = 0; 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(0x24,rs1_interrupt);
set_intr_gate(0x23,rs2_interrupt); set_intr_gate(0x23,rs2_interrupt);
init(tty_table[64].read_q->data); init(tty_table[64].read_q->data);
init(tty_table[65].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); outb(inb_p(0x21)&0xE7,0x21);
} }
...@@ -108,6 +166,6 @@ void rs_write(struct tty_struct * tty) ...@@ -108,6 +166,6 @@ void rs_write(struct tty_struct * tty)
cli(); cli();
if (!EMPTY(tty->write_q)) if (!EMPTY(tty->write_q))
outb_p(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1); 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(); sti();
} }
...@@ -83,7 +83,9 @@ int fg_console = 0; ...@@ -83,7 +83,9 @@ int fg_console = 0;
struct tty_queue * table_list[]={ struct tty_queue * table_list[]={
con_queues + 0, con_queues + 1, con_queues + 0, con_queues + 1,
rs_queues + 0, rs_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) void change_console(unsigned int new_console)
...@@ -122,15 +124,27 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -122,15 +124,27 @@ void copy_to_cooked(struct tty_struct * tty)
{ {
unsigned char c; 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"); printk("copy_to_cooked: missing queues\n\r");
return; return;
} }
cli();
if (tty->busy) {
sti();
return;
}
tty->busy = 1;
sti();
while (1) { while (1) {
if (EMPTY(tty->read_q)) if (EMPTY(tty->read_q))
break; break;
if (FULL(tty->secondary)) if (FULL(tty->secondary)) {
if (tty->secondary->proc_list)
if (tty->secondary->proc_list != current)
current->counter = 0;
break; break;
}
GETCH(tty->read_q,c); GETCH(tty->read_q,c);
if (c==13) { if (c==13) {
if (I_CRNL(tty)) if (I_CRNL(tty))
...@@ -153,7 +167,6 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -153,7 +167,6 @@ void copy_to_cooked(struct tty_struct * tty)
if (c<32) if (c<32)
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
tty->write(tty);
} }
DEC(tty->secondary->head); DEC(tty->secondary->head);
} }
...@@ -170,7 +183,6 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -170,7 +183,6 @@ void copy_to_cooked(struct tty_struct * tty)
if (c<32) if (c<32)
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(127,tty->write_q);
tty->write(tty);
} }
DEC(tty->secondary->head); DEC(tty->secondary->head);
continue; continue;
...@@ -180,13 +192,11 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -180,13 +192,11 @@ void copy_to_cooked(struct tty_struct * tty)
if ((STOP_CHAR(tty) != _POSIX_VDISABLE) && if ((STOP_CHAR(tty) != _POSIX_VDISABLE) &&
(c==STOP_CHAR(tty))) { (c==STOP_CHAR(tty))) {
tty->stopped=1; tty->stopped=1;
tty->write(tty);
continue; continue;
} }
if ((START_CHAR(tty) != _POSIX_VDISABLE) && if ((START_CHAR(tty) != _POSIX_VDISABLE) &&
(c==START_CHAR(tty))) { (c==START_CHAR(tty))) {
tty->stopped=0; tty->stopped=0;
tty->write(tty);
continue; continue;
} }
} }
...@@ -221,9 +231,11 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -221,9 +231,11 @@ void copy_to_cooked(struct tty_struct * tty)
} else } else
PUTCH(c,tty->write_q); PUTCH(c,tty->write_q);
} }
tty->write(tty);
PUTCH(c,tty->secondary); PUTCH(c,tty->secondary);
} }
tty->write(tty);
tty->busy = 0;
if (!EMPTY(tty->secondary))
wake_up(&tty->secondary->proc_list); wake_up(&tty->secondary->proc_list);
} }
...@@ -270,7 +282,8 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags) ...@@ -270,7 +282,8 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
tty = TTY_TABLE(channel); tty = TTY_TABLE(channel);
if (!(tty->read_q && tty->secondary)) if (!(tty->read_q && tty->secondary))
return -EIO; 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)); return(tty_signal(SIGTTIN, tty));
if (channel & 0x80) if (channel & 0x80)
other_tty = tty_table + (channel ^ 0x40); other_tty = tty_table + (channel ^ 0x40);
...@@ -295,15 +308,14 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags) ...@@ -295,15 +308,14 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
copy_to_cooked(tty); copy_to_cooked(tty);
while (nr>0) { while (nr>0) {
if (other_tty && other_tty->write) if (other_tty && other_tty->write)
other_tty->write(other_tty); TTY_WRITE(other_tty);
cli(); cli();
if (EMPTY(tty->secondary) || (L_CANON(tty) && if (EMPTY(tty->secondary) || (L_CANON(tty) &&
!FULL(tty->read_q) && !tty->secondary->data)) { !FULL(tty->read_q) && !tty->secondary->data)) {
if (!current->timeout || if (!current->timeout)
(current->signal & ~current->blocked)) { break;
sti(); if (current->signal & ~current->blocked)
break; break;
}
if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty)) if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
break; break;
interruptible_sleep_on(&tty->secondary->proc_list); interruptible_sleep_on(&tty->secondary->proc_list);
...@@ -329,11 +341,12 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags) ...@@ -329,11 +341,12 @@ int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
break; break;
} while (nr>0 && !EMPTY(tty->secondary)); } while (nr>0 && !EMPTY(tty->secondary));
wake_up(&tty->read_q->proc_list); wake_up(&tty->read_q->proc_list);
if (time)
current->timeout = time+jiffies;
if (L_CANON(tty) || b-buf >= minimum) if (L_CANON(tty) || b-buf >= minimum)
break; break;
if (time)
current->timeout = time+jiffies;
} }
sti();
current->timeout = 0; current->timeout = 0;
if (b-buf) if (b-buf)
return b-buf; return b-buf;
...@@ -355,9 +368,13 @@ int tty_write(unsigned channel, char * buf, int nr) ...@@ -355,9 +368,13 @@ int tty_write(unsigned channel, char * buf, int nr)
tty = TTY_TABLE(channel); tty = TTY_TABLE(channel);
if (!(tty->write_q && tty->write)) if (!(tty->write_q && tty->write))
return -EIO; return -EIO;
if (L_TOSTOP(tty) && if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
(current->tty == channel) && (tty->pgrp != current->pgrp)) (current->tty == channel) && (tty->pgrp != current->pgrp))
return(tty_signal(SIGTTOU, tty)); return(tty_signal(SIGTTOU, tty));
if (nr < 0)
return -EINVAL;
if (!nr)
return 0;
while (nr>0) { while (nr>0) {
sleep_if_full(tty->write_q); sleep_if_full(tty->write_q);
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
...@@ -381,11 +398,15 @@ int tty_write(unsigned channel, char * buf, int nr) ...@@ -381,11 +398,15 @@ int tty_write(unsigned channel, char * buf, int nr)
cr_flag = 0; cr_flag = 0;
PUTCH(c,tty->write_q); PUTCH(c,tty->write_q);
} }
tty->write(tty); TTY_WRITE(tty);
if (nr>0) if (nr>0)
schedule(); schedule();
} }
return (b-buf); if (b-buf)
return b-buf;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
return 0;
} }
void chr_dev_init(void) void chr_dev_init(void)
...@@ -402,10 +423,14 @@ void tty_init(void) ...@@ -402,10 +423,14 @@ void tty_init(void)
rs_queues[1] = (struct tty_queue) {0x3f8,0,0,0,""}; rs_queues[1] = (struct tty_queue) {0x3f8,0,0,0,""};
rs_queues[3] = (struct tty_queue) {0x2f8,0,0,0,""}; rs_queues[3] = (struct tty_queue) {0x2f8,0,0,0,""};
rs_queues[4] = (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++) { for (i=0 ; i<256 ; i++) {
tty_table[i] = (struct tty_struct) { tty_table[i] = (struct tty_struct) {
{0, 0, 0, 0, 0, INIT_C_CC}, {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 NULL, NULL, NULL, NULL
}; };
} }
...@@ -418,9 +443,10 @@ void tty_init(void) ...@@ -418,9 +443,10 @@ void tty_init(void)
IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
0, /* console termio */ 0, /* console termio */
INIT_C_CC}, INIT_C_CC},
0, /* initial pgrp */ -1, /* initial pgrp */
0, /* initial session */ 0, /* initial session */
0, /* initial stopped */ 0, /* initial stopped */
0, /* initial busy */
{video_num_lines,video_num_columns,0,0}, {video_num_lines,video_num_columns,0,0},
con_write, con_write,
con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3 con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
...@@ -434,6 +460,7 @@ void tty_init(void) ...@@ -434,6 +460,7 @@ void tty_init(void)
0, 0,
0, 0,
INIT_C_CC}, INIT_C_CC},
-1,
0, 0,
0, 0,
0, 0,
...@@ -450,6 +477,7 @@ void tty_init(void) ...@@ -450,6 +477,7 @@ void tty_init(void)
0, 0,
0, 0,
INIT_C_CC}, INIT_C_CC},
-1,
0, 0,
0, 0,
0, 0,
...@@ -464,6 +492,7 @@ void tty_init(void) ...@@ -464,6 +492,7 @@ void tty_init(void)
IXON | ISIG | ICANON, IXON | ISIG | ICANON,
0, 0,
INIT_C_CC}, INIT_C_CC},
-1,
0, 0,
0, 0,
0, 0,
......
...@@ -53,7 +53,12 @@ static void flush(struct tty_queue * queue) ...@@ -53,7 +53,12 @@ static void flush(struct tty_queue * queue)
static void wait_until_sent(struct tty_struct * tty) 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) static void send_break(struct tty_struct * tty)
...@@ -137,7 +142,7 @@ static int get_termio(struct tty_struct * tty, struct termio * termio) ...@@ -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, static int set_termio(struct tty_struct * tty, struct termio * termio,
int channel) int channel)
...@@ -255,11 +260,11 @@ int tty_ioctl(int dev, int cmd, int arg) ...@@ -255,11 +260,11 @@ int tty_ioctl(int dev, int cmd, int arg)
switch (arg) { switch (arg) {
case TCOOFF: case TCOOFF:
tty->stopped = 1; tty->stopped = 1;
tty->write(tty); TTY_WRITE(tty);
return 0; return 0;
case TCOON: case TCOON:
tty->stopped = 0; tty->stopped = 0;
tty->write(tty); TTY_WRITE(tty);
return 0; return 0;
case TCIOFF: case TCIOFF:
if (STOP_CHAR(tty)) if (STOP_CHAR(tty))
......
...@@ -359,9 +359,9 @@ volatile void do_exit(long code) ...@@ -359,9 +359,9 @@ volatile void do_exit(long code)
if (current->tty >= 0) { if (current->tty >= 0) {
tty = TTY_TABLE(current->tty); tty = TTY_TABLE(current->tty);
if (tty->pgrp>0) if (tty->pgrp > 0)
kill_pg(tty->pgrp, SIGHUP, 1); kill_pg(tty->pgrp, SIGHUP, 1);
tty->pgrp = 0; tty->pgrp = -1;
tty->session = 0; tty->session = 0;
} }
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
......
This diff is collapsed.
...@@ -126,9 +126,9 @@ void schedule(void) ...@@ -126,9 +126,9 @@ void schedule(void)
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) { if (*p) {
if ((*p)->timeout && (*p)->timeout < jiffies) { if ((*p)->timeout && (*p)->timeout < jiffies)
if ((*p)->state == TASK_INTERRUPTIBLE) {
(*p)->timeout = 0; (*p)->timeout = 0;
if ((*p)->state == TASK_INTERRUPTIBLE)
(*p)->state = TASK_RUNNING; (*p)->state = TASK_RUNNING;
} }
if ((*p)->alarm && (*p)->alarm < jiffies) { if ((*p)->alarm && (*p)->alarm < jiffies) {
...@@ -178,29 +178,45 @@ int sys_pause(void) ...@@ -178,29 +178,45 @@ int sys_pause(void)
return -EINTR; 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) static inline void __sleep_on(struct task_struct **p, int state)
{ {
struct task_struct *tmp;
unsigned int flags; unsigned int flags;
if (!p) if (!p)
return; return;
if (current == &(init_task.task)) if (current == task[0])
panic("task[0] trying to sleep"); panic("task[0] trying to sleep");
__asm__("pushfl ; popl %0":"=r" (flags)); __asm__("pushfl ; popl %0":"=r" (flags));
tmp = *p; current->next_wait = *p;
task[0]->next_wait = NULL;
*p = current; *p = current;
current->state = state; current->state = state;
/* make sure interrupts are enabled: there should be no more races here */
sti(); sti();
repeat: schedule(); schedule();
if (*p && *p != current) { if (current->next_wait != task[0])
current->state = TASK_UNINTERRUPTIBLE; wake_up(p);
(**p).state = 0; current->next_wait = NULL;
goto repeat;
}
if (*p = tmp)
tmp->state=0;
__asm__("pushl %0 ; popfl"::"r" (flags)); __asm__("pushl %0 ; popfl"::"r" (flags));
} }
...@@ -214,17 +230,6 @@ void sleep_on(struct task_struct **p) ...@@ -214,17 +230,6 @@ void sleep_on(struct task_struct **p)
__sleep_on(p,TASK_UNINTERRUPTIBLE); __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 * OK, here are some floppy things that shouldn't be in the kernel
* proper. They are here because the floppy needs a timer, and this * proper. They are here because the floppy needs a timer, and this
...@@ -261,14 +266,6 @@ int ticks_to_floppy_on(unsigned int nr) ...@@ -261,14 +266,6 @@ int ticks_to_floppy_on(unsigned int nr)
return mon_timer[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) void floppy_off(unsigned int nr)
{ {
moff_timer[nr]=3*HZ; moff_timer[nr]=3*HZ;
......
...@@ -17,8 +17,6 @@ CPP =gcc -E -nostdinc -I../include ...@@ -17,8 +17,6 @@ CPP =gcc -E -nostdinc -I../include
OBJS = memory.o swap.o OBJS = memory.o swap.o
all: mm.o
mm.o: $(OBJS) mm.o: $(OBJS)
$(LD) -r -o mm.o $(OBJS) $(LD) -r -o mm.o $(OBJS)
......
...@@ -213,7 +213,13 @@ static unsigned long put_page(unsigned long page,unsigned long address) ...@@ -213,7 +213,13 @@ static unsigned long put_page(unsigned long page,unsigned long address)
*page_table = tmp | 7; *page_table = tmp | 7;
page_table = (unsigned long *) tmp; 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 */ /* no need for invalidate */
return page; return page;
} }
...@@ -243,7 +249,13 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address) ...@@ -243,7 +249,13 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address)
*page_table = tmp|7; *page_table = tmp|7;
page_table = (unsigned long *) tmp; 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 */ /* no need for invalidate */
return page; return page;
} }
...@@ -296,8 +308,10 @@ void un_wp_page(unsigned long * table_entry) ...@@ -296,8 +308,10 @@ void un_wp_page(unsigned long * table_entry)
*/ */
void do_wp_page(unsigned long error_code,unsigned long address) 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"); printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
do_exit(SIGSEGV);
}
if (address - current->start_code >= TASK_SIZE) { if (address - current->start_code >= TASK_SIZE) {
printk("Bad things happen: page error in do_wp_page\n\r"); printk("Bad things happen: page error in do_wp_page\n\r");
do_exit(SIGSEGV); do_exit(SIGSEGV);
...@@ -305,7 +319,6 @@ void do_wp_page(unsigned long error_code,unsigned long address) ...@@ -305,7 +319,6 @@ void do_wp_page(unsigned long error_code,unsigned long address)
un_wp_page((unsigned long *) un_wp_page((unsigned long *)
(((address>>10) & 0xffc) + (0xfffff000 & (((address>>10) & 0xffc) + (0xfffff000 &
*((unsigned long *) ((address>>20) &0xffc))))); *((unsigned long *) ((address>>20) &0xffc)))));
} }
void write_verify(unsigned long address) void write_verify(unsigned long address)
...@@ -436,8 +449,10 @@ void do_no_page(unsigned long error_code, ...@@ -436,8 +449,10 @@ void do_no_page(unsigned long error_code,
if (last_checked >= CHECK_LAST_NR) if (last_checked >= CHECK_LAST_NR)
last_checked = 0; last_checked = 0;
last_pages[last_checked] = address & 0xfffff000; last_pages[last_checked] = address & 0xfffff000;
if (address < TASK_SIZE) if (address < TASK_SIZE) {
printk("\n\rBAD!! KERNEL PAGE MISSING\n\r"); printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
do_exit(SIGSEGV);
}
if (address - tsk->start_code >= TASK_SIZE) { if (address - tsk->start_code >= TASK_SIZE) {
printk("Bad things happen: nonexistent page error in do_no_page\n\r"); printk("Bad things happen: nonexistent page error in do_no_page\n\r");
do_exit(SIGSEGV); do_exit(SIGSEGV);
...@@ -567,12 +582,12 @@ void show_mem(void) ...@@ -567,12 +582,12 @@ void show_mem(void)
/* This routine handles page faults. It determines the address, /* This routine handles page faults. It determines the address,
and the problem then passes it off to one of the appropriate and the problem then passes it off to one of the appropriate
routines. */ 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; unsigned long address;
/* get the address */ /* get the address */
__asm__ ("movl %%cr2,%0":"=r" (address)); __asm__("movl %%cr2,%0":"=r" (address));
if (!(error_code & 1)) { if (!(error_code & 1)) {
do_no_page(error_code, address, current); do_no_page(error_code, address, current);
return; return;
......
...@@ -155,37 +155,38 @@ int swap_out(void) ...@@ -155,37 +155,38 @@ int swap_out(void)
static int dir_entry = 1024; static int dir_entry = 1024;
static int page_entry = -1; static int page_entry = -1;
int counter = VM_PAGES; int counter = VM_PAGES;
int pg_table = 0; int pg_table;
repeat: check_dir:
while (counter > 0) { if (counter < 0)
counter -= 1024; goto no_swap;
dir_entry++;
if (dir_entry >= 1024) if (dir_entry >= 1024)
dir_entry = FIRST_VM_PAGE>>10; dir_entry = FIRST_VM_PAGE>>10;
if (pg_table = pg_dir[dir_entry]) if (!(1 & (pg_table = pg_dir[dir_entry]))) {
break; if (pg_table) {
printk("bad page-table at pg_dir[%d]: %08x\n\r",
dir_entry,pg_table);
pg_dir[dir_entry] = 0;
} }
if (counter <= 0) { counter -= 1024;
printk("Out of swap-memory\n"); dir_entry++;
return 0; goto check_dir;
}
if (!(pg_table & 1)) {
printk("bad page-table at pg_dir[%d]: %08x\n\r",dir_entry,
pg_table);
return 0;
} }
pg_table &= 0xfffff000; pg_table &= 0xfffff000;
while (counter > 0) { check_table:
if (counter < 0)
goto no_swap;
counter--; counter--;
page_entry++; page_entry++;
if (page_entry >= 1024) { if (page_entry >= 1024) {
page_entry = -1; page_entry = -1;
goto repeat; dir_entry++;
goto check_dir;
} }
if (try_to_swap_out(page_entry + (unsigned long *) pg_table)) if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
return 1; return 1;
} goto check_table;
no_swap:
printk("Out of swap-memory\n\r"); printk("Out of swap-memory\n\r");
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment