Commit ec1d1994 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.75

parent f8c02520
......@@ -546,6 +546,16 @@ S: Boterkorfhoek 34
S: 7546 JA Enschede
S: Netherlands
N: David S. Miller
E: davem@caip.rutgers.edu
D: Sparc hacker
D: New Linux-Activists maintainer
D: Linux Emacs elf/qmagic support + other libc/gcc things
D: Yee bore de yee bore! ;-)
S: 2 Bristol Court
S: East Brunswick, New Jersey 08816
S: USA
N: Rick Miller
E: rick@discus.mil.wi.us
D: Linux Device Registrar (Major/minor numbers), "au-play", "bwBASIC"
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 74
SUBLEVEL = 75
ARCH = i386
all: Version zImage
.EXPORT_ALL_VARIABLES:
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
......@@ -13,6 +11,8 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else echo sh; fi ; fi)
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
all: do-it-all
#
# Make "config" the default target if there is no configuration file or
# "depend" the target if there is no top-level dependency information.
......@@ -21,11 +21,14 @@ ifeq (.config,$(wildcard .config))
include .config
ifeq (.depend,$(wildcard .depend))
include .depend
do-it-all: Version arch-all
else
CONFIGURATION = depend
do-it-all: depend
endif
else
CONFIGURATION = config
do-it-all: config
endif
#
......@@ -55,7 +58,7 @@ SVGA_MODE= -DSVGA_MODE=NORMAL_VGA
# standard CFLAGS
#
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
ifdef CONFIG_CPP
CFLAGS := $(CFLAGS) -x c++
......@@ -156,6 +159,7 @@ boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h
$(CPP) -traditional $< -o $@
tools/version.o: tools/version.c include/linux/version.h
$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o tools/version.o tools/version.c
init/main.o: $(CONFIGURE) init/main.c
$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
......
......@@ -17,22 +17,7 @@ CPP =$(CC) -E
AR =ar
STRIP =strip
zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
$(MAKE) -C zBoot
zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build
tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage
sync
zdisk: zImage
dd bs=8192 if=zImage of=/dev/fd0
zlilo: $(CONFIGURE) zImage
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi
cat zImage > $(INSTALL_PATH)/vmlinuz
cp zSystem.map $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
arch-all: tools/system
tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs
$(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \
......@@ -44,24 +29,6 @@ tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs
nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
sort > System.map
boot/setup.o: boot/setup.s
$(AS) -o $@ $<
boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
$(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \
$(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \
$(LIBS) \
-o tools/zSystem
nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
sort > zSystem.map
#
# Leave these dummy entries for now to tell people that they are going away..
......@@ -74,4 +41,4 @@ lilo:
@exit 1
archclean:
rm -f boot/bootsect boot/setup
@rm -f boot/head.o
......@@ -6,6 +6,7 @@
#include <asm/system.h>
#undef halt
#define halt .long PAL_halt
/*
......
......@@ -19,6 +19,8 @@ CPP =$(CC) -E
AR =ar
STRIP =strip
CFLAGS := $(CFLAGS) -pipe
ifdef CONFIG_M486
CFLAGS := $(CFLAGS) -m486
else
......@@ -29,6 +31,8 @@ CFLAGS := $(CFLAGS) -m386
endif
endif
arch-all: zImage
zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
$(MAKE) -C zBoot
......
......@@ -37,7 +37,7 @@ startup_32:
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss _stack_start,%esp
lss stack_start,%esp
/*
* Clear BSS first so that there are no surprises...
*/
......@@ -164,7 +164,7 @@ is386: pushl %ecx # restore original EFLAGS
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss _stack_start,%esp
lss stack_start,%esp
xorl %eax,%eax
lldt %ax
pushl %eax # These are the parameters to main :-)
......@@ -295,6 +295,10 @@ _empty_zero_page:
_floppy_track_buffer:
.fill 512*2*MAX_BUFFER_SECTORS,1,0
stack_start:
.long _init_user_stack+4096
.long KERNEL_DS
/* This is the default interrupt "handler" :-) */
int_msg:
.asciz "Unknown interrupt\n"
......
......@@ -71,6 +71,20 @@ int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
*/
int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
/*
* hardsect_size contains the size of the hardware sector of a device.
*
* hardsect_size[MAJOR][MINOR]
*
* if (!hardsect_size[MAJOR])
* then 512 bytes is assumed.
* else
* sector_size is hardsect_size[MAJOR][MINOR]
* This is currently set by some scsi device and read by the msdos fs driver
* This might be a some uses later.
*/
int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
/*
* look for a free request in the first N entries.
* NOTE: interrupts must be disabled on the way in, and will still
......
......@@ -152,7 +152,7 @@
* 2.9 Fulfilled the Longshine LCS-7260 support; with great help and
* experiments by Serge Robyns.
* First attempts to support the TEAC CD-55A drives; but still not
* useable yet.
* usable yet.
* Implemented the CDROMMULTISESSION and CDROMMULTISESSION_SYS ioctls;
* this is an attempt to handle multi session CDs more "transparent"
* (redirection handling has to be done within the isofs routines, and
......@@ -243,7 +243,7 @@
* linux/fs/isofs/inode.c
* if set to 0 here
*/
#define TEAC 0 /* if 1: enable TEAC CD-55A support (not useable yet) */
#define TEAC 0 /* if 1: enable TEAC CD-55A support (not usable yet) */
#define JUKEBOX 1 /* tray control: eject tray if no disk is in */
#define EJECT 1 /* tray control: eject tray after last use */
#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
......@@ -625,7 +625,7 @@ static void sbpcd_dprintf(int level, char *fmt, ...)
}
/*
* DDI interface: runtime trace bit pattern maintainance
* DDI interface: runtime trace bit pattern maintenance
*/
static int sbpcd_dbg_ioctl(unsigned long arg, int level)
{
......
......@@ -2346,6 +2346,7 @@ int do_screendump(int arg, int mode)
memcpy_tofs(buf,(char *)origin,2*chcount);
break;
case 2:
gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3));
buf+=4; /* ioctl#, console#, x,y */
memcpy_fromfs((char *)origin,buf,2*chcount);
break;
......@@ -2445,9 +2446,12 @@ static inline int atedge(const int p)
}
/* constrain v such that v <= u */
static inline short limit(const unsigned short v, const unsigned short u)
static inline unsigned short limit(const unsigned short v, const unsigned short u)
{
return ((v > u) ? u : v);
/* gcc miscompiles the ?: operator, so don't use it.. */
if (v > u)
return u;
return v;
}
/* invoked via ioctl(TIOCLINUX) */
......
......@@ -16,7 +16,7 @@ static char rcsid[] =
*
* $Log: cyclades.c,v $
* Revision 1.35 1994/12/16 13:54:18 steffen
* addditional patch by Marcio Saito for board detection
* additional patch by Marcio Saito for board detection
* Accidently left out in 1.34
*
* Revision 1.34 1994/12/10 12:37:12 steffen
......@@ -304,7 +304,7 @@ static unsigned char *tmp_buf = 0;
static struct semaphore tmp_buf_sem = MUTEX;
/*
* This is used to look up the divsor speeds and the timeouts
* This is used to look up the divisor speeds and the timeouts
* We're normally limited to 15 distinct baud rates. The extra
* are accessed via settings in info->flags.
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
......@@ -326,7 +326,7 @@ static char baud_bpr[] = { /* 25 MHz baud rate period table */
0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15};
static char baud_cor3[] = { /* receive threashold */
static char baud_cor3[] = { /* receive threshold */
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01};
......@@ -1925,7 +1925,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
case TIOCMSET:
ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
/* The following commands are imcompletely implemented!!! */
/* The following commands are incompletely implemented!!! */
case TIOCGSOFTCAR:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(unsigned int *));
......@@ -2038,7 +2038,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
info->count = 1;
}
#ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d: decrmenting count to %d\n", __LINE__, info->count - 1);
printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);
#endif
if (--info->count < 0) {
printk("cy_close: bad serial port count for ttys%d: %d\n",
......@@ -2204,7 +2204,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif
info->count--;
#ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d: decrmenting count to %d\n", __LINE__, info->count);
printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
#endif
info->blocked_open++;
......@@ -2263,7 +2263,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
if (!tty_hung_up_p(filp)){
info->count++;
#ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d: incrmenting count to %d\n", __LINE__, info->count);
printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
#endif
}
info->blocked_open--;
......@@ -2279,7 +2279,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
/*
* This routine is called whenever a serial port is opened. It
* performs the serial-specific initalization for the tty structure.
* performs the serial-specific initialization for the tty structure.
*/
int
cy_open(struct tty_struct *tty, struct file * filp)
......@@ -2304,7 +2304,7 @@ cy_open(struct tty_struct *tty, struct file * filp)
#endif
info->count++;
#ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d: incrmenting count to %d\n", __LINE__, info->count);
printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
#endif
tty->driver_data = info;
info->tty = tty;
......
......@@ -2,8 +2,6 @@
#define _KBD_KERN_H
#include <linux/interrupt.h>
#define set_leds() mark_bh(KEYBOARD_BH)
#include <linux/keyboard.h>
extern char *func_table[MAX_NR_FUNC];
......@@ -66,6 +64,14 @@ extern unsigned long kbd_init(unsigned long);
extern unsigned char getledstate(void);
extern void setledstate(struct kbd_struct *kbd, unsigned int led);
extern inline void set_leds(void)
{
/* con_init calls (indirectly) set_leds before kbd_init
has been called; ignore these early calls */
if (bh_base[KEYBOARD_BH].routine)
mark_bh(KEYBOARD_BH);
}
extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
{
return ((kbd->modeflags >> flag) & 1);
......
......@@ -129,7 +129,7 @@ kd_mksound(unsigned int count, unsigned int ticks)
int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
int i;
int i, perm;
unsigned int console;
unsigned char ucval;
struct kbd_struct * kbd;
......@@ -140,13 +140,25 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (!vc_cons_allocated(console)) /* impossible? */
return -ENOIOCTLCMD;
/*
* To have permissions to do most of the vt ioctls, we either have
* to be the owner of the tty, or super-user.
*/
perm = 0;
if (current->tty == tty || suser())
perm = 1;
kbd = kbd_table + console;
switch (cmd) {
case KIOCSOUND:
if (!perm)
return -EPERM;
kd_mksound((unsigned int)arg, 0);
return 0;
case KDMKTONE:
if (!perm)
return -EPERM;
{
unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
......@@ -190,7 +202,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* doesn't do a whole lot. i'm not sure if it should do any
* restoration of modes or what...
*/
if (!suser())
if (!perm)
return -EPERM;
switch (arg) {
case KD_GRAPHICS:
......@@ -232,7 +244,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EINVAL;
case KDSKBMODE:
if (!suser())
if (!perm)
return -EPERM;
switch(arg) {
case K_RAW:
......@@ -313,7 +325,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
struct kbkeycode * const a = (struct kbkeycode *)arg;
unsigned int sc, kc;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
if (i)
......@@ -354,7 +366,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
u_char s;
u_short v;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
if (i)
......@@ -445,7 +457,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
u_char *p;
char *q;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
if (i)
......@@ -530,7 +542,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
struct kbdiacrs *a = (struct kbdiacrs *)arg;
unsigned int ct;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
if (i)
......@@ -554,7 +566,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return 0;
case KDSKBLED:
if (!suser())
if (!perm)
return -EPERM;
if (arg & ~0x77)
return -EINVAL;
......@@ -582,7 +594,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
struct vt_mode *vtmode = (struct vt_mode *)arg;
char mode;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
if (i)
......@@ -659,7 +671,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* to preserve sanity).
*/
case VT_ACTIVATE:
if (!suser())
if (!perm)
return -EPERM;
if (arg == 0 || arg > MAX_NR_CONSOLES)
return -ENXIO;
......@@ -674,7 +686,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* wait until the specified VT has been activated
*/
case VT_WAITACTIVE:
if (!suser())
if (!perm)
return -EPERM;
if (arg == 0 || arg > MAX_NR_CONSOLES)
return -ENXIO;
......@@ -697,7 +709,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* 2: completed switch-to OK
*/
case VT_RELDISP:
if (!suser())
if (!perm)
return -EPERM;
if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
return -EINVAL;
......@@ -747,7 +759,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* Disallocate memory associated to VT (but leave VT1)
*/
case VT_DISALLOCATE:
if (!suser())
if (!perm)
return -EPERM;
if (arg > MAX_NR_CONSOLES)
return -ENXIO;
......@@ -776,7 +788,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
{
struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
ushort ll,cc;
if (!suser())
if (!perm)
return -EPERM;
i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
if (i)
......@@ -787,7 +799,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
}
case PIO_FONT:
if (!suser())
if (!perm)
return -EPERM;
return con_set_font((char *)arg);
/* con_set_font() defined in console.c */
......@@ -797,7 +809,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
/* con_get_font() defined in console.c */
case PIO_SCRNMAP:
if (!suser())
if (!perm)
return -EPERM;
return con_set_trans((char *)arg);
/* con_set_trans() defined in console.c */
......
......@@ -27,7 +27,7 @@
* Dmitry Gorodchanin : SLIP memory leaks
* Dmitry Gorodchanin : Code cleanup. Reduce tty driver
* buffering from 4096 to 256 bytes.
* Improving SLIP responce time.
* Improving SLIP response time.
* CONFIG_SLIP_MODE_SLIP6.
* ifconfig sl? up & down now works correctly.
* Modularization.
......
......@@ -54,7 +54,7 @@ struct slip {
unsigned long rx_packets; /* inbound frames counter */
unsigned long tx_packets; /* outbound frames counter */
unsigned long rx_errors; /* Parity, etc. errors */
unsigned long tx_errors; /* Palnned stuff */
unsigned long tx_errors; /* Planned stuff */
unsigned long rx_dropped; /* No memory for skb */
unsigned long tx_dropped; /* When MTU change */
unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
......
......@@ -144,7 +144,7 @@
with a MIDI card, which frequently also uses 0x330.
This can also be overridden on the command line to the kernel, via LILO or
LODLIN. */
LOADLIN. */
static unsigned short bases[7] = {
#ifdef BUSLOGIC_PORT_OVERRIDE
BUSLOGIC_PORT_OVERRIDE,
......
......@@ -165,6 +165,8 @@ static struct blist blacklist[] =
{"MEDIAVIS","CDR-H93MV","1.31"}, /* Locks up if polled for lun != 0 */
{"SANKYO", "CP525","6.64"}, /* causes failed REQ SENSE, extra reset */
{"HP", "C1750A", "3226"}, /* scanjet iic */
{"HP", "C1790A", ""}, /* scanjet iip */
{"HP", "C2500A", ""}, /* scanjet iicx */
{NULL, NULL, NULL}};
static int blacklisted(unsigned char * response_data){
......@@ -2188,7 +2190,7 @@ static int scsi_register_host(Scsi_Host_Template * tpnt)
}
/*
* Similarily, this entry point should be called by a loadable module if it
* Similarly, this entry point should be called by a loadable module if it
* is trying to remove a low level scsi driver from the system.
*/
static void scsi_unregister_host(Scsi_Host_Template * tpnt)
......
......@@ -49,6 +49,7 @@ struct hd_struct * sd;
Scsi_Disk * rscsi_disks;
static int * sd_sizes;
static int * sd_blocksizes;
static int * sd_hardsizes; /* Hardware sector size */
extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
......@@ -994,6 +995,21 @@ static int sd_init_onedisk(int i)
return i;
};
}
{
/*
The msdos fs need to know the hardware sector size
So I have created this table. See ll_rw_blk.c
Jacques Gelinas (Jacques@solucorp.qc.ca)
*/
int m;
int hard_sector = rscsi_disks[i].sector_size;
/* There is 16 minor allocated for each devices */
for (m=i<<4; m<((i+1)<<4); m++){
sd_hardsizes[m] = hard_sector;
}
printk ("SCSI Hardware sector size is %d bytes on device sd%c\n"
,hard_sector,i+'a');
}
if(rscsi_disks[i].sector_size == 1024)
rscsi_disks[i].capacity <<= 1; /* Change this into 512 byte sectors */
if(rscsi_disks[i].sector_size == 256)
......@@ -1042,9 +1058,14 @@ static void sd_init()
sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(int));
for(i=0;i<(sd_template.dev_max << 4);i++) sd_blocksizes[i] = 1024;
sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(int));
for(i=0;i<(sd_template.dev_max << 4);i++){
sd_blocksizes[i] = 1024;
sd_hardsizes[i] = 512;
}
blksize_size[MAJOR_NR] = sd_blocksizes;
hardsect_size[MAJOR_NR] = sd_hardsizes;
sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(struct hd_struct));
......
......@@ -290,11 +290,14 @@ static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt);
static inline int find_and_clear_bit_16(unsigned short *field)
{
int rv;
unsigned long flags;
save_flags(flags);
cli();
if (*field == 0) panic("No free mscp");
asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b"
: "=&r" (rv), "=m" (*field) : "1" (*field));
sti();
restore_flags(flags);
return rv;
}
......
......@@ -29,7 +29,7 @@
* to be short.
*/
#define DCACHE_NAME_LEN 15
#define DCACHE_SIZE 64
#define DCACHE_SIZE 128
struct hash_list {
struct dir_cache_entry * next;
......
......@@ -17,11 +17,6 @@
#include <linux/malloc.h>
#include <linux/errno.h>
#define MULTISESSION /* emoenke@gwdg.de */
#ifdef MULTISESSION
#include <linux/cdrom.h>
#endif MULTISESSION
#include <asm/system.h>
#include <asm/segment.h>
......@@ -150,14 +145,6 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
unsigned int blocksize_bits;
int high_sierra;
int dev=s->s_dev;
#ifdef MULTISESSION
int i;
unsigned int vol_desc_start;
unsigned int *p_vol_desc_start=&vol_desc_start;
struct inode inode_fake;
struct file file_fake;
extern struct file_operations * get_blkfops(unsigned int);
#endif MULTISESSION
struct iso_volume_descriptor *vdp;
struct hs_volume_descriptor *hdp;
......@@ -197,27 +184,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
#ifdef MULTISESSION
/*
* look if the driver can tell the multi session redirection
* value; this allows to do the redirection if we are looking
* for the volume descriptor, and to avoid it during "raw" access.
*/
vol_desc_start=0;
inode_fake.i_rdev=dev;
i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
&file_fake,
CDROMMULTISESSION_SYS,
(unsigned long) p_vol_desc_start);
if (i!=0) vol_desc_start=0;
#if 0
printk("isofs.inode: CDROMMULTISESSION_SYS rc=%d\n",i);
printk("isofs.inode: vol_desc_start = %d\n", vol_desc_start);
#endif
for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) {
#else
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
#endif MULTISESSION
if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
s->s_dev=0;
printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
......
......@@ -18,7 +18,7 @@ endif
.s.o:
$(AS) -o $*.o $<
OBJS= namei.o inode.o file.o dir.o misc.o fat.o
OBJS= buffer.o namei.o inode.o file.o dir.o misc.o fat.o mmap.o
msdos.o: $(OBJS)
$(LD) -r -o msdos.o $(OBJS)
......
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
struct buffer_head *msdos_bread (
struct super_block *sb,
int block)
{
struct buffer_head *ret = NULL;
if (sb->s_blocksize == 512){
ret = bread (sb->s_dev,block,512);
}else{
struct buffer_head *real = bread (sb->s_dev,block>>1,1024);
if (real != NULL){
ret = (struct buffer_head *)kmalloc (sizeof(struct buffer_head)
,GFP_KERNEL);
if (ret != NULL){
/* #Specification: msdos / strategy / special device / dummy blocks
Many special device (Scsi optical disk for one) use
larger hardware sector size. This allows for higher
capacity.
Most of the time, the MsDOS file system that sit
on this device is totally unaligned. It use logically
512 bytes sector size, with logical sector starting
in the middle of a hardware block. The bad news is
that a hardware sector may hold data own by two
different files. This means that the hardware sector
must be read, patch and written allmost all the time.
Needless to say that it kills write performance
on all OS.
Internally the linux msdos fs is using 512 bytes
logical sector. When accessing such a device, we
allocate dummy buffer cache blocks, that we stuff
with the information of a real one (1k large).
This strategy is used to hide this difference to
the core of the msdos fs. The slowdown is not
hidden though!
*/
/*
THe memset is there only to catch errors. The msdos
fs is only unsing b_data
*/
memset (ret,0,sizeof(*ret));
ret->b_data = real->b_data;
if (block & 1) ret->b_data += 512;
ret->b_next = real;
}else{
brelse (real);
}
}
}
return ret;
}
struct buffer_head *msdos_getblk (
struct super_block *sb,
int block)
{
struct buffer_head *ret = NULL;
if (sb->s_blocksize == 512){
ret = getblk (sb->s_dev,block,512);
}else{
/* #Specification: msdos / special device / writing
A write is always preceded by a read of the complete block
(large hardware sector size). This defeat write performance.
There is a possibility to optimize this when writing large
chunk by making sure we are filling large block. Volunter ?
*/
ret = msdos_bread (sb,block);
}
return ret;
}
void msdos_brelse (
struct super_block *sb,
struct buffer_head *bh)
{
if (bh != NULL){
if (sb->s_blocksize == 512){
brelse (bh);
}else{
brelse (bh->b_next);
/* We can free the dummy because a new one is allocated at
each msdos_getblk() and msdos_bread().
*/
kfree (bh);
}
}
}
void msdos_mark_buffer_dirty (
struct super_block *sb,
struct buffer_head *bh,
int dirty_val)
{
if (sb->s_blocksize != 512){
bh = bh->b_next;
}
mark_buffer_dirty (bh,dirty_val);
}
void msdos_set_uptodate (
struct super_block *sb,
struct buffer_head *bh,
int val)
{
if (sb->s_blocksize != 512){
bh = bh->b_next;
}
bh->b_uptodate = val;
}
int msdos_is_uptodate (
struct super_block *sb,
struct buffer_head *bh)
{
if (sb->s_blocksize != 512){
bh = bh->b_next;
}
return bh->b_uptodate;
}
void msdos_ll_rw_block (
struct super_block *sb,
int opr,
int nbreq,
struct buffer_head *bh[32])
{
if (sb->s_blocksize == 512){
ll_rw_block(opr,nbreq,bh);
}else{
struct buffer_head *tmp[32];
int i;
for (i=0; i<nbreq; i++){
tmp[i] = bh[i]->b_next;
}
ll_rw_block(opr,nbreq,tmp);
}
}
......@@ -14,6 +14,8 @@
#include <linux/stat.h>
#include <linux/string.h>
#include "msbuffer.h"
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
#define ROUND_UP(x) (((x)+3) & ~3)
......@@ -62,6 +64,7 @@ int msdos_readdir(
struct dirent *dirent, /* dirent in user space */
int count)
{
struct super_block *sb = inode->i_sb;
int ino,i,i2,last;
char c,*walk;
struct buffer_head *bh;
......
......@@ -10,6 +10,7 @@
#include <linux/string.h>
#include <linux/stat.h>
#include "msbuffer.h"
static struct fat_cache *fat_cache,cache[FAT_CACHE];
......@@ -28,16 +29,16 @@ int fat_access(struct super_block *sb,int nr,int new_value)
first = nr*3/2;
last = first+1;
}
if (!(bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
SECTOR_BITS)))) {
if (!(bh = bread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
SECTOR_BITS),SECTOR_SIZE))) {
printk("bread in fat_access failed\n");
return 0;
}
if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS))
bh2 = bh;
else {
if (!(bh2 = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
>> SECTOR_BITS)))) {
if (!(bh2 = bread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
>> SECTOR_BITS),SECTOR_SIZE))) {
brelse(bh);
printk("bread in fat_access failed\n");
return 0;
......@@ -74,16 +75,16 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
mark_buffer_dirty(bh, 1);
for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
if (!(c_bh = bread(sb->s_dev,MSDOS_SB(sb)->
fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
fat_length*copy))) break;
fat_length*copy,SECTOR_SIZE))) break;
memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE);
mark_buffer_dirty(c_bh, 1);
if (bh != bh2) {
if (!(c_bh2 = msdos_sread(sb->s_dev,
if (!(c_bh2 = bread(sb->s_dev,
MSDOS_SB(sb)->fat_start+(first >>
SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy
+1))) {
+1,SECTOR_SIZE))) {
brelse(c_bh);
break;
}
......
......@@ -18,6 +18,8 @@
#include <linux/stat.h>
#include <linux/string.h>
#include "msbuffer.h"
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
......@@ -55,6 +57,52 @@ struct inode_operations msdos_file_inode_operations = {
NULL, /* permission */
NULL /* smap */
};
/* #Specification: msdos / special devices / mmap
Mmapping does work because a special mmap is provide in that case.
Note that it is much less efficient than the generic_mmap normally
used since it allocate extra buffer. generic_mmap is used for
normal device (512 bytes hardware sectors).
*/
static struct file_operations msdos_file_operations_1024 = {
NULL, /* lseek - default */
msdos_file_read, /* read */
msdos_file_write, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
msdos_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
file_fsync /* fsync */
};
/* #Specification: msdos / special devices / swap file
Swap file can't work on special devices with a large sector
size (1024 bytes hard sector). Those devices have a weird
MsDOS filesystem layout. Generally a single hardware sector
may contain 2 unrelated logical sector. This mean that there is
no easy way to do a mapping between disk sector of a file and virtual
memory. So swap file is difficult (not available right now)
on those devices. Off course, Ext2 does not have this problem.
*/
struct inode_operations msdos_file_inode_operations_1024 = {
&msdos_file_operations_1024, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* bmap */
msdos_truncate, /* truncate */
NULL, /* permission */
NULL /* smap */
};
#define MSDOS_PREFETCH 32
struct msdos_pre {
......@@ -72,6 +120,7 @@ static void msdos_prefetch (
struct msdos_pre *pre,
int nb) /* How many must be prefetch at once */
{
struct super_block *sb = inode->i_sb;
struct buffer_head *bhreq[MSDOS_PREFETCH]; /* Buffers not */
/* already read */
int nbreq=0; /* Number of buffers in bhreq */
......@@ -85,12 +134,12 @@ static void msdos_prefetch (
bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
if (bh == NULL) break;
pre->bhlist[pre->nblist++] = bh;
if (!bh->b_uptodate) bhreq[nbreq++] = bh;
if (!msdos_is_uptodate(sb,bh)) bhreq[nbreq++] = bh;
}else{
break;
}
}
if (nbreq > 0) ll_rw_block (READ,nbreq,bhreq);
if (nbreq > 0) msdos_ll_rw_block (sb,READ,nbreq,bhreq);
for (i=pre->nblist; i<MSDOS_PREFETCH; i++) pre->bhlist[i] = NULL;
}
......@@ -103,6 +152,7 @@ int msdos_file_read(
char *buf,
int count)
{
struct super_block *sb = inode->i_sb;
char *start = buf;
char *end = buf + count;
int i;
......@@ -172,7 +222,7 @@ int msdos_file_read(
}
PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count));
wait_on_buffer(bh);
if (!bh->b_uptodate){
if (!msdos_is_uptodate(sb,bh)){
/* read error ? */
brelse (bh);
break;
......@@ -216,6 +266,7 @@ int msdos_file_write(
char *buf,
int count)
{
struct super_block *sb = inode->i_sb;
int sector,offset,size,left,written;
int error,carry;
char *start,*to,ch;
......@@ -258,7 +309,7 @@ int msdos_file_write(
error = -EIO;
break;
}
}else if (!(bh = msdos_sread(inode->i_dev,sector))) {
}else if (!(bh = bread(inode->i_dev,sector,SECTOR_SIZE))) {
error = -EIO;
break;
}
......@@ -292,7 +343,7 @@ int msdos_file_write(
inode->i_size = filp->f_pos;
inode->i_dirt = 1;
}
bh->b_uptodate = 1;
msdos_set_uptodate(sb,bh,1);
mark_buffer_dirty(bh, 0);
brelse(bh);
}
......
......@@ -11,10 +11,13 @@
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/locks.h>
#include "msbuffer.h"
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
......@@ -79,7 +82,8 @@ static struct super_operations msdos_sops = {
static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
gid_t *gid,int *umask,int *debug,int *fat,int *quiet)
gid_t *gid,int *umask,int *debug,int *fat,int *quiet,
int *blksize)
{
char *this_char,*value;
......@@ -145,6 +149,14 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
if (value) return 0;
*quiet = 1;
}
else if (!strcmp(this_char,"blocksize")) {
*blksize = simple_strtoul(value,&value,0);
if (*value)
return 0;
if (*blksize != 512 && *blksize != 1024){
printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n");
}
}
else return 0;
}
return 1;
......@@ -153,7 +165,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
/* Read the super block of an MS-DOS FS. */
struct super_block *msdos_read_super(struct super_block *s,void *data,
struct super_block *msdos_read_super(struct super_block *sb,void *data,
int silent)
{
struct buffer_head *bh;
......@@ -164,28 +176,34 @@ struct super_block *msdos_read_super(struct super_block *s,void *data,
uid_t uid;
gid_t gid;
int umask;
int blksize = 512;
if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
if (blksize != 512){
printk ("MSDOS: Hardware sector size is %d\n",blksize);
}
}
if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask,
&debug,&fat,&quiet)) {
s->s_dev = 0;
&debug,&fat,&quiet,&blksize)
|| (blksize != 512 && blksize != 1024)) {
sb->s_dev = 0;
return NULL;
}
cache_init();
lock_super(s);
set_blocksize(s->s_dev, SECTOR_SIZE);
bh = bread(s->s_dev, 0, SECTOR_SIZE);
unlock_super(s);
if (bh == NULL) {
s->s_dev = 0;
lock_super(sb);
/* The first read is always 1024 bytes */
sb->s_blocksize = 1024;
set_blocksize(sb->s_dev, 1024);
bh = bread(sb->s_dev, 0, 1024);
unlock_super(sb);
if (bh == NULL || !msdos_is_uptodate(sb,bh)) {
brelse (bh);
sb->s_dev = 0;
printk("MSDOS bread failed\n");
return NULL;
}
b = (struct msdos_boot_sector *) bh->b_data;
s->s_blocksize = 512; /* Using this small block size solve the */
/* the misfit with buffer cache and cluster */
/* because cluster (DOS) are often aligned */
/* on odd sector */
s->s_blocksize_bits = 9; /* we cannot handle anything else yet */
set_blocksize(sb->s_dev, blksize);
/*
* The DOS3 partition size limit is *not* 32M as many people think.
* Instead, it is 64K sectors (with the usual sector size being
......@@ -206,75 +224,85 @@ struct super_block *msdos_read_super(struct super_block *s,void *data,
logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size);
sector_mult = logical_sector_size >> SECTOR_BITS;
MSDOS_SB(s)->cluster_size = b->cluster_size*sector_mult;
MSDOS_SB(s)->fats = b->fats;
MSDOS_SB(s)->fat_start = CF_LE_W(b->reserved)*sector_mult;
MSDOS_SB(s)->fat_length = CF_LE_W(b->fat_length)*sector_mult;
MSDOS_SB(s)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W(
MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult;
MSDOS_SB(sb)->fats = b->fats;
MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult;
MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult;
MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W(
b->fat_length))*sector_mult;
MSDOS_SB(s)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries
MSDOS_SB(sb)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries
));
MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+ROUND_TO_MULTIPLE((
MSDOS_SB(s)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE((
MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
sector_mult);
data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ?
CF_LE_W(*((unsigned short *) &b->sectors)) :
CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(s)->data_start;
CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start;
error = !b->cluster_size || !sector_mult;
if (!error) {
MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/
MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/
b->cluster_size/sector_mult : 0;
MSDOS_SB(s)->fat_bits = fat ? fat : MSDOS_SB(s)->clusters >
MSDOS_SB(sb)->fat_bits = fat ? fat : MSDOS_SB(sb)->clusters >
MSDOS_FAT12 ? 16 : 12;
error = !MSDOS_SB(s)->fats || (MSDOS_SB(s)->dir_entries &
(MSDOS_DPS-1)) || MSDOS_SB(s)->clusters+2 > MSDOS_SB(s)->
fat_length*SECTOR_SIZE*8/MSDOS_SB(s)->fat_bits ||
error = !MSDOS_SB(sb)->fats || (MSDOS_SB(sb)->dir_entries &
(MSDOS_DPS-1)) || MSDOS_SB(sb)->clusters+2 > MSDOS_SB(sb)->
fat_length*SECTOR_SIZE*8/MSDOS_SB(sb)->fat_bits ||
(logical_sector_size & (SECTOR_SIZE-1)) || !b->secs_track ||
!b->heads;
}
brelse(bh);
/*
This must be done after the brelse because the bh is a dummy
allocated by msdos_bread (see buffer.c)
*/
sb->s_blocksize = blksize; /* Using this small block size solve the */
/* the misfit with buffer cache and cluster */
/* because cluster (DOS) are often aligned */
/* on odd sector */
sb->s_blocksize_bits = blksize == 512 ? 9 : 10;
if (error || debug) {
/* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
"uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(s)->fat_bits,check,
conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(s)) ?
"uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(sb)->fat_bits,check,
conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(sb)) ?
",bmap" : "");
printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
"se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(s)->cluster_size,
MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,MSDOS_SB(s)->
fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries,
MSDOS_SB(s)->data_start,CF_LE_W(*(unsigned short *) &b->
"se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size,
MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->
fat_length,MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
MSDOS_SB(sb)->data_start,CF_LE_W(*(unsigned short *) &b->
sectors),b->total_sect,logical_sector_size);
printk ("Transaction block size = %d\n",blksize);
}
if (error) {
if (!silent)
printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n",
s->s_dev);
s->s_dev = 0;
sb->s_dev);
sb->s_dev = 0;
return NULL;
}
s->s_magic = MSDOS_SUPER_MAGIC;
MSDOS_SB(s)->name_check = check;
MSDOS_SB(s)->conversion = conversion;
sb->s_magic = MSDOS_SUPER_MAGIC;
MSDOS_SB(sb)->name_check = check;
MSDOS_SB(sb)->conversion = conversion;
/* set up enough so that it can read an inode */
s->s_op = &msdos_sops;
MSDOS_SB(s)->fs_uid = uid;
MSDOS_SB(s)->fs_gid = gid;
MSDOS_SB(s)->fs_umask = umask;
MSDOS_SB(s)->quiet = quiet;
MSDOS_SB(s)->free_clusters = -1; /* don't know yet */
MSDOS_SB(s)->fat_wait = NULL;
MSDOS_SB(s)->fat_lock = 0;
MSDOS_SB(s)->prev_free = 0;
if (!(s->s_mounted = iget(s,MSDOS_ROOT_INO))) {
s->s_dev = 0;
sb->s_op = &msdos_sops;
MSDOS_SB(sb)->fs_uid = uid;
MSDOS_SB(sb)->fs_gid = gid;
MSDOS_SB(sb)->fs_umask = umask;
MSDOS_SB(sb)->quiet = quiet;
MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */
MSDOS_SB(sb)->fat_wait = NULL;
MSDOS_SB(sb)->fat_lock = 0;
MSDOS_SB(sb)->prev_free = 0;
if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
sb->s_dev = 0;
printk("get root inode failed\n");
return NULL;
}
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
return s;
return sb;
}
......@@ -321,6 +349,7 @@ int msdos_bmap(struct inode *inode,int block)
void msdos_read_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *raw_entry;
int nr;
......@@ -384,7 +413,9 @@ void msdos_read_inode(struct inode *inode)
inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode)
? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) |
S_IFREG;
inode->i_op = &msdos_file_inode_operations; /* Now can always bmap */
inode->i_op = sb->s_blocksize == 1024
? &msdos_file_inode_operations_1024
: &msdos_file_inode_operations;
MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
inode->i_nlink = 1;
inode->i_size = CF_LE_L(raw_entry->size);
......@@ -404,6 +435,7 @@ void msdos_read_inode(struct inode *inode)
void msdos_write_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *raw_entry;
......
......@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/stat.h>
#include "msbuffer.h"
#define PRINTK(x)
/* Well-known binary file extensions */
......@@ -111,6 +112,7 @@ void unlock_fat(struct super_block *sb)
int msdos_add_cluster(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
int count,nr,limit,last,current,sector,last_sector;
struct buffer_head *bh;
int cluster_size = MSDOS_SB(inode->i_sb)->cluster_size;
......@@ -173,7 +175,7 @@ if (last) printk("next set to %d\n",fat_access(inode->i_sb,last,-1));
printk("getblk failed\n");
else {
memset(bh->b_data,0,SECTOR_SIZE);
bh->b_uptodate = 1;
msdos_set_uptodate(sb,bh,1);
mark_buffer_dirty(bh, 1);
brelse(bh);
}
......@@ -255,6 +257,7 @@ void date_unix2dos(int unix_date,unsigned short *time,
int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
struct msdos_dir_entry **de)
{
struct super_block *sb = dir->i_sb;
int sector,offset;
while (1) {
......@@ -269,7 +272,7 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
if (*bh)
brelse(*bh);
PRINTK (("get_entry sector apres brelse\n"));
if (!(*bh = msdos_sread(dir->i_dev,sector))) {
if (!(*bh = bread(dir->i_dev,sector,SECTOR_SIZE))) {
printk("Directory sread (sector %d) failed\n",sector);
continue;
}
......@@ -343,7 +346,7 @@ static int raw_scan_sector(struct super_block *sb,int sector,char *name,
struct inode *inode;
int entry,start,done;
if (!(bh = msdos_sread(sb->s_dev,sector))) return -EIO;
if (!(bh = bread(sb->s_dev,sector,SECTOR_SIZE))) return -EIO;
data = (struct msdos_dir_entry *) bh->b_data;
for (entry = 0; entry < MSDOS_DPS; entry++) {
if (name) RSS_NAME
......
/*
* fs/msdos/mmap.c
*
* Written by Jacques Gelinas (jacques@solucorp.qc.ca)
* Inspired by fs/nfs/mmap.c (Jaon Tombs 15 Aug 1993)
*
* msdos mmap handling
*/
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/shm.h>
#include <linux/errno.h>
#include <linux/mman.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/msdos_fs.h>
/*
* Fill in the supplied page for mmap
*/
static unsigned long msdos_file_mmap_nopage(
struct vm_area_struct * area,
unsigned long address,
unsigned long page,
int error_code)
{
struct inode * inode = area->vm_inode;
unsigned int clear;
int pos;
long gap; /* distance from eof to pos */
address &= PAGE_MASK;
pos = address - area->vm_start + area->vm_offset;
clear = 0;
gap = inode->i_size - pos;
if (gap <= 0){
/* mmaping beyond end of file */
clear = PAGE_SIZE;
}else{
int cur_read;
int need_read;
struct file filp;
if (gap < PAGE_SIZE){
clear = PAGE_SIZE - gap;
}
filp.f_reada = 0;
filp.f_pos = pos;
need_read = PAGE_SIZE - clear;
{
unsigned long cur_fs = get_fs();
set_fs (KERNEL_DS);
cur_read = msdos_file_read (inode,&filp,(char*)page
,need_read);
set_fs (cur_fs);
}
if (cur_read != need_read){
printk ("MSDOS: Error while reading an mmap file %d <> %d\n"
,cur_read,need_read);
}
}
if (clear > 0){
memset ((char*)page+PAGE_SIZE-clear,0,clear);
}
return page;
}
struct vm_operations_struct msdos_file_mmap = {
NULL, /* open */
NULL, /* close */
NULL, /* unmap */
NULL, /* protect */
NULL, /* sync */
NULL, /* advise */
msdos_file_mmap_nopage, /* nopage */
NULL, /* wppage */
NULL, /* swapout */
NULL, /* swapin */
};
/*
* This is used for a general mmap of an msdos file
* Returns 0 if ok, or a negative error code if not.
*/
int msdos_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
{
if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported now */
return -EINVAL;
if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
return -EINVAL;
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
if (!IS_RDONLY(inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
vma->vm_inode = inode;
inode->i_count++;
vma->vm_ops = &msdos_file_mmap;
return 0;
}
/* buffer.c 13/12/94 20.19.10 */
struct buffer_head *msdos_bread (struct super_block *sb, int block);
struct buffer_head *msdos_getblk (struct super_block *sb, int block);
void msdos_brelse (struct super_block *sb, struct buffer_head *bh);
void msdos_mark_buffer_dirty (struct super_block *sb,
struct buffer_head *bh,
int dirty_val);
void msdos_set_uptodate (struct super_block *sb,
struct buffer_head *bh,
int val);
int msdos_is_uptodate (struct super_block *sb, struct buffer_head *bh);
void msdos_ll_rw_block (struct super_block *sb, int opr,
int nbreq, struct buffer_head *bh[32]);
/* These macros exist to avoid modifying all the code */
/* They should be removed one day I guess */
#define brelse(b) msdos_brelse(sb,b)
#define bread(d,b,s) msdos_bread(sb,b)
#define getblk(d,b,s) msdos_getblk(sb,b)
#define mark_buffer_dirty(b,v) msdos_mark_buffer_dirty(sb,b,v)
......@@ -13,6 +13,8 @@
#include <linux/string.h>
#include <linux/stat.h>
#include "msbuffer.h"
#define PRINTK(x)
/* MS-DOS "device special files" */
......@@ -107,6 +109,7 @@ static int msdos_find(struct inode *dir,const char *name,int len,
int msdos_lookup(struct inode *dir,const char *name,int len,
struct inode **result)
{
struct super_block *sb = dir->i_sb;
int ino,res;
struct msdos_dir_entry *de;
struct buffer_head *bh;
......@@ -173,6 +176,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
struct inode **result)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *de;
int res,ino;
......@@ -209,6 +213,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
int msdos_create(struct inode *dir,const char *name,int len,int mode,
struct inode **result)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *de;
char msdos_name[MSDOS_NAME];
......@@ -256,6 +261,7 @@ static void dump_fat(struct super_block *sb,int start)
int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *de;
struct inode *inode,*dot;
......@@ -313,6 +319,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
static int msdos_empty(struct inode *dir)
{
struct super_block *sb = dir->i_sb;
loff_t pos;
struct buffer_head *bh;
struct msdos_dir_entry *de;
......@@ -338,6 +345,7 @@ static int msdos_empty(struct inode *dir)
int msdos_rmdir(struct inode *dir,const char *name,int len)
{
struct super_block *sb = dir->i_sb;
int res,ino;
struct buffer_head *bh;
struct msdos_dir_entry *de;
......@@ -379,6 +387,7 @@ static int msdos_unlinkx(
int len,
int nospc) /* Flag special file ? */
{
struct super_block *sb = dir->i_sb;
int res,ino;
struct buffer_head *bh;
struct msdos_dir_entry *de;
......@@ -425,6 +434,7 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,
struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
struct msdos_dir_entry *old_de,int old_ino)
{
struct super_block *sb = old_dir->i_sb;
struct buffer_head *new_bh;
struct msdos_dir_entry *new_de;
struct inode *new_inode,*old_inode;
......@@ -476,6 +486,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
struct msdos_dir_entry *old_de,int old_ino)
{
struct super_block *sb = old_dir->i_sb;
struct buffer_head *new_bh,*free_bh,*dotdot_bh;
struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
......@@ -594,6 +605,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
struct inode *new_dir,const char *new_name,int new_len)
{
struct super_block *sb = old_dir->i_sb;
char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
struct buffer_head *old_bh;
struct msdos_dir_entry *old_de;
......
......@@ -243,17 +243,16 @@ static int get_version(char * buffer)
static int get_cpuinfo(char * buffer)
{
/* to conserve memory, we define the strins yes and no in
advance */
char *yes="yes";
char *no="no";
char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6",
"7","DX/4"},
{"Pentium 60/66","Pentium 90/100","3",
"4","5","6","7","8"}};
char mask[2];
mask[0] = x86_mask+'@';
mask[1] = '\0';
return sprintf(buffer,"cpu\t\t: %c86\n"
"model\t\t: %s\n"
"mask\t\t: %c\n"
"mask\t\t: %s\n"
"vid\t\t: %s\n"
"fdiv_bug\t: %s\n"
"math\t\t: %s\n"
......@@ -269,20 +268,20 @@ static int get_cpuinfo(char * buffer)
"CMPXCHGB8B\t: %s\n",
x86+'0',
x86_model ? model[x86-4][x86_model-1] : "Unknown",
x86_mask+'@',
x86_mask ? mask : "Unknown",
x86_vendor_id,
fdiv_bug ? yes : no,
hard_math ? yes : no,
hlt_works_ok ? yes : no,
wp_works_ok ? yes : no,
x86_capability & 1 ? yes : no,
x86_capability & 2 ? yes : no,
x86_capability & 4 ? yes : no,
x86_capability & 8 ? yes : no,
x86_capability & 16 ? yes : no,
x86_capability & 32 ? yes : no,
x86_capability & 128 ? yes : no,
x86_capability & 256 ? yes : no
fdiv_bug ? "yes" : "no",
hard_math ? "yes" : "no",
hlt_works_ok ? "yes" : "no",
wp_works_ok ? "yes" : "no",
x86_capability & 1 ? "yes" : "no",
x86_capability & 2 ? "yes" : "no",
x86_capability & 4 ? "yes" : "no",
x86_capability & 8 ? "yes" : "no",
x86_capability & 16 ? "yes" : "no",
x86_capability & 32 ? "yes" : "no",
x86_capability & 128 ? "yes" : "no",
x86_capability & 256 ? "yes" : "no"
);
}
......@@ -431,7 +430,7 @@ static int get_stat(int pid, char * buffer)
else
tty_pgrp = -1;
return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
%lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %u %lu %lu %lu %lu %lu %lu \
%lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
%lu %lu %lu %lu\n",
pid,
(*p)->comm,
......
......@@ -58,16 +58,8 @@ static void UMSDOS_truncate(struct inode *inode)
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1;
}
/*
See inode.c
Some entry point are filled dynamically with function pointers
from the msdos file_operations and file_inode_operations.
The idea is to have the code as independent as possible from
the msdos file system.
*/
/* Function for normal file system (512 bytes hardware sector size) */
struct file_operations umsdos_file_operations = {
NULL, /* lseek - default */
UMSDOS_file_read, /* read */
......@@ -94,10 +86,41 @@ struct inode_operations umsdos_file_inode_operations = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* bmap */
msdos_bmap, /* bmap */
UMSDOS_truncate,/* truncate */
NULL, /* permission */
msdos_smap /* smap */
};
/* For other with larger and unaligned file system */
struct file_operations umsdos_file_operations_no_bmap = {
NULL, /* lseek - default */
UMSDOS_file_read, /* read */
UMSDOS_file_write, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
msdos_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
file_fsync /* fsync */
};
struct inode_operations umsdos_file_inode_operations_no_bmap = {
&umsdos_file_operations_no_bmap, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* bmap */
UMSDOS_truncate,/* truncate */
NULL, /* permission */
NULL, /* smap */
};
......@@ -45,6 +45,9 @@ void UMSDOS_put_inode(struct inode *inode)
PRINTK (("put inode %x owner %x pos %d dir %x\n",inode
,inode->u.umsdos_i.i_emd_owner,inode->u.umsdos_i.pos
,inode->u.umsdos_i.i_emd_dir));
if (inode != NULL && inode == pseudo_root){
printk ("Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n");
}
msdos_put_inode(inode);
}
......@@ -152,18 +155,11 @@ void umsdos_patch_inode (
if (!umsdos_isinit(inode)){
inode->u.umsdos_i.i_emd_dir = 0;
if (S_ISREG(inode->i_mode)){
static char is_init = 0;
if (!is_init){
/*
I don't want to change the msdos file system code
so I get the address of some subroutine dynamically
once.
*/
umsdos_file_inode_operations.bmap = inode->i_op->bmap;
if (inode->i_op->bmap != NULL){
inode->i_op = &umsdos_file_inode_operations;
is_init = 1;
}else{
inode->i_op = &umsdos_file_inode_operations_no_bmap;
}
inode->i_op = &umsdos_file_inode_operations;
}else if (S_ISDIR(inode->i_mode)){
if (dir != NULL){
umsdos_setup_dir_inode(inode);
......@@ -409,7 +405,7 @@ struct super_block *UMSDOS_read_super(
msdos directory, with all limitation of msdos.
*/
struct super_block *sb = msdos_read_super(s,data,silent);
printk ("UMSDOS Alpha 0.5a (compatibility level %d.%d, fast msdos)\n"
printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
,UMSDOS_VERSION,UMSDOS_RELEASE);
if (sb != NULL){
sb->s_op = &umsdos_sops;
......
......@@ -223,12 +223,14 @@ int umsdos_parse (
of the extension will be mangled. This solve the
following problem:
#
touch FILE
# FILE is invalid for DOS, so mangling is applied
# file.{_1 is created in the DOS directory
touch file.{_1
# To UMSDOS file point to a single DOS entry.
# So file.{_1 has to be mangled.
#
*/
static char special[]={
SPECIAL_MANGLING,'\0'
......@@ -270,7 +272,9 @@ int umsdos_parse (
Control character are converted to #.
Space are converted to #.
The following character are also converted to #.
#
" * + , / : ; < = > ? [ \ ] | ~
#
Sometime, the problem is not in MsDOS itself but in
command.com.
......@@ -316,10 +320,12 @@ int umsdos_parse (
Here is the list of DOS pseudo devices:
#
"prn","con","aux","nul",
"lpt1","lpt2","lpt3","lpt4",
"com1","com2","com3","com4",
"clock$"
#
and some standard ones for common DOS programs
......
......@@ -483,6 +483,7 @@ int UMSDOS_link (
Given a file /foo/file
#
ln /foo/file /tmp/file2
become internally
......@@ -490,6 +491,7 @@ int UMSDOS_link (
mv /foo/file /foo/-LINK1
ln -s /foo/-LINK1 /foo/file
ln -s /foo/-LINK1 /tmp/file2
#
Using this strategy, we can operate on /foo/file or /foo/file2.
We can remove one and keep the other, like a normal Unix hard link.
......@@ -502,6 +504,7 @@ int UMSDOS_link (
The strategy for hard link introduces a side effect that
may or may not be acceptable. Here is the sequence
#
mkdir subdir1
touch subdir1/file
mkdir subdir2
......@@ -509,6 +512,7 @@ int UMSDOS_link (
rm subdir1/file
rmdir subdir1
rmdir: subdir1: Directory not empty
#
This happen because there is an invisible file (--link) in
subdir1 which is referenced by subdir2/file.
......@@ -519,12 +523,14 @@ int UMSDOS_link (
Another weakness of hard link come from the fact that
it is based on hidden symbolic links. Here is an example.
#
mkdir /subdir1
touch /subdir1/file
mkdir /subdir2
ln /subdir1/file subdir2/file
mv /subdir1 subdir3
ls -l /subdir2/file
#
Since /subdir2/file is a hidden symbolic link
to /subdir1/..hlinkNNN, accessing it will fail since
......@@ -765,6 +771,7 @@ int UMSDOS_rmdir(
but you rapidly get iput() all around. Here is an exemple
of what I am trying to avoid.
#
if (a){
...
if(b){
......@@ -783,10 +790,12 @@ int UMSDOS_rmdir(
}
// Was iput finally done ?
return status;
#
Here is the style I am using. Still sometime I do the
first when things are very simple (or very complicated :-( )
#
if (a){
if (b){
...
......@@ -797,6 +806,7 @@ int UMSDOS_rmdir(
...
}
return status;
#
Again, while this help clarifying the code, I often get a lot
of iput(), unlike the first style, where I can place few
......@@ -812,6 +822,7 @@ int UMSDOS_rmdir(
where an iput() is done, the inode is simply nulled, disabling
the last one.
#
if (a){
if (b){
...
......@@ -824,6 +835,7 @@ int UMSDOS_rmdir(
}
iput (dir);
return status;
#
Note that the umsdos_lockcreate() and umsdos_unlockcreate() function
pair goes against this practice of "forgetting" the inode as soon
......
/*
* include/asm-alpha/bugs.h
*
* Copyright (C) 1994 Linus Torvalds
*/
/*
* This is included by init/main.c to check for architecture-dependent bugs.
*
* Needs:
* void check_bugs(void);
*/
/*
* I don't know of any alpha bugs yet.. Nice chip
*/
static void check_bugs(void)
{
}
/*
* include/asm-i386/processor.h
*
* Copyright (C) 1994 Linus Torvalds
*/
#ifndef __ASM_I386_PROCESSOR_H
#define __ASM_I386_PROCESSOR_H
/*
* Bus types
*/
extern int EISA_bus;
#define MCA_bus 0
struct thread_struct {
unsigned long ksp;
unsigned long usp;
unsigned long ptbr;
unsigned int pcc;
unsigned int asn;
unsigned long unique;
unsigned long flags;
unsigned long res1, res2;
};
#define INIT_TSS { \
0, 0, 0, \
0, 0, 0, \
0, 0, 0, \
}
#endif /* __ASM_I386_PROCESSOR_H */
......@@ -62,6 +62,10 @@
#define PAL_rtsys 61
#define PAL_rti 63
#define halt() __asm__ __volatile__(".long 0");
#define move_to_user_mode() halt()
#define switch_to(x) halt()
#ifndef mb
#define mb() __asm__ __volatile__("mb": : :"memory")
#endif
......@@ -77,4 +81,44 @@ __asm__ __volatile__( \
: "$0", "$1", "$16", "$22", "$23", "$24", "$25"); \
__old_ipl; })
#define cli() swpipl(7)
#define sti() swpipl(0)
#define save_flags(flags) do { flags = swpipl(7); } while (0)
#define restore_flags(flags) swpipl(flags)
extern inline unsigned long xchg_u32(int * m, unsigned long val)
{
unsigned long dummy, dummy2;
__asm__ __volatile__(
"\n1:\t"
"ldl_l %0,%1\n\t"
"bis %2,%2,%3\n\t"
"stl_c %3,%1\n\t"
"beq %3,1b\n"
: "=r" (val), "=m" (*m), "=r" (dummy), "=r" (dummy2)
: "1" (*m), "2" (val));
return val;
}
extern inline unsigned long xchg_u64(long * m, unsigned long val)
{
unsigned long dummy, dummy2;
__asm__ __volatile__(
"\n1:\t"
"ldq_l %0,%1\n\t"
"bis %2,%2,%3\n\t"
"stq_c %3,%1\n\t"
"beq %3,1b\n"
: "=r" (val), "=m" (*m), "=r" (dummy), "=r" (dummy2)
: "1" (*m), "2" (val));
return val;
}
extern inline void * xchg_ptr(void *m, void *val)
{
return (void *) xchg_u64((long *) m, (unsigned long) val);
}
#endif
......@@ -21,13 +21,13 @@ typedef long ptrdiff_t;
* header files exported to user space
*/
typedef signed char __s8;
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef signed short __s16;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef signed int __s32;
typedef __signed__ int __s32;
typedef unsigned int __u32;
/*
......@@ -35,14 +35,14 @@ typedef unsigned int __u32;
*/
#if ((~0UL) == 0xffffffff)
#ifndef __STRICT_ANSI__
typedef signed long long __s64;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
#else
typedef signed long __s64;
typedef __signed__ long __s64;
typedef unsigned long __u64;
#endif
......
/*
* include/asm-generic/string.h
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef _ASM_GENERIC_STRING_H_
#define _ASM_GENERIC_STRING_H_
/*
* Portable string functions. These are not complete:
* memcpy() and memmove() are still missing.
*/
#ifdef __USE_PORTABLE_strcpy
extern inline char * strcpy(char * dest,const char *src)
{
char *xdest = dest;
while(*dest++ = *src++);
return xdest;
}
#endif
#ifdef __USE_PORTABLE_strncpy
extern inline char * strncpy(char * dest,const char *src,size_t count)
{
char *xdest = dest;
while((*dest++ = *src++) && --count);
return dest;
}
#endif
#ifdef __USE_PORTABLE_strcat
extern inline char * strcat(char * dest, const char * src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++))
;
return tmp;
}
#endif
#ifdef __USE_PORTABLE_strncat
extern inline char * strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
if (count) {
while (*dest)
dest++;
while ((*dest++ = *src++)) {
if (--count == 0)
break;
}
}
return tmp;
}
#endif
#ifdef __USE_PORTABLE_strcmp
extern int strcmp(const char * cs,const char * ct)
{
register char __res;
while(1) {
if(__res = *cs - *ct++ && *cs++)
break;
}
return __res;
}
#endif
#ifdef __USE_PORTABLE_strncmp
extern inline int strncmp(const char * cs,const char * ct,size_t count)
{
register char __res;
while(count) {
if(__res = *cs - *ct++ || !*cs++)
break;
count--;
}
return __res;
}
#endif
#ifdef __USE_PORTABLE_strchr
extern inline char * strchr(const char * s,char c)
{
const char ch = c;
for(; *s != ch; ++s)
if (*s == '\0')
return( NULL );
return( (char *) s);
}
#endif
#ifdef __USE_PORTABLE_strlen
extern inline size_t strlen(const char * s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc) ;
return(sc - s);
}
#endif
#ifdef __USE_PORTABLE_strspn
extern inline size_t strspn(const char *s, const char *accept)
{
const char *p;
const char *a;
size_t count = 0;
for (p = s; *p != '\0'; ++p)
{
for (a = accept; *a != '\0'; ++a)
if (*p == *a)
break;
if (*a == '\0')
return count;
else
++count;
}
return count;
}
#endif
#ifdef __USE_PORTABLE_strpbrk
extern inline char * strpbrk(const char * cs,const char * ct)
{
const char *sc1,*sc2;
for( sc1 = cs; *sc1 != '\0'; ++sc1)
for( sc2 = ct; *sc2 != '\0'; ++sc2)
if (*sc1 == *sc2)
return((char *) sc1);
return( NULL );
}
#endif
#ifdef __USE_PORTABLE_strtok
extern inline char * strtok(char * s,const char * ct)
{
char *sbegin, *send;
static char *ssave = NULL;
sbegin = s ? s : ssave;
if (!sbegin) {
return NULL;
}
sbegin += strspn(sbegin,ct);
if (*sbegin == '\0') {
ssave = NULL;
return( NULL );
}
send = strpbrk( sbegin, ct);
if (send && *send != '\0')
*send++ = '\0';
ssave = send;
return (sbegin);
}
#endif
#ifdef __USE_PORTABLE_memset
extern inline void * memset(void * s,char c,size_t count)
{
void *xs = s;
while(n--)
*s++ = c;
return xs;
}
#endif
#ifdef __USE_PORTABLE_memcpy
#error "Portable memcpy() not implemented yet"
#endif
#ifdef __USE_PORTABLE_memmove
#error "Portable memmove() not implemented yet"
#endif
#ifdef __USE_PORTABLE_memcmp
extern inline int memcmp(const void * cs,const void * ct,size_t count)
{
const unsigned char *su1, *su2;
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if (*su1 != *su2)
return((*su1 < *su2) ? -1 : +1);
return(0);
}
#endif
#endif /* _ASM_GENERIC_STRING_H_ */
/*
* include/asm-i386/bugs.h
*
* Copyright (C) 1994 Linus Torvalds
*/
/*
* This is included by init/main.c to check for architecture-dependent bugs.
*
* Needs:
* void check_bugs(void);
*/
#define CONFIG_BUGi386
static void no_halt(char *s, int *ints)
{
hlt_works_ok = 0;
}
static void no_387(char *s, int *ints)
{
hard_math = 0;
__asm__("movl %%cr0,%%eax\n\t"
"orl $0xE,%%eax\n\t"
"movl %%eax,%%cr0\n\t" : : : "ax");
}
static char fpu_error = 0;
static void copro_timeout(void)
{
fpu_error = 1;
timer_table[COPRO_TIMER].expires = jiffies+100;
timer_active |= 1<<COPRO_TIMER;
printk("387 failed: trying to reset\n");
send_sig(SIGFPE, last_task_used_math, 1);
outb_p(0,0xf1);
outb_p(0,0xf0);
}
static void check_fpu(void)
{
static double x = 4195835.0;
static double y = 3145727.0;
unsigned short control_word;
if (!hard_math) {
#ifndef CONFIG_MATH_EMULATION
printk("No coprocessor found and no math emulation present.\n");
printk("Giving up.\n");
for (;;) ;
#endif
return;
}
/*
* check if exception 16 works correctly.. This is truly evil
* code: it disables the high 8 interrupts to make sure that
* the irq13 doesn't happen. But as this will lead to a lockup
* if no exception16 arrives, it depends on the fact that the
* high 8 interrupts will be re-enabled by the next timer tick.
* So the irq13 will happen eventually, but the exception 16
* should get there first..
*/
printk("Checking 386/387 coupling... ");
timer_table[COPRO_TIMER].expires = jiffies+50;
timer_table[COPRO_TIMER].fn = copro_timeout;
timer_active |= 1<<COPRO_TIMER;
__asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait": :"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
timer_active &= ~(1<<COPRO_TIMER);
if (fpu_error)
return;
if (!ignore_irq13) {
printk("Ok, fpu using old IRQ13 error reporting\n");
return;
}
__asm__("fninit\n\t"
"fldl %1\n\t"
"fdivl %2\n\t"
"fmull %2\n\t"
"fldl %1\n\t"
"fsubp %%st,%%st(1)\n\t"
"fistpl %0\n\t"
"fwait\n\t"
"fninit"
: "=m" (*&fdiv_bug)
: "m" (*&x), "m" (*&y));
if (!fdiv_bug) {
printk("Ok, fpu using exception 16 error reporting.\n");
return;
}
printk("Ok, FDIV bug i%c86 system\n", '0'+x86);
}
static void check_hlt(void)
{
printk("Checking 'hlt' instruction... ");
if (!hlt_works_ok) {
printk("disabled\n");
return;
}
__asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
printk("Ok.\n");
}
static void check_bugs(void)
{
check_fpu();
check_hlt();
system_utsname.machine[1] = '0' + x86;
}
/*
* include/asm-i386/processor.h
*
* Copyright (C) 1994 Linus Torvalds
*/
#ifndef __ASM_I386_PROCESSOR_H
#define __ASM_I386_PROCESSOR_H
/*
* System setup and hardware bug flags..
*/
extern char hard_math;
extern char x86; /* lower 4 bits */
extern char x86_vendor_id[13];
extern char x86_model; /* lower 4 bits */
extern char x86_mask; /* lower 4 bits */
extern int x86_capability; /* field of flags */
extern int fdiv_bug;
extern char ignore_irq13;
extern char wp_works_ok; /* doesn't work on a 386 */
extern char hlt_works_ok; /* problems on some 486Dx4's and old 386's */
#define start_bh_atomic() \
__asm__ __volatile__("incl _intr_count")
#define end_bh_atomic() \
__asm__ __volatile__("decl _intr_count")
/*
* Bus types (default is ISA, but people can check others with these..)
* MCA_bus hardcoded to 0 for now.
*/
extern int EISA_bus;
#define MCA_bus 0
/*
* User space process size: 3GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
#define TASK_SIZE 0xc0000000
/*
* Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
*/
#define IO_BITMAP_SIZE 32
struct i387_hard_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
};
struct i387_soft_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long top;
struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 bytes */
unsigned char lookahead;
struct info *info;
unsigned long entry_eip;
};
union i387_union {
struct i387_hard_struct hard;
struct i387_soft_struct soft;
};
struct thread_struct {
unsigned short back_link,__blh;
unsigned long esp0;
unsigned short ss0,__ss0h;
unsigned long esp1;
unsigned short ss1,__ss1h;
unsigned long esp2;
unsigned short ss2,__ss2h;
unsigned long cr3;
unsigned long eip;
unsigned long eflags;
unsigned long eax,ecx,edx,ebx;
unsigned long esp;
unsigned long ebp;
unsigned long esi;
unsigned long edi;
unsigned short es, __esh;
unsigned short cs, __csh;
unsigned short ss, __ssh;
unsigned short ds, __dsh;
unsigned short fs, __fsh;
unsigned short gs, __gsh;
unsigned short ldt, __ldth;
unsigned short trace, bitmap;
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
unsigned long tr;
unsigned long cr2, trap_no, error_code;
/* floating point info */
union i387_union i387;
/* virtual 86 mode info */
struct vm86_struct * vm86_info;
unsigned long screen_bitmap;
unsigned long v86flags, v86mask, v86mode;
};
#define INIT_TSS { \
0,0, \
sizeof(init_kernel_stack) + (long) &init_kernel_stack, \
KERNEL_DS, 0, \
0,0,0,0,0,0, \
(long) &swapper_pg_dir, \
0,0,0,0,0,0,0,0,0,0, \
USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0, \
_LDT(0),0, \
0, 0x8000, \
{~0, }, /* ioperm */ \
_TSS(0), 0, 0,0, \
{ { 0, }, }, /* 387 state */ \
NULL, 0, 0, 0, 0 /* vm86_info */ \
}
#endif /* __ASM_I386_PROCESSOR_H */
......@@ -18,6 +18,125 @@ __asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
"mov %%ax,%%gs" \
: /* no outputs */ :"i" (USER_DS), "i" (USER_CS):"ax")
/*
* Entry into gdt where to find first TSS. GDT layout:
* 0 - nul
* 1 - kernel code segment
* 2 - kernel data segment
* 3 - user code segment
* 4 - user data segment
* ...
* 8 - TSS #0
* 9 - LDT #0
* 10 - TSS #1
* 11 - LDT #1
*/
#define FIRST_TSS_ENTRY 8
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
#define store_TR(n) \
__asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \
"shrl $4,%%eax" \
:"=a" (n) \
:"0" (0),"i" (FIRST_TSS_ENTRY<<3))
/* This special macro can be used to load a debugging register */
#define loaddebug(register) \
__asm__("movl %0,%%edx\n\t" \
"movl %%edx,%%db" #register "\n\t" \
: /* no output */ \
:"m" (current->debugreg[register]) \
:"dx");
/*
* switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used
* the math co-processor latest.
*
* It also reloads the debug regs if necessary..
*/
#define switch_to(tsk) do { \
__asm__("cli\n\t" \
"xchgl %%ecx,_current\n\t" \
"ljmp %0\n\t" \
"sti\n\t" \
"cmpl %%ecx,_last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
: /* no output */ \
:"m" (*(((char *)&tsk->tss.tr)-4)), \
"c" (tsk) \
:"cx"); \
/* Now maybe reload the debug registers */ \
if(current->debugreg[7]){ \
loaddebug(0); \
loaddebug(1); \
loaddebug(2); \
loaddebug(3); \
loaddebug(6); \
} \
} while (0)
#define _set_base(addr,base) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %%dl,%1\n\t" \
"movb %%dh,%2" \
: /* no output */ \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7)), \
"d" (base) \
:"dx")
#define _set_limit(addr,limit) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %1,%%dh\n\t" \
"andb $0xf0,%%dh\n\t" \
"orb %%dh,%%dl\n\t" \
"movb %%dl,%1" \
: /* no output */ \
:"m" (*(addr)), \
"m" (*((addr)+6)), \
"d" (limit) \
:"dx")
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
static inline unsigned long _get_base(char * addr)
{
unsigned long __base;
__asm__("movb %3,%%dh\n\t"
"movb %2,%%dl\n\t"
"shll $16,%%edx\n\t"
"movw %1,%%dx"
:"=&d" (__base)
:"m" (*((addr)+2)),
"m" (*((addr)+4)),
"m" (*((addr)+7)));
return __base;
}
#define get_base(ldt) _get_base( ((char *)&(ldt)) )
static inline unsigned long get_limit(unsigned long segment)
{
unsigned long __limit;
__asm__("lsll %1,%0"
:"=r" (__limit):"r" (segment));
return __limit+1;
}
#define nop() __asm__ __volatile__ ("nop")
/*
......@@ -34,12 +153,32 @@ __asm__ __volatile__ ( \
:"ax")
extern inline unsigned long xchg_u8(char * m, unsigned long val)
{
__asm__("xchgb %b0,%1":"=q" (val),"=m" (*m):"0" (val):"memory");
return val;
}
extern inline unsigned long xchg_u16(short * m, unsigned long val)
{
__asm__("xchgw %w0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
return val;
}
extern inline unsigned long xchg_u32(long * m, unsigned long val)
{
__asm__("xchgl %0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
return val;
}
extern inline int tas(char * m)
{
char res;
return xchg_u8(m,1);
}
__asm__("xchgb %0,%1":"=q" (res),"=m" (*m):"0" (0x1));
return res;
extern inline void * xchg_ptr(void * m, void * val)
{
return (void *) xchg_u32(m, (unsigned long) val);
}
#define sti() __asm__ __volatile__ ("sti": : :"memory")
......@@ -104,5 +243,10 @@ __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
#define set_ldt_desc(n,addr,size) \
_set_tssldt_desc(((char *) (n)),((int)(addr)),((size << 3) - 1),"0x82")
/*
* This is the ldt that every process will get unless we need
* something other than this.
*/
extern struct desc_struct default_ldt;
#endif
......@@ -30,7 +30,7 @@ typedef unsigned short __u16;
typedef __signed__ long __s32;
typedef unsigned long __u32;
#ifndef __STRICT_ANSI__
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
......
/* include/asm-sparc/bugs.h: Sparc probes for various bugs.
*
* Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
*/
/*
* This is included by init/main.c to check for architecture-dependent bugs.
*
* Needs:
* void check_bugs(void);
*/
#define CONFIG_BUGSPARC
#include <asm/openprom.h>
extern struct promvec *romvec;
extern int tbase_needs_unmapping; /* We do the bug workaround in pagetables.c */
static void check_mmu()
{
register struct promvec *romvec;
register int root_node;
register unsigned int present;
root_node = (*(romvec->pv_nodeops->no_nextnode))(0);
tbase_needs_unmapping=0;
present = 0;
(*(romvec->pv_nodeops->no_getprop))(root_node, "buserr-type",
(char *) &present);
if(present == 1)
{
tbase_needs_unmapping=1;
printk("MMU bug found: not allowing trapbase to be cached\n");
}
return;
}
static void
check_bugs(void)
{
check_mmu();
}
#ifndef _SPARC_OPENPROM_H
#define _SPARC_OPENPROM_H
/* openprom.h: Prom structures and defines for access to the OPENBOOT
prom routines and data areas.
......@@ -16,7 +19,7 @@
#define LINUX_OPPROM_MAGIC 0x10010407
/* The device functions structure for the v0 prom. Nice and neat, open,
close, read & write divied up between net + block + char devices. We
close, read & write divvied up between net + block + char devices. We
also have a seek routine only usable for block devices. The divide
and conquer strategy of this struct becomes unnecessary for v2.
......@@ -51,7 +54,7 @@ struct linux_dev_v0_funcs {
the time can be a pain in the rear after a while. Why v2 has memory
allocations in here are beyond me. Perhaps they figure that if you
are going to use only the prom's device drivers then your memory
management is either non-existant or pretty sad. :-)
management is either non-existent or pretty sad. :-)
*/
struct linux_dev_v2_funcs {
......@@ -64,7 +67,7 @@ struct linux_dev_v2_funcs {
caddr_t (*v2_dumb_mem_alloc)(caddr_t va, unsigned sz);
void (*v2_dumb_mem_free)(caddr_t va, unsigned sz);
/* "dumb" mmap() munmap(), copy on write? whats that? */
/* "dumb" mmap() munmap(), copy on write? what's that? */
caddr_t (*v2_dumb_mmap)(caddr_t virta, int asi, unsigned prot, unsigned sz);
void (*v2_dumb_munmap)(caddr_t virta, unsigned size);
......@@ -103,7 +106,7 @@ struct linux_mem_v0 {
struct linux_mlist_v0 **v0_available; /* what phys. is left over */
};
/* Arguements sent to the kernel from the boot prompt. */
/* Arguments sent to the kernel from the boot prompt. */
struct linux_arguments_v0 {
char *argv[8]; /* argv format for boot string */
......@@ -260,3 +263,5 @@ struct nodeops {
int (*no_setprop)(int node, caddr_t name, caddr_t val, int len);
caddr_t (*no_nextprop)(int node, caddr_t name);
};
#endif /* !(_SPARC_OPENPROM_H) */
......@@ -10,19 +10,21 @@
* however this won't be for a while.
*/
typedef signed char __s8;
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef signed short __s16;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef signed int __s32;
typedef __signed__ int __s32;
typedef unsigned int __u32;
/* Only 32-bit sparcs for now so.... */
typedef signed long long __s64;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long __s64;
typedef unsigned long long __s64;
#endif
#ifdef __KERNEL__
......
......@@ -44,4 +44,6 @@ extern int * blk_size[MAX_BLKDEV];
extern int * blksize_size[MAX_BLKDEV];
extern int * hardsect_size[MAX_BLKDEV];
#endif
......@@ -9,12 +9,13 @@
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif
#ifndef UTS_NODENAME
#define UTS_NODENAME "(none)" /* set by sethostname() */
#endif
#ifndef UTS_MACHINE
#define UTS_MACHINE "i386" /* hardware type */
#define UTS_MACHINE "unknown"
#endif
#ifndef UTS_NODENAME
#define UTS_NODENAME "(none)" /* set by sethostname() */
#endif
#ifndef UTS_DOMAINNAME
......
......@@ -124,6 +124,11 @@ extern unsigned short int ntohs(unsigned short int);
extern unsigned long int htonl(unsigned long int);
extern unsigned short int htons(unsigned short int);
extern unsigned long int __ntohl(unsigned long int);
extern unsigned short int __ntohs(unsigned short int);
extern unsigned long int __constant_ntohl(unsigned long int);
extern unsigned short int __constant_ntohs(unsigned short int);
extern __inline__ unsigned long int
__ntohl(unsigned long int x)
{
......
......@@ -2,6 +2,8 @@
#ifndef _LINUX_INTERRUPT_H
#define _LINUX_INTERRUPT_H
#include <asm/bitops.h>
struct bh_struct {
void (*routine)(void *);
void *data;
......@@ -27,17 +29,17 @@ enum {
extern inline void mark_bh(int nr)
{
__asm__ __volatile__("orl %1,%0":"=m" (bh_active):"ir" (1<<nr));
set_bit(nr, &bh_active);
}
extern inline void disable_bh(int nr)
{
__asm__ __volatile__("andl %1,%0":"=m" (bh_mask):"ir" (~(1<<nr)));
clear_bit(nr, &bh_mask);
}
extern inline void enable_bh(int nr)
{
__asm__ __volatile__("orl %1,%0":"=m" (bh_mask):"ir" (1<<nr));
set_bit(nr, &bh_mask);
}
#endif
......@@ -110,12 +110,6 @@ struct fat_cache {
#ifdef __KERNEL__
static inline struct buffer_head *msdos_sread(int dev,int sector)
{
return bread(dev,sector,SECTOR_SIZE);
}
/* misc.c */
extern void fs_panic(struct super_block *s,char *msg);
......@@ -180,6 +174,7 @@ extern int msdos_readdir (struct inode *inode, struct file *filp,
/* file.c */
extern struct inode_operations msdos_file_inode_operations;
extern struct inode_operations msdos_file_inode_operations_1024;
extern int msdos_file_read(struct inode *, struct file *, char *, int);
extern int msdos_file_write(struct inode *, struct file *, char *, int);
extern struct inode_operations msdos_file_inode_operations_no_bmap;
......
......@@ -27,7 +27,7 @@ enum root_directory_inos {
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
PROC_PROFILE /* wether enabled or not */
PROC_PROFILE /* whether enabled or not */
};
enum pid_directory_inos {
......
......@@ -57,8 +57,8 @@ struct rusage {
#define RLIM_INFINITY ((long)(~0UL>>1))
struct rlimit {
int rlim_cur;
int rlim_max;
long rlim_cur;
long rlim_max;
};
#define PRIO_MIN (-99)
......
......@@ -11,52 +11,14 @@
#define HZ 100
/*
* System setup and hardware bug flags..
*/
extern char hard_math;
extern char x86; /* lower 4 bits */
extern char x86_vendor_id[13];
extern char x86_model; /* lower 4 bits */
extern char x86_mask; /* lower 4 bits */
extern int x86_capability; /* field of flags */
extern int fdiv_bug;
extern char ignore_irq13;
extern char wp_works_ok; /* doesn't work on a 386 */
extern char hlt_works_ok; /* problems on some 486Dx4's and old 386's */
extern unsigned long intr_count;
extern unsigned long event;
#define start_bh_atomic() \
__asm__ __volatile__("incl _intr_count")
#define end_bh_atomic() \
__asm__ __volatile__("decl _intr_count")
/*
* Bus types (default is ISA, but people can check others with these..)
* MCA_bus hardcoded to 0 for now.
*/
extern int EISA_bus;
#define MCA_bus 0
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/tasks.h>
#include <asm/system.h>
/*
* User space process size: 3GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
#define TASK_SIZE 0xc0000000
/*
* Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
*/
#define IO_BITMAP_SIZE 32
/*
* These are the constant used to fake the fixed-point load-average
* counting. Some notes:
......@@ -98,6 +60,8 @@ extern unsigned long avenrun[]; /* Load averages */
#include <linux/math_emu.h>
#include <linux/ptrace.h>
#include <asm/processor.h>
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
......@@ -119,82 +83,6 @@ asmlinkage void schedule(void);
#endif /* __KERNEL__ */
struct i387_hard_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
};
struct i387_soft_struct {
long cwd;
long swd;
long twd;
long fip;
long fcs;
long foo;
long fos;
long top;
struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 bytes */
unsigned char lookahead;
struct info *info;
unsigned long entry_eip;
};
union i387_union {
struct i387_hard_struct hard;
struct i387_soft_struct soft;
};
struct tss_struct {
unsigned short back_link,__blh;
unsigned long esp0;
unsigned short ss0,__ss0h;
unsigned long esp1;
unsigned short ss1,__ss1h;
unsigned long esp2;
unsigned short ss2,__ss2h;
unsigned long cr3;
unsigned long eip;
unsigned long eflags;
unsigned long eax,ecx,edx,ebx;
unsigned long esp;
unsigned long ebp;
unsigned long esi;
unsigned long edi;
unsigned short es, __esh;
unsigned short cs, __csh;
unsigned short ss, __ssh;
unsigned short ds, __dsh;
unsigned short fs, __fsh;
unsigned short gs, __gsh;
unsigned short ldt, __ldth;
unsigned short trace, bitmap;
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
unsigned long tr;
unsigned long cr2, trap_no, error_code;
union i387_union i387;
};
#define INIT_TSS { \
0,0, \
sizeof(init_kernel_stack) + (long) &init_kernel_stack, \
KERNEL_DS, 0, \
0,0,0,0,0,0, \
(long) &swapper_pg_dir, \
0,0,0,0,0,0,0,0,0,0, \
USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0, \
_LDT(0),0, \
0, 0x8000, \
{~0, }, /* ioperm */ \
_TSS(0), 0, 0,0, \
{ { 0, }, } /* 387 state */ \
}
struct files_struct {
int count;
fd_set close_on_exec;
......@@ -286,10 +174,6 @@ struct task_struct {
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
char comm[16];
/* virtual 86 mode stuff */
struct vm86_struct * vm86_info;
unsigned long screen_bitmap;
unsigned long v86flags, v86mask, v86mode;
/* file system info */
int link_count;
struct tty_struct *tty; /* NULL if no tty */
......@@ -298,7 +182,7 @@ struct task_struct {
/* ldt for this task - used by Wine. If NULL, default_ldt is used */
struct desc_struct *ldt;
/* tss for this task */
struct tss_struct tss;
struct thread_struct tss;
/* filesystem information */
struct fs_struct fs[1];
/* open file information */
......@@ -345,7 +229,6 @@ struct task_struct {
{ 0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
/* math */ 0, \
/* comm */ "swapper", \
/* vm86_info */ NULL, 0, 0, 0, 0, \
/* fs info */ 0,NULL, \
/* ipc */ NULL, \
/* ldt */ NULL, \
......@@ -381,79 +264,6 @@ extern int in_group_p(gid_t grp);
extern int request_irq(unsigned int irq,void (*handler)(int), unsigned long flags, const char *device);
extern void free_irq(unsigned int irq);
/*
* Entry into gdt where to find first TSS. GDT layout:
* 0 - nul
* 1 - kernel code segment
* 2 - kernel data segment
* 3 - user code segment
* 4 - user data segment
* ...
* 8 - TSS #0
* 9 - LDT #0
* 10 - TSS #1
* 11 - LDT #1
*/
#define FIRST_TSS_ENTRY 8
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
#define store_TR(n) \
__asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \
"shrl $4,%%eax" \
:"=a" (n) \
:"0" (0),"i" (FIRST_TSS_ENTRY<<3))
/*
* switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used
* tha math co-processor latest.
*/
#define switch_to(tsk) \
__asm__("cli\n\t" \
"xchgl %%ecx,_current\n\t" \
"ljmp %0\n\t" \
"sti\n\t" \
"cmpl %%ecx,_last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
: /* no output */ \
:"m" (*(((char *)&tsk->tss.tr)-4)), \
"c" (tsk) \
:"cx")
#define _set_base(addr,base) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %%dl,%1\n\t" \
"movb %%dh,%2" \
: /* no output */ \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7)), \
"d" (base) \
:"dx")
#define _set_limit(addr,limit) \
__asm__("movw %%dx,%0\n\t" \
"rorl $16,%%edx\n\t" \
"movb %1,%%dh\n\t" \
"andb $0xf0,%%dh\n\t" \
"orb %%dh,%%dl\n\t" \
"movb %%dl,%1" \
: /* no output */ \
:"m" (*(addr)), \
"m" (*((addr)+6)), \
"d" (limit) \
:"dx")
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
/*
* The wait-queues are circular lists, and you have to be *very* sure
* to keep them correct. Use only these two functions to add/remove
......@@ -556,30 +366,6 @@ extern inline void up(struct semaphore * sem)
wake_up(&sem->wait);
}
static inline unsigned long _get_base(char * addr)
{
unsigned long __base;
__asm__("movb %3,%%dh\n\t"
"movb %2,%%dl\n\t"
"shll $16,%%edx\n\t"
"movw %1,%%dx"
:"=&d" (__base)
:"m" (*((addr)+2)),
"m" (*((addr)+4)),
"m" (*((addr)+7)));
return __base;
}
#define get_base(ldt) _get_base( ((char *)&(ldt)) )
static inline unsigned long get_limit(unsigned long segment)
{
unsigned long __limit;
__asm__("lsll %1,%0"
:"=r" (__limit):"r" (segment));
return __limit+1;
}
#define REMOVE_LINKS(p) do { unsigned long flags; \
save_flags(flags) ; cli(); \
(p)->next_task->prev_task = (p)->prev_task; \
......@@ -609,21 +395,6 @@ static inline unsigned long get_limit(unsigned long segment)
#define for_each_task(p) \
for (p = &init_task ; (p = p->next_task) != &init_task ; )
/*
* This is the ldt that every process will get unless we need
* something other than this.
*/
extern struct desc_struct default_ldt;
/* This special macro can be used to load a debugging register */
#define loaddebug(register) \
__asm__("movl %0,%%edx\n\t" \
"movl %%edx,%%db" #register "\n\t" \
: /* no output */ \
:"m" (current->debugreg[register]) \
:"dx");
#endif /* __KERNEL__ */
#endif
......@@ -11,19 +11,28 @@
extern "C" {
#endif
extern char * strcpy(char *,const char *);
extern char * strncpy(char *,const char *,size_t);
extern char * strcat(char *, const char *);
extern char * strncat(char *, const char *, size_t);
extern char * strchr(const char *,char);
extern char * strpbrk(const char *,const char *);
extern char * strtok(char *,const char *);
extern size_t strlen(const char *);
extern size_t strspn(const char *,const char *);
extern int strcmp(const char *,const char *);
extern int strncmp(const char *,const char *,size_t);
extern void * memset(void *,char,size_t);
extern void * memcpy(void *,const void *,size_t);
extern void * memmove(void *,const void *,size_t);
extern int memcmp(const void *,const void *,size_t);
/*
* Include machine specific inline routines
*/
#include <asm/string.h>
#ifdef __USE_PORTABLE_STRINGS_H_
/*
* include/generic/string.h imports all the string functions,
* for which no appropriate assembler replacements have been provided.
*/
#include <asm-generic/string.h>
#endif
#ifdef __cplusplus
}
#endif
......
......@@ -143,9 +143,7 @@ _INLINE_ void run_task_queue(task_queue *list)
void (*f) (void *);
while(1) {
p = &tq_last;
__asm__ __volatile__("xchgl %0,%2" : "=r" (p) :
"0" (p), "m" (*list) : "memory");
p = xchg_ptr(list,&tq_last);
if(p == &tq_last)
break;
......
......@@ -28,7 +28,7 @@ typedef unsigned short nlink_t;
typedef int daddr_t;
typedef long off_t;
#ifndef __STRICT_ANSI__
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define _LOFF_T
typedef long long loff_t;
#endif
......
......@@ -24,12 +24,12 @@
#include <linux/utsname.h>
#include <linux/ioport.h>
#include <asm/bugs.h>
extern unsigned long * prof_buffer;
extern unsigned long prof_len;
extern char etext, end;
extern char *linux_banner;
asmlinkage void lcall7(void);
struct desc_struct default_ldt;
/*
* we need this inline - forking from kernel space will result
......@@ -159,8 +159,6 @@ unsigned char aux_device_present;
int ramdisk_size;
int root_mountflags = 0;
static char fpu_error = 0;
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char *get_options(char *str, int *ints)
......@@ -183,6 +181,10 @@ struct {
} bootsetups[] = {
{ "reserve=", reserve_setup },
{ "ramdisk=", ramdisk_setup },
#ifdef CONFIG_BUGi386
{ "no-hlt", no_halt },
{ "no387", no_387 },
#endif
#ifdef CONFIG_INET
{ "ether=", eth_setup },
#endif
......@@ -352,17 +354,6 @@ static void parse_options(char *line)
console_loglevel = 10;
continue;
}
if (!strcmp(line,"no-hlt")) {
hlt_works_ok = 0;
continue;
}
if (!strcmp(line,"no387")) {
hard_math = 0;
__asm__("movl %%cr0,%%eax\n\t"
"orl $0xE,%%eax\n\t"
"movl %%eax,%%cr0\n\t" : : : "ax");
continue;
}
if (checksetup(line))
continue;
/*
......@@ -409,91 +400,7 @@ static void copy_options(char * to, char * from)
*to = '\0';
}
static void copro_timeout(void)
{
fpu_error = 1;
timer_table[COPRO_TIMER].expires = jiffies+100;
timer_active |= 1<<COPRO_TIMER;
printk("387 failed: trying to reset\n");
send_sig(SIGFPE, last_task_used_math, 1);
outb_p(0,0xf1);
outb_p(0,0xf0);
}
static void check_fpu(void)
{
static double x = 4195835.0;
static double y = 3145727.0;
unsigned short control_word;
if (!hard_math) {
#ifndef CONFIG_MATH_EMULATION
printk("No coprocessor found and no math emulation present.\n");
printk("Giving up.\n");
for (;;) ;
#endif
return;
}
/*
* check if exception 16 works correctly.. This is truly evil
* code: it disables the high 8 interrupts to make sure that
* the irq13 doesn't happen. But as this will lead to a lockup
* if no exception16 arrives, it depends on the fact that the
* high 8 interrupts will be re-enabled by the next timer tick.
* So the irq13 will happen eventually, but the exception 16
* should get there first..
*/
printk("Checking 386/387 coupling... ");
timer_table[COPRO_TIMER].expires = jiffies+50;
timer_table[COPRO_TIMER].fn = copro_timeout;
timer_active |= 1<<COPRO_TIMER;
__asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait": :"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
timer_active &= ~(1<<COPRO_TIMER);
if (fpu_error)
return;
if (!ignore_irq13) {
printk("Ok, fpu using old IRQ13 error reporting\n");
return;
}
__asm__("fninit\n\t"
"fldl %1\n\t"
"fdivl %2\n\t"
"fmull %2\n\t"
"fldl %1\n\t"
"fsubp %%st,%%st(1)\n\t"
"fistpl %0\n\t"
"fwait\n\t"
"fninit"
: "=m" (*&fdiv_bug)
: "m" (*&x), "m" (*&y));
if (!fdiv_bug) {
printk("Ok, fpu using exception 16 error reporting.\n");
return;
}
printk("Ok, FDIV bug i%c86 system\n", '0'+x86);
}
static void check_hlt(void)
{
printk("Checking 'hlt' instruction... ");
if (!hlt_works_ok) {
printk("disabled\n");
return;
}
__asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
printk("Ok.\n");
}
static void check_bugs(void)
{
check_fpu();
check_hlt();
}
extern void check_bugs(void);
asmlinkage void start_kernel(void)
{
......@@ -501,7 +408,6 @@ asmlinkage void start_kernel(void)
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
set_call_gate(&default_ldt,lcall7);
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
......@@ -567,7 +473,6 @@ asmlinkage void start_kernel(void)
sti();
check_bugs();
system_utsname.machine[1] = '0' + x86;
printk(linux_banner);
move_to_user_mode();
......
......@@ -240,7 +240,7 @@ asmlinkage int sys_fork(struct pt_regs regs)
if (p->ldt != NULL)
memcpy(p->ldt, current->ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
}
p->tss.bitmap = offsetof(struct tss_struct,io_bitmap);
p->tss.bitmap = offsetof(struct thread_struct,io_bitmap);
for (i = 0; i < IO_BITMAP_SIZE+1 ; i++) /* IO bitmap is actually SIZE+1 */
p->tss.io_bitmap[i] = ~0;
if (last_task_used_math == current)
......
......@@ -144,6 +144,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(block_fsync),
X(wait_for_request),
X(blksize_size),
X(hardsect_size),
X(blk_size),
X(blk_dev),
X(is_read_only),
......
......@@ -95,9 +95,9 @@ unsigned long prof_len = 0;
extern void mem_use(void);
extern int timer_interrupt(void);
asmlinkage int system_call(void);
static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, };
unsigned long init_user_stack[1024] = { STACK_MAGIC, };
static struct vm_area_struct init_mmap = INIT_MMAP;
struct task_struct init_task = INIT_TASK;
......@@ -108,55 +108,8 @@ struct task_struct *last_task_used_math = NULL;
struct task_struct * task[NR_TASKS] = {&init_task, };
long user_stack [ PAGE_SIZE>>2 ] = { STACK_MAGIC, };
struct {
long * a;
short b;
} stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
struct kernel_stat kstat = { 0 };
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
*
* Careful.. There are problems with IBM-designed IRQ13 behaviour.
* Don't touch unless you *really* know how it works.
*/
asmlinkage void math_state_restore(void)
{
__asm__ __volatile__("clts");
if (last_task_used_math == current)
return;
timer_table[COPRO_TIMER].expires = jiffies+50;
timer_active |= 1<<COPRO_TIMER;
if (last_task_used_math)
__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
else
__asm__("fnclex");
last_task_used_math = current;
if (current->used_math) {
__asm__("frstor %0": :"m" (current->tss.i387));
} else {
__asm__("fninit");
current->used_math=1;
}
timer_active &= ~(1<<COPRO_TIMER);
}
#ifndef CONFIG_MATH_EMULATION
asmlinkage void math_emulate(long arg)
{
printk("math-emulation not enabled and no coprocessor found.\n");
printk("killing %s.\n",current->comm);
send_sig(SIGFPE,current,1);
schedule();
}
#endif /* CONFIG_MATH_EMULATION */
unsigned long itimer_ticks = 0;
unsigned long itimer_next = ~0;
......@@ -252,14 +205,6 @@ asmlinkage void schedule(void)
return;
kstat.context_swtch++;
switch_to(next);
/* Now maybe reload the debug registers */
if(current->debugreg[7]){
loaddebug(0);
loaddebug(1);
loaddebug(2);
loaddebug(3);
loaddebug(6);
};
}
asmlinkage int sys_pause(void)
......@@ -801,10 +746,12 @@ static void show_task(int nr,struct task_struct * p)
printk(stat_nam[p->state]);
else
printk(" ");
#ifdef __i386__
if (p == current)
printk(" current ");
else
printk(" %08lX ", ((unsigned long *)p->tss.esp)[3]);
#endif
for (free = 1; free < 1024 ; free++) {
if (((unsigned long *)p->kernel_stack_page)[free])
break;
......@@ -837,29 +784,11 @@ void show_state(void)
void sched_init(void)
{
int i;
struct desc_struct * p;
bh_base[TIMER_BH].routine = timer_bh;
bh_base[TQUEUE_BH].routine = tqueue_bh;
bh_base[IMMEDIATE_BH].routine = immediate_bh;
if (sizeof(struct sigaction) != 16)
panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&init_task.tss);
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&default_ldt,1);
set_system_gate(0x80,&system_call);
p = gdt+2+FIRST_TSS_ENTRY;
for(i=1 ; i<NR_TASKS ; i++) {
task[i] = NULL;
p->a=p->b=0;
p++;
p->a=p->b=0;
p++;
}
/* Clear NT, so that we won't have troubles with that later on */
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
load_TR(0);
load_ldt(0);
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
......
......@@ -16,11 +16,17 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/config.h>
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
asmlinkage int system_call(void);
asmlinkage void lcall7(void);
struct desc_struct default_ldt;
static inline void console_verbose(void)
{
extern int console_loglevel;
......@@ -218,10 +224,52 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
math_error();
}
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
*
* Careful.. There are problems with IBM-designed IRQ13 behaviour.
* Don't touch unless you *really* know how it works.
*/
asmlinkage void math_state_restore(void)
{
__asm__ __volatile__("clts");
if (last_task_used_math == current)
return;
timer_table[COPRO_TIMER].expires = jiffies+50;
timer_active |= 1<<COPRO_TIMER;
if (last_task_used_math)
__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
else
__asm__("fnclex");
last_task_used_math = current;
if (current->used_math) {
__asm__("frstor %0": :"m" (current->tss.i387));
} else {
__asm__("fninit");
current->used_math=1;
}
timer_active &= ~(1<<COPRO_TIMER);
}
#ifndef CONFIG_MATH_EMULATION
asmlinkage void math_emulate(long arg)
{
printk("math-emulation not enabled and no coprocessor found.\n");
printk("killing %s.\n",current->comm);
send_sig(SIGFPE,current,1);
schedule();
}
#endif /* CONFIG_MATH_EMULATION */
void trap_init(void)
{
int i;
struct desc_struct * p;
set_call_gate(&default_ldt,lcall7);
set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug);
set_trap_gate(2,&nmi);
......@@ -242,4 +290,21 @@ void trap_init(void)
set_trap_gate(17,&alignment_check);
for (i=18;i<48;i++)
set_trap_gate(i,&reserved);
set_system_gate(0x80,&system_call);
/* set up GDT task & ldt entries */
p = gdt+FIRST_TSS_ENTRY;
set_tss_desc(p, &init_task.tss);
p++;
set_ldt_desc(p, &default_ldt, 1);
p++;
for(i=1 ; i<NR_TASKS ; i++) {
p->a=p->b=0;
p++;
p->a=p->b=0;
p++;
}
/* Clear NT, so that we won't have troubles with that later on */
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
load_TR(0);
load_ldt(0);
}
......@@ -39,8 +39,8 @@
/*
* virtual flags (16 and 32-bit versions)
*/
#define VFLAGS (*(unsigned short *)&(current->v86flags))
#define VEFLAGS (current->v86flags)
#define VFLAGS (*(unsigned short *)&(current->tss.v86flags))
#define VEFLAGS (current->tss.v86flags)
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
......@@ -52,13 +52,13 @@ asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
{
unsigned long tmp;
if (!current->vm86_info) {
if (!current->tss.vm86_info) {
printk("no vm86_info: BAD\n");
do_exit(SIGSEGV);
}
set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->v86mask);
memcpy_tofs(&current->vm86_info->regs,regs,sizeof(*regs));
put_fs_long(current->screen_bitmap,&current->vm86_info->screen_bitmap);
set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->tss.v86mask);
memcpy_tofs(&current->tss.vm86_info->regs,regs,sizeof(*regs));
put_fs_long(current->tss.screen_bitmap,&current->tss.vm86_info->screen_bitmap);
tmp = current->tss.esp0;
current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0;
......@@ -117,16 +117,16 @@ asmlinkage int sys_vm86(struct vm86_struct * v86)
switch (info.cpu_type) {
case CPU_286:
current->v86mask = 0;
current->tss.v86mask = 0;
break;
case CPU_386:
current->v86mask = NT_MASK | IOPL_MASK;
current->tss.v86mask = NT_MASK | IOPL_MASK;
break;
case CPU_486:
current->v86mask = AC_MASK | NT_MASK | IOPL_MASK;
current->tss.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
break;
default:
current->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
current->tss.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
break;
}
......@@ -136,9 +136,9 @@ asmlinkage int sys_vm86(struct vm86_struct * v86)
pt_regs->eax = 0;
current->saved_kernel_stack = current->tss.esp0;
current->tss.esp0 = (unsigned long) pt_regs;
current->vm86_info = v86;
current->tss.vm86_info = v86;
current->screen_bitmap = info.screen_bitmap;
current->tss.screen_bitmap = info.screen_bitmap;
if (info.flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(current);
__asm__ __volatile__("movl %0,%%esp\n\t"
......@@ -178,7 +178,7 @@ static inline void clear_TF(struct vm86_regs * regs)
static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs)
{
set_flags(VEFLAGS, eflags, current->v86mask);
set_flags(VEFLAGS, eflags, current->tss.v86mask);
set_flags(regs->eflags, eflags, SAFE_MASK);
if (eflags & IF_MASK)
set_IF(regs);
......@@ -186,7 +186,7 @@ static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs
static inline void set_vflags_short(unsigned short flags, struct vm86_regs * regs)
{
set_flags(VFLAGS, flags, current->v86mask);
set_flags(VFLAGS, flags, current->tss.v86mask);
set_flags(regs->eflags, flags, SAFE_MASK);
if (flags & IF_MASK)
set_IF(regs);
......@@ -198,7 +198,7 @@ static inline unsigned long get_vflags(struct vm86_regs * regs)
if (VEFLAGS & VIF_MASK)
flags |= IF_MASK;
return flags | (VEFLAGS & current->v86mask);
return flags | (VEFLAGS & current->tss.v86mask);
}
static inline int is_revectored(int nr, struct revectored_struct * bitmap)
......@@ -287,9 +287,9 @@ static void do_int(struct vm86_regs *regs, int i, unsigned char * ssp, unsigned
unsigned short seg = get_fs_word((void *) ((i<<2)+2));
if (seg == BIOSSEG || regs->cs == BIOSSEG ||
is_revectored(i, &current->vm86_info->int_revectored))
is_revectored(i, &current->tss.vm86_info->int_revectored))
return_to_32bit(regs, VM86_INTx + (i << 8));
if (i==0x21 && is_revectored(AH(regs),&current->vm86_info->int21_revectored))
if (i==0x21 && is_revectored(AH(regs),&current->tss.vm86_info->int21_revectored))
return_to_32bit(regs, VM86_INTx + (i << 8));
pushw(ssp, sp, get_vflags(regs));
pushw(ssp, sp, regs->cs);
......
......@@ -4,8 +4,196 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include <linux/string.h>
/*
* stupid library routines.. The optimized versions should generally be found
* as inline code in <asm-xx/string.h>
*
* These are buggy as well..
*/
/* all the actual functions should be inline anyway, so.. */
#include <linux/types.h>
char * ___strtok = NULL;
char * strcpy(char * dest,const char *src)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}
char * strncpy(char * dest,const char *src,size_t count)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0' && --count)
/* nothing */;
return tmp;
}
char * strcat(char * dest, const char * src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
char * strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
if (count) {
while (*dest)
dest++;
while ((*dest++ = *src++)) {
if (--count == 0)
break;
}
}
return tmp;
}
int strcmp(const char * cs,const char * ct)
{
register char __res;
while (1) {
if ((__res = *cs - *ct++) != 0 && *cs++)
break;
}
return __res;
}
int strncmp(const char * cs,const char * ct,size_t count)
{
register char __res = 0;
while (count) {
if ((__res = *cs - *ct++) != 0 || !*cs++)
break;
count--;
}
return __res;
}
char * strchr(const char * s,char c)
{
const char ch = c;
for(; *s != ch; ++s)
if (*s == '\0')
return NULL;
return (char *) s;
}
size_t strlen(const char * s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
size_t strspn(const char *s, const char *accept)
{
const char *p;
const char *a;
size_t count = 0;
for (p = s; *p != '\0'; ++p) {
for (a = accept; *a != '\0'; ++a) {
if (*p == *a)
break;
}
if (*a == '\0')
return count;
++count;
}
return count;
}
char * strpbrk(const char * cs,const char * ct)
{
const char *sc1,*sc2;
for( sc1 = cs; *sc1 != '\0'; ++sc1) {
for( sc2 = ct; *sc2 != '\0'; ++sc2) {
if (*sc1 == *sc2)
return (char *) sc1;
}
}
return NULL;
}
char * strtok(char * s,const char * ct)
{
char *sbegin, *send;
sbegin = s ? s : ___strtok;
if (!sbegin) {
return NULL;
}
sbegin += strspn(sbegin,ct);
if (*sbegin == '\0') {
___strtok = NULL;
return( NULL );
}
send = strpbrk( sbegin, ct);
if (send && *send != '\0')
*send++ = '\0';
___strtok = send;
return (sbegin);
}
void * memset(void * s,char c,size_t count)
{
char *xs = (char *) s;
while (count--)
*xs++ = c;
return s;
}
void * memcpy(void * dest,const void *src,size_t count)
{
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
void * memmove(void * dest,const void *src,size_t count)
{
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
int memcmp(const void * cs,const void * ct,size_t count)
{
const unsigned char *su1, *su2;
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if (*su1 != *su2)
return((*su1 < *su2) ? -1 : +1);
return(0);
}
......@@ -1001,7 +1001,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (regs->eflags & VM_MASK) {
unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
if (bit < 32)
current->screen_bitmap |= 1 << bit;
current->tss.screen_bitmap |= 1 << bit;
}
if (!(vma->vm_page_prot & PAGE_USER))
goto bad_area;
......
......@@ -2118,6 +2118,16 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
return 0;
}
#endif
case IP_MULTICAST_LOOP:
{
unsigned char ucval;
ucval=get_fs_byte((unsigned char *)optval);
if(ucval!=0 && ucval!=1)
return -EINVAL;
sk->ip_mc_loop=(int)ucval;
return 0;
}
case IP_MULTICAST_IF:
{
/* Not fully tested */
......@@ -2357,6 +2367,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
case IP_MULTICAST_TTL:
val=sk->ip_mc_ttl;
break;
case IP_MULTICAST_LOOP:
val=sk->ip_mc_loop;
break;
case IP_MULTICAST_IF:
err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
if(err)
......
......@@ -90,12 +90,13 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
timer_active = del_timer(&sp->timer);
if (!timer_active)
sp->timer.expires = 0;
len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
sp->socket?SOCK_INODE(sp->socket)->i_uid:0);
sp->socket?SOCK_INODE(sp->socket)->i_uid:0,
timer_active?sp->timeout:0);
if (timer_active)
add_timer(&sp->timer);
/*
......
This diff is collapsed.
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