Commit 06d9f6ff authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.97.5 (September 12, 1992)

SCSI CD-ROM support by David Giller (based on sd.c by Drew)

Microsoft Busmouse support by Teemu Rantanen

Do the same buffer cleanups to extfs that we just did to Minixfs.

Efficient VGA emulation in dosemu wanted to know when we write
to the pseudo-VGA memory area. Add vm86 mode hooks for that.

[Original announcement below]

Patch 5 fixes the extended filesystem problems (thanks to Remy Card), as
well as including many smaller fixes (some more fs cleanups, the CDROM
patches and several other minor changes).  Pl5 finally removes even the
last few header-files that were incompatible with the normal headers, so
the "-nostdinc -I$(KERNELHDRS)" stuff is gone.

Patch 5 should also fix the problems with iopl() that resulted in the
X8514-server having problems with 0.97.pl2 and above.

In case people are wondering, my schedule for 1.0 looks something like
this:

 - 0.98 out in about a week: this is essentially 0.97.5 + the tcp/ip
   directory, as well as any fixes that may come up.  I'll try to get
   the loadable driver interface into it too.

 - 0.99 out after 0.98 has been shaken down: a month or so.

 - 1.0 will be the same as 0.99: the only changes will be eventual
   trivial bug-fixes in case 0.99 has some problems.  This is just to
   try to get over the "X.0" bug syndrome.

There are a few on-going projects: depending on circumstances these will
be implemented sooner or later, so I won't give any promises.  These
include: loadable drivers/fs's (alpha-patches already availabla), full
support for different block-sizes (some work still required), and a
extensive rewrite of the mm routines (I'll want to make a vmm interface
similar to the vfs interface for the filesystem routines).

                Linus
