Commit a6614639 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.61

parent ba97e35a
......@@ -64,7 +64,7 @@ S: 6369 BG Simpelveld
S: The Netherlands
N: Hennus Bergman
E: hennus@sky.nl.mugnet.org [My uucp-fed Linux box at home]
E: hennus@sky.ow.org [My uucp-fed Linux box at home]
D: Author and maintainer of the QIC-02 tape driver
S: The Netherlands
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 60
SUBLEVEL = 61
ARCH = i386
......
This README belongs to release 2.6 or newer of the SoundBlaster Pro
This README belongs to release 2.7 or newer of the SoundBlaster Pro
(Matsushita, Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
The driver is able to drive the whole family of "traditional" IDE-style (that
......@@ -6,6 +6,14 @@ has nothing to do with the new "Enhanced IDE" drive standard) Matsushita,
Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
There exists an "IBM External ISA CD-ROM Drive" which in fact is a CR-562
with a special controller board. This drive is supported (the interface is
of the "LaserMate" type), and it is possibly the best buy today (cheaper than
an internal drive, and you can use it as an internal, too - f.e. plug it into
a soundcard). If you own such a drive, please mail me the DOS driver (gzipped
and uuencoded) and the specifications (exact name, address range etc.) I still
have to confirm my opinion. ;-)
This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives.
The matter that some other brand's drives work with newer sound card
interfaces does NOT make the drives compatible. :-)
......@@ -49,8 +57,8 @@ to change old drives to any ID, too. He writes in this sense:
To use more than 4 drives (now that the single-speed CR-521's are as cheap as
50$), you need a second interface card and you have to "duplicate" the driver.
Just copy sbpcd.c into sbpcd2.c and so forth and change SBPCD_ISSUE
accordingly.
Just copy sbpcd.c into sbpcd2.c and so forth and change SBPCD_ISSUE (at top
of sbpcd2.c) accordingly.
The driver supports reading of data from the CD and playing of audio tracks.
The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
......@@ -72,9 +80,10 @@ the beginning of each single frame.
The software interface possibly may change a bit the day the SCSI driver
supports it too.
MultiSession is supported, "ManySession" (not recommended, see below)
alternatively.
Photo CDs work, too (even with my "old" CR-521).
With the CR-562 and CR-563 drives, MultiSession is supported, "ManySession"
(not recommended, see below) alternatively.
Photo CDs work, too (the "old" drives like CR-521 can access only the first
session of a photoCD).
At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's package to convert
photo CD image files.
......@@ -189,6 +198,57 @@ distribution) which MUST get handled with a block_size of 1024. Generally,
one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
do not use block=2048 with those.
At the beginning of sbpcd.c, you will find some "#define"s (f.e. EJECT and
JUKEBOX). With that, you can configure the driver for some special things.
The following program disables the auto-eject feature during runtime:
/*=================== begin program ========================================*/
/*
* set the "eject" switch (enable/disable auto-ejecting)
*
* (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
* may be used & enhanced freely
*
* Disables or enables the auto-eject feature at run time.
* Works only if a CD is in the drive (just like the feature itself ;-)
* Useful for a "quiet" shutdown or for weird audio player programs.
*/
#define EJECT 0 /* 0: disable, 1: enable auto-ejecting */
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
static char arg=EJECT;
static int drive;
static int err;
main(int argc, char *argv[])
{
/*
* open /dev/cdrom
*/
drive=open("/dev/cdrom", 0);
if (drive<0)
{
fprintf(stderr, "can't open drive /dev/cdrom.\n");
exit (-1);
}
/*
* set EJECT_SW
*/
err=ioctl(drive, CDROMEJECT_SW, arg);
if (err!=0)
{
fprintf(stderr, "can't set EJECT_SW (error %d).\n", err);
exit (-1);
}
else
fprintf(stdout, "EJECT_SW set to %d\n", arg);
}
/*===================== end program ========================================*/
Auto-probing at boot time:
--------------------------
......
......@@ -2856,8 +2856,8 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
{
if (request_irq(irq_used, cdu31a_interrupt, SA_INTERRUPT, "cdu31a"))
{
irq_used = 0;
printk("Unable to grab IRQ%d for the CDU31A driver\n", irq_used);
irq_used = 0;
}
}
......
......@@ -348,6 +348,7 @@ struct floppy_struct *current_type[N_DRIVE] = {
struct floppy_struct user_params[N_DRIVE];
static int floppy_sizes[256];
static int floppy_blocksizes[256] = { 0, };
/*
* The driver is trying to determine the correct media format
......@@ -2848,7 +2849,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (floppy_grab_irq_and_dma())
return -EBUSY;
if(filp->f_flags & O_EXCL)
if (filp->f_flags & O_EXCL)
UDRS->fd_ref = -1;
else
UDRS->fd_ref++;
......@@ -2956,7 +2957,10 @@ static int floppy_revalidate(dev_t dev)
UDRS->generation++;
if(!current_type[drive] && !TYPE(dev)){
/* auto-sensing */
if (!(bh = getblk(dev,0,1024))){
int size = floppy_blocksizes[MINOR(dev)];
if (!size)
size = 1024;
if (!(bh = getblk(dev,0,size))){
redo_fd_request();
return 1;
}
......@@ -3062,6 +3066,7 @@ void floppy_init(void)
floppy_sizes[i] = MAX_DISK_SIZE;
blk_size[MAJOR_NR] = floppy_sizes;
blksize_size[MAJOR_NR] = floppy_blocksizes;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
timer_active &= ~(1 << FLOPPY_TIMER);
......
......@@ -1182,7 +1182,6 @@ mcd_init(unsigned long mem_start, unsigned long mem_end)
mcd_invalidate_buffers();
mcdPresent = 1;
printk("\n");
return mem_start;
}
......
......@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P.
*
* NOTE: This is release 2.6.
* NOTE: This is release 2.7.
* It works with my SbPro & drive CR-521 V2.11 from 2/92
* and with the new CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa.
......@@ -128,6 +128,10 @@
*
* 2.6 Nothing new.
*
* 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
* 0 disables, 1 enables auto-ejecting. Useful to keep the tray in
* during shutdown.
*
* TODO
*
* disk change detection
......@@ -203,7 +207,7 @@
#include "blk.h"
#define VERSION "2.6 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "2.7 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
......@@ -303,6 +307,9 @@ static int autoprobe[] =
0x320, 2, /* SPEA Media FX */
0x340, 2, /* SPEA Media FX */
0x350, 2, /* SPEA Media FX */
/* due to incomplete address decoding of the SbPro card, these must be last */
0x630, 0, /* "sound card #9" (default) */
0x650, 0, /* "sound card #9" */
#if 0
/* some "hazardous" locations (ethernet cards) */
0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
......@@ -310,9 +317,6 @@ static int autoprobe[] =
0x370, 0, /* Lasermate, CI-101P */
0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
/* excluded due to incomplete address decoding of the SbPro card */
0x630, 0, /* "sound card #9" (default) */
0x650, 0, /* "sound card #9" */
#endif
};
......@@ -390,6 +394,7 @@ static int sbpcd_debug = (1<<DBG_INF) |
#else
static int sbpcd_debug = (1<<DBG_INF) |
(1<<DBG_TOC) |
(1<<DBG_MUL) |
(1<<DBG_UPC);
#endif
#endif
......@@ -481,6 +486,7 @@ static struct {
char drive_model[4];
char firmware_version[4];
char f_eject; /* auto-eject flag: 0 or 1 */
u_char *sbp_buf; /* Pointer to internal data buffer,
space allocated during sbpcd_init() */
int sbp_first_frame; /* First frame in buffer */
......@@ -2390,7 +2396,7 @@ static int sbp_status(void)
/*==========================================================================*/
/*==========================================================================*/
/*
* ioctl support, adopted from scsi/sr_ioctl.c and mcd.c
* ioctl support
*/
static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
......@@ -2583,6 +2589,12 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
DriveStruct[d].audio_state=0;
return (0);
case CDROMEJECT_SW:
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT_SW entered.\n"));
if (!new_drive) return (0);
DriveStruct[d].f_eject=arg;
return (0);
case CDROMVOLCTRL: /* Volume control */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMVOLCTRL entered.\n"));
st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
......@@ -2918,7 +2930,9 @@ static void DO_SBPCD_REQUEST(void)
}
DPRINTF((DBG_BSZ,"SBPCD: read sector %d (%d sectors)\n", block, nsect));
#if 0
DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4));
#endif
sbp_transfer();
/* if we satisfied the request from the buffer, we're done. */
......@@ -3007,7 +3021,7 @@ static void sbp_read_cmd(void)
DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
blk2msf(DriveStruct[d].lba_multi+16),
blk2msf(block)));
block=DriveStruct[d].lba_multi+16;
block=DriveStruct[d].lba_multi+block;
}
#endif MANY_SESSION
}
......@@ -3323,9 +3337,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
do
i=yy_LockDoor(0);
while (i!=0);
#if EJECT
if (new_drive) yy_SpinDown();
#endif
if (DriveStruct[d].f_eject) yy_SpinDown();
}
}
}
......@@ -3550,6 +3562,12 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
DriveStruct[d].sbp_current = 0; /* Frame being currently read */
DriveStruct[d].CD_changed=1;
DriveStruct[d].frame_size=CD_FRAMESIZE;
#if EJECT
if (new_drive) DriveStruct[d].f_eject=1;
else DriveStruct[d].f_eject=0;
#else
DriveStruct[d].f_eject=0;
#endif
xx_ReadStatus();
i=ResponseStatus(); /* returns orig. status or p_busy_new */
......
/* $Id: tpqic02.c,v 0.4.1.4 1994/07/21 02:15:45 root Exp root $
/* $Id: tpqic02.c,v 0.4.1.5 1994/10/29 02:46:13 root Exp root $
*
* Driver for tape drive support for Linux-i386 1.1.30
* Driver for tape drive support for Linux-i386 1.1.58
*
* Copyright (c) 1992, 1993, 1994 by H. H. Bergman. All rights reserved.
* Current e-mail address: hennus@sky.nl.mugnet.org [This is a UUCP link.]
* Secondary e-mail address: csg279@wing.rug.nl [IP connected, but flaky]
* Current e-mail address: hennus@sky.ow.org [This is a UUCP link.]
* [If you are unable to reach me directly, try the TAPE mailing list
* channel on linux-activists@niksula.hut.fi using "X-Mn-Key: TAPE" as
* the first line in your message.]
......@@ -35,6 +34,9 @@
* You are not allowed to change this line nor the text above.
*
* $Log: tpqic02.c,v $
* Revision 0.4.1.5 1994/10/29 02:46:13 root
* Minor cleanups.
*
* Revision 0.4.1.4 1994/07/21 02:15:45 root
* ifdef'd DDI. Exception masks.
*
......@@ -191,10 +193,8 @@
* Also, be careful to avoid IO conflicts with other devices!
*/
#include <linux/config.h>
#include <linux/autoconf.h>
/* skip this driver if not required for this configuration */
#if CONFIG_QIC02_TAPE
/*
#define TDEBUG
......@@ -233,8 +233,8 @@
*/
#ifdef CONFIG_QIC02_DYNCONF
/* This may hold the dynamic configuration info for the interface
* card+drive info in future versions.
/* This holds the dynamic configuration info for the interface
* card+drive info if runtime configuration has been selected.
*/
struct mtconfiginfo qic02_tape_dynconf = { 0, }; /* user settable */
struct qic02_ccb qic02_tape_ccb = { 0, }; /* private stuff */
......@@ -256,8 +256,8 @@ static volatile struct mtget ioctl_status; /* current generic status */
static volatile struct tpstatus tperror; /* last drive status */
static char rcs_revision[] = "$Revision: 0.4.1.4 $";
static char rcs_date[] = "$Date: 1994/07/21 02:15:45 $";
static char rcs_revision[] = "$Revision: 0.4.1.5 $";
static char rcs_date[] = "$Date: 1994/10/29 02:46:13 $";
/* Flag bits for status and outstanding requests.
* (Could all be put in one bit-field-struct.)
......@@ -285,7 +285,7 @@ static volatile unsigned long dma_bytes_done;
static volatile unsigned dma_mode = 0; /* !=0 also means DMA in use */
static flag need_rewind = YES;
static dev_t current_tape_dev = QIC02_TAPE_MAJOR << 8;
static dev_t current_tape_dev = MKDEV(QIC02_TAPE_MAJOR, 0);
static int extra_blocks_left = BLOCKS_BEYOND_EW;
......@@ -570,7 +570,9 @@ static void report_error(int s)
#endif
/* perform appropriate action for certain exceptions */
/* Perform appropriate action for certain exceptions.
* should return a value to indicate stop/continue (in case of bad blocks)
*/
static void handle_exception(int exnr, int exbits)
{
if (exnr==EXC_NCART) {
......@@ -1358,9 +1360,7 @@ static int do_ioctl_cmd(int cmd)
return do_qic_cmd(QCMD_REWIND, TIM_R);
case MTOFFL:
tpqputs(TPQD_IOCTLS, "MTOFFL rewinding & going offline"); /*---*/
/******* What exactly are we supposed to do, to take it offline????
*****/
tpqputs(TPQD_IOCTLS, "MTOFFL rewinding & going offline");
/* Doing a drive select will clear (unlock) the current drive.
* But that requires support for multiple drives and locking.
*/
......@@ -1927,8 +1927,9 @@ static int qic02_tape_read(struct inode * inode, struct file * filp, char * buf,
}
if (TP_DIAGS(current_tape_dev))
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x\n",
MINOR(dev), buf, count, filp->f_pos, flags);
MINOR(dev), buf, count, (unsigned long) filp->f_pos, flags);
if (count % TAPE_BLKSIZE) { /* Only allow mod 512 bytes at a time. */
tpqputs(TPQD_BLKSZ, "Wrong block size");
......@@ -2100,8 +2101,9 @@ static int qic02_tape_write(struct inode * inode, struct file * filp, char * buf
}
if (TP_DIAGS(current_tape_dev))
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x\n",
MINOR(dev), buf, count, filp->f_pos, flags);
MINOR(dev), buf, count, (unsigned long) filp->f_pos, flags);
if (count % TAPE_BLKSIZE) { /* only allow mod 512 bytes at a time */
tpqputs(TPQD_BLKSZ, "Wrong block size");
......@@ -2587,7 +2589,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
if (!suser())
return -EPERM;
verify_area(VERIFY_READ, (int *) ioarg, sizeof(int));
c = get_fs_long((int *) ioarg);
c = get_user_long((int *) ioarg);
if (c==0) {
QIC02_TAPE_DEBUG = 0;
return 0;
......@@ -2619,7 +2621,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp = (char *) &qic02_tape_dynconf;
argp = (char *) ioarg;
for (i=0; i<sizeof(qic02_tape_dynconf); i++)
put_fs_byte(*stp++, argp++);
put_user_byte(*stp++, argp++);
return 0;
} else if (c == (MTIOCSETCONFIG & IOCCMD_MASK)) {
......@@ -2646,7 +2648,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp = (char *) &qic02_tape_dynconf;
argp = (char *) ioarg;
for (i=0; i<sizeof(qic02_tape_dynconf); i++)
*stp++ = get_fs_byte(argp++);
*stp++ = get_user_byte(argp++);
if (status_zombie==NO)
qic02_release_resources(); /* and go zombie */
if (update_ifc_masks(qic02_tape_dynconf.ifc_type))
......@@ -2678,7 +2680,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp = (char *) &operation;
argp = (char *) ioarg;
for (i=0; i<sizeof(operation); i++)
*stp++ = get_fs_byte(argp++);
*stp++ = get_user_byte(argp++);
/* ---note: mt_count is signed, negative seeks must be
* --- translated to seeks in opposite direction!
......@@ -2740,7 +2742,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp = (char *) &ioctl_status;
argp = (char *) ioarg;
for (i=0; i<sizeof(ioctl_status); i++)
put_fs_byte(*stp++, argp++);
put_user_byte(*stp++, argp++);
return 0;
......@@ -2773,7 +2775,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp = (char *) &ioctl_tell;
argp = (char *) ioarg;
for (i=0; i<sizeof(ioctl_tell); i++)
put_fs_byte(*stp++, argp++);
put_user_byte(*stp++, argp++);
return 0;
} else
......@@ -2793,7 +2795,10 @@ static struct file_operations qic02_tape_fops = {
NULL, /* mmap not allowed */
qic02_tape_open, /* open */
qic02_tape_release, /* release */
NULL /* fsync */
NULL, /* fsync */
NULL, /* fasync */
NULL, /* check_media_change */
NULL /* revalidate */
};
/* align `a' at `size' bytes. `size' must be a power of 2 */
......@@ -2870,7 +2875,6 @@ static int qic02_get_resources(void)
/* init() is called from chr_dev_init() in drivers/char/mem.c */
long qic02_tape_init(long kmem_start)
/* Shouldn't this be a caddr_t ? */
{
......@@ -2969,5 +2973,3 @@ long qic02_tape_init(long kmem_start)
return kmem_start;
} /* qic02_tape_init */
#endif /* CONFIG_QIC02_TAPE */
......@@ -34,9 +34,10 @@
# DE620_IO The DE620 I/O-port address (0x378 == default)
# DE620_IRQ The DE620 IRQ number to use (IRQ7 == default)
# DE620_DEBUG Enable or disable DE600 debugging (default off)
# DEPCA The DIGITAL series of AT Ethernet Cards (DE100, DE200)
# DEPCA_IRQ Set the desired IRQ (=0, for autoprobe)
# DEPCA_DEBUG Set the desired debug level
# DEPCA The DIGITAL series of LANCE based Ethernet Cards
# (DEPCA, DE100, DE200/1/2, DE210, DE422 (EISA))
# EWRK3 The DIGITAL series of AT Ethernet Cards (DE203/4/5)
# EWRK3_DEBUG Set the desired debug level
#
# The following options exist, but cannot be set in this file.
......@@ -57,4 +58,5 @@ EL2_OPTS = #-DEL2_AUI
NE_OPTS =
HP_OPTS =
PLIP_OPTS =
DEPCA_OPTS = -DDEPCA_IRQ=0 -DDEPCA_DEBUG=1
DEPCA_OPTS = -DDEPCA_DEBUG=1
EWRK3_OPTS = -DEWRK3_DEBUG=1
......@@ -142,6 +142,11 @@ NETDRV_OBJS := $(NETDRV_OBJS) depca.o
depca.o: depca.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(DEPCA_OPTS) -c $<
endif
ifdef CONFIG_EWRK3
NETDRV_OBJS := $(NETDRV_OBJS) ewrk3.o
ewrk3.o: ewrk3.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(EWRK3_OPTS) -c $<
endif
ifdef CONFIG_ATP
NETDRV_OBJS := $(NETDRV_OBJS) atp.o
endif
......
The EtherWORKS 3 driver in this distribution is designed to work with all
kernels > 1.1.33 (approx) and includes tools in the 'ewrk3tools'
subdirectory to allow set up of the card, similar to the MSDOS
'NICSETUP.EXE' tools provided on the DOS drivers disk (type 'make' in that
subdirectory to make the tools).
The supported cards are DE203, DE204 and DE205. All other cards are NOT
supported - refer to the depca files for running the LANCE based network
cards from Digital.
The ability to load this driver as a loadable module has been included and
used extensively during the driver development (to save those long reboot
sequences). To utilise this ability, you have to do 8 things:
0) have a copy of the loadable modules code installed on your system.
1) copy ewrk3.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) edit the source code near line 1750 to reflect the I/O address and
IRQ you're using.
3) compile ewrk3.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
kernel with the ewrk3 configuration turned off and reboot.
5) insmod ewrk3.o
6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts.
To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod ewrk3'.
The performance we've achieved so far has been measured through the 'ttcp'
tool at 975kB/s. This measures the total tcp stack performance which
includes the card, so don't expect to get much nearer the 1.25MB/s
theoretical ethernet rate.
Enjoy!
Dave
......@@ -49,6 +49,7 @@ extern int el3_probe(struct device *);
extern int at1500_probe(struct device *);
extern int at1700_probe(struct device *);
extern int depca_probe(struct device *);
extern int ewrk3_probe(struct device *);
extern int el1_probe(struct device *);
extern int el16_probe(struct device *);
extern int elplus_probe(struct device *);
......@@ -108,6 +109,9 @@ ethif_probe(struct device *dev)
#ifdef CONFIG_DEPCA /* DEC DEPCA */
&& depca_probe(dev)
#endif
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
&& ewrk3_probe(dev)
#endif
#ifdef CONFIG_EL1 /* 3c501 */
&& el1_probe(dev)
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -24,7 +24,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
loff_t offset;
int chars;
int written = 0;
int cluster_list[4];
int cluster_list[8];
struct buffer_head * bhlist[NBUF];
int blocks_per_cluster;
unsigned int size;
......@@ -159,7 +159,7 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
int blocksize_bits, i;
unsigned int blocks, rblocks, left;
int bhrequest, uptodate;
int cluster_list[4];
int cluster_list[8];
int blocks_per_cluster;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * buflist[NBUF];
......
......@@ -122,6 +122,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
if (32 != sizeof (struct minix_inode))
panic("bad i-node size");
lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev,1,BLOCK_SIZE))) {
s->s_dev=0;
unlock_super(s);
......
......@@ -20,7 +20,6 @@ int fat_access(struct super_block *sb,int nr,int new_value)
{
struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
unsigned char *p_first,*p_last;
void *data,*data2,*c_data,*c_data2;
int first,last,next,copy;
if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) return 0;
......@@ -30,17 +29,15 @@ int fat_access(struct super_block *sb,int nr,int new_value)
last = first+1;
}
if (!(bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
SECTOR_BITS),&data))) {
SECTOR_BITS)))) {
printk("bread in fat_access failed\n");
return 0;
}
if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS))
bh2 = bh;
data2 = data;
}
else {
if (!(bh2 = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
>> SECTOR_BITS),&data2))) {
>> SECTOR_BITS)))) {
brelse(bh);
printk("bread in fat_access failed\n");
return 0;
......@@ -48,13 +45,13 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
if (MSDOS_SB(sb)->fat_bits == 16) {
p_first = p_last = NULL; /* GCC needs that stuff */
next = CF_LE_W(((unsigned short *) data)[(first &
next = CF_LE_W(((unsigned short *) bh->b_data)[(first &
(SECTOR_SIZE-1)) >> 1]);
if (next >= 0xfff7) next = -1;
}
else {
p_first = &((unsigned char *) data)[first & (SECTOR_SIZE-1)];
p_last = &((unsigned char *) data2)[(first+1) &
p_first = &((unsigned char *) bh->b_data)[first & (SECTOR_SIZE-1)];
p_last = &((unsigned char *) bh2->b_data)[(first+1) &
(SECTOR_SIZE-1)];
if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
else next = (*p_first+(*p_last << 8)) & 0xfff;
......@@ -62,7 +59,7 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
if (new_value != -1) {
if (MSDOS_SB(sb)->fat_bits == 16)
((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >>
((unsigned short *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
1] = CT_LE_W(new_value);
else {
if (nr & 1) {
......@@ -79,25 +76,25 @@ int fat_access(struct super_block *sb,int nr,int new_value)
for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
fat_length*copy,&c_data))) break;
memcpy(c_data,data,SECTOR_SIZE);
fat_length*copy))) break;
memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE);
mark_buffer_dirty(c_bh, 1);
if (data != data2 || bh != bh2) {
if (bh != bh2) {
if (!(c_bh2 = msdos_sread(sb->s_dev,
MSDOS_SB(sb)->fat_start+(first >>
SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy
+1,&c_data2))) {
+1))) {
brelse(c_bh);
break;
}
memcpy(c_data2,data2,SECTOR_SIZE);
memcpy(c_bh2->b_data,bh2->b_data,SECTOR_SIZE);
brelse(c_bh2);
}
brelse(c_bh);
}
}
brelse(bh);
if (data != data2) brelse(bh2);
if (bh != bh2) brelse(bh2);
return next;
}
......
......@@ -30,7 +30,7 @@ static struct file_operations msdos_file_operations = {
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
generic_mmap, /* mmap */
generic_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
file_fsync /* fsync */
......@@ -52,7 +52,7 @@ struct inode_operations msdos_file_inode_operations = {
msdos_bmap, /* bmap */
msdos_truncate, /* truncate */
NULL, /* permission */
NULL /* smap */
NULL /* smap */
};
/*
......@@ -127,12 +127,11 @@ int msdos_file_read(
int sector;
if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
break;
if (!(bh = msdos_sread(inode->i_dev,sector,&data)))
if (!(bh = msdos_sread(inode->i_dev,sector)))
break;
}else{
bh = pre.bhlist[pre.nolist];
pre.bhlist[pre.nolist++] = NULL;
data = bh->b_data;
wait_on_buffer(bh);
if (!bh->b_uptodate){
/* read error ? */
......@@ -140,6 +139,7 @@ int msdos_file_read(
break;
}
}
data = bh->b_data;
offset = filp->f_pos & (SECTOR_SIZE-1);
filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
if (MSDOS_I(inode)->i_binary) {
......@@ -183,7 +183,6 @@ int msdos_file_write(
int error,carry;
char *start,*to,ch;
struct buffer_head *bh;
void *data;
int binary_mode = MSDOS_I(inode)->i_binary;
if (!inode) {
......@@ -211,25 +210,28 @@ int msdos_file_write(
}
offset = filp->f_pos & (SECTOR_SIZE-1);
size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
if (binary_mode && offset == 0 && size == SECTOR_SIZE){
if (binary_mode
&& offset == 0
&& (size == SECTOR_SIZE
|| filp->f_pos + size >= inode->i_size)){
/* No need to read the block first since we will */
/* completely overwrite it */
/* or at least write past the end of file */
if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){
error = -EIO;
break;
}
data = bh->b_data;
}else if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
}else if (!(bh = msdos_sread(inode->i_dev,sector))) {
error = -EIO;
break;
}
if (binary_mode) {
memcpy_fromfs(data+offset,buf,written = size);
memcpy_fromfs(bh->b_data+offset,buf,written = size);
buf += size;
}
else {
written = left = SECTOR_SIZE-offset;
to = (char *) data+(filp->f_pos & (SECTOR_SIZE-1));
to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1));
if (carry) {
*to++ = '\n';
left--;
......
......@@ -172,20 +172,7 @@ struct super_block *msdos_read_super(struct super_block *s,void *data,
}
cache_init();
lock_super(s);
if (MAJOR(s->s_dev) == FLOPPY_MAJOR){
/* Patch for floppy which lacks a table ??? */
static int tbdef[]={
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
1024,1024,1024,1024,1024,
};
blksize_size[FLOPPY_MAJOR] = tbdef;
}
set_blocksize (s->s_dev,SECTOR_SIZE);
set_blocksize(s->s_dev, SECTOR_SIZE);
bh = bread(s->s_dev, 0, SECTOR_SIZE);
unlock_super(s);
if (bh == NULL) {
......
......@@ -256,7 +256,6 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
struct msdos_dir_entry **de)
{
int sector,offset;
void *data;
while (1) {
offset = *pos;
......@@ -270,12 +269,12 @@ 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,&data))) {
if (!(*bh = msdos_sread(dir->i_dev,sector))) {
printk("Directory sread (sector %d) failed\n",sector);
continue;
}
PRINTK (("get_entry apres sread\n"));
*de = (struct msdos_dir_entry *) (data+(offset &
*de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
(SECTOR_SIZE-1)));
return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
MSDOS_DIR_BITS);
......@@ -344,7 +343,8 @@ 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,(void **) &data))) return -EIO;
if (!(bh = msdos_sread(sb->s_dev,sector))) return -EIO;
data = (struct msdos_dir_entry *) bh->b_data;
for (entry = 0; entry < MSDOS_DPS; entry++) {
if (name) RSS_NAME
else {
......
......@@ -33,7 +33,10 @@ asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int
return -EBADF;
error = -ENOTDIR;
if (file->f_op && file->f_op->readdir) {
error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
int size = count;
if (count == 1)
size = sizeof(*dirent);
error = verify_area(VERIFY_WRITE, dirent, size);
if (!error)
error = file->f_op->readdir(inode,file,dirent,count);
}
......
......@@ -273,7 +273,13 @@ void UMSDOS_write_inode(struct inode *inode)
newattrs.ia_atime = inode->i_atime;
newattrs.ia_ctime = inode->i_ctime;
newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME;
/*
UMSDOS_notify_change is convenient to call here
to update the EMD entry associated with this inode.
But it has the side effect to re"dirt" the inode.
*/
UMSDOS_notify_change (inode, &newattrs);
inode->i_dirt = 0;
}
int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
......@@ -319,6 +325,7 @@ int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
struct file filp;
struct umsdos_dirent entry;
filp.f_pos = inode->u.umsdos_i.pos;
filp.f_reada = 0;
PRINTK (("pos = %d ",filp.f_pos));
/* Read only the start of the entry since we don't touch */
/* the name */
......
......@@ -35,7 +35,6 @@ static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit)
int end, i, j, tmp;
u_long *bmap;
char res;
bmap=(u_long *)bh->b_data;
end = end_bit >> 5;
......
......@@ -377,10 +377,16 @@ struct cdrom_read_audio
/* read type-1 data */
/*
* preliminary extension for transferring audio frames
* currently used by sbpcd.c
* currently used by cdu31a.c and sbpcd.c
* (still may change if other drivers will use it, too):
*/
#define CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */
/*
* preliminary extension for enable (1) / disable (0) auto-ejecting
* currently used by sbpcd.c
* (still may change if other drivers will use it, too):
*/
#define CDROMEJECT_SW 0x530f /* arg: 0 or 1 */
#endif _LINUX_CDROM_H
......@@ -39,7 +39,7 @@ struct ipc_perm
#define IPC_NOID ((void *) -2) /* being allocated/destroyed */
/*
* These are used to wrap system calls. See ipc/util.c, libipc.c
* These are used to wrap system calls. See ipc/util.c.
*/
struct ipc_kludge {
struct msgbuf *msgp;
......
......@@ -110,13 +110,9 @@ struct fat_cache {
#ifdef __KERNEL__
static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
static inline struct buffer_head *msdos_sread(int dev,int sector)
{
struct buffer_head *bh = bread(dev,sector, 512);
if (bh != NULL){
*start = bh->b_data; /* From the time of 1024 bytes block */
}
return bh;
return bread(dev,sector,SECTOR_SIZE);
}
......
......@@ -6,15 +6,6 @@
#define MSG_NOERROR 010000 /* no error if message is too big */
#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/
/* one msg structure for each message */
struct msg {
struct msg *msg_next; /* next message on queue */
long msg_type;
char *msg_spot; /* message text address */
short msg_ts; /* message text size */
};
/* one msqid structure for each queue on the system */
struct msqid_ds {
struct ipc_perm msg_perm;
......@@ -32,14 +23,13 @@ struct msqid_ds {
ushort msg_lrpid; /* last receive pid */
};
/* message buffer for msgsnd and msgrcv calls */
struct msgbuf {
long mtype; /* type of message */
char mtext[1]; /* message text */
};
/* buffer for msgctl calls IPC_INFO, MSG_INFO */
struct msginfo {
int msgpool;
int msgmap;
......@@ -65,6 +55,14 @@ struct msginfo {
#ifdef __KERNEL__
/* one msg structure for each message */
struct msg {
struct msg *msg_next; /* next message on queue */
long msg_type;
char *msg_spot; /* message text address */
short msg_ts; /* message text size */
};
/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_INFO 12
......
......@@ -290,7 +290,7 @@ struct task_struct {
struct tty_struct *tty; /* NULL if no tty */
/* shm stuff */
struct shm_desc *shm;
struct sem_undo *semun;
struct sem_undo *semundo;
/* ldt for this task - used by Wine. If NULL, default_ldt is used */
struct desc_struct *ldt;
/* tss for this task */
......
......@@ -26,16 +26,7 @@ struct semid_ds {
ushort sem_nsems; /* no. of semaphores in array */
};
/* One semaphore structure for each semaphore in the system. */
struct sem {
short sempid; /* pid of last operation */
ushort semval; /* current value */
ushort semncnt; /* num procs awaiting increase in semval */
ushort semzcnt; /* num procs awaiting semval = 0 */
};
/* semop system calls takes an array of these.*/
/* semop system calls takes an array of these. */
struct sembuf {
ushort sem_num; /* semaphore index in array */
short sem_op; /* semaphore operation */
......@@ -44,12 +35,13 @@ struct sembuf {
/* arg for semctl system calls. */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
ushort *array; /* array for GETALL & SETALL */
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
ushort *array; /* array for GETALL & SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
void *__pad;
};
struct seminfo {
int semmap;
int semmni;
......@@ -77,6 +69,15 @@ struct seminfo {
#define SEMUSZ 20 /* sizeof struct sem_undo */
#ifdef __KERNEL__
/* One semaphore structure for each semaphore in the system. */
struct sem {
short sempid; /* pid of last operation */
ushort semval; /* current value */
ushort semncnt; /* num procs awaiting increase in semval */
ushort semzcnt; /* num procs awaiting semval = 0 */
};
/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_INFO 19
......
......@@ -3,7 +3,7 @@
#include <linux/ipc.h>
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
time_t shm_atime; /* last attach time */
time_t shm_dtime; /* last detach time */
......@@ -12,9 +12,9 @@ struct shmid_ds {
unsigned short shm_lpid; /* pid of last operator */
short shm_nattch; /* no. of current attaches */
/* the following are private */
unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct shm_desc *attaches; /* descriptors for attaches */
unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct shm_desc *attaches; /* descriptors for attaches */
};
/* mode for attach */
......@@ -34,34 +34,35 @@ struct shminfo {
int shmall;
};
/* address range for shared memory attaches if no address passed to shmat() */
#define SHM_RANGE_START 0x40000000
#define SHM_RANGE_END 0x60000000
/* _SHM_ID_BITS is a variable you can adjust to */
/* tune the kernel. It determines the value of */
/* SHMMNI, which specifies the maximum no. of */
/* shared segments (system wide). SRB. */
#define _SHM_ID_BITS 7 /* keep as low as possible */
/* a static array is declared */
/* using SHMMNI */
/* format of page table entries that correspond to shared memory pages
currently out in swap space (see also mm/swap.c):
bit 0 (PAGE_PRESENT) is = 0
bits 7..1 (SWP_TYPE) are = SHM_SWP_TYPE
bits 31..8 are used like this:
bits 14..8 (SHM_ID) the id of the shared memory segment
bits 29..15 (SHM_IDX) the index of the page within the shared memory segment
(actually only bits 24..15 get used since SHMMAX is so low)
bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach
*/
#define __SHM_IDX_BITS (BITS_PER_PTR-2-SHM_IDX_SHIFT)
/* !!!!!!!?????
* Why reserve the two (2) high bits of the signature (shm_sgn) field?
* Since, as far as I can see, only the high bit is used (SHM_READ_ONLY).
* SRB.
*/
#define _SHM_IDX_BITS (__SHM_IDX_BITS+PAGE_SHIFT>=BITS_PER_PTR?\
BITS_PER_PTR-PAGE_SHIFT-1:__SHM_IDX_BITS) /* sanity check */
/* not present page table entry format bit 0 is 0, low byte defined in mm.h */
#define SHM_ID_SHIFT 8
/* Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
there is a static array of size SHMMNI. */
#define _SHM_ID_BITS 7
#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1)
#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS)
#define _SHM_IDX_BITS 15
#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1)
#define SHM_READ_ONLY (1<<(BITS_PER_PTR-1))
#define SHM_READ_ONLY (1<<31)
/* We must have SHM_ID_SHIFT + _SHM_ID_BITS + _SHM_IDX_BITS + 1 <= 32
and SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). */
#define SHMMAX 0x3fa000 /* max shared seg size (bytes) */
#define SHMMIN 1 /* really PAGE_SIZE */ /* min shared seg size (bytes) */
......@@ -106,4 +107,3 @@ struct shm_desc {
#endif /* _LINUX_SHM_H_ */
......@@ -29,7 +29,7 @@ void msg_init (void)
{
int id;
for (id=0; id < MSGMNI; id++)
for (id = 0; id < MSGMNI; id++)
msgque[id] = (struct msqid_ds *) IPC_UNUSED;
msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
msg_lock = NULL;
......@@ -53,14 +53,14 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
return err;
if ((mtype = get_fs_long (&msgp->mtype)) < 1)
return -EINVAL;
id = msqid % MSGMNI;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
return -EINVAL;
ipcp = &msq->msg_perm;
slept:
if (ipcp->seq != (msqid / MSGMNI))
if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
return -EIDRM;
if (ipcperms(ipcp, S_IWUGO))
return -EACCES;
......@@ -83,7 +83,7 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
memcpy_fromfs (msgh->msg_spot, msgp->mtext, msgsz);
if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
|| ipcp->seq != msqid / MSGMNI) {
|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
kfree(msgh);
return -EIDRM;
}
......@@ -125,7 +125,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
if (err)
return err;
id = msqid % MSGMNI;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
if (msq == IPC_NOID || msq == IPC_UNUSED)
return -EINVAL;
......@@ -138,7 +138,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
* msgtyp < 0 => get message with least type must be < abs(msgtype).
*/
while (!nmsg) {
if(ipcp->seq != msqid / MSGMNI)
if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
return -EIDRM;
if (ipcperms (ipcp, S_IRUGO))
return -EACCES;
......@@ -174,7 +174,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
if (nmsg == msq->msg_first)
msq->msg_first = nmsg->msg_next;
else {
for (tmsg= msq->msg_first; tmsg;
for (tmsg = msq->msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_next == nmsg)
break;
......@@ -213,7 +213,7 @@ static int findkey (key_t key)
int id;
struct msqid_ds *msq;
for (id=0; id <= max_msqid; id++) {
for (id = 0; id <= max_msqid; id++) {
while ((msq = msgque[id]) == IPC_NOID)
interruptible_sleep_on (&msg_lock);
if (msq == IPC_UNUSED)
......@@ -230,7 +230,7 @@ static int newque (key_t key, int msgflg)
struct msqid_ds *msq;
struct ipc_perm *ipcp;
for (id=0; id < MSGMNI; id++)
for (id = 0; id < MSGMNI; id++)
if (msgque[id] == IPC_UNUSED) {
msgque[id] = (struct msqid_ds *) IPC_NOID;
goto found;
......@@ -250,7 +250,7 @@ static int newque (key_t key, int msgflg)
ipcp->key = key;
ipcp->cuid = ipcp->uid = current->euid;
ipcp->gid = ipcp->cgid = current->egid;
ipcp->seq = msg_seq;
msq->msg_perm.seq = msg_seq;
msq->msg_first = msq->msg_last = NULL;
msq->rwait = msq->wwait = NULL;
msq->msg_cbytes = msq->msg_qnum = 0;
......@@ -264,7 +264,7 @@ static int newque (key_t key, int msgflg)
used_queues++;
if (msg_lock)
wake_up (&msg_lock);
return (int) msg_seq * MSGMNI + id;
return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
}
int sys_msgget (key_t key, int msgflg)
......@@ -286,7 +286,7 @@ int sys_msgget (key_t key, int msgflg)
return -EIDRM;
if (ipcperms(&msq->msg_perm, msgflg))
return -EACCES;
return msq->msg_perm.seq * MSGMNI +id;
return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
}
static void freeque (int id)
......@@ -295,7 +295,7 @@ static void freeque (int id)
struct msg *msgp, *msgh;
msq->msg_perm.seq++;
msg_seq++;
msg_seq = (msg_seq+1) % ((unsigned)(1<<31)/MSGMNI); /* increment, but avoid overflow */
msgbytes -= msq->msg_cbytes;
if (id == max_msqid)
while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));
......@@ -319,7 +319,8 @@ static void freeque (int id)
int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
int id, err;
struct msqid_ds *msq, tbuf;
struct msqid_ds *msq;
struct msqid_ds tbuf;
struct ipc_perm *ipcp;
if (msqid < 0 || cmd < 0)
......@@ -353,7 +354,7 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
case MSG_STAT:
if (!buf)
return -EFAULT;
err = verify_area (VERIFY_WRITE, buf, sizeof (*msq));
err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
if (err)
return err;
if (msqid > max_msqid)
......@@ -363,46 +364,62 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
return -EINVAL;
if (ipcperms (&msq->msg_perm, S_IRUGO))
return -EACCES;
id = msqid + msq->msg_perm.seq * MSGMNI;
memcpy_tofs (buf, msq, sizeof(*msq));
id = (unsigned int) msq->msg_perm.seq * MSGMNI + msqid;
tbuf.msg_perm = msq->msg_perm;
tbuf.msg_stime = msq->msg_stime;
tbuf.msg_rtime = msq->msg_rtime;
tbuf.msg_ctime = msq->msg_ctime;
tbuf.msg_cbytes = msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
memcpy_tofs (buf, &tbuf, sizeof(*buf));
return id;
case IPC_SET:
if (!buf)
return -EFAULT;
err = verify_area (VERIFY_READ, buf, sizeof (*buf));
if (err)
return err;
memcpy_fromfs (&tbuf, buf, sizeof (*buf));
break;
case IPC_STAT:
if (!buf)
return -EFAULT;
err = verify_area (VERIFY_WRITE, buf, sizeof(*msq));
err = verify_area (VERIFY_WRITE, buf, sizeof(*buf));
if (err)
return err;
break;
}
id = msqid % MSGMNI;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
return -EINVAL;
ipcp = &msq->msg_perm;
if (ipcp->seq != msqid / MSGMNI)
if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
return -EIDRM;
ipcp = &msq->msg_perm;
switch (cmd) {
case IPC_STAT:
if (ipcperms (ipcp, S_IRUGO))
return -EACCES;
memcpy_tofs (buf, msq, sizeof (*msq));
tbuf.msg_perm = msq->msg_perm;
tbuf.msg_stime = msq->msg_stime;
tbuf.msg_rtime = msq->msg_rtime;
tbuf.msg_ctime = msq->msg_ctime;
tbuf.msg_cbytes = msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
memcpy_tofs (buf, &tbuf, sizeof (*buf));
return 0;
break;
case IPC_RMID: case IPC_SET:
case IPC_SET:
if (!suser() && current->euid != ipcp->cuid &&
current->euid != ipcp->uid)
return -EPERM;
if (cmd == IPC_RMID) {
freeque (id);
return 0;
}
if (tbuf.msg_qbytes > MSGMNB && !suser())
return -EPERM;
msq->msg_qbytes = tbuf.msg_qbytes;
......@@ -411,10 +428,14 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
(S_IRWXUGO & tbuf.msg_perm.mode);
msq->msg_ctime = CURRENT_TIME;
break;
return 0;
case IPC_RMID:
if (!suser() && current->euid != ipcp->cuid &&
current->euid != ipcp->uid)
return -EPERM;
freeque (id);
return 0;
default:
return -EINVAL;
break;
}
return 0;
}
This diff is collapsed.
This diff is collapsed.
......@@ -13,7 +13,7 @@
#include <linux/stat.h>
void ipc_init (void);
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr);
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr);
#ifdef CONFIG_SYSVIPC
......@@ -21,16 +21,16 @@ int ipcperms (struct ipc_perm *ipcp, short flag);
extern void sem_init (void), msg_init (void), shm_init (void);
extern int sys_semget (key_t key, int nsems, int semflg);
extern int sys_semop (int semid, struct sembuf *sops, unsigned nsops);
extern int sys_semctl (int semid, int semnum, int cmd, void *arg);
extern int sys_semctl (int semid, int semnum, int cmd, union semun arg);
extern int sys_msgget (key_t key, int msgflg);
extern int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
extern int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
int msgflg);
extern int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
extern int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
extern int sys_shmget (key_t key, int size, int flag);
extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr);
extern int sys_shmdt (char *shmaddr);
extern int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
void ipc_init (void)
{
......@@ -71,8 +71,16 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
return sys_semop (first, (struct sembuf *)ptr, second);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL:
return sys_semctl (first, second, third, ptr);
case SEMCTL: {
union semun fourth;
int err;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err;
fourth.__pad = (void *) get_fs_long(ptr);
return sys_semctl (first, second, third, fourth);
}
default:
return -EINVAL;
}
......@@ -82,10 +90,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
case MSGRCV: {
struct ipc_kludge tmp;
struct ipc_kludge tmp;
int err;
if (!ptr)
return -EINVAL;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
return err;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp));
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
third);
......@@ -93,14 +104,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
return sys_msgctl (first, second,
(struct msqid_ds *) ptr);
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
default:
return -EINVAL;
}
if (call <= SHMCTL)
switch (call) {
case SHMAT: /* returning shmaddr > 2G will screw up */
case SHMAT:
return sys_shmat (first, (char *) ptr, second,
(ulong *) third);
case SHMDT:
......@@ -108,8 +118,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
return sys_shmctl (first, second,
(struct shmid_ds *) ptr);
return sys_shmctl (first, second, (struct shmid_ds *) ptr);
default:
return -EINVAL;
}
......
......@@ -411,7 +411,7 @@ NORET_TYPE void do_exit(long code)
intr_count = 0;
}
fake_volatile:
if (current->semun)
if (current->semundo)
sem_exit();
if (current->shm)
shm_exit();
......
......@@ -28,6 +28,7 @@
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/locks.h>
#include <linux/string.h>
#ifdef CONFIG_INET
#include <linux/net.h>
#include <linux/netdevice.h>
......@@ -46,7 +47,6 @@ extern void (*do_floppy)(void);
#endif
extern int sys_tz;
extern int ___strtok;
extern int request_dma(unsigned int dmanr, char * deviceID);
extern void free_dma(unsigned int dmanr);
......@@ -92,6 +92,13 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(open_namei),
X(inode_setattr),
X(inode_change_ok),
X(generic_mmap),
X(set_blocksize),
X(getblk),
X(bread),
X(brelse),
X(ll_rw_block),
X(__wait_on_buffer),
/* device registration */
X(register_chrdev),
......@@ -156,6 +163,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(printk),
X(sprintf),
X(vsprintf),
X(simple_strtoul),
X(system_utsname),
X(sys_call_table),
......@@ -206,26 +214,16 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
#endif
/* Added to make file system as module */
X(set_writetime),
X(getblk),
X(inode_setattr),
X(sys_tz),
X(inode_change_ok),
X(__wait_on_super),
X(file_fsync),
X(simple_strtoul),
X(generic_mmap),
X(set_blocksize),
X(clear_inode),
X(refile_buffer),
X(___strtok),
X(brelse),
X(bread),
X(init_fifo),
X(super_blocks),
X(chrdev_inode_operations),
X(blkdev_inode_operations),
X(ll_rw_block),
X(__wait_on_buffer),
X(read_ahead),
/********************************************************
* Do not add anything below this line,
......
......@@ -319,7 +319,7 @@ int unmap_page_range(unsigned long from, unsigned long size)
for (pc = pcnt; pc--; page_table++) {
if ((page = *page_table) != 0) {
*page_table = 0;
if (1 & page) {
if (PAGE_PRESENT & page) {
if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
if (current->mm->rss > 0)
--current->mm->rss;
......
......@@ -624,7 +624,7 @@ static int inet_create(struct socket *sock, int protocol)
sk->prot = prot;
sk->sleep = sock->wait;
sk->daddr = 0;
sk->saddr = ip_my_addr();
sk->saddr = 0 /* ip_my_addr() */;
sk->err = 0;
sk->next = NULL;
sk->pair = NULL;
......@@ -749,6 +749,7 @@ static int inet_release(struct socket *sock, struct socket *peer)
/* This will destroy it. */
release_sock(sk);
sock->data = NULL;
sk->socket = NULL;
return(0);
}
......@@ -1261,6 +1262,10 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/*
* This routine must find a socket given a TCP or UDP header.
* Everything is assumed to be in net order.
*
* We give priority to more closely bound ports: if some socket
* is bound to a particular foreign address, it will get the packet
* rather than somebody listening to any address..
*/
struct sock *get_sock(struct proto *prot, unsigned short num,
......@@ -1268,6 +1273,8 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
unsigned short rnum, unsigned long laddr)
{
struct sock *s;
struct sock *result = NULL;
int badness = -1;
unsigned short hnum;
hnum = ntohs(num);
......@@ -1284,21 +1291,41 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)];
s != NULL; s = s->next)
{
int score = 0;
if (s->num != hnum)
continue;
if(s->dead && (s->state == TCP_CLOSE))
continue;
if(ip_addr_match(s->saddr,laddr) == 0)
continue;
if(prot == &udp_prot)
/* local address matches? */
if (s->saddr) {
if (s->saddr != laddr)
continue;
score++;
}
/* remote address matches? */
if (s->daddr) {
if (s->daddr != raddr)
continue;
score++;
}
/* remote port matches? */
if (s->dummy_th.dest) {
if (s->dummy_th.dest != rnum)
continue;
score++;
}
/* perfect match? */
if (score == 3)
return s;
if(ip_addr_match(s->daddr,raddr)==0)
continue;
if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0)
/* no, check if this is the best so far.. */
if (score <= badness)
continue;
return(s);
result = s;
badness = score;
}
return(NULL);
return result;
}
static struct proto_ops inet_proto_ops = {
......
......@@ -200,13 +200,6 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
int tmp;
unsigned long src;
/*
* If there is no 'from' address as yet, then make it our loopback
*/
if (saddr == 0)
saddr = ip_my_addr();
buff = skb->data;
/*
......@@ -255,6 +248,12 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
raddr = (rt == NULL) ? 0 : rt->rt_gateway;
}
/*
* No source addr so make it our addr
*/
if (saddr == 0)
saddr = src;
/*
* No gateway so aim at the real destination
*/
......
......@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
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->dead?0:SOCK_INODE(sp->socket)->i_uid);
sp->socket?SOCK_INODE(sp->socket)->i_uid:0);
if (timer_active)
add_timer(&sp->timer);
/*
......
......@@ -542,9 +542,9 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l
/*
* broadcast addresses can be special cases..
*/
if ((rt->rt_gateway == 0) &&
(rt->rt_dev->flags & IFF_BROADCAST) &&
if (rt->rt_flags & RTF_GATEWAY)
continue;
if ((rt->rt_dev->flags & IFF_BROADCAST) &&
(rt->rt_dev->pa_brdaddr == daddr))
break;
}
......
......@@ -89,6 +89,10 @@
* Michael Pall : Undo the last fix in tcp_read_urg() (multi URG PUSH broke rlogin).
* Michael Pall : Fix the multi URG PUSH problem in tcp_readable(), select() after URG works now.
* Michael Pall : recv(...,MSG_OOB) never blocks in the BSD api.
* Alan Cox : Changed the semantics of sk->socket to
* fix a race and a signal problem with
* accept() and async I/O.
* Alan Cox : Relaxed the rules on tcp_sendto().
*
*
* To Fix:
......@@ -1227,7 +1231,7 @@ static int tcp_sendto(struct sock *sk, unsigned char *from,
{
if (flags & ~(MSG_OOB|MSG_DONTROUTE))
return -EINVAL;
if (!tcp_connected(sk->state))
if (sk->state == TCP_CLOSE)
return -ENOTCONN;
if (addr_len < sizeof(*addr))
return -EINVAL;
......@@ -2084,6 +2088,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk->dummy_th.res2 = 0;
newsk->acked_seq = skb->h.th->seq + 1;
newsk->copied_seq = skb->h.th->seq;
newsk->socket = NULL;
/*
* Grab the ttl and tos values and use them
......
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