parent 80b335c6
......@@ -45,6 +45,12 @@ KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKDB_NO
#
# comment this line to turn off keyboard NUM LOCK
#
NUM_LOCK = -DKBD_NUMERIC_LOCK
#
# comment this line if you don't want the emulation-code
#
......@@ -78,7 +84,7 @@ LD86 =ld86 -0
AS =as
LD =ld
HOSTCC =gcc -static
CC =gcc -nostdinc -I$(KERNELHDRS) $(PROFILING)
CC =gcc -DKERNEL
MAKE =make
CPP =$(CC) -E
AR =ar
......@@ -112,7 +118,7 @@ linuxsubdirs: dummy
Version:
@./makever.sh
@echo \#define UTS_RELEASE \"0.97.pl4-`cat .version`\" > tools/version.h
@echo \#define UTS_RELEASE \"0.97.pl5-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
......
[ NOTE! As of linux-0.97.pl5, the linux kernel include-files have
finally been totally integrated with the normal headers. That means
no more "-nostdinc -I$(KERNELHDRS)" in the Makefiles etc, but it
also means that you /have/ to have the correct /usr/include/linux
and ../asm symlinks. See "Basic configuration 2" ]
VERY QUICK AND DIRTY README
by Lars Wirzenius
......@@ -30,22 +36,18 @@ the FPU if it finds one, even with MATH_EMULATION defined. The kernel
will be slightly bigger. It is probably not worth it to recompile the
kernel just to get rid of the emulation.
[ Linus' note1: if you have a correctly installed gcc-2.2.2d, you can
also remove the "-nostdinc -I$(KERNELHDRS)" thing from the main
Makefile CC definition. But it doesn't hurt to have it, as long as
KERNELHDRS is correctly defined ]
2. Create a symlink:
2. Create the symlinks:
ln -s /usr/src/linux/include/linux /usr/include/linux
ln -fs /usr/src/linux/include/linux /usr/include/linux
ln -fs /usr/src/linux/include/asm /usr/include/asm
This is required so that tools/build.c will compile and link (it
requires the standard versions of headers instead of the kernel specific
headers, as it is a normal application, not kernel code).
This is required so that the linux sources will correctly find their
header files - it is also used by the normal user-level header files to
get some system-specific information.
[ Linus' note2: This is automatically done by the gcc-2.2.2d
[ Linus' note2: This is automatically done by the gcc-2.2.2d and newer
installation script, so if you have the new compiler, you should
already have this link ]
already have these links ]
* Things you may want to get rid of
......
......@@ -280,8 +280,8 @@ chsvga: cld
mov ax,#0xc000
mov es,ax
lea si,msg1
call prtstr
#ifndef SVGA_MODE
call prtstr
flush: in al,#0x60 ! Flush the keyboard buffer
cmp al,#0x82
jb nokey
......@@ -425,6 +425,17 @@ l1: inc si
lea cx,selmod
jmp cx
nogen: cld
lea si,idoakvga
mov di,#0x08
mov cx,#0x08
repe
cmpsb
jne nooak
lea si,dscoakvga
lea di,mooakvga
lea cx,selmod
jmp cx
nooak: cld
lea si,idparadise ! Check Paradise 'clues'
mov di,#0x7d
mov cx,#0x04
......@@ -688,6 +699,7 @@ idati: .ascii "761295520"
idcandt: .byte 0xa5
idgenoa: .byte 0x77, 0x00, 0x66, 0x99
idparadise: .ascii "VGA="
idoakvga: .ascii "OAK VGA "
! Manufacturer: Numofmodes: Mode:
......@@ -701,6 +713,7 @@ moparadise: .byte 0x02, 0x55, 0x54
motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
mooakvga: .byte 0x05, 0x00, 0x07, 0x4f, 0x50, 0x51
! msb = Cols lsb = Rows:
......@@ -714,6 +727,7 @@ dscparadise: .word 0x8419, 0x842b
dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
dscoakvga: .word 0x2819, 0x5019, 0x843c, 0x8419, 0x842C
.text
endtext:
......
......@@ -35,7 +35,7 @@ clean:
depend dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
$(CPP) -M *.c >> tmp_make
cp tmp_make Makefile
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
......
......@@ -28,6 +28,10 @@
#include <asm/system.h>
#include <asm/io.h>
#ifdef CONFIG_BLK_DEV_SR
extern int check_cdrom_media_change(int, int);
#endif
static struct buffer_head * hash_table[NR_HASH];
static struct buffer_head * free_list = NULL;
static struct buffer_head * unused_list = NULL;
......@@ -121,14 +125,27 @@ void check_disk_change(int dev)
int i;
struct buffer_head * bh;
if (MAJOR(dev) != 2)
return;
if (!(bh = getblk(dev,0,1024)))
return;
i = floppy_change(bh);
brelse(bh);
if (!i)
switch(MAJOR(dev)){
case 2: /* floppy disc */
if (!(bh = getblk(dev,0,1024)))
return;
i = floppy_change(bh);
brelse(bh);
break;
#ifdef CONFIG_BLK_DEV_SR
case 11: /* CDROM */
i = check_cdrom_media_change(dev, 0);
if (i) printk("Flushing buffers and inodes for CDROM\n");
break;
#endif
default:
return;
};
if (!i) return;
for (i=0 ; i<NR_SUPER ; i++)
if (super_block[i].s_dev == dev)
put_super(super_block[i].s_dev);
......
......@@ -62,6 +62,6 @@ struct inode_operations ext_blkdev_inode_operations = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
ext_bmap, /* bmap */
ext_truncate /* truncate */
NULL, /* bmap */
NULL /* truncate */
};
......@@ -62,7 +62,7 @@ struct inode_operations ext_chrdev_inode_operations = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
ext_bmap, /* bmap */
ext_truncate /* truncate */
NULL, /* bmap */
NULL /* truncate */
};
......@@ -48,14 +48,14 @@ struct inode_operations ext_dir_inode_operations = {
ext_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
ext_bmap, /* bmap */
NULL, /* bmap */
ext_truncate /* truncate */
};
static int ext_readdir(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
unsigned int block,offset,i;
unsigned int offset,i;
char c;
struct buffer_head * bh;
struct ext_dir_entry * de;
......@@ -64,8 +64,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev, block, BLOCK_SIZE))) {
bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
if (!bh) {
filp->f_pos += 1024-offset;
continue;
}
......
......@@ -30,6 +30,14 @@
#include <linux/fs.h>
#include <linux/ext_fs.h>
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
static int ext_file_read(struct inode *, struct file *, char *, int);
static int ext_file_write(struct inode *, struct file *, char *, int);
......@@ -65,17 +73,9 @@ struct inode_operations ext_file_inode_operations = {
ext_truncate /* truncate */
};
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
int read,left,chars,nr;
int read,left,chars;
int block, blocks, offset;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * buflist[NBUF];
......@@ -104,12 +104,9 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
do {
if (blocks) {
--blocks;
if (nr = ext_bmap(inode,block++)) {
*bhb = getblk(inode->i_dev, nr, BLOCK_SIZE);
if (!(*bhb)->b_uptodate)
ll_rw_block(READ,*bhb);
} else
*bhb = NULL;
*bhb = ext_getblk(inode,block++,0);
if (*bhb && !(*bhb)->b_uptodate)
ll_rw_block(READ,*bhb);
if (++bhb == &buflist[NBUF])
bhb = buflist;
......@@ -160,7 +157,7 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
static int ext_file_write(struct inode * inode, struct file * filp, char * buf, int count)
{
off_t pos;
int written,block,c;
int written,c;
struct buffer_head * bh;
char * p;
......@@ -182,7 +179,8 @@ static int ext_file_write(struct inode * inode, struct file * filp, char * buf,
pos = filp->f_pos;
written = 0;
while (written<count) {
if (!(block = ext_create_block(inode,pos/BLOCK_SIZE))) {
bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
if (!bh) {
if (!written)
written = -ENOSPC;
break;
......@@ -190,14 +188,15 @@ static int ext_file_write(struct inode * inode, struct file * filp, char * buf,
c = BLOCK_SIZE - (pos % BLOCK_SIZE);
if (c > count-written)
c = count-written;
if (c == BLOCK_SIZE)
bh = getblk(inode->i_dev, block, BLOCK_SIZE);
else
bh = bread(inode->i_dev, block, BLOCK_SIZE);
if (!bh) {
if (!written)
written = -EIO;
break;
if (c != BLOCK_SIZE && !bh->b_uptodate) {
ll_rw_block(READ,bh);
wait_on_buffer(bh);
if (!bh->b_uptodate) {
brelse(bh);
if (!written)
written = -EIO;
break;
}
}
p = (pos % BLOCK_SIZE) + bh->b_data;
pos += c;
......
......@@ -41,7 +41,7 @@ __asm__("cld\n\t" \
"stosl" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
int ext_free_block(int dev, int block)
void ext_free_block(int dev, int block)
{
struct super_block * sb;
struct buffer_head * bh;
......@@ -50,21 +50,15 @@ int ext_free_block(int dev, int block)
if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device");
lock_super (sb);
if (block < sb->u.ext_sb.s_firstdatazone
|| block >= sb->u.ext_sb.s_nzones)
panic("trying to free block not in datazone");
if (block < sb->u.ext_sb.s_firstdatazone ||
block >= sb->u.ext_sb.s_nzones) {
printk("trying to free block not in datazone\n");
return;
}
bh = get_hash_table(dev, block, sb->s_blocksize);
if (bh) {
if (bh->b_count > 1) {
brelse(bh);
free_super (sb);
return 0;
}
if (bh)
bh->b_dirt=0;
bh->b_uptodate=0;
if (bh->b_count)
brelse(bh);
}
brelse(bh);
if (sb->u.ext_sb.s_firstfreeblock)
efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
if (!sb->u.ext_sb.s_firstfreeblock || efb->count == 254) {
......@@ -87,7 +81,7 @@ printk("ext_free_block: block full, skipping to %d\n", block);
sb->s_dirt = 1;
sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
free_super (sb);
return 1;
return;
}
int ext_new_block(int dev)
......
......@@ -22,6 +22,14 @@
int sync_dev(int dev);
static inline void wait_on_buffer(struct buffer_head * bh)
{
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
void ext_put_inode(struct inode *inode)
{
inode->i_size = 0;
......@@ -152,130 +160,190 @@ void ext_statfs (struct super_block *sb, struct statfs *buf)
/* Don't know what value to put in buf->f_fsid */
}
static int _ext_bmap(struct inode * inode,int block,int create)
#define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
static int block_bmap(struct buffer_head * bh, int nr)
{
int tmp;
if (!bh)
return 0;
tmp = ((unsigned long *) bh->b_data)[nr];
brelse(bh);
return tmp;
}
int ext_bmap(struct inode * inode,int block)
{
struct buffer_head * bh;
int i;
if (block<0) {
printk("_ext_bmap: block<0");
printk("ext_bmap: block<0");
return 0;
}
if (block >= 9+256+256*256+256*256*256) {
printk("_ext_bmap: block>big");
printk("ext_bmap: block>big");
return 0;
}
if (block<9) {
if (create && !inode->i_data[block])
if (inode->i_data[block]=ext_new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_data[block];
}
if (block<9)
return inode_bmap(inode,block);
block -= 9;
if (block<256) {
if (create && !inode->i_data[9])
if (inode->i_data[9]=ext_new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_data[9])
return 0;
if (!(bh = bread(inode->i_dev, inode->i_data[9], BLOCK_SIZE)))
i = inode_bmap(inode,9);
if (!i)
return 0;
i = ((unsigned long *) (bh->b_data))[block];
if (create && !i)
if (i=ext_new_block(inode->i_dev)) {
((unsigned long *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
}
block -= 256;
if (block<256*256) {
if (create && !inode->i_data[10])
if (inode->i_data[10]=ext_new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_data[10])
return 0;
if (!(bh=bread(inode->i_dev, inode->i_data[10], BLOCK_SIZE)))
return 0;
i = ((unsigned long *)bh->b_data)[block>>8];
if (create && !i)
if (i=ext_new_block(inode->i_dev)) {
((unsigned long *) (bh->b_data))[block>>8]=i;
bh->b_dirt=1;
}
brelse(bh);
i = inode_bmap(inode,10);
if (!i)
return 0;
if (!(bh=bread(inode->i_dev, i, BLOCK_SIZE)))
i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
if (!i)
return 0;
i = ((unsigned long *)bh->b_data)[block&255];
if (create && !i)
if (i=ext_new_block(inode->i_dev)) {
((unsigned long *) (bh->b_data))[block&255]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
}
if (create && !inode->i_data[11])
if (inode->i_data[11] = ext_new_block(inode->i_dev)) {
inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
}
if (!inode->i_data[11])
return 0;
if (!(bh = bread(inode->i_dev, inode->i_data[11], BLOCK_SIZE)))
return 0;
i = ((unsigned long *) bh->b_data)[block >> 16];
if (create && !i)
if (i = ext_new_block(inode->i_dev)) {
((unsigned long *) bh->b_data)[block >> 16] = i;
bh->b_dirt = 1;
}
brelse (bh);
block -= 256*256;
i = inode_bmap(inode,11);
if (!i)
return 0;
if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE)))
return 0;
i = ((unsigned long *) bh->b_data)[(block >> 8) & 255];
if (create && !i)
if (i = ext_new_block(inode->i_dev)) {
((unsigned long *) bh->b_data)[(block >> 8) & 255] = i;
bh->b_dirt = 1;
}
brelse (bh);
i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
if (!i)
return 0;
if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE)))
i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
if (!i)
return 0;
i = ((unsigned long *) bh->b_data)[block & 255];
if (create && !i)
if (i = ext_new_block(inode->i_dev)) {
((unsigned long *) bh->b_data)[block & 255] = i;
bh->b_dirt = 1;
return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
}
static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
{
int tmp;
unsigned long * p;
struct buffer_head * result;
p = inode->u.ext_i.i_data + nr;
repeat:
tmp = *p;
if (tmp) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp == *p)
return result;
brelse(result);
goto repeat;
}
if (!create)
return NULL;
tmp = ext_new_block(inode->i_dev);
if (!tmp)
return NULL;
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (*p) {
ext_free_block(inode->i_dev,tmp);
brelse(result);
goto repeat;
}
*p = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
return result;
}
static struct buffer_head * block_getblk(struct buffer_head * bh, int nr, int create)
{
int tmp;
unsigned long * p;
struct buffer_head * result;
if (!bh)
return NULL;
if (!bh->b_uptodate) {
ll_rw_block(READ,bh);
wait_on_buffer(bh);
if (!bh->b_uptodate) {
brelse(bh);
return NULL;
}
brelse (bh);
return i;
printk("ext_bmap: triple indirection not yet implemented\n");
return 0;
}
p = nr + (unsigned long *) bh->b_data;
repeat:
tmp = *p;
if (tmp) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (tmp == *p) {
brelse(bh);
return result;
}
brelse(result);
goto repeat;
}
if (!create) {
brelse(bh);
return NULL;
}
tmp = ext_new_block(bh->b_dev);
if (!tmp) {
brelse(bh);
return NULL;
}
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (*p) {
ext_free_block(bh->b_dev,tmp);
brelse(result);
goto repeat;
}
*p = tmp;
bh->b_dirt = 1;
brelse(bh);
return result;
}
int ext_bmap(struct inode * inode,int block)
struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
{
return _ext_bmap(inode,block,0);
struct buffer_head * bh;
if (block<0) {
printk("ext_getblk: block<0\n");
return NULL;
}
if (block >= 9+256+256*256+256*256*256) {
printk("ext_getblk: block>big\n");
return NULL;
}
if (block<9)
return inode_getblk(inode,block,create);
block -= 9;
if (block<256) {
bh = inode_getblk(inode,9,create);
return block_getblk(bh,block,create);
}
block -= 256;
if (block<256*256) {
bh = inode_getblk(inode,10,create);
bh = block_getblk(bh,block>>8,create);
return block_getblk(bh,block & 255,create);
}
block -= 256*256;
bh = inode_getblk(inode,11,create);
bh = block_getblk(bh,block>>16,create);
bh = block_getblk(bh,(block>>8) & 255,create);
return block_getblk(bh,block & 255,create);
}
int ext_create_block(struct inode * inode, int block)
struct buffer_head * ext_bread(struct inode * inode, int block, int create)
{
return _ext_bmap(inode,block,1);
struct buffer_head * bh;
bh = ext_getblk(inode,block,create);
if (!bh || bh->b_uptodate)
return bh;
ll_rw_block(READ,bh);
wait_on_buffer(bh);
if (bh->b_uptodate)
return bh;
brelse(bh);
return NULL;
}
void ext_read_inode(struct inode * inode)
......@@ -299,7 +367,7 @@ void ext_read_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_rdev = raw_inode->i_zone[0];
else for (block = 0; block < 12; block++)
inode->i_data[block] = raw_inode->i_zone[block];
inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
brelse(bh);
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
......@@ -314,8 +382,8 @@ void ext_read_inode(struct inode * inode)
inode->i_op = &ext_blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
inode->i_op = &ext_fifo_inode_operations;
inode->i_size = 0;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
......@@ -341,7 +409,7 @@ void ext_write_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = inode->i_rdev;
else for (block = 0; block < 12; block++)
raw_inode->i_zone[block] = inode->i_data[block];
raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
......
......@@ -20,8 +20,6 @@
#include <asm/segment.h>
#include <const.h>
/*
* comment out this line if you want names > EXT_NAME_LEN chars to be
* truncated. Else they will be disallowed.
......@@ -90,7 +88,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
const char * name, int namelen, struct ext_dir_entry ** res_dir,
struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
{
int block;
long offset;
struct buffer_head * bh;
struct ext_dir_entry * de;
......@@ -105,9 +102,8 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (namelen > EXT_NAME_LEN)
namelen = EXT_NAME_LEN;
#endif
if (!(block = dir->i_data[0]))
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
bh = ext_bread(dir,0,0);
if (!bh)
return NULL;
if (prev_dir)
*prev_dir = NULL;
......@@ -119,10 +115,9 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) ||
!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
if (!bh)
continue;
}
de = (struct ext_dir_entry *) bh->b_data;
if (prev_dir)
*prev_dir = NULL;
......@@ -187,7 +182,7 @@ int ext_lookup(struct inode * dir,const char * name, int len,
static struct buffer_head * ext_add_entry(struct inode * dir,
const char * name, int namelen, struct ext_dir_entry ** res_dir)
{
int block,i;
int i;
long offset;
unsigned short rec_len;
struct buffer_head * bh;
......@@ -205,9 +200,8 @@ static struct buffer_head * ext_add_entry(struct inode * dir,
#endif
if (!namelen)
return NULL;
if (!(block = dir->i_data[0]))
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
bh = ext_bread(dir,0,0);
if (!bh)
return NULL;
rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
offset = 0;
......@@ -219,13 +213,9 @@ printk ("ext_add_entry: skipping to next block\n");
#endif
brelse(bh);
bh = NULL;
block = ext_create_block(dir,offset>>BLOCK_SIZE_BITS);
if (!block)
bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
if (!bh)
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
offset += BLOCK_SIZE;
continue;
}
de = (struct ext_dir_entry *) bh->b_data;
}
if (offset >= dir->i_size) {
......@@ -248,13 +238,11 @@ printk ("ext_add_entry: skipping to next block\n");
}
brelse (bh);
bh = NULL;
block = ext_create_block (dir,offset>>BLOCK_SIZE_BITS);
#ifdef EXTFS_DEBUG
printk ("ext_add_entry : creating next block\n");
#endif
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
if (!bh)
return NULL; /* Other thing to do ??? */
de = (struct ext_dir_entry *) bh->b_data;
}
......@@ -361,8 +349,8 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev
inode->i_op = &ext_blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
inode->i_op = &ext_fifo_inode_operations;
inode->i_size = 0;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
......@@ -410,21 +398,14 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
- 2 bytes for the name length
- 8 bytes for the name */
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_data[0] = ext_new_block(inode->i_dev))) {
dir_block = ext_bread(inode,0,1);
if (!dir_block) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
inode->i_dirt = 1;
if (!(dir_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -EIO;
}
de = (struct ext_dir_entry *) dir_block->b_data;
de->inode=inode->i_ino;
de->rec_len=16;
......@@ -438,7 +419,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
inode->i_nlink = 2;
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
inode->i_dirt = 1;
bh = ext_add_entry(dir,name,len,&de);
if (!bh) {
......@@ -462,13 +443,11 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
*/
static int empty_dir(struct inode * inode)
{
int block;
unsigned long offset;
struct buffer_head * bh;
struct ext_dir_entry * de, * de1;
if (inode->i_size < 2 * 12 || !inode->i_data[0] ||
!(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
if (inode->i_size < 2 * 12 || !(bh = ext_bread(inode,0,0))) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 1;
}
......@@ -484,13 +463,11 @@ static int empty_dir(struct inode * inode)
while (offset < inode->i_size ) {
if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
brelse(bh);
block = ext_bmap(inode, offset >> BLOCK_SIZE_BITS);
if (!block) {
bh = ext_bread(inode, offset >> BLOCK_SIZE_BITS,1);
if (!bh) {
offset += BLOCK_SIZE;
continue;
}
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
return 0;
de = (struct ext_dir_entry *) bh->b_data;
}
if (de->inode) {
......@@ -621,21 +598,14 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym
}
inode->i_mode = S_IFLNK | 0777;
inode->i_op = &ext_symlink_inode_operations;
if (!(inode->i_data[0] = ext_new_block(inode->i_dev))) {
name_block = ext_bread(inode,0,1);
if (!name_block) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
inode->i_dirt = 1;
if (!(name_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -EIO;
}
i = 0;
while (i < 1023 && (c=get_fs_byte(symname++)))
name_block->b_data[i++] = c;
......@@ -807,9 +777,8 @@ static int do_ext_rename(struct inode * old_dir, const char * old_name, int old_
if (subdir(new_dir, old_inode))
goto end_rename;
retval = -EIO;
if (!old_inode->i_data[0])
goto end_rename;
if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0], BLOCK_SIZE)))
dir_bh = ext_bread(old_inode,0,0);
if (!dir_bh)
goto end_rename;
if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
goto end_rename;
......
......@@ -50,13 +50,13 @@ static int ext_follow_link(struct inode * dir, struct inode * inode,
unsigned short fs;
struct buffer_head * bh;
*res_inode = NULL;
if (!dir) {
dir = current->root;
dir->i_count++;
}
if (!inode) {
iput(dir);
*res_inode = NULL;
return -ENOENT;
}
if (!S_ISLNK(inode->i_mode)) {
......@@ -64,15 +64,18 @@ static int ext_follow_link(struct inode * dir, struct inode * inode,
*res_inode = inode;
return 0;
}
__asm__("mov %%fs,%0":"=r" (fs));
if ((current->link_count > 5) || !inode->i_data[0] ||
!(bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
if (current->link_count > 5) {
iput(dir);
iput(inode);
*res_inode = NULL;
return -ELOOP;
}
if (!(bh = ext_bread(inode, 0, 0))) {
iput(inode);
iput(dir);
return -EIO;
}
iput(inode);
__asm__("mov %%fs,%0":"=r" (fs));
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
current->link_count++;
error = open_namei(bh->b_data,flag,mode,res_inode,dir);
......@@ -94,10 +97,7 @@ static int ext_readlink(struct inode * inode, char * buffer, int buflen)
}
if (buflen > 1023)
buflen = 1023;
if (inode->i_data[0])
bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE);
else
bh = NULL;
bh = ext_bread(inode, 0, 0);
iput(inode);
if (!bh)
return 0;
......
......@@ -32,146 +32,208 @@
static int trunc_direct(struct inode * inode)
{
int i;
int result = 0;
int i, tmp;
unsigned long * p;
struct buffer_head * bh;
int retry = 0;
#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
repeat:
for (i = DIRECT_BLOCK ; i < 9 ; i++) {
if (i < DIRECT_BLOCK)
p = inode->u.ext_i.i_data+i;
if (!(tmp = *p))
continue;
bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
if (i < DIRECT_BLOCK) {
brelse(bh);
goto repeat;
if (!inode->i_data[i])
}
if ((bh && bh->b_count != 1) || tmp != *p) {
retry = 1;
brelse(bh);
continue;
result = 1;
if (ext_free_block(inode->i_dev,inode->i_data[i]))
inode->i_data[i] = 0;
}
*p = 0;
inode->i_dirt = 1;
brelse(bh);
ext_free_block(inode->i_dev,tmp);
}
return result;
return retry;
}
static int trunc_indirect(struct inode * inode, int offset, unsigned long * p)
{
int i;
struct buffer_head * bh = NULL;
int i, tmp;
struct buffer_head * bh;
struct buffer_head * ind_bh;
unsigned long * ind;
int result = 0;
int retry = 0;
#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
if (*p)
bh = bread(inode->i_dev, *p, BLOCK_SIZE);
if (!bh)
tmp = *p;
if (!tmp)
return 0;
ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp != *p) {
brelse(ind_bh);
return 1;
}
if (!ind_bh) {
*p = 0;
return 0;
}
repeat:
for (i = INDIRECT_BLOCK ; i < 256 ; i++) {
if (i < 0)
i = 0;
if (i < INDIRECT_BLOCK)
goto repeat;
ind = i+(unsigned long *) bh->b_data;
if (!*ind)
ind = i+(unsigned long *) ind_bh->b_data;
tmp = *ind;
if (!tmp)
continue;
bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
if (i < INDIRECT_BLOCK) {
brelse(bh);
goto repeat;
}
if ((bh && bh->b_count != 1) || tmp != *ind) {
retry = 1;
brelse(bh);
continue;
result = 1;
if (ext_free_block(inode->i_dev,*ind))
*ind = 0;
}
*ind = 0;
ind_bh->b_dirt = 1;
brelse(bh);
ext_free_block(inode->i_dev,tmp);
}
ind = (unsigned long *) bh->b_data;
ind = (unsigned long *) ind_bh->b_data;
for (i = 0; i < 256; i++)
if (*(ind++))
break;
brelse(bh);
if (i >= 256) {
result = 1;
if (ext_free_block(inode->i_dev,*p))
if (i >= 256)
if (ind_bh->b_count != 1)
retry = 1;
else {
tmp = *p;
*p = 0;
}
return result;
inode->i_dirt = 1;
ext_free_block(inode->i_dev,tmp);
}
brelse(ind_bh);
return retry;
}
static int trunc_dindirect(struct inode * inode, int offset, unsigned long * p)
{
int i;
struct buffer_head * bh = NULL;
int i,tmp;
struct buffer_head * dind_bh;
unsigned long * dind;
int result = 0;
int retry = 0;
#define DINDIRECT_BLOCK ((DIRECT_BLOCK-offset)>>8)
if (*p)
bh = bread(inode->i_dev, *p, BLOCK_SIZE);
if (!bh)
tmp = *p;
if (!tmp)
return 0;
dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp != *p) {
brelse(dind_bh);
return 1;
}
if (!dind_bh) {
*p = 0;
return 0;
}
repeat:
for (i = DINDIRECT_BLOCK ; i < 256 ; i ++) {
if (i < 0)
i = 0;
if (i < DINDIRECT_BLOCK)
goto repeat;
dind = i+(unsigned long *) bh->b_data;
if (!*dind)
dind = i+(unsigned long *) dind_bh->b_data;
tmp = *dind;
if (!tmp)
continue;
result |= trunc_indirect(inode,offset+(i<<8),dind);
retry |= trunc_indirect(inode,offset+(i<<8),dind);
dind_bh->b_dirt = 1;
}
dind = (unsigned long *) bh->b_data;
dind = (unsigned long *) dind_bh->b_data;
for (i = 0; i < 256; i++)
if (*(dind++))
break;
brelse(bh);
if (i >= 256) {
result = 1;
if (ext_free_block(inode->i_dev,*p))
if (i >= 256)
if (dind_bh->b_count != 1)
retry = 1;
else {
tmp = *p;
*p = 0;
}
return result;
inode->i_dirt = 1;
ext_free_block(inode->i_dev,tmp);
}
brelse(dind_bh);
return retry;
}
static int trunc_tindirect(struct inode * inode)
{
int i;
struct buffer_head * bh = NULL;
unsigned long * tind;
int result = 0;
int i,tmp;
struct buffer_head * tind_bh;
unsigned long * tind, * p;
int retry = 0;
#define TINDIRECT_BLOCK ((DIRECT_BLOCK-(256*256+256+9))>>16)
if (inode->i_data[11])
bh = bread(inode->i_dev, inode->i_data[11], BLOCK_SIZE);
if (!bh)
p = inode->u.ext_i.i_data+11;
if (!(tmp = *p))
return 0;
tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp != *p) {
brelse(tind_bh);
return 1;
}
if (!tind_bh) {
*p = 0;
return 0;
}
repeat:
for (i = TINDIRECT_BLOCK ; i < 256 ; i ++) {
if (i < 0)
i = 0;
if (i < TINDIRECT_BLOCK)
goto repeat;
tind = i+(unsigned long *) bh->b_data;
if (!*tind)
continue;
result |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
tind = i+(unsigned long *) tind_bh->b_data;
retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
tind_bh->b_dirt = 1;
}
tind = (unsigned long *) bh->b_data;
tind = (unsigned long *) tind_bh->b_data;
for (i = 0; i < 256; i++)
if (*(tind++))
break;
brelse(bh);
if (i >= 256) {
result = 1;
if (ext_free_block(inode->i_dev,inode->i_data[11]))
inode->i_data[11] = 0;
}
return result;
if (i >= 256)
if (tind_bh->b_count != 1)
retry = 1;
else {
tmp = *p;
*p = 0;
inode->i_dirt = 1;
ext_free_block(inode->i_dev,tmp);
}
brelse(tind_bh);
return retry;
}
void ext_truncate(struct inode * inode)
{
int flag;
int retry;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
while (1) {
flag = trunc_direct(inode);
flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]);
flag |= trunc_dindirect(inode,9+256,(unsigned long *)&inode->i_data[10]);
flag |= trunc_tindirect(inode);
if (!flag)
retry = trunc_direct(inode);
retry |= trunc_indirect(inode,9,inode->u.ext_i.i_data+9);
retry |= trunc_dindirect(inode,9+256,inode->u.ext_i.i_data+10);
retry |= trunc_tindirect(inode);
if (!retry)
break;
current->counter = 0;
schedule();
......
......@@ -84,16 +84,16 @@ static int fifo_open(struct inode * inode,struct file * filp)
wake_up(&PIPE_READ_WAIT(*inode));
if (PIPE_READERS(*inode))
wake_up(&PIPE_WRITE_WAIT(*inode));
if (retval || inode->i_size)
if (retval || PIPE_BASE(*inode))
return retval;
page = get_free_page(GFP_KERNEL);
if (inode->i_size) {
if (PIPE_BASE(*inode)) {
free_page(page);
return 0;
}
if (!page)
return -ENOMEM;
inode->i_size = page;
PIPE_BASE(*inode) = (char *) page;
return 0;
}
......
......@@ -117,8 +117,8 @@ void iput(struct inode * inode)
return;
}
if (inode->i_pipe) {
wake_up(&inode->i_wait);
wake_up(&inode->i_wait2);
wake_up(&PIPE_READ_WAIT(*inode));
wake_up(&PIPE_WRITE_WAIT(*inode));
}
repeat:
if (inode->i_count>1) {
......@@ -126,8 +126,9 @@ void iput(struct inode * inode)
return;
}
if (inode->i_pipe) {
free_page(inode->i_size);
inode->i_size = 0;
unsigned long page = (unsigned long) PIPE_BASE(*inode);
PIPE_BASE(*inode) = NULL;
free_page(page);
}
if (!inode->i_dev) {
inode->i_count--;
......@@ -188,7 +189,7 @@ struct inode * get_pipe_inode(void)
if (!(inode = get_empty_inode()))
return NULL;
if (!(inode->i_size = get_free_page(GFP_USER))) {
if (!(PIPE_BASE(*inode) = (char *) get_free_page(GFP_USER))) {
inode->i_count = 0;
return NULL;
}
......
......@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/termios.h>
static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
......@@ -17,17 +18,27 @@ static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
switch (cmd) {
case FIBMAP:
if (filp->f_inode->i_op == NULL) return -EBADF;
if (filp->f_inode->i_op->bmap == NULL) return -EINVAL;
if (filp->f_inode->i_op == NULL)
return -EBADF;
if (filp->f_inode->i_op->bmap == NULL)
return -EINVAL;
verify_area((void *) arg,4);
block = get_fs_long((long *) arg);
block = filp->f_inode->i_op->bmap(filp->f_inode,block);
put_fs_long(block,(long *) arg);
return 0;
case FIGETBSZ:
if (filp->f_inode->i_sb == NULL) return -EBADF;
if (filp->f_inode->i_sb == NULL)
return -EBADF;
verify_area((void *) arg,4);
put_fs_long(filp->f_inode->i_sb->s_blocksize,
(long *) arg);
return 0;
case FIONREAD:
verify_area((void *) arg,4);
put_fs_long(filp->f_inode->i_size - filp->f_pos,
(long *) arg);
return 0;
default:
return -EINVAL;
}
......
......@@ -138,7 +138,7 @@ void minix_statfs (struct super_block *sb, struct statfs *buf)
/* Don't know what value to put in buf->f_fsid */
}
#define inode_bmap(inode,nr) ((inode)->i_data[(nr)])
#define inode_bmap(inode,nr) ((inode)->u.minix_i.i_data[(nr)])
static int block_bmap(struct buffer_head * bh, int nr)
{
......@@ -185,13 +185,15 @@ int minix_bmap(struct inode * inode,int block)
static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
{
int tmp;
unsigned short *p;
struct buffer_head * result;
p = inode->u.minix_i.i_data + nr;
repeat:
tmp = inode->i_data[nr];
tmp = *p;
if (tmp) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp == inode->i_data[nr])
if (tmp == *p)
return result;
brelse(result);
goto repeat;
......@@ -202,12 +204,12 @@ static struct buffer_head * inode_getblk(struct inode * inode, int nr, int creat
if (!tmp)
return NULL;
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (inode->i_data[nr]) {
if (*p) {
minix_free_block(inode->i_dev,tmp);
brelse(result);
goto repeat;
}
inode->i_data[nr] = tmp;
*p = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
return result;
......@@ -324,7 +326,7 @@ void minix_read_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_rdev = raw_inode->i_zone[0];
else for (block = 0; block < 9; block++)
inode->i_data[block] = raw_inode->i_zone[block];
inode->u.minix_i.i_data[block] = raw_inode->i_zone[block];
brelse(bh);
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
......@@ -339,8 +341,8 @@ void minix_read_inode(struct inode * inode)
inode->i_op = &minix_blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
inode->i_op = &minix_fifo_inode_operations;
inode->i_size = 0;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
......@@ -367,7 +369,7 @@ void minix_write_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = inode->i_rdev;
else for (block = 0; block < 9; block++)
raw_inode->i_zone[block] = inode->i_data[block];
raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
......
......@@ -14,8 +14,6 @@
#include <asm/segment.h>
#include <const.h>
/*
* comment out this line if you want names > MINIX_NAME_LEN chars to be
* truncated. Else they will be disallowed.
......@@ -260,8 +258,8 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
inode->i_op = &minix_blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode)) {
inode->i_op = &minix_fifo_inode_operations;
inode->i_size = 0;
inode->i_pipe = 1;
PIPE_BASE(*inode) = NULL;
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
......@@ -322,7 +320,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
inode->i_nlink = 2;
dir_block->b_dirt = 1;
brelse(dir_block);
inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
inode->i_dirt = 1;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
......
......@@ -26,6 +26,7 @@
static int trunc_direct(struct inode * inode)
{
unsigned short * p;
struct buffer_head * bh;
int i, tmp;
int retry = 0;
......@@ -33,20 +34,20 @@ static int trunc_direct(struct inode * inode)
repeat:
for (i = DIRECT_BLOCK ; i < 7 ; i++) {
tmp = inode->i_data[i];
if (!tmp)
p = i + inode->u.minix_i.i_data;
if (!(tmp = *p))
continue;
bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
if (i < DIRECT_BLOCK) {
brelse(bh);
goto repeat;
}
if ((bh && bh->b_count != 1) || tmp != inode->i_data[i]) {
if ((bh && bh->b_count != 1) || tmp != *p) {
retry = 1;
brelse(bh);
continue;
}
inode->i_data[i] = 0;
*p = 0;
inode->i_dirt = 1;
brelse(bh);
minix_free_block(inode->i_dev,tmp);
......@@ -120,20 +121,20 @@ static int trunc_dindirect(struct inode * inode)
{
int i, tmp;
struct buffer_head * dind_bh;
unsigned short * dind;
unsigned short * dind, * p;
int retry = 0;
#define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
tmp = inode->i_data[8];
if (!tmp)
p = 8 + inode->u.minix_i.i_data;
if (!(tmp = *p))
return 0;
dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
if (tmp != inode->i_data[8]) {
if (tmp != *p) {
brelse(dind_bh);
return 1;
}
if (!dind_bh) {
inode->i_data[8] = 0;
*p = 0;
return 0;
}
repeat:
......@@ -154,8 +155,8 @@ static int trunc_dindirect(struct inode * inode)
if (dind_bh->b_count != 1)
retry = 1;
else {
tmp = inode->i_data[8];
inode->i_data[8] = 0;
tmp = *p;
*p = 0;
inode->i_dirt = 1;
minix_free_block(inode->i_dev,tmp);
}
......@@ -170,13 +171,9 @@ void minix_truncate(struct inode * inode)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
if (inode->i_data[7] & 0xffff0000) {
printk("BAD! minix inode has 16 high bits set\n");
inode->i_data[7] = 0;
}
while (1) {
retry = trunc_direct(inode);
retry |= trunc_indirect(inode,7,(unsigned short *)&inode->i_data[7]);
retry |= trunc_indirect(inode,7,inode->u.minix_i.i_data+7);
retry |= trunc_dindirect(inode);
if (!retry)
break;
......
......@@ -226,7 +226,7 @@ int get_cluster(struct inode *inode,int cluster)
if ((this = fat_access(inode->i_sb,this,-1)) == -1) return 0;
if (!this) return 0;
}
if (!(MSDOS_I(inode)->i_busy || inode->i_nlink))
if (!(MSDOS_I(inode)->i_busy && inode->i_nlink))
cache_add(inode,cluster,this);
/* don't add clusters of moved files, because we can't invalidate them
when this inode is returned. */
......
......@@ -8,8 +8,6 @@
* Some corrections by tytso.
*/
#include <const.h>
#include <asm/segment.h>
#include <linux/errno.h>
......@@ -218,7 +216,7 @@ int open_namei(const char * pathname, int flag, int mode,
struct task_struct ** p;
mode &= 07777 & ~current->umask;
mode |= I_REGULAR;
mode |= S_IFREG;
error = dir_namei(pathname,&namelen,&basename,base,&dir);
if (error)
return error;
......
......@@ -32,7 +32,7 @@ static int pipe_read(struct inode * inode, struct file * filp, char * buf, int c
chars = count;
if (chars > size)
chars = size;
memcpy_tofs(buf, (char *)inode->i_size+PIPE_TAIL(*inode), chars );
memcpy_tofs(buf, PIPE_BASE(*inode)+PIPE_TAIL(*inode), chars );
read += chars;
PIPE_TAIL(*inode) += chars;
PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
......@@ -75,7 +75,7 @@ static int pipe_write(struct inode * inode, struct file * filp, char * buf, int
chars = count;
if (chars > size)
chars = size;
memcpy_fromfs((char *)inode->i_size+PIPE_HEAD(*inode), buf, chars );
memcpy_fromfs(PIPE_BASE(*inode)+PIPE_HEAD(*inode), buf, chars );
written += chars;
PIPE_HEAD(*inode) += chars;
PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
......
......@@ -18,8 +18,6 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <const.h>
/*
* Ok, Peter made a complicated, but straightforward multiple_wait() function.
* I have rewritten this, taking some shortcuts: This code may not be easy to
......
......@@ -25,10 +25,7 @@ static void cp_old_stat(struct inode * inode, struct old_stat * statbuf)
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_rdev;
if( S_ISFIFO(inode->i_mode) )
tmp.st_size = 0;
else
tmp.st_size = inode->i_size;
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
......@@ -48,10 +45,7 @@ static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_rdev;
if( S_ISFIFO(inode->i_mode) )
tmp.st_size = 0;
else
tmp.st_size = inode->i_size;
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
......@@ -74,12 +68,10 @@ static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
}
blocks += indirect;
}
tmp.st_blksize = 512;
tmp.st_blocks = blocks;
} else {
tmp.st_blksize = inode->i_blksize;
tmp.st_blocks = inode->i_blocks;
}
} else
tmp.st_blocks = (inode->i_blocks * inode->i_blksize) / 512;
tmp.st_blksize = 512;
memcpy_tofs(statbuf,&tmp,sizeof(tmp));
}
......
......@@ -6,46 +6,51 @@
* the two short jumps: using outb's to a nonexistent port seems
* to guarantee better timings even on fast machines.
*
* On the other hand, I'd like to be sure of a non-existent port:
* I feel a bit unsafe abou using 0x80.
*
* Linus
*/
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
#else
#define __SLOW_DOWN_IO __asm__ __volatile__("inb $0x80,%%al":::"ax")
#endif
#ifdef REALLY_SLOW_IO
#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
#else
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
extern void inline outb(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %0,%1"
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
}
extern void inline outb_p(char value, unsigned short port)
extern unsigned int inline inb(unsigned short port)
{
__asm__ __volatile__ ("outb %0,%1\n\t"
#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
#endif
"outb %0,$0x80"
::"a" ((char) value),"d" ((unsigned short) port));
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
:"=a" (_v):"d" ((unsigned short) port),"0" (0));
return _v;
}
extern unsigned char inline inb(unsigned short port)
extern void inline outb_p(char value, unsigned short port)
{
unsigned char _v;
__asm__ __volatile__ ("inb %1,%0"
:"=a" (_v):"d" ((unsigned short) port));
return _v;
__asm__ __volatile__ ("outb %%al,%%dx"
::"a" ((char) value),"d" ((unsigned short) port));
SLOW_DOWN_IO;
}
extern unsigned char inline inb_p(unsigned short port)
extern unsigned int inline inb_p(unsigned short port)
{
unsigned char _v;
__asm__ __volatile__ ("inb %1,%0\n\t"
#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
#endif
"outb %0,$0x80"
:"=a" (_v):"d" ((unsigned short) port));
unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
:"=a" (_v):"d" ((unsigned short) port),"0" (0));
SLOW_DOWN_IO;
return _v;
}
......
......@@ -12,9 +12,26 @@
* Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
* gt7080a@prism.gatech.edu (13JUL92)
*
* Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
*
* Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
* 8/28/92
*
* Microsoft Bus Mouse support folded into 0.97pl4 code
* by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
* Changes: Logitech and Microsoft support in the same kernel.
* Defined new constants in busmouse.h for MS mice.
* Added int mse_busmouse_type to distinguish busmouse types
* Added a couple of new functions to handle differences in using
* MS vs. Logitech (where the int variable wasn't appropriate).
*
*/
#define MOUSE_IRQ 5
#define LOGITECH_BUSMOUSE 0 /* Minor device # for Logitech */
#define MICROSOFT_BUSMOUSE 2 /* Minor device # for Microsoft */
/*--------- LOGITECH BUSMOUSE ITEMS -------------*/
#define MSE_DATA_PORT 0x23c
#define MSE_SIGNATURE_PORT 0x23d
......@@ -35,10 +52,35 @@
#define MSE_DEFAULT_MODE 0x90
#define MSE_SIGNATURE_BYTE 0xa5
/* useful macros */
/* useful Logitech Mouse macros */
#define MSE_INT_OFF() outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
#define MSE_INT_ON() outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
/*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
#define MS_MSE_DATA_PORT 0x23d
#define MS_MSE_SIGNATURE_PORT 0x23d
#define MS_MSE_CONTROL_PORT 0x23c
#define MS_MSE_CONFIG_PORT 0x23f
#define MS_MSE_ENABLE_INTERRUPTS 0x11
#define MS_MSE_DISABLE_INTERRUPTS 0x10
#define MS_MSE_READ_BUTTONS 0x00
#define MS_MSE_READ_X 0x01
#define MS_MSE_READ_Y 0x02
#define MS_MSE_START 0x80
#define MS_MSE_COMMAND_MODE 0x07
/* useful microsoft busmouse macros */
#define MS_MSE_INT_OFF() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
outb(MS_MSE_DISABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
#define MS_MSE_INT_ON() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
outb(MS_MSE_ENABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
struct mouse_status
{
......@@ -54,8 +96,13 @@ struct mouse_status
struct inode *inode;
};
/* Variable Definitions */
extern int mse_busmouse_type; /* to distinguish what type mouse we're working with */
/* Function Prototypes */
extern long mouse_init(long);
#endif
/****************************************************************************************
* *
* SCSI header library for linux *
* (C) 1992 David Giller rafetmad@oxy.edu *
* *
* <linux/cdrom.h> -- CD-ROM IOCTLs and structs *
* *
****************************************************************************************/
#ifndef _LINUX_CDROM_H
#define _LINUX_CDROM_H
/*
*
* For IOCTL calls, we will commandeer byte 0x53, or 'S'.
*
*/
/*
* These are flags for the SCMD_DOORLOCK command. They really should be defined
* somewhere more standard.
*/
#define SR_REMOVAL_PREVENT 1
#define SR_REMOVAL_ALLOW 0
/*
* CD-ROM-specific SCSI command opcodes
*/
/*
* Group 2 (10-byte). All of these are called 'optional' by SCSI-II.
*/
#define SCMD_READ_TOC 0x43 /* read table of contents */
#define SCMD_PLAYAUDIO_MSF 0x47 /* play data at time offset */
#define SCMD_PLAYAUDIO_TI 0x48 /* play data at track/index */
#define SCMD_PAUSE_RESUME 0x4B /* pause/resume audio */
#define SCMD_READ_SUBCHANNEL 0x42 /* read SC info on playing disc */
#define SCMD_PLAYAUDIO10 0x45 /* play data at logical block */
#define SCMD_READ_HEADER 0x44 /* read TOC header */
/*
* Group 5
*/
#define SCMD_PLAYAUDIO12 0xA5 /* play data at logical block */
#define SCMD_PLAYTRACK_REL12 0xA9 /* play track at relative offset*/
/*
* Group 6 Commands
*/
#define SCMD_CD_PLAYBACK_CONTROL 0xC9 /* Sony vendor-specific audio */
#define SCMD_CD_PLAYBACK_STATUS 0xC4 /* control opcodes. info please!*/
/*
* CD-ROM capacity structure.
*/
struct scsi_capacity
{
u_long capacity;
u_long lbasize;
};
/*
* CD-ROM MODE_SENSE/MODE_SELECT parameters
*/
#define ERR_RECOVERY_PARMS 0x01
#define DISCO_RECO_PARMS 0x02
#define FORMAT_PARMS 0x03
#define GEOMETRY_PARMS 0x04
#define CERTIFICATION_PARMS 0x06
#define CACHE_PARMS 0x38
/*
* standard mode-select header prepended to all mode-select commands
*/
struct ccs_modesel_head
{
u_char _r1; /* reserved */
u_char medium; /* device-specific medium type */
u_char _r2; /* reserved */
u_char block_desc_length; /* block descriptor length */
u_char density; /* device-specific density code */
u_char number_blocks_hi; /* number of blocks in this block desc */
u_char number_blocks_med;
u_char number_blocks_lo;
u_char _r3;
u_char block_length_hi; /* block length for blocks in this desc */
u_short block_length;
};
/*
* error recovery parameters
*/
struct ccs_err_recovery
{
u_char _r1 : 2; /* reserved */
u_char page_code : 6; /* page code */
u_char page_length; /* page length */
u_char awre : 1; /* auto write realloc enabled */
u_char arre : 1; /* auto read realloc enabled */
u_char tb : 1; /* transfer block */
u_char rc : 1; /* read continuous */
u_char eec : 1; /* enable early correction */
u_char per : 1; /* post error */
u_char dte : 1; /* disable transfer on error */
u_char dcr : 1; /* disable correction */
u_char retry_count; /* error retry count */
u_char correction_span; /* largest recov. to be attempted, bits */
u_char head_offset_count; /* head offset (2's C) for each retry */
u_char strobe_offset_count; /* data strobe " */
u_char recovery_time_limit; /* time limit on recovery attempts */
};
/*
* disco/reco parameters
*/
struct ccs_disco_reco
{
u_char _r1 : 2; /* reserved */
u_char page_code : 6; /* page code */
u_char page_length; /* page length */
u_char buffer_full_ratio; /* write buffer reconnect threshold */
u_char buffer_empty_ratio; /* read " */
u_short bus_inactivity_limit; /* limit on bus inactivity time */
u_short disconnect_time_limit; /* minimum disconnect time */
u_short connect_time_limit; /* minimum connect time */
u_short _r2; /* reserved */
};
/*
* drive geometry parameters
*/
struct ccs_geometry
{
u_char _r1 : 2; /* reserved */
u_char page_code : 6; /* page code */
u_char page_length; /* page length */
u_char cyl_ub; /* #cyls */
u_char cyl_mb;
u_char cyl_lb;
u_char heads; /* #heads */
u_char precomp_cyl_ub; /* precomp start */
u_char precomp_cyl_mb;
u_char precomp_cyl_lb;
u_char current_cyl_ub; /* reduced current start */
u_char current_cyl_mb;
u_char current_cyl_lb;
u_short step_rate; /* stepping motor rate */
u_char landing_cyl_ub; /* landing zone */
u_char landing_cyl_mb;
u_char landing_cyl_lb;
u_char _r2;
u_char _r3;
u_char _r4;
};
/*
* cache parameters
*/
struct ccs_cache
{
u_char _r1 : 2; /* reserved */
u_char page_code : 6; /* page code */
u_char page_length; /* page length */
u_char mode; /* cache control byte */
u_char threshold; /* prefetch threshold */
u_char max_prefetch; /* maximum prefetch size */
u_char max_multiplier; /* maximum prefetch multiplier */
u_char min_prefetch; /* minimum prefetch size */
u_char min_multiplier; /* minimum prefetch multiplier */
u_char _r2[8];
};
/*
* CDROM IOCTL structures
*/
struct cdrom_msf
{
u_char cdmsf_min0; /* start minute */
u_char cdmsf_sec0; /* start second */
u_char cdmsf_frame0; /* start frame */
u_char cdmsf_min1; /* end minute */
u_char cdmsf_sec1; /* end second */
u_char cdmsf_frame1; /* end frame */
};
struct cdrom_ti
{
u_char cdti_trk0; /* start track */
u_char cdti_ind0; /* start index */
u_char cdti_trk1; /* end track */
u_char cdti_ind1; /* end index */
};
struct cdrom_tochdr
{
u_char cdth_trk0; /* start track */
u_char cdth_trk1; /* end track */
};
struct cdrom_tocentry
{
u_char cdte_track;
u_char cdte_adr :4;
u_char cdte_ctrl :4;
u_char cdte_format;
union
{
struct
{
u_char minute;
u_char second;
u_char frame;
} msf;
int lba;
} cdte_addr;
u_char cdte_datamode;
};
/*
* CD-ROM address types (cdrom_tocentry.cdte_format)
*/
#define CDROM_LBA 0x01
#define CDROM_MSF 0x02
/*
* bit to tell whether track is data or audio
*/
#define CDROM_DATA_TRACK 0x04
/*
* The leadout track is always 0xAA, regardless of # of tracks on disc
*/
#define CDROM_LEADOUT 0xAA
struct cdrom_subchnl
{
u_char cdsc_format;
u_char cdsc_audiostatus;
u_char cdsc_adr: 4;
u_char cdsc_ctrl: 4;
u_char cdsc_trk;
u_char cdsc_ind;
union
{
struct
{
u_char minute;
u_char second;
u_char frame;
} msf;
int lba;
} cdsc_absaddr;
union
{
struct
{
u_char minute;
u_char second;
u_char frame;
} msf;
int lba;
} cdsc_reladdr;
};
/*
* return value from READ SUBCHANNEL DATA
*/
#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */
#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */
#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */
#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */
#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */
#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */
struct cdrom_volctrl
{
u_char channel0;
u_char channel1;
u_char channel2;
u_char channel3;
};
struct cdrom_read
{
int cdread_lba;
caddr_t cdread_bufaddr;
int cdread_buflen;
};
#ifdef FIVETWELVE
#define CDROM_MODE1_SIZE 512
#else
#define CDROM_MODE1_SIZE 2048
#endif FIVETWELVE
#define CDROM_MODE2_SIZE 2336
/*
* CD-ROM IOCTL commands
*/
#define CDROMPAUSE 0x5301 /* pause */
#define CDROMRESUME 0x5302 /* resume */
#define CDROMPLAYMSF 0x5303 /* (stuct cdrom_msf) */
/* SCMD_PLAY_AUDIO_MSF */
#define CDROMPLAYTRKIND 0x5304 /* (struct cdrom_ti) */
/* SCMD_PLAY_AUDIO_TI */
#define CDROMREADTOCHDR 0x5305 /* (struct cdrom_tochdr) */
/* read the TOC header */
#define CDROMREADTOCENTRY 0x5306 /* (struct cdrom_tocentry) */
/* read a TOC entry */
#define CDROMSTOP 0x5307 /* stop the drive motor */
#define CDROMSTART 0x5308 /* turn the motor on */
#define CDROMEJECT 0x5309 /* eject CD-ROM media */
#define CDROMVOLCTRL 0x530a /* (struct cdrom_volctrl) */
/* vlume control */
#define CDROMSUBCHNL 0x530b /* (struct cdrom_subchnl) */
/* read sub-channel data */
#define CDROMREADMODE2 0x530c /* (struct cdrom_read) */
/* read type-2 data (not suppt) */
#define CDROMREADMODE1 0x530d /* (struct cdrom_read) */
/* read type-1 data */
/*
* Linux-specific CD-ROM ioctls for convenience and ISO-9660 support
*/
#define CDROMDOORLOCK 0x5380 /* lock the eject mechanism */
#define CDROMDOORUNLOCK 0x5381 /* unlock the mechanism */
#endif _LINUX_CDROM_H
......@@ -24,6 +24,8 @@
#define CONFIG_BLK_DEV_HD
#undef CONFIG_BLK_DEV_SD
#define CONFIG_BLK_DEV_SD
#undef CONFIG_BLK_DEV_SR
#define CONFIG_BLK_DEV_SR
#undef CONFIG_BLK_DEV_ST
#define CONFIG_BLK_DEV_ST
......
......@@ -65,6 +65,7 @@
#define CONFIG_BLK_DEV_HD
#undef CONFIG_BLK_DEV_SD
#undef CONFIG_BLK_DEV_ST
#undef CONFIG_BLK_DEV_SR
/*
......@@ -80,7 +81,7 @@
#undef CONFIG_SCSI_ULTRASTOR
#undef CONFIG_SCSI_7000FASST
#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_CD) || \
#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_SR) || \
defined(CONFIG_CHR_DEV_ST)
#ifndef CONFIG_SCSI
#define CONFIG_SCSI
......
......@@ -78,12 +78,14 @@ extern struct inode * ext_new_inode(int dev);
extern void ext_free_inode(struct inode * inode);
extern unsigned long ext_count_free_inodes(struct super_block *sb);
extern int ext_new_block(int dev);
extern int ext_free_block(int dev, int block);
extern void ext_free_block(int dev, int block);
extern unsigned long ext_count_free_blocks(struct super_block *sb);
extern int ext_create_block(struct inode *, int);
extern int ext_bmap(struct inode *,int);
extern struct buffer_head * ext_getblk(struct inode *, int, int);
extern struct buffer_head * ext_bread(struct inode *, int, int);
extern void ext_truncate(struct inode *);
extern void ext_put_super(struct super_block *);
extern void ext_write_super(struct super_block *);
......
......@@ -5,6 +5,7 @@
* extended file system inode data in memory
*/
struct ext_inode_info {
unsigned long i_data[16];
};
#endif
......@@ -15,20 +15,20 @@
/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
*
* 0 - unused (nodev)
* 1 - /dev/mem
* 2 - /dev/fd
* 3 - /dev/hd
* 4 - /dev/ttyx
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
* 8 - /dev/sd
* 9 - /dev/st
* 0 - unused (nodev)
* 1 - /dev/mem
* 2 - /dev/fd
* 3 - /dev/hd
* 4 - /dev/ttyx
* 5 - /dev/tty
* 6 - /dev/lp
* 7 -
* 8 - /dev/sd
* 9 - /dev/st
* 10 - mice
* 11 - scsi cdrom
*/
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3 || (x)==8)
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
......@@ -47,16 +47,6 @@ extern void buffer_init(void);
#define NULL ((void *) 0)
#endif
#define PIPE_READ_WAIT(inode) ((inode).i_wait)
#define PIPE_WRITE_WAIT(inode) ((inode).i_wait2)
#define PIPE_HEAD(inode) ((inode).i_data[0])
#define PIPE_TAIL(inode) ((inode).i_data[1])
#define PIPE_READERS(inode) ((inode).i_data[2])
#define PIPE_WRITERS(inode) ((inode).i_data[3])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#define NIL_FILP ((struct file *)0)
#define SEL_IN 1
#define SEL_OUT 2
......@@ -113,6 +103,7 @@ struct buffer_head {
struct buffer_head * b_reqnext; /* request queue */
};
#include <linux/pipe_fs_i.h>
#include <linux/minix_fs_i.h>
#include <linux/ext_fs_i.h>
#include <linux/msdos_fs_i.h>
......@@ -131,11 +122,9 @@ struct inode {
time_t i_ctime;
unsigned long i_blksize;
unsigned long i_blocks;
unsigned long i_data[16];
struct inode_operations * i_op;
struct super_block * i_sb;
struct wait_queue * i_wait;
struct wait_queue * i_wait2; /* for pipes */
struct file_lock *i_flock;
unsigned short i_count;
unsigned short i_flags;
......@@ -146,6 +135,7 @@ struct inode {
unsigned char i_seek;
unsigned char i_update;
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
struct ext_inode_info ext_i;
struct msdos_inode_info msdos_i;
......
#ifndef _LINUX_KD_H
#define _LINUX_KD_H
/* 0x4B is 'K', to avoid collision with termios and vt */
#define SWAPMONO 0x4B00 /* use mca as output device */
#define SWAPCGA 0x4B01 /* use cga as output device */
#define SWAPEGA 0x4B02 /* use ega as output device */
#define SWAPVGA 0x4B03 /* use vga as output device */
#define CONS_CURRENT 0x4B04 /* return current output device */
#define MONO 0x01
#define CGA 0x02
#define EGA 0x03
#define SW_B40x25 0x4B05 /* 40x25 mono text (cga/ega) */
#define SW_C40x25 0x4B06 /* 40x24 color text (cga/ega) */
#define SW_B80x25 0x4B07 /* 80x25 mono text (cga/ega) */
#define SW_C80x25 0x4B08 /* 80x25 color text (cga/ega) */
#define SW_BG320 0x4B09 /* 320x200 mono graphics (cga/ega) */
#define SW_CG320 0x4B0A /* 320x200 color graphics (cga/ega) */
#define SW_BG640 0x4B0B /* 640x200 mono graphics (cga/ega) */
#define SW_CG320_D 0x4B0C /* 320x200 graphics (ega mode d) */
#define SW_CG640_E 0x4B0D /* 640x200 graphics (ega mode e) */
#define SW_EGAMONOAPA 0x4B0E /* 640x350 graphics (ega mode f) */
#define SW_ENH_MONOAPA2 0x4B0F /* 640x350 graphics extd mem (ega mode f*) */
#define SW_CG640x350 0x4B10 /* 640x350 graphics (ega mode 10) */
#define SW_ENH_CG640 0x4B11 /* 640x350 graphics extd mem (ega mode 10*) */
#define SW_EGAMONO80x25 0x4B12 /* 80x25 mono text (ega mode 7) */
#define SW_ENHB40x25 0x4B13 /* enhanced 40x25 mono text (ega) */
#define SW_ENHC40x25 0x4B14 /* enhanced 40x25 color text (ega) */
#define SW_ENHB80x25 0x4B15 /* enhanced 80x25 mono text (ega) */
#define SW_ENHC80x25 0x4B16 /* enhanced 80x25 color text (ega) */
#define SW_ENHB80x43 0x4B17 /* enhanced 80x43 mono text (ega) */
#define SW_ENHC80x43 0x4B18 /* enhanced 80x43 color text (ega) */
#define SW_MCAMODE 0x4B19 /* reinit mca */
#define SW_ATT640 0x4B1A /* 640x400 16color */
/* should add more vga modes, etc */
#define CONS_GET 0x4B1B /* get current display mode */
#define M_B40x25 0 /* 40x25 mono (cga/ega) */
#define M_C40x25 1 /* 40x25 color (cga/ega) */
#define M_B80x25 2 /* 80x25 mono (cga/ega) */
#define M_C80x25 3 /* 80x25 color (cga/ega) */
#define M_BG320 4 /* 320x200 mono (cga/ega) */
#define M_CG320 5 /* 320x200 color (cga/ega) */
#define M_BG640 6 /* 640x200 mono (cga/ega) */
#define M_EGAMONO80x25 7 /* 80x25 mono (ega) */
#define M_CG320_D 13 /* ega mode d */
#define M_CG640_E 14 /* ega mode e */
#define M_EFAMONOAPA 15 /* ega mode f */
#define M_CG640x350 16 /* ega mode 10 */
#define M_ENHMONOAPA2 17 /* ega mode f with ext mem */
#define M_ENH_CG640 18 /* ega mode 10* */
#define M_ENH_B40x25 19 /* ega enh 40x25 mono */
#define M_ENH_C40x25 20 /* ega enh 40x25 color */
#define M_ENH_B80x25 21 /* ega enh 80x25 mono */
#define M_ENH_C80x25 22 /* ega enh 80x25 color */
#define M_ENH_B80x43 0x70 /* ega enh 80x43 mono */
#define M_ENH_C80x43 0x71 /* ega enh 80x43 color */
#define M_MCA_MODE 0xff /* monochrome adapter mode */
#define MCA_GET 0x4B1C /* get mca display mode */
#define CGA_GET 0x4B1D /* get cga display mode */
#define EGA_GET 0x4B1E /* get ega display mode */
#define MAPCONS 0x4B1F /* map current video mem into address space */
#define MAPMONO 0x4B20 /* map mca video mem into address space */
#define MAPCGA 0x4B21 /* map cga video mem into address space */
#define MAPEGA 0x4B22 /* map ega video mem into address space */
#define MAPVGA 0x4B23 /* map vga video mem into address space */
struct port_io_struc {
char dir; /* direction in vs out */
unsigned short port;
char data;
};
#define IN_ON_PORT 0x00
#define OUT_ON_PORT 0x01
struct port_io_arg {
struct port_io_struc args[4];
};
#define MCAIO 0x4B24 /* i/o to mca video board */
#define CGAIO 0x4B25 /* i/o to cga video board */
#define EGAIO 0x4B26 /* i/o to ega video board */
#define VGAIO 0x4B27 /* i/o to vga video board */
#define GIO_FONT8x8 0x4B28 /* gets current 8x8 font used */
#define PIO_FONT8x8 0x4B29 /* use supplied 8x8 font */
#define GIO_FONT8x14 0x4B2A /* gets current 8x14 font used */
#define PIO_FONT8x14 0x4B2B /* use supplied 8x14 font */
#define GIO_FONT8x16 0x4B2C /* gets current 8x16 font used */
#define PIO_FONT8x16 0x4B2D /* use supplied 8x16 font */
#define MKDIOADDR 32 /* io bitmap size from <linux/sched.h> */
struct kd_disparam {
long type; /* type of display */
char *addr; /* display mem address */
ushort ioaddr[MKDIOADDR]; /* valid i/o addresses */
};
#define KDDISPTYPE 0x4B2E /* gets display info */
#define KD_MONO 0x01
#define KD_HERCULES 0x02
#define KD_CGA 0x03
#define KD_EGA 0x04
#define KIOCSOUND 0x4B2F /* start sound generation (0 for off) */
#define KDMKTONE 0x4B30 /* generate tone */
#define KDGETLED 0x4B31 /* return current led flags */
#define KDSETLED 0x4B32 /* set current led flags */
#define LED_SCR 0x01 /* scroll lock */
#define LED_CAP 0x04 /* caps lock */
#define LED_NUM 0x02 /* num lock */
#define KDGKBTYPE 0x4B33 /* get keyboard type */
#define KB_84 0x01
#define KB_101 0x02
#define KB_OTHER 0x03
#define KDADDIO 0x4B34 /* add i/o port as valid */
#define KDDELIO 0x4B35 /* del i/o port as valid */
#define KDENABIO 0x4B36 /* enable i/o to video board */
#define KDDISABIO 0x4B37 /* disable i/o to video board */
struct kd_quemode {
int qsize; /* desired # elem in queue */
int signo; /* signal to send when queue not empty */
char *qaddr; /* user virt addr of queue */
};
#define KDQUEMODE 0x4B38 /* enable/disable special queue mode */
#define KDSBORDER 0x4B39 /* set screen boarder in ega text mode */
#define KDSETMODE 0x4B3A /* set text/grahics mode */
#define KD_TEXT 0x00
#define KD_GRAPHICS 0x01
#define KD_TEXT0 0x02 /* ? */
#define KD_TEXT1 0x03 /* ? */
#define KDGETMODE 0x4B3B /* get current mode */
struct kd_memloc {
char *vaddr; /* virt addr to map to */
char *physaddr; /* phys addr to map from */
long length; /* number of bytes */
long ioflg; /* enable i/o if set */
};
#define KDMAPDISP 0x4B3C /* map display into address space */
#define KDUNMAPDISP 0x4B3D /* unmap display from address space */
#define KDVDCTYPE 0x4B3E /* return vdc controller/display info */
#define KIOCINFO 0x4B3F /* tell what the device is */
typedef char scrnmap_t;
#define E_TABSZ 256
#define GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */
#define PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */
#define GIO_ATTR 0x4B42 /* get screen attributes */
#define GIO_COLOR 0x4B43 /* return nonzero if display is color */
#define K_RAW 0x00
#define K_XLATE 0x01
#define KDGKBMODE 0x4B44 /* gets current keyboard mode */
#define KDSKBMODE 0x4B45 /* sets current keyboard mode */
struct kbentry {
u_char kb_table;
u_char kb_index;
u_char kb_value;
};
#define K_NORMTAB 0x00
#define K_SHIFTTAB 0x01
#define K_ALTTAB 0x02
#define K_ALTSHIFTTAB 0x03
#define K_SRQTAB 0x04
#define KDGKBENT 0x4B46 /* gets one entry in translation table */
#define KDSKBENT 0x4B47 /* sets one entry in translation table */
#endif /* _LINUX_KD_H */
......@@ -5,6 +5,7 @@
* minix fs inode data in memory
*/
struct minix_inode_info {
unsigned short i_data[16];
};
#endif
#ifndef _LINUX_MKTIME_H
#define _LINUX_MKTIME_H
struct mktime {
int sec;
int min;
int hour;
int day;
int mon;
int year;
};
#endif
#ifndef _LINUX_MMAN_H
#define _LINUX_MMAN_H
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
#define PROT_NONE 0x0 /* page can not be accessed */
#define MAP_SHARED 1 /* Share changes */
#define MAP_PRIVATE 2 /* Changes are private */
#define MAP_TYPE 0xf /* Mask for type of mapping */
#define MAP_FIXED 0x10 /* Interpret addr exactly */
#endif /* _LINUX_MMAN_H */
......@@ -3,6 +3,7 @@
#define BUSMOUSE_MINOR 0
#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2
long mouse_init(long);
......
#ifndef _LINUX_PIPE_FS_I_H
#define _LINUX_PIPE_FS_I_H
struct pipe_inode_info {
struct wait_queue * read_wait;
struct wait_queue * write_wait;
char * base;
unsigned int head;
unsigned int tail;
unsigned int readers;
unsigned int writers;
};
#define PIPE_READ_WAIT(inode) ((inode).u.pipe_i.read_wait)
#define PIPE_WRITE_WAIT(inode) ((inode).u.pipe_i.write_wait)
#define PIPE_BASE(inode) ((inode).u.pipe_i.base)
#define PIPE_HEAD(inode) ((inode).u.pipe_i.head)
#define PIPE_TAIL(inode) ((inode).u.pipe_i.tail)
#define PIPE_READERS(inode) ((inode).u.pipe_i.readers)
#define PIPE_WRITERS(inode) ((inode).u.pipe_i.writers)
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#endif
......@@ -160,6 +160,7 @@ struct task_struct {
unsigned short rss; /* number of resident pages */
char comm[8];
struct vm86_struct * vm86_info;
unsigned long screen_bitmap;
/* file system info */
int link_count;
int tty; /* -1 if no tty, so it must be signed */
......@@ -211,7 +212,7 @@ struct task_struct {
/* math */ 0, \
/* rss */ 2, \
/* comm */ "swapper", \
/* vm86_info */ NULL, \
/* vm86_info */ NULL, 0, \
/* fs info */ 0,-1,0022,NULL,NULL,NULL, \
/* libraries */ { { NULL, 0, 0}, }, 0, \
/* filp */ {NULL,}, 0, \
......
......@@ -249,6 +249,8 @@ extern void change_speed(unsigned int line);
extern void send_break(unsigned int line);
extern int get_serial_info(unsigned int, struct serial_struct *);
extern int set_serial_info(unsigned int, struct serial_struct *);
extern int get_modem_info(unsigned int, unsigned int *);
extern int set_modem_info(unsigned int, unsigned int, unsigned int *);
/* pty.c */
......
......@@ -42,14 +42,15 @@ struct vm86_regs {
long gs;
};
/*
* flags isn't even used yet: it's just there as an example of
* what kind of information we might want to give sys_vm86() (or
* want it to return to us).
*/
struct vm86_struct {
struct vm86_regs regs;
unsigned long flags;
unsigned long screen_bitmap;
};
/*
* flags masks
*/
#define VM86_SCREEN_BITMAP 1
#endif
#ifndef _LINUX_VT_H
#define _LINUX_VT_H
/* 0x56 is 'V', to avoid collision with termios and kd */
#define VT_OPENQRY 0x5600 /* find available vt */
struct vt_mode {
char mode; /* vt mode */
char waitv; /* if set, hang on writes if not active */
short relsig; /* signal to raise on release req */
short acqsig; /* signal to raise on acquisition */
short frsig; /* unused (set to 0) */
};
#define VT_GETMODE 0x5601 /* get mode of active vt */
#define VT_SETMODE 0x5602 /* set mode of active vt */
#define VT_AUTO 0x00 /* auto vt switching */
#define VT_PROCESS 0x01 /* process controls switching */
struct vt_stat {
ushort v_active; /* active vt */
ushort v_signal; /* signal to send */
ushort v_state; /* vt bitmask */
};
#define VT_GETSTATE 0x5603 /* get global vt state info */
#define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */
#define VT_RELDISP 0x5605 /* release display */
#define VT_ACTIVATE 0x5606 /* make vt active */
#endif /* _LINUX_VT_H */
......@@ -5,11 +5,11 @@
*/
#include <stdarg.h>
#include <time.h>
#include <asm/system.h>
#include <asm/io.h>
#include <linux/mktime.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/config.h>
......@@ -63,8 +63,7 @@ extern long chr_dev_init(long,long);
extern void floppy_init(void);
extern void sock_init(void);
extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm);
extern void malloc_grab_pages(void);
extern long kernel_mktime(struct mktime * time);
#ifdef CONFIG_SCSI
extern void scsi_dev_init(void);
......@@ -106,23 +105,23 @@ inb_p(0x71); \
static void time_init(void)
{
struct tm time;
struct mktime time;
do {
time.tm_sec = CMOS_READ(0);
time.tm_min = CMOS_READ(2);
time.tm_hour = CMOS_READ(4);
time.tm_mday = CMOS_READ(7);
time.tm_mon = CMOS_READ(8);
time.tm_year = CMOS_READ(9);
} while (time.tm_sec != CMOS_READ(0));
BCD_TO_BIN(time.tm_sec);
BCD_TO_BIN(time.tm_min);
BCD_TO_BIN(time.tm_hour);
BCD_TO_BIN(time.tm_mday);
BCD_TO_BIN(time.tm_mon);
BCD_TO_BIN(time.tm_year);
time.tm_mon--;
time.sec = CMOS_READ(0);
time.min = CMOS_READ(2);
time.hour = CMOS_READ(4);
time.day = CMOS_READ(7);
time.mon = CMOS_READ(8);
time.year = CMOS_READ(9);
} while (time.sec != CMOS_READ(0));
BCD_TO_BIN(time.sec);
BCD_TO_BIN(time.min);
BCD_TO_BIN(time.hour);
BCD_TO_BIN(time.day);
BCD_TO_BIN(time.mon);
BCD_TO_BIN(time.year);
time.mon--;
startup_time = kernel_mktime(&time);
}
......@@ -184,7 +183,6 @@ void start_kernel(void)
buffer_init();
time_init();
floppy_init();
malloc_grab_pages();
sock_init();
sti();
#ifdef CONFIG_SCSI
......
......@@ -45,7 +45,7 @@ clean:
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
$(CPP) -M *.c >> tmp_make
cp tmp_make Makefile
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
......
......@@ -37,7 +37,7 @@ clean:
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
$(CPP) -M *.c >> tmp_make
cp tmp_make Makefile
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep); done
......
#ifndef _BLK_H
#define _BLK_H
#define NR_BLK_DEV 10
#define NR_BLK_DEV 12
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
......@@ -133,7 +133,16 @@ extern void set_device_ro(int dev,int flag);
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif
#elif (MAJOR_NR == 11)
/* scsi CD-ROM */
#define DEVICE_NAME "CD-ROM"
#define DEVICE_INTR do_sr
#define DEVICE_REQUEST do_sr_request
#define DEVICE_NR(device) (MINOR(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#else
/* unknown blk device */
#error "unknown blk device"
......
......@@ -75,9 +75,6 @@ static int seek = 0;
extern unsigned char current_DOR;
#define immoutb_p(val,port) \
__asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
#define TYPE(x) ((x)>>2)
#define DRIVE(x) ((x)&0x03)
......@@ -343,12 +340,15 @@ __asm__("cld ; rep ; movsl" \
static void setup_DMA(void)
{
unsigned long addr,count;
unsigned char dma_code;
dma_code = DMA_WRITE;
if (command == FD_READ)
dma_code = DMA_READ;
if (command == FD_FORMAT) {
addr = (long) tmp_floppy_area;
count = floppy->sect*4;
}
else {
} else {
addr = (long) CURRENT->buffer;
count = 1024;
}
......@@ -362,31 +362,30 @@ static void setup_DMA(void)
if (command == FD_WRITE)
copy_buffer(CURRENT->buffer,tmp_floppy_area);
}
/* mask DMA 2 */
cli();
#ifndef HHB_SYSMACROS
immoutb_p(4|2,10);
/* mask DMA 2 */
outb_p(4|2,10);
/* output command byte. I don't know why, but everyone (minix, */
/* sanches & canton) output this twice, first to 12 then to 11 */
__asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"
"outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::
"a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE)));
outb_p(dma_code,12);
outb_p(dma_code,11);
/* 8 low bits of addr */
immoutb_p(addr,4);
outb_p(addr,4);
addr >>= 8;
/* bits 8-15 of addr */
immoutb_p(addr,4);
outb_p(addr,4);
addr >>= 8;
/* bits 16-19 of addr */
immoutb_p(addr,0x81);
outb_p(addr,0x81);
/* low 8 bits of count-1 */
count--;
immoutb_p(count,5);
outb_p(count,5);
count >>= 8;
/* high 8 bits of count-1 */
immoutb_p(count,5);
outb_p(count,5);
/* activate DMA 2 */
immoutb_p(0|2,10);
outb_p(0|2,10);
#else /* just to show off my macros -- hhb */
DISABLE_DMA(DMA2);
CLEAR_DMA_FF(DMA2);
......
......@@ -162,7 +162,7 @@ static void make_request(int major,int rw, struct buffer_head * bh)
}
repeat:
cli();
if ((major == 3 || major == 8 )&& (req = blk_dev[major].current_request)) {
if ((major == 3 || major == 8 || major == 11)&& (req = blk_dev[major].current_request)) {
while (req = req->next) {
if (req->dev == bh->b_dev &&
!req->waiting &&
......
......@@ -22,10 +22,11 @@ LOWLEVELSSRC = seagate2.s
LOWLEVELCSRC = aha1542.c fdomain.c seagate.c ultrastor.c 7000fasst.c
LOWLEVELHSRC = aha1542.h fdomain.h seagate.h ultrastor.h 7000fasst.o
CSRC = hosts.c sd.c sd_ioctl.c st.c st_ioctl.c scsi.c scsi_ioctl.c $(LOWLEVELCSRC)
HSRC = hosts.h sd.h st.h scsi.h scsi_ioctl.h $(LOWLEVELHSRC)
CSRC = hosts.c sd.c sd_ioctl.c st.c st_ioctl.c sr.c sr_ioctl.c scsi.c scsi_ioctl.c $(LOWLEVELCSRC)
HSRC = hosts.h sd.h st.h sr.h sr_ioctl.h scsi.h scsi_ioctl.h $(LOWLEVELHSRC)
OBJS = scsi.o hosts.o scsi_ioctl.o sd.o sd_ioctl.o st.o st_ioctl.o \
sr.o sr_ioctl.o \
aha1542.o fdomain.o seagate.o seagate2.o ultrastor.o 7000fasst.o
all: scsi.a
......
......@@ -188,7 +188,7 @@ int aha1542_test_port(void)
/* What's this little function for? */
char *aha1542_info(void)
{
static char buffer[] = "Adaptec 1542";
static char buffer[] = ""; /* looks nicer without anything here */
return buffer;
}
......@@ -200,6 +200,8 @@ void aha1542_intr_handle(void)
do_done = NULL;
#ifdef DEBUG
{
int flag = inb(INTRFLAGS);
printk("aha1542_intr_handle: ");
if (!(flag&ANYINTR)) printk("no interrupt?");
if (flag&MBIF) printk("MBIF ");
......@@ -209,6 +211,7 @@ void aha1542_intr_handle(void)
printk("status %02x\n", inb(STATUS));
if (ccb.tarstat|ccb.hastat)
printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
};
#endif
aha1542_intr_reset();
if (!my_done) {
......@@ -236,9 +239,11 @@ void aha1542_intr_handle(void)
if (ccb.tarstat == 2) {
int i;
DEB(printk("aha1542_intr_handle: sense:"));
#ifdef DEBUG
for (i = 0; i < 12; i++)
printk("%02x ", ccb.cdb[ccb.cdblen+i]);
printk("\n");
#endif
/*
DEB(printk("aha1542_intr_handle: buf:"));
for (i = 0; i < bufflen; i++)
......@@ -259,6 +264,12 @@ int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int buffle
DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
if(*cmd == REQUEST_SENSE){
memcpy(buff, &ccb.cdb[ccb.cdblen], bufflen);
done(aha1542_host, 0);
return 0;
};
#ifdef DEBUG
if (*cmd == READ_10 || *cmd == WRITE_10)
i = xscsi2int(cmd+2);
......@@ -387,10 +398,10 @@ int aha1542_detect(int hostnum)
aha1542_intr_reset();
}
aha1542_stat();
DEB(aha1542_stat());
setup_mailboxes();
aha1542_stat();
DEB(aha1542_stat());
DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
call_buh();
......
......@@ -30,14 +30,19 @@
#include "st.h"
#endif
#ifdef CONFIG_BLK_DEV_SR
#include "sr.h"
#endif
/*
static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
*/
#define INTERNAL_ERROR (printk ("Internal error in file %s, line %s.\n", __FILE__, __LINE__), panic(""))
#define INTERNAL_ERROR (printk ("Internal error in file %s, line %d.\n", __FILE__, __LINE__), panic(""))
static void scsi_done (int host, int result);
static void update_timeout (void);
static void print_inquiry(unsigned char *data);
static int time_start;
static int time_elapsed;
......@@ -214,6 +219,13 @@ static void scan_scsis (void)
scsi_tapes[NR_ST].device = &scsi_devices[NR_SCSI_DEVICES];
#endif
break;
case TYPE_ROM:
printk("Detected scsi CD-ROM at host %d, ID %d, lun %d \n", host_nr, dev, lun);
#ifdef CONFIG_BLK_DEV_SR
if (!(maxed = (NR_SR >= MAX_SR)))
scsi_CDs[NR_SR].device = &scsi_devices[NR_SCSI_DEVICES];
#endif
break;
default :
#ifdef DEBUG
printk("Detected scsi disk at host %d, ID %d, lun %d \n", host_nr, dev, lun);
......@@ -224,11 +236,20 @@ static void scan_scsis (void)
#endif
}
print_inquiry(scsi_result);
if (maxed)
{
printk ("scsi : already have detected maximum number of SCSI %ss Unable to \n"
"add drive at SCSI host %s, ID %d, LUN %d\n\r", (type == TYPE_TAPE) ?
"tape" : "disk", scsi_hosts[host_nr].name,
printk ("Already have detected "
"maximum number of SCSI "
"%ss Unable to \n"
"add drive at SCSI host "
"%s, ID %d, LUN %d\n\r",
(type == TYPE_TAPE) ?
"tape" :
(type == TYPE_DISK) ?
"disk" : "CD-ROM",
scsi_hosts[host_nr].name,
dev, lun);
type = -1;
break;
......@@ -246,7 +267,7 @@ for (; *p != ' '; ++p);
*p = 0;
printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
(type == TYPE_TAPE) ? 't' : 'd',
(type == TYPE_TAPE) ? 't' : ((type == TYPE_ROM) ? 'r' : 'd'),
(type == TYPE_TAPE) ?
#ifdef CONFIG_BLK_DEV_ST
NR_ST
......@@ -254,11 +275,20 @@ printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
-1
#endif
:
(type == TYPE_ROM ?
#ifdef CONFIG_BLK_DEV_SR
NR_SR
#else
-1
#endif
:
#ifdef CONFIG_BLK_DEV_SD
NR_SD
#else
-1
#endif
)
,host_nr , dev, lun, p);
if (type == TYPE_TAPE)
#ifdef CONFIG_BLK_DEV_ST
......@@ -267,11 +297,17 @@ printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
;
#endif
else
else if (type == TYPE_DISK)
#ifdef CONFIG_BLK_DEV_SD
++NR_SD;
#else
;
#endif
else
#ifdef CONFIG_BLK_DEV_SR
++NR_SR;
#else
;
#endif
}
++slave;
......@@ -289,17 +325,22 @@ printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
"%d tape%s "
#endif
"total.\n",
#ifdef CONFIG_BLK_DEV_SR
"%d CD-ROM drive%s "
#endif
"total.\n"
#ifdef CONFIG_BLK_DEV_SD
NR_SD, (NR_SD != 1) ? "s" : ""
#ifdef CONFIG_BLK_DEV_ST
,
#endif
, NR_SD, (NR_SD != 1) ? "s" : ""
#endif
#ifdef CONFIG_BLK_DEV_ST
NR_ST, (NR_ST != 1) ? "s" : ""
, NR_ST, (NR_ST != 1) ? "s" : ""
#endif
#ifdef CONFIG_BLK_DEV_SR
, NR_SR, (NR_SR != 1) ? "s" : ""
#endif
);
in_scan = 0;
......@@ -388,7 +429,6 @@ update_timeout();
"bufflen = %d, done = %08x)\n", host, target, cmnd, buffer, bufflen, done);
#endif
if (scsi_hosts[host].can_queue)
{
#ifdef DEBUG
......@@ -557,8 +597,8 @@ static void reset (int host)
static int check_sense (int host)
{
if (((sense_buffer[0] & 0x70) >> 4) == 7)
switch (sense_buffer[2] & 0xf)
if (((last_cmnd[host].sense_buffer[0] & 0x70) >> 4) == 7)
switch (last_cmnd[host].sense_buffer[2] & 0xf)
{
case NO_SENSE:
case RECOVERED_ERROR:
......@@ -600,6 +640,7 @@ static void scsi_done (int host, int result)
#define FINISHED 0
#define MAYREDO 1
#define REDO 3
#define PENDING 4
#ifdef DEBUG
printk("In scsi_done(host = %d, result = %06x)\n", host, result);
......@@ -705,6 +746,7 @@ static void scsi_done (int host, int result)
#endif
scsi_request_sense (host, last_cmnd[host].target, last_cmnd[host].lun);
status = PENDING;
break;
case CONDITION_GOOD:
......@@ -786,6 +828,7 @@ static void scsi_done (int host, int result)
switch (status)
{
case FINISHED:
case PENDING:
break;
case MAYREDO:
......@@ -836,7 +879,7 @@ static void scsi_done (int host, int result)
#undef FINISHED
#undef REDO
#undef MAYREDO
#undef PENDING
}
/*
......@@ -1056,5 +1099,59 @@ void scsi_dev_init (void)
#ifdef CONFIG_BLK_DEV_ST
st_init(); /* init scsi tapes */
#endif
#ifdef CONFIG_BLK_DEV_SR
sr_init();
#endif
}
#endif
static void print_inquiry(unsigned char *data)
{
int i;
printk(" Vendor:");
for (i = 8; i < 15; i++)
{
if (data[i] >= 20)
printk("%c", data[i]);
else
printk(" ");
}
printk(" Model:");
for (i = 16; i < 31; i++)
{
if (data[i] >= 20)
printk("%c", data[i]);
else
printk(" ");
}
printk(" Rev:");
for (i = 32; i < 35; i++)
{
if (data[i] >= 20)
printk("%c", data[i]);
else
printk(" ");
}
printk("\n");
i = data[0] & 0x1f;
printk(" Type: %s ", i == 0x00 ? "Direct-Access " :
i == 0x01 ? "Sequential-Access" :
i == 0x02 ? "Printer " :
i == 0x03 ? "Processor " :
i == 0x04 ? "WORM " :
i == 0x05 ? "CD-ROM " :
i == 0x06 ? "Scanner " :
i == 0x07 ? "Optical Device " :
i == 0x08 ? "Medium Changer " :
i == 0x09 ? "Communications " :
"Unknown " );
printk("ANSI SCSI revision: %02x\n", data[2] & 0x07);
}
......@@ -254,6 +254,9 @@ extern void scsi_dev_init (void);
/*
You guesed it. This sends a command to the selected SCSI host
extern void print_inquiry(unsigned char *data);
*/
......
......@@ -38,7 +38,7 @@ struct hd_struct sd[MAX_SD << 4];
int NR_SD=0;
Scsi_Disk rscsi_disks[MAX_SD];
static int sd_sizes[MAX_SD << 4];
static int sd_sizes[MAX_SD << 4] = {0, };
static int this_count;
static int the_result;
......@@ -56,9 +56,7 @@ static struct gendisk sd_gendisk;
static void sd_geninit (void) {
int i;
for (i = 0; i < NR_SD; ++i)
sd_sizes[i << 4] =
(sd[i << 4].nr_sects = rscsi_disks[i].capacity) >>
(BLOCK_SIZE_BITS - 9);
sd[i << 4].nr_sects = rscsi_disks[i].capacity;
sd_gendisk.nr_real = NR_SD;
}
......@@ -414,9 +412,8 @@ void sd_init(void)
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blk_size[MAJOR_NR] = sd_sizes;
blkdev_fops[MAJOR_NR] = &sd_fops;
blkdev_fops[MAJOR_NR] = &sd_fops;
sd_gendisk.next = gendisk_head;
gendisk_head = &sd_gendisk;
}
}
#endif
/*
* sr.c by David Giller
*
* adapted from:
* sd.c Copyright (C) 1992 Drew Eckhardt
* Linux scsi disk driver by
* Drew Eckhardt
*
* <drew@colorado.edu>
*/
#include <linux/config.h>
#ifdef CONFIG_BLK_DEV_SR
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include "scsi.h"
#include "sr.h"
#define MAJOR_NR 11
#include "../blk.h"
#define MAX_RETRIES 0
#define SR_TIMEOUT 200
int NR_SR=0;
Scsi_CD scsi_CDs[MAX_SR];
static int sr_sizes[MAX_SR << 4];
static unsigned long int this_count;
struct block_buffer
{
unsigned block;
unsigned start;
unsigned use:1;
unsigned char buffer[2048];
};
static struct block_buffer bb[MAX_SR];
static int sr_result;
static int sr_open(struct inode *, struct file *);
extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
static void sr_release(struct inode * inode, struct file * file)
{
sync_dev(inode->i_rdev);
}
static struct file_operations sr_fops =
{
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
NULL, /* select */
sr_ioctl, /* ioctl */
sr_open, /* no special open code */
sr_release /* release */
};
/*
* The sense_buffer is where we put data for all mode sense commands performed.
*/
static unsigned char sense_buffer[255];
/*
* rw_intr is the interrupt routine for the device driver. It will be notified on the
* end of a SCSI read / write, and will take on of several actions based on success or failure.
*/
static void rw_intr (int host, int result)
{
if (SR_HOST != host)
{
panic ("sr.o : rw_intr() recieving interrupt for different host.");
}
if (!result)
{ /* No error */
if (bb[DEVICE_NR(CURRENT->dev)].use)
{
memcpy((char *)CURRENT->buffer,
bb[DEVICE_NR(CURRENT->dev)].buffer +
(bb[DEVICE_NR(CURRENT->dev)].start << 9),
this_count << 9);
}
CURRENT->nr_sectors -= this_count;
#ifdef DEBUG
printk("(%x %x %x) ",CURRENT->bh, CURRENT->nr_sectors,
this_count);
#endif
if (CURRENT->nr_sectors)
{
CURRENT->sector += this_count;
CURRENT->errors = 0;
if (!CURRENT->bh)
{
(char *) CURRENT->buffer += this_count << 9;
} else {
end_request(1);
do_sr_request();
}
}
else
{
end_request(1); /* All done */
do_sr_request();
}
}
/* We only come through here if we have an error of some kind */
if (driver_byte(result) != 0) {
bb[DEVICE_NR(CURRENT->dev)].block = -1;
if ((sense_buffer[0] & 0x7f) == 0x70) {
if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
/* detected disc change. set a bit and quietly refuse */
/* further access. */
scsi_CDs[DEVICE_NR(CURRENT->dev)].changed = 1;
end_request(0);
return;
}
}
if (sense_buffer[2] == ILLEGAL_REQUEST) {
printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
if (scsi_CDs[DEVICE_NR(CURRENT->dev)].ten) {
scsi_CDs[DEVICE_NR(CURRENT->dev)].ten = 0;
do_sr_request();
result = 0;
return;
} else {
end_request(0);
do_sr_request(); /* Do next request */
return;
}
}
if (sense_buffer[2] == NOT_READY) {
printk("CDROM not ready. Make sure you have a disc in the drive.\n");
end_request(0);
do_sr_request(); /* Do next request */
return;
};
}
/* We only get this far if we have an error we have not recognized */
if(result) {
printk("SCSI CD error : host %d id %d lun %d return code = %03x\n",
scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no,
scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id,
scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun,
result);
if (status_byte(result) == CHECK_CONDITION)
printk("\tSense class %x, sense error %x, extended sense %x\n",
sense_class(sense_buffer[0]),
sense_error(sense_buffer[0]),
sense_buffer[2] & 0xf);
end_request(0);
do_sr_request();
}
}
static int sr_open(struct inode * inode, struct file * filp)
{
if (filp->f_mode)
check_disk_change(inode->i_rdev);
return 0;
}
/*
* do_sr_request() is the request handler function for the sr driver. Its function in life
* is to take block device requests, and translate them to SCSI commands.
*/
void do_sr_request (void)
{
unsigned int dev, block, realcount;
unsigned char cmd[10], *buffer, tries;
tries = 2;
repeat:
INIT_REQUEST;
dev = MINOR(CURRENT->dev);
block = CURRENT->sector;
bb[dev].start = block % 4;
block = block / 4;
if (dev >= NR_SR)
{
/* printk("CD-ROM request error: invalid device.\n"); */
end_request(0);
tries = 2;
goto repeat;
}
if (!scsi_CDs[dev].use)
{
/* printk("CD-ROM request error: device marked not in use.\n"); */
end_request(0);
tries = 2;
goto repeat;
}
if (scsi_CDs[dev].changed)
{
/*
* quietly refuse to do anything to a changed disc until the changed bit has been reset
*/
/* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */
end_request(0);
tries = 2;
goto repeat;
}
if (!CURRENT->bh)
this_count = CURRENT->nr_sectors;
else
this_count = (CURRENT->bh->b_size / 512);
if (bb[dev].start)
{
bb[dev].use = 1;
this_count = ((this_count > 4 - bb[dev].start) ?
(4 - bb[dev].start) : (this_count));
if (bb[dev].block == block)
{
rw_intr(SR_HOST, 0);
return;
}
buffer = bb[dev].buffer;
bb[dev].block = block;
}
else if (this_count < 4)
{
bb[dev].use = 1;
if (bb[dev].block == block)
{
rw_intr(SR_HOST, 0);
return;
}
buffer = bb[dev].buffer;
bb[dev].block = block;
}
else
{
this_count -= this_count % 4;
buffer = CURRENT->buffer;
bb[dev].use = 0;
}
realcount = (this_count + 3) / 4;
switch (CURRENT->cmd)
{
case WRITE:
end_request(0);
goto repeat;
break;
case READ :
cmd[0] = READ_6;
break;
default :
printk ("Unknown sr command %d\r\n", CURRENT->cmd);
panic("");
}
cmd[1] = (SR_LUN << 5) & 0xe0;
if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten)
{
if (realcount > 0xffff)
{
realcount = 0xffff;
this_count = realcount * 4;
}
cmd[0] += READ_10 - READ_6 ;
cmd[2] = (unsigned char) (block >> 24) & 0xff;
cmd[3] = (unsigned char) (block >> 16) & 0xff;
cmd[4] = (unsigned char) (block >> 8) & 0xff;
cmd[5] = (unsigned char) block & 0xff;
cmd[6] = cmd[9] = 0;
cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
cmd[8] = (unsigned char) realcount & 0xff;
}
else
{
if (realcount > 0xff)
{
realcount = 0xff;
this_count = realcount * 4;
}
cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
cmd[2] = (unsigned char) ((block >> 8) & 0xff);
cmd[3] = (unsigned char) block & 0xff;
cmd[4] = (unsigned char) realcount;
cmd[5] = 0;
}
scsi_do_cmd (SR_HOST, SR_ID, (void *) cmd, buffer, realcount << 11,
rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
}
void sr_init(void)
{
int i;
for (i = 0; i < NR_SR; ++i)
{
scsi_CDs[i].capacity = 0x1fffff;
scsi_CDs[i].sector_size = 2048;
scsi_CDs[i].use = 1;
scsi_CDs[i].ten = 1;
scsi_CDs[i].remap = 1;
scsi_CDs[i].changed = 0;
sr_sizes[i] = scsi_CDs[i].capacity;
bb[i].block = -1;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blk_size[MAJOR_NR] = sr_sizes;
blkdev_fops[MAJOR_NR] = &sr_fops;
}
#endif
/*
* sr.h by David Giller
* CD-ROM disk driver header file
*
* adapted from:
* sd.h Copyright (C) 1992 Drew Eckhardt
* SCSI disk driver header file by
* Drew Eckhardt
*
* <drew@colorado.edu>
*/
#ifndef _SR_H
#define _SR_H
#include "scsi.h"
#define MAX_SR 2
extern int NR_SR;
typedef struct
{
unsigned capacity; /* size in blocks */
unsigned sector_size; /* size in bytes */
Scsi_Device *device;
unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */
unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift*/
unsigned ten:1; /* support ten byte commands */
unsigned remap:1; /* support remapping */
unsigned use:1; /* is this device still supportable */
unsigned changed:1; /* disk changed flag */
} Scsi_CD;
extern Scsi_CD scsi_CDs[MAX_SR];
void sr_init(void);
#define SR_HOST (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no)
#define SR_ID (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id)
#define SR_LUN (scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun)
#endif
#include <linux/config.h>
#ifdef CONFIG_BLK_DEV_SR
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <asm/segment.h>
#include <linux/errno.h>
#include "../blk.h"
#include "scsi.h"
#include "sr.h"
#include <linux/cdrom.h>
#define IOCTL_RETRIES 3
/* The CDROM is fairly slow, so we need a little extra time */
#define IOCTL_TIMEOUT 200
static u_char sr_cmd[10];
static u_char data_buffer[255];
static u_char sense_buffer[255];
static int the_result;
static struct wait_queue *sr_cmd_wait = NULL; /* For waiting until cmd done*/
static u_char sr_lock = 0; /* To make sure that only one person is doing
an ioctl at one time */
static int target;
extern int scsi_ioctl (int dev, int cmd, void *arg);
static void lock_sr_ioctl( void )
{
/* We do not use wakeup here because there could conceivably be three
processes trying to get at the drive simultaneously, and we would
be screwed if that happened.
*/
while (sr_lock);
sr_lock = 1;
}
static void unlock_sr_ioctl( void )
{
sr_lock = 0;
}
static void sr_ioctl_done( int host, int result )
{
the_result = result;
wake_up(&sr_cmd_wait);
}
/* We do our own retries because we want to know what the specific
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
static int do_ioctl( void )
{
int retries = IOCTL_RETRIES;
retry:
the_result = -1;
scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id,
(void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done,
IOCTL_TIMEOUT, (void *) sense_buffer, 0);
while (the_result < 0) sleep_on(&sr_cmd_wait);
if(driver_byte(the_result) != 0 &&
(sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
scsi_CDs[target].changed = 1;
printk("Disc change detected.\n");
};
if (the_result && retries)
{
retries--;
goto retry;
}
/* Minimal error checking. Ignore cases we know about, and report the rest. */
if(driver_byte(the_result) != 0)
switch(sense_buffer[2] & 0xf) {
case UNIT_ATTENTION:
scsi_CDs[target].changed = 1;
printk("Disc change detected.\n");
break;
case NOT_READY: /* This happens if there is no disc in drive */
printk("CDROM not ready. Make sure there is a disc in the drive.\n");
break;
case ILLEGAL_REQUEST:
printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
break;
default:
printk("SCSI CD error: host %d id %d lun %d return code = %03x\n",
scsi_CDs[target].device->host_no,
scsi_CDs[target].device->id,
scsi_CDs[target].device->lun,
the_result);
printk("\tSense class %x, sense error %x, extended sense %x\n",
sense_class(sense_buffer[0]),
sense_error(sense_buffer[0]),
sense_buffer[2] & 0xf);
};
return the_result;
}
/*
* This function checks to see if the media has been changed in the
* CDROM drive. It is possible that we have already sensed a change,
* or the drive may have sensed one and not yet reported it. We must
* be ready for either case. This function always reports the current
* value of the changed bit. If flag is 0, then the changed bit is reset.
* This function could be done as an ioctl, but we would need to have
* an inode for that to work, and we do not always have one.
*/
int check_cdrom_media_change(int full_dev, int flag){
int retval;
lock_sr_ioctl();
target = MINOR(full_dev);
if (target >= NR_SR) {
printk("CD-ROM request error: invalid device.\n");
unlock_sr_ioctl();
return 0;
};
sr_cmd[0] = TEST_UNIT_READY;
sr_cmd[1] = (scsi_CDs[target].device->lun << 5) & 0xe0;
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
retval = do_ioctl();
if(retval){ /* Unable to test, unit probably not ready. This usually
means there is no disc in the drive. Mark as changed,
and we will figure it out later once the drive is
available again. */
scsi_CDs[target].changed = 1;
unlock_sr_ioctl();
return 1; /* This will force a flush, if called from
check_disk_change */
};
retval = scsi_CDs[target].changed;
if(!flag) scsi_CDs[target].changed = 0;
unlock_sr_ioctl();
return retval;
}
int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
{
int dev = inode->i_rdev;
int result;
target = MINOR(dev);
switch (cmd)
{
/* linux-specific */
case CDROMDOORUNLOCK:
lock_sr_ioctl();
sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = SR_REMOVAL_ALLOW;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMDOORLOCK:
lock_sr_ioctl();
sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = SR_REMOVAL_PREVENT;
result = do_ioctl();
unlock_sr_ioctl();
return result;
/* Sun-compatible */
case CDROMPAUSE:
lock_sr_ioctl();
sr_cmd[0] = SCMD_PAUSE_RESUME;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
sr_cmd[8] = 1;
sr_cmd[9] = 0;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMRESUME:
lock_sr_ioctl();
sr_cmd[0] = SCMD_PAUSE_RESUME;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
sr_cmd[8] = 0;
sr_cmd[9] = 0;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMPLAYMSF:
{
struct cdrom_msf msf;
lock_sr_ioctl();
memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = 0;
sr_cmd[3] = msf.cdmsf_min0;
sr_cmd[4] = msf.cdmsf_sec0;
sr_cmd[5] = msf.cdmsf_frame0;
sr_cmd[6] = msf.cdmsf_min1;
sr_cmd[7] = msf.cdmsf_sec1;
sr_cmd[8] = msf.cdmsf_frame1;
sr_cmd[9] = 0;
result = do_ioctl();
unlock_sr_ioctl();
return result;
}
case CDROMPLAYTRKIND:
{
struct cdrom_ti ti;
lock_sr_ioctl();
memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
sr_cmd[0] = SCMD_PLAYAUDIO_TI;
sr_cmd[1] = scsi_CDs[target].device->lun << 5;
sr_cmd[2] = 0;
sr_cmd[3] = 0;
sr_cmd[4] = ti.cdti_trk0;
sr_cmd[5] = ti.cdti_ind0;
sr_cmd[6] = 0;
sr_cmd[7] = ti.cdti_trk1;
sr_cmd[8] = ti.cdti_ind1;
sr_cmd[9] = 0;
result = do_ioctl();
unlock_sr_ioctl();
return result;
}
case CDROMREADTOCHDR:
return -EINVAL;
case CDROMREADTOCENTRY:
return -EINVAL;
case CDROMSTOP:
lock_sr_ioctl();
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 0;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMSTART:
lock_sr_ioctl();
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 1;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMEJECT:
lock_sr_ioctl();
sr_cmd[0] = START_STOP;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = 0x02;
result = do_ioctl();
unlock_sr_ioctl();
return result;
case CDROMVOLCTRL:
return -EINVAL;
case CDROMSUBCHNL:
return -EINVAL;
case CDROMREADMODE2:
return -EINVAL;
case CDROMREADMODE1:
return -EINVAL;
RO_IOCTLS(dev,arg);
default:
return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
}
}
#endif
......@@ -23,8 +23,11 @@ chr_drv.a: $(OBJS)
$(AR) rcs chr_drv.a $(OBJS)
sync
console.o: console.c
$(CC) $(CFLAGS) $(NUM_LOCK) -c -o console.o console.c
keyboard.o: keyboard.c
$(CC) $(CFLAGS) $(KEYBOARD) -c -o keyboard.o keyboard.c
$(CC) $(CFLAGS) $(KEYBOARD) $(NUM_LOCK) -c -o keyboard.o keyboard.c
clean:
rm -f core *.o *.a tmp_make keyboard.s
......
......@@ -17,8 +17,21 @@
* removed assignment chr_fops[10] = &mouse_fops; see mouse.c
* renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
* renamed this file mouse.c => busmouse.c
*
* version 0.1
*
* Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
*
* Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
* 8/28/92
*
* Microsoft Bus Mouse support folded into 0.97pl4 code
* by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
* Changes: Logitech and Microsoft support in the same kernel.
* Defined new constants in busmouse.h for MS mice.
* Added int mse_busmouse_type to distinguish busmouse types
* Added a couple of new functions to handle differences in using
* MS vs. Logitech (where the int variable wasn't appropriate).
*
* version 0.2
*/
#include <linux/kernel.h>
......@@ -33,6 +46,7 @@
#include <asm/system.h>
#include <asm/irq.h>
static struct mouse_status mouse;
static void mouse_interrupt(int unused)
......@@ -65,11 +79,47 @@ static void mouse_interrupt(int unused)
wake_up(&mouse.inode->i_wait);
MSE_INT_ON();
}
/* Use separate function for MS mice - keep both short & fast */
static void ms_mouse_interrupt(int unused)
{
char dx, dy, buttons;
outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
outb((inb(MS_MSE_DATA_PORT) | 0x20), MS_MSE_DATA_PORT);
outb(MS_MSE_READ_X, MS_MSE_CONTROL_PORT);
dx = inb(MS_MSE_DATA_PORT);
outb(MS_MSE_READ_Y, MS_MSE_CONTROL_PORT);
dy = inb(MS_MSE_DATA_PORT);
outb(MS_MSE_READ_BUTTONS, MS_MSE_CONTROL_PORT);
buttons = ~(inb(MS_MSE_DATA_PORT)) & 0x07;
outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT);
mouse.buttons = buttons;
mouse.latch_buttons |= buttons;
mouse.dx += dx;
mouse.dy += dy;
mouse.ready = 1;
if (mouse.inode && mouse.inode->i_wait)
wake_up(&mouse.inode->i_wait);
}
static void release_mouse(struct inode * inode, struct file * file)
{
MSE_INT_OFF();
if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
MSE_INT_OFF();
} else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
MS_MSE_INT_OFF();
} /* else if next mouse type, etc. */
mouse.active = 0;
mouse.ready = 0;
mouse.inode = NULL;
......@@ -88,15 +138,31 @@ static int open_mouse(struct inode * inode, struct file * file)
mouse.dx = 0;
mouse.dy = 0;
mouse.buttons = mouse.latch_buttons = 0x80;
if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
/* once we get to here mouse is unused, IRQ is busy */
mouse.active = 0; /* it's not active, fix it */
return -EBUSY; /* IRQ is busy, so we're BUSY */
} /* if we can't get the IRQ and mouse not active */
MSE_INT_ON();
if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
/* once we get to here mouse is unused, IRQ is busy */
mouse.active = 0; /* it's not active, fix it */
return -EBUSY; /* IRQ is busy, so we're BUSY */
} /* if we can't get the IRQ and mouse not active */
MSE_INT_ON();
} else if (mse_busmouse_type == MICROSOFT_BUSMOUSE) {
if (request_irq(MOUSE_IRQ, ms_mouse_interrupt)) {
/* once we get to here mouse is unused, IRQ is busy */
mouse.active = 0; /* it's not active, fix it */
return -EBUSY; /* IRQ is busy, so we're BUSY */
} /* if we can't get the IRQ and mouse not active */
outb(MS_MSE_START, MS_MSE_CONTROL_PORT);
MS_MSE_INT_ON();
}
return 0;
}
static int write_mouse(struct inode * inode, struct file * file, char * buffer, int count)
{
return -EINVAL;
......@@ -108,8 +174,10 @@ static int read_mouse(struct inode * inode, struct file * file, char * buffer, i
if (count < 3) return -EINVAL;
if (!mouse.ready) return -EAGAIN;
MSE_INT_OFF();
if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
MSE_INT_OFF();
}
put_fs_byte(mouse.latch_buttons | 0x80, buffer);
......@@ -131,7 +199,10 @@ static int read_mouse(struct inode * inode, struct file * file, char * buffer, i
mouse.latch_buttons = mouse.buttons;
mouse.ready = 0;
MSE_INT_ON();
if (mse_busmouse_type == LOGITECH_BUSMOUSE) {
MSE_INT_ON();
}
return i;
}
......@@ -165,7 +236,7 @@ long bus_mouse_init(long kmem_start)
for (i = 0; i < 100000; i++); /* busy loop */
if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
printk("No bus mouse detected.\n");
printk("No Logitech bus mouse detected.\n");
mouse.present = 0;
return kmem_start;
}
......@@ -179,6 +250,19 @@ long bus_mouse_init(long kmem_start)
mouse.buttons = mouse.latch_buttons = 0x80;
mouse.dx = 0;
mouse.dy = 0;
printk("Bus mouse detected and installed.\n");
printk("Logitech Bus mouse detected and installed.\n");
return kmem_start;
}
long ms_bus_mouse_init(long kmem_start)
{
MS_MSE_INT_OFF();
mouse.present = 1;
mouse.active = mouse.ready = 0;
mouse.buttons = mouse.latch_buttons = 0x80;
mouse.dx = mouse.dy = 0;
printk("Microsoft Bus mouse detected and installed.\n");
return kmem_start;
}
......@@ -39,12 +39,12 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kd.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <sys/kd.h>
#include "vt_kern.h"
#define NPAR 16
......@@ -187,6 +187,13 @@ static int console_blanked = 0;
#define kbdleds (vt_cons[currcons].vc_kbdleds)
#define vtmode (vt_cons[currcons].vt_mode)
#if defined KBD_NUMERIC_LOCK
#define NUMLED_DEFAULT 0x02
#else
#define NUMLED_DEFAULT 0
#endif
#define SET(mode,fg,v) \
(mode) = (v); \
if (currcons == fg_console) \
......@@ -866,7 +873,7 @@ static void reset_terminal(int currcons, int do_clear)
ckmode = 0;
kapplic = 0;
lfnlmode = 0;
kleds = 2;
kleds = NUMLED_DEFAULT;
kmode = 0;
set_leds();
} else {
......@@ -874,7 +881,7 @@ static void reset_terminal(int currcons, int do_clear)
decckm = 0;
kbdapplic = 0;
lnm = 0;
kbdleds = 2;
kbdleds = NUMLED_DEFAULT;
kbdmode = 0;
}
......
......@@ -29,13 +29,20 @@
#define NUMLED 0x02
#define CAPSLED 0x04
#if defined KBD_NUMERIC_LOCK
#define NUMLED_DEFAULT NUMLED
#else
#define NUMLED_DEFAULT 0
#endif
#define NO_META_BIT 0x80
unsigned char kapplic = 0;
unsigned char ckmode = 0;
unsigned char krepeat = 1;
unsigned char kmode = 0;
unsigned char kleds = NUMLED;
unsigned char kleds = NUMLED_DEFAULT;
unsigned char ke0 = 0;
unsigned char kraw = 0;
unsigned char kbd_flags = KBDFLAGS;
......@@ -48,7 +55,7 @@ extern struct tty_queue *table_list[];
typedef void (*fptr)(int);
static unsigned char old_leds = 2;
static unsigned char old_leds = NUMLED;
static int diacr = -1;
static int npadch = 0;
fptr key_table[];
......
......@@ -4,6 +4,11 @@
* Generic mouse open routine by Johan Myreen
*
* Based on code from Linus
*
* Teemu Rantanen's Microsoft Busmouse support and Derrick Cole's
* changes incorporated into 0.97pl4
* by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
* See busmouse.c for particulars.
*/
#include <linux/fs.h>
......@@ -14,6 +19,9 @@ extern struct file_operations bus_mouse_fops;
extern struct file_operations psaux_fops;
extern long bus_mouse_init(long);
extern long psaux_init(long);
extern long ms_bus_mouse_init(long);
int mse_busmouse_type;
static int mouse_open(struct inode * inode, struct file * file)
{
......@@ -21,8 +29,11 @@ static int mouse_open(struct inode * inode, struct file * file)
file->f_op = &bus_mouse_fops;
else if (MINOR(inode->i_rdev) == PSMOUSE_MINOR)
file->f_op = &psaux_fops;
else if (MINOR(inode->i_rdev) == MS_BUSMOUSE_MINOR)
file->f_op = &bus_mouse_fops;
else
return -ENODEV;
mse_busmouse_type = (int) MINOR(inode->i_rdev);
return file->f_op->open(inode,file);
}
......@@ -41,6 +52,8 @@ long mouse_init(long kmem_start)
{
kmem_start = bus_mouse_init(kmem_start);
kmem_start = psaux_init(kmem_start);
kmem_start = ms_bus_mouse_init(kmem_start);
mse_busmouse_type = -1;
chrdev_fops[10] = &mouse_fops;
return kmem_start;
}
......@@ -444,6 +444,54 @@ int set_serial_info(unsigned int line, struct serial_struct * info)
return 0;
}
int get_modem_info(unsigned int line, unsigned int *value)
{
unsigned port = (serial_table + line)->port;
unsigned char control = inb(port+4);
unsigned char status = inb(port+6);
unsigned int result;
result = ((control & 0x02) ? TIOCM_RTS : 0)
| ((control & 0x01) ? TIOCM_DTR : 0)
| ((status & 0x80) ? TIOCM_CAR : 0)
| ((status & 0x40) ? TIOCM_RNG : 0)
| ((status & 0x20) ? TIOCM_DSR : 0)
| ((status & 0x10) ? TIOCM_CTS : 0);
put_fs_long(result,(unsigned long *) value);
return 0;
}
int set_modem_info(unsigned int line, unsigned int cmd, unsigned int *value)
{
unsigned port = (serial_table + line)->port;
unsigned char control = inb(port+4);
unsigned int arg = get_fs_long((unsigned long *) value);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
control |= 0x02;
if (arg & TIOCM_DTR)
control |= 0x01;
break;
case TIOCMBIC:
if (arg & TIOCM_RTS)
control &= ~0x02;
if (arg & TIOCM_DTR)
control &= ~0x01;
break;
case TIOCMSET:
control = (control & ~0x03)
| ((arg & TIOCM_RTS) ? 0x02 : 0)
| ((arg & TIOCM_DTR) ? 0x01 : 0);
break;
default:
return -EINVAL;
}
outb(port,control);
return 0;
}
long rs_init(long kmem_start)
{
int i;
......
......@@ -18,12 +18,12 @@
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/ctype.h>
#include <linux/kd.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <sys/kd.h>
#include "vt_kern.h"
#define QUEUES (3*(NR_CONSOLES+NR_SERIALS+2*NR_PTYS))
......
......@@ -375,13 +375,16 @@ int tty_ioctl(struct inode * inode, struct file * file,
set_window_size(other_tty,(struct winsize *) arg);
return set_window_size(tty,(struct winsize *) arg);
case TIOCMGET:
return -EINVAL; /* not implemented */
if (!IS_A_SERIAL(dev))
return -EINVAL;
verify_area((void *) arg,sizeof(unsigned int *));
return get_modem_info(dev-64,(unsigned int *) arg);
case TIOCMBIS:
return -EINVAL; /* not implemented */
case TIOCMBIC:
return -EINVAL; /* not implemented */
case TIOCMSET:
return -EINVAL; /* not implemented */
if (!IS_A_SERIAL(dev))
return -EINVAL;
return set_modem_info(dev-64,cmd,(unsigned int *) arg);
case TIOCGSOFTCAR:
return -EINVAL; /* not implemented */
case TIOCSSOFTCAR:
......
......@@ -10,13 +10,13 @@
#include <linux/tty.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <asm/io.h>
#include <asm/segment.h>
#include "vt_kern.h"
#include <sys/kd.h>
#include <sys/vt.h>
/*
* console (vt and kd) routines, as defined by usl svr4 manual
......
......@@ -4,7 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include <time.h>
#include <linux/mktime.h>
/*
* This isn't the library routine, it is only used in the kernel.
......@@ -38,21 +38,21 @@ static int month[12] = {
DAY*(31+29+31+30+31+30+31+31+30+31+30)
};
long kernel_mktime(struct tm * tm)
long kernel_mktime(struct mktime * time)
{
long res;
int year;
year = tm->tm_year - 70;
year = time->year - 70;
/* magic offsets (y+1) needed to get leapyears right.*/
res = YEAR*year + DAY*((year+1)/4);
res += month[tm->tm_mon];
res += month[time->mon];
/* and (y+2) here. If it wasn't a leap-year, we have to adjust */
if (tm->tm_mon>1 && ((year+2)%4))
if (time->mon>1 && ((year+2)%4))
res -= DAY;
res += DAY*(tm->tm_mday-1);
res += HOUR*tm->tm_hour;
res += MINUTE*tm->tm_min;
res += tm->tm_sec;
res += DAY*(time->day-1);
res += HOUR*time->hour;
res += MINUTE*time->min;
res += time->sec;
return res;
}
......@@ -139,12 +139,33 @@ unsigned long save_v86_state(int signr,struct vm86_regs * regs)
do_exit(SIGSEGV);
}
memcpy_tofs(&(current->vm86_info->regs),regs,sizeof(*regs));
put_fs_long(current->screen_bitmap,&(current->vm86_info->screen_bitmap));
stack = current->tss.esp0;
current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0;
return stack;
}
static void mark_screen_rdonly(struct task_struct * tsk)
{
unsigned long tmp;
unsigned long *pg_table;
if (tmp = tsk->tss.cr3) {
tmp = *(unsigned long *) tmp;
if (tmp & PAGE_PRESENT) {
tmp &= 0xfffff000;
pg_table = (0xA00000 >> PAGE_SHIFT) + (unsigned long *) tmp;
tmp = 32;
while (tmp--) {
if (PAGE_PRESENT & *pg_table)
*pg_table &= ~PAGE_RW;
pg_table++;
}
}
}
}
int sys_vm86(struct vm86_struct * v86)
{
struct vm86_struct info;
......@@ -171,6 +192,9 @@ int sys_vm86(struct vm86_struct * v86)
current->saved_kernel_stack = current->tss.esp0;
current->tss.esp0 = (unsigned long) pt_regs;
current->vm86_info = v86;
current->screen_bitmap = info.screen_bitmap;
if (info.flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(current);
__asm__ __volatile__("movl %0,%%esp\n\t"
"pushl $ret_from_sys_call\n\t"
"ret"::"g" ((long) &(info.regs)),"a" (info.regs.eax));
......
......@@ -126,17 +126,17 @@ _system_call:
movl %eax,EAX(%esp) # save the return value
.align 4,0x90
ret_from_sys_call:
movl EFLAGS(%esp),%eax
testl $VM_MASK,%eax
jne 1f
movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
testl $VM_MASK,%eax # different then
jne 4f
cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 2f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 2f
1: orl $IF_MASK,%eax # these just try to make sure
4: orl $IF_MASK,%eax # these just try to make sure
andl $~NT_MASK,%eax # the program doesn't do anything
movl %eax,EFLAGS(%esp) # stupid
cmpl $0,_need_resched
1: cmpl $0,_need_resched
jne reschedule
movl _current,%eax
cmpl _task,%eax # task[0] cannot have signals
......
......@@ -50,6 +50,9 @@
big buffers around for itself.) I guess I'll have return from
syscall fill up the free page descriptors. -RAB */
/* since the advent of GFP_ATOMIC, I've changed the malloc code to
use it and return NULL if it can't get a page. -RAB */
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
......@@ -91,84 +94,6 @@ struct _bucket_dir bucket_dir[] = {
{ 4096, (struct bucket_desc *) 0},
{ 0, (struct bucket_desc *) 0}}; /* End of list marker */
/* Where to keep the extra pages, and how many. */
#define FREE_PAGES 20
static volatile unsigned long free_pages[FREE_PAGES]={0,};
volatile short free_page_ptr=0; /* this -1 is next free page. */
/* malloc_free_page makes sure that we have all the free pages we
want around before actually freeing the page. */
/* called with interrupts off. */
void
malloc_free_page (unsigned long addr)
{
if (free_page_ptr < FREE_PAGES)
free_pages[free_page_ptr++] = addr;
else
free_page (addr);
}
/* Fill up the extra page buffer. Should be called quite often to make
sure we have some floating around. */
void
malloc_grab_pages(void)
{
while (free_page_ptr < FREE_PAGES)
{
unsigned long page;
page = get_free_page (GFP_KERNEL);
if (page == 0)
{
printk ("malloc_grab_pages: Can't happen. no memory.\n");
continue;
}
/* see if we still need the page. This can only happen if
we get interrupted while we are trying to get some pages,
and we are out of pages. It shouldn't happen, but it
could and we had better check for it. */
cli();
if (free_page_ptr < FREE_PAGES)
{
free_pages[free_page_ptr] = page;
free_page_ptr++;
}
else
{
free_page(page);
}
sti();
}
}
/* called with interrupts off. */
static inline unsigned long
malloc_get_free_page (void)
{
unsigned long page;
int page_ptr;
if (free_page_ptr > 0)
{
page_ptr = --free_page_ptr;
page = free_pages[page_ptr];
free_pages[page_ptr] = 0;
return (page);
}
printk ("malloc_get_free_page: Calling malloc_grab_pages\n");
/* this routine turns on interrupts. Maybe we should do a pushflags
pop flags around it. */
malloc_grab_pages();
cli();
page_ptr = --free_page_ptr;
page = free_pages[page_ptr];
free_pages[page_ptr] = 0;
return (page);
}
/*
* This contains a linked list of free bucket descriptor blocks
*/
......@@ -177,24 +102,26 @@ static struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;
/*
* This routine initializes a bucket description page.
*/
static inline void init_bucket_desc()
static inline int init_bucket_desc()
{
struct bucket_desc *bdesc, *first;
int i;
int i;
/* this turns interrupt on, so we should be carefull. */
first = bdesc = (struct bucket_desc *) malloc_get_free_page();
first = bdesc = (struct bucket_desc *) get_free_page(GFP_ATOMIC);
if (!bdesc)
panic("Out of memory in init_bucket_desc()");
return 1;
for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
bdesc->next = bdesc+1;
bdesc++;
}
/*
* This is done last, to avoid race conditions in case
* This is done last, to avoid race conditions in case
* get_free_page() sleeps and this routine gets called again....
*/
/* Get free page will not sleep because of the GFP_ATOMIC */
bdesc->next = free_bucket_desc;
free_bucket_desc = first;
return (0);
}
void *malloc(unsigned int len)
......@@ -210,36 +137,41 @@ void *malloc(unsigned int len)
for (bdir = bucket_dir; bdir->size; bdir++)
if (bdir->size >= len)
break;
if (!bdir->size) {
printk("malloc called with impossibly large argument (%d)\n",
len);
panic("malloc: bad arg");
printk("malloc called with impossibly large argument (%d)\n", len);
return NULL;
}
/*
* Now we search for a bucket descriptor which has free space
*/
cli(); /* Avoid race conditions */
for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)
for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)
if (bdesc->freeptr)
break;
/*
* If we didn't find a bucket with free space, then we'll
* If we didn't find a bucket with free space, then we'll
* allocate a new one.
*/
if (!bdesc) {
char *cp;
int i;
if (!free_bucket_desc)
init_bucket_desc();
char *cp;
int i;
if (!free_bucket_desc)
if (init_bucket_desc()) {
sti();
return NULL;
}
bdesc = free_bucket_desc;
free_bucket_desc = bdesc->next;
bdesc->refcnt = 0;
bdesc->bucket_size = bdir->size;
bdesc->page = bdesc->freeptr =
(void *) cp = malloc_get_free_page();
if (!cp)
panic("Out of memory in kernel malloc()");
(void *) cp = get_free_page(GFP_ATOMIC);
if (!cp) {
sti();
return NULL;
}
/* Set up the chain of free objects */
for (i=PAGE_SIZE/bdir->size; i > 1; i--) {
*((char **) cp) = cp + bdir->size;
......@@ -253,14 +185,14 @@ void *malloc(unsigned int len)
bdesc->freeptr = *((void **) retval);
bdesc->refcnt++;
sti(); /* OK, we're safe again */
return(retval);
return retval;
}
/*
* Here is the free routine. If you know the size of the object that you
* are freeing, then free_s() will use that information to speed up the
* search for the bucket descriptor.
*
*
* We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"
*/
void free_s(void *obj, int size)
......@@ -278,7 +210,7 @@ void free_s(void *obj, int size)
if (bdir->size < size)
continue;
for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
if (bdesc->page == page)
if (bdesc->page == page)
goto found;
prev = bdesc;
}
......@@ -307,11 +239,10 @@ void free_s(void *obj, int size)
panic("malloc bucket chains corrupted");
bdir->chain = bdesc->next;
}
malloc_free_page((unsigned long) bdesc->page);
free_page((unsigned long) bdesc->page);
bdesc->next = free_bucket_desc;
free_bucket_desc = bdesc;
}
sti();
return;
}
......@@ -350,7 +350,7 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
* when the page is referenced. current assumptions
* cause it to be treated as demand allocation.
*/
if (mask == 4 || to >= high_memory)
if (mask == 4 || to >= high_memory || !mem_map[MAP_NR(to)])
*page_table++ = 0; /* not present */
else {
++current->rss;
......@@ -788,14 +788,19 @@ void show_mem(void)
void do_page_fault(unsigned long *esp, unsigned long error_code)
{
unsigned long address;
unsigned long user_esp;
unsigned long user_esp = 0;
if ((0xffff & esp[1]) == 0xf)
user_esp = esp[3];
else
user_esp = 0;
/* get the address */
__asm__("movl %%cr2,%0":"=r" (address));
if (esp[2] & VM_MASK) {
unsigned int bit;
bit = (address - 0xA0000) >> PAGE_SHIFT;
if (bit < 32)
current->screen_bitmap |= 1 << bit;
} else
if ((0xffff & esp[1]) == 0xf)
user_esp = esp[3];
if (!(error_code & 1))
do_no_page(error_code, address, current, user_esp);
else
......
......@@ -8,12 +8,11 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/mman.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <sys/mman.h>
/*
* description of effects of mapping type and prot in current implementation.
* this is due to the current handling of page faults in memory.c. the expected
......
......@@ -247,7 +247,7 @@ static int try_to_swap_out(unsigned long * table_ptr)
*table_ptr = 0;
invalidate();
free_page(page);
return !mem_map[MAP_NR(page)];
return 1 + mem_map[MAP_NR(page)];
}
/*
......@@ -316,9 +316,10 @@ static int swap_out(unsigned int priority)
swap_table++;
goto check_dir;
}
if (try_to_swap_out(swap_page + (unsigned long *) pg_table)) {
p->rss--;
return 1;
switch (try_to_swap_out(swap_page + (unsigned long *) pg_table)) {
case 0: break;
case 1: p->rss--; return 1;
default: p->rss--;
}
swap_page++;
goto check_table;
......@@ -517,6 +518,7 @@ static int try_to_unuse(unsigned int swap_nr)
read_swap_page(page>>1, (char *) tmp);
if (*ppage == page) {
*ppage = tmp | (PAGE_DIRTY | 7);
++p->rss;
swap_free(page>>1);
tmp = 0;
}
......
......@@ -35,7 +35,7 @@ clean:
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
$(CPP) -M *.c >> tmp_make
cp tmp_make Makefile
@for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE) dep) || exit; done
......
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