Commit 5f50b72d authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.52

parent c3347054
This diff is collapsed.
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 51
SUBLEVEL = 52
ARCH = i386
......
......@@ -541,5 +541,4 @@ _sys_call_table:
.long _sys_setfsuid
.long _sys_setfsgid
.long _sys_llseek /* 140 */
.space (NR_syscalls-139)*4
.space (NR_syscalls-140)*4
......@@ -75,14 +75,13 @@ extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
#elif (MAJOR_NR == FLOPPY_MAJOR)
static void floppy_on(unsigned int nr);
static void floppy_off(unsigned int nr);
#define DEVICE_NAME "floppy"
#define DEVICE_INTR do_floppy
#define DEVICE_REQUEST do_fd_request
#define DEVICE_NR(device) ( ((device) & 3) | (((device) & 0x80 ) >> 5 ))
#define DEVICE_ON(device) floppy_on(DEVICE_NR(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
#elif (MAJOR_NR == HD_MAJOR)
......
This diff is collapsed.
......@@ -80,7 +80,7 @@ static int hd_error = 0;
struct hd_i_struct {
unsigned int head,sect,cyl,wpcom,lzone,ctl;
};
static struct hd_driveid *hd_ident_info[MAX_HD];
static struct hd_driveid *hd_ident_info[MAX_HD] = {0, };
#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
......@@ -275,16 +275,21 @@ static void identify_intr(void)
{
unsigned int dev = DEVICE_NR(CURRENT->dev);
unsigned short stat = inb_p(HD_STATUS);
struct hd_driveid id;
struct hd_driveid *id = hd_ident_info[dev];
if (unmask_intr[dev])
sti();
if (stat & (BUSY_STAT|ERR_STAT))
printk (" hd%c: identity unknown\n", dev+'a');
else {
insw(HD_DATA, (char *)&id, sizeof(id)/2); /* get ID bytes */
max_mult[dev] = id.max_multsect;
if ((id.cur_valid&1) && id.cur_cyls && id.cur_heads && (id.cur_heads <= 16) && id.cur_sectors) {
if (stat & (BUSY_STAT|ERR_STAT)) {
printk (" hd%c: non-IDE device, CHS=%d%d%d\n", dev+'a',
hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
if (id != NULL) {
hd_ident_info[dev] = NULL;
kfree_s (id, 512);
}
} else {
insw(HD_DATA, id, 256); /* get ID info */
max_mult[dev] = id->max_multsect;
if ((id->field_valid&1) && id->cur_cyls && id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
/*
* Extract the physical drive geometry for our use.
* Note that we purposely do *not* update the bios_info.
......@@ -292,31 +297,24 @@ static void identify_intr(void)
* still have the same logical view as the BIOS does,
* which keeps the partition table from being screwed.
*/
hd_info[dev].cyl = id.cur_cyls;
hd_info[dev].head = id.cur_heads;
hd_info[dev].sect = id.cur_sectors;
hd_info[dev].cyl = id->cur_cyls;
hd_info[dev].head = id->cur_heads;
hd_info[dev].sect = id->cur_sectors;
}
fixstring (id.serial_no, sizeof(id.serial_no));
fixstring (id.fw_rev, sizeof(id.fw_rev));
fixstring (id.model, sizeof(id.model));
fixstring (id->serial_no, sizeof(id->serial_no));
fixstring (id->fw_rev, sizeof(id->fw_rev));
fixstring (id->model, sizeof(id->model));
printk (" hd%c: %.40s, %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
dev+'a', id.model, id.cyls*id.heads*id.sectors/2048,
id.buf_size/2, hd_info[dev].cyl, hd_info[dev].head,
hd_info[dev].sect, id.max_multsect);
/* save drive info for later query via HDIO_GETIDENTITY */
if (NULL != (hd_ident_info[dev] = (struct hd_driveid *)kmalloc(sizeof(id),GFP_ATOMIC)))
*hd_ident_info[dev] = id;
/* Quantum drives go weird at this point, so reset them! */
/* In fact, we should probably do a reset in any case in */
/* case we changed the geometry */
if (!strncmp(id.model, "QUANTUM", 7))
reset = 1;
/* flush remaining 384 (reserved/undefined) ID bytes: */
insw(HD_DATA,(char *)&id,sizeof(id)/2);
insw(HD_DATA,(char *)&id,sizeof(id)/2);
insw(HD_DATA,(char *)&id,sizeof(id)/2);
dev+'a', id->model, id->cyls*id->heads*id->sectors/2048,
id->buf_size/2, hd_info[dev].cyl, hd_info[dev].head,
hd_info[dev].sect, id->max_multsect);
/*
* Early model Quantum drives go weird at this point,
* but doing a recalibrate seems to "fix" them.
* (Doing a full reset confuses some newer model Quantums)
*/
if (!strncmp(id->model, "QUANTUM", 7))
special_op[dev] = recalibrate[dev] = 1;
}
#if (HD_DELAY > 0)
last_req = read_timer();
......@@ -1040,7 +1038,7 @@ static void hd_geninit(void)
}
hd[i<<6].nr_sects = bios_info[i].head *
bios_info[i].sect * bios_info[i].cyl;
hd_ident_info[i] = NULL;
hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
special_op[i] = 1;
}
if (NR_HD) {
......
......@@ -22,6 +22,7 @@
#define RAMDISK_MINOR 1
extern void wait_for_keypress(void);
char *rd_start;
int rd_length = 0;
......@@ -102,7 +103,7 @@ static void do_load(void)
int i = 1;
int nblocks;
char *cp;
/*
* Check for a super block on the diskette.
* The old-style boot/root diskettes had their RAM image
......@@ -164,9 +165,6 @@ static void do_load(void)
}
}
int floppy_grab_irq_and_dma(void);
void floppy_release_irq_and_dma(void);
/*
* If the root device is the RAM disk, try to load it.
* In order to do this, the root device is originally set to the
......@@ -174,6 +172,9 @@ void floppy_release_irq_and_dma(void);
*/
void rd_load(void)
{
struct inode inode;
struct file filp;
/* If no RAM disk specified, give up early. */
if (!rd_length)
return;
......@@ -184,12 +185,18 @@ void rd_load(void)
if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR)
return;
/* ugly, ugly */
if (floppy_grab_irq_and_dma()) {
printk("Unable to grab floppy IRQ/DMA for loading ramdisk image\n");
return;
/* for Slackware install disks */
printk(KERN_NOTICE "VFS: Insert ramdisk floppy and press ENTER\n");
wait_for_keypress();
memset(&filp, 0, sizeof(filp));
memset(&inode, 0, sizeof(inode));
inode.i_rdev = ROOT_DEV;
filp.f_mode = 1; /* read only */
filp.f_inode = &inode;
if(blkdev_open(&inode, &filp) == 0 ){
do_load();
if(filp.f_op && filp.f_op->release)
filp.f_op->release(&inode,&filp);
}
check_disk_change(ROOT_DEV);
do_load();
floppy_release_irq_and_dma();
}
......@@ -2100,7 +2100,8 @@ static void clear_selection()
*/
#define colourmap ((char *)0xa0000)
#define blackwmap ((char *)0xb0000)
/* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */
#define blackwmap ((char *)0xa0000)
#define cmapsz 8192
#define seq_port_reg (0x3c4)
#define seq_port_val (0x3c5)
......
......@@ -4,6 +4,7 @@
* - Thanks much to Gunter Windau for pointing out to me where the error
* checking ought to be.
* Copyright (C) 1993 by Nigel Gamble (added interrupt code)
* Copyright (C) 1994 by Alan Cox (Modularised it)
*/
#include <linux/errno.h>
......@@ -17,6 +18,24 @@
#include <asm/segment.h>
#include <asm/system.h>
/* the BIOS manuals say there can be up to 4 lpt devices
* but I have not seen a board where the 4th address is listed
* if you have different hardware change the table below
* please let me know if you have different equipment
* if you have more than 3 printers, remember to increase LP_NO
*/
struct lp_struct lp_table[] = {
{ 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
{ 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
{ 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
};
#define LP_NO 3
#ifdef MODULE
#include <linux/module.h>
#include "../../tools/version.h"
#endif
/*
* All my debugging code assumes that you debug with only one printer at
* a time. RWWH
......@@ -305,7 +324,9 @@ static int lp_open(struct inode * inode, struct file * file)
}
LP_F(minor) |= LP_BUSY;
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
return 0;
}
......@@ -321,6 +342,9 @@ static void lp_release(struct inode * inode, struct file * file)
}
LP_F(minor) &= ~LP_BUSY;
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
}
......@@ -418,6 +442,8 @@ static struct file_operations lp_fops = {
lp_release
};
#ifndef MODULE
long lp_init(long kmem_start)
{
int offset = 0;
......@@ -450,3 +476,42 @@ long lp_init(long kmem_start)
printk("lp_init: no lp devices found\n");
return kmem_start;
}
#else
char kernel_version[]= UTS_RELEASE;
int init_module(void)
{
int offset = 0;
unsigned int testvalue = 0;
int count = 0;
if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
printk("unable to get major %d for line printer\n", LP_MAJOR);
return -EIO;
}
/* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) {
/* write to port & read back to check */
outb_p( LP_DUMMY, LP_B(offset));
for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
;
testvalue = inb_p(LP_B(offset));
if (testvalue == LP_DUMMY) {
LP_F(offset) |= LP_EXIST;
lp_reset(offset);
printk("lp_init: lp%d exists, ", offset);
if (LP_IRQ(offset))
printk("using IRQ%d\n", LP_IRQ(offset));
else
printk("using polling driver\n");
count++;
}
}
if (count == 0)
printk("lp_init: no lp devices found\n");
return 0;
}
#endif
......@@ -453,6 +453,8 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
goto handle_newline;
}
if (c == EOF_CHAR(tty)) {
if (tty->canon_head != tty->read_head)
set_bit(TTY_PUSH, &tty->flags);
c = __DISABLED_CHAR;
goto handle_newline;
}
......@@ -718,24 +720,6 @@ static inline void copy_from_read_buf(struct tty_struct *tty,
*nr -= n;
}
/*
* Called to gobble up an immediately following EOF when there is no
* more room in buf (this can happen if the user "pushes" some
* characters using ^D). This prevents the next read() from falsely
* returning EOF.
*/
static inline void gobble_eof(struct tty_struct *tty)
{
cli();
if ((tty->read_cnt) &&
(tty->read_buf[tty->read_tail] == __DISABLED_CHAR) &&
clear_bit(tty->read_tail, &tty->read_flags)) {
tty->read_tail = (tty->read_tail+1) & (N_TTY_BUF_SIZE-1);
tty->read_cnt--;
}
sti();
}
static int read_chan(struct tty_struct *tty, struct file *file,
unsigned char *buf, unsigned int nr)
{
......@@ -744,6 +728,9 @@ static int read_chan(struct tty_struct *tty, struct file *file,
unsigned char *b = buf;
int minimum, time;
int retval = 0;
int size;
do_it_again:
if (!tty->read_buf) {
printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
......@@ -858,7 +845,6 @@ static int read_chan(struct tty_struct *tty, struct file *file,
put_fs_byte(c, b++);
if (--nr)
continue;
gobble_eof(tty);
break;
}
if (--tty->canon_data < 0) {
......@@ -896,7 +882,14 @@ static int read_chan(struct tty_struct *tty, struct file *file,
current->state = TASK_RUNNING;
current->timeout = 0;
return (b - buf) ? b - buf : retval;
size = b - buf;
if (size && nr)
clear_bit(TTY_PUSH, &tty->flags);
if (!size && clear_bit(TTY_PUSH, &tty->flags))
goto do_it_again;
if (!size && !retval)
clear_bit(TTY_PUSH, &tty->flags);
return (size ? size : retval);
}
static int write_chan(struct tty_struct * tty, struct file * file,
......
......@@ -1242,6 +1242,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
case TIOCSTI:
if ((current->tty != tty) && !suser())
return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval)
return retval;
ch = get_fs_byte((char *) arg);
tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
return 0;
......@@ -1254,6 +1257,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
sizeof (struct winsize));
return 0;
case TIOCSWINSZ:
retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (struct winsize));
if (retval)
return retval;
memcpy_fromfs(&tmp_ws, (struct winsize *) arg,
sizeof (struct winsize));
if (memcmp(&tmp_ws, &tty->winsize,
......@@ -1279,6 +1286,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
redirect = real_tty;
return 0;
case FIONBIO:
retval = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
if (retval)
return retval;
arg = get_fs_long((unsigned long *) arg);
if (arg)
file->f_flags |= O_NONBLOCK;
......@@ -1371,6 +1381,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
arg = get_fs_long((unsigned long *) arg);
return tty_set_ldisc(tty, arg);
case TIOCLINUX:
retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval)
return retval;
switch (get_fs_byte((char *)arg))
{
case 0:
......
......@@ -98,6 +98,9 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
return retval;
if (opt & TERMIOS_TERMIO) {
retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termio));
if (retval)
return retval;
tmp_termios = *tty->termios;
memcpy_fromfs(&tmp_termio, (struct termio *) arg,
sizeof (struct termio));
......@@ -109,9 +112,13 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
#undef SET_LOW_BITS
} else
} else {
retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
if (retval)
return retval;
memcpy_fromfs(&tmp_termios, (struct termios *) arg,
sizeof (struct termios));
}
if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
......@@ -307,6 +314,10 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
(unsigned long *) arg);
return 0;
case TIOCGLCKTRMIOS:
retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (unsigned long));
if (retval)
return retval;
arg = get_fs_long((unsigned long *) arg);
retval = verify_area(VERIFY_WRITE, (void *) arg,
sizeof (struct termios));
......@@ -319,7 +330,15 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
case TIOCSLCKTRMIOS:
if (!suser())
return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (unsigned long));
if (retval)
return retval;
arg = get_fs_long((unsigned long *) arg);
retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (struct termios));
if (retval)
return retval;
memcpy_fromfs(&real_tty->termios_locked,
(struct termios *) arg,
sizeof (struct termios));
......
......@@ -78,6 +78,7 @@ make one yourself. The wiring is:
#include <netinet/in.h>
#include <errno.h>
#include <linux/delay.h>
#include <linux/lp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
......@@ -196,7 +197,7 @@ plip_init(struct device *dev)
struct net_local *pl;
/* Check that there is something at base_addr. */
outb(0x00, PAR_CONTROL(dev));
outb(LP_PINITP, PAR_CONTROL(dev));
outb(0x00, PAR_DATA(dev));
if (inb(PAR_DATA(dev)) != 0x00)
return -ENODEV;
......@@ -212,9 +213,9 @@ plip_init(struct device *dev)
printk("%s: configured for parallel port at %#3x",
dev->name, dev->base_addr);
autoirq_setup(0);
outb(0x00, PAR_CONTROL(dev));
outb(0x10, PAR_CONTROL(dev));
outb(0x00, PAR_CONTROL(dev));
outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
outb(LP_PINITP|LP_PSELECP|LP_PINTEN, PAR_CONTROL(dev));
outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
dev->irq = autoirq_report(1);
if (dev->irq)
printk(", probed IRQ %d.\n", dev->irq);
......@@ -368,7 +369,7 @@ plip_open(struct device *dev)
irq2dev_map[dev->irq] = dev;
sti();
/* enable rx interrupt. */
outb(0x10, PAR_CONTROL(dev));
outb(LP_PINITP|LP_PSELECP|LP_PINTEN, PAR_CONTROL(dev));
plip_device_clear(dev);
dev->start = 1;
#ifdef MODULE
......@@ -393,7 +394,7 @@ plip_close(struct device *dev)
/* make sure that we don't register the timer */
del_timer(&lp->tl);
/* release the interrupt. */
outb(0x00, PAR_CONTROL(dev));
outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
......
/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $
* linux/include/asm/dma.h: Defines for using and allocating dma channels.
* Written by Hennus Bergman, 1992.
* High DMA channel support & info by Hannu Savolainen
* and John Boyd, Nov. 1992.
*/
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
#include <asm/io.h> /* need byte IO */
#define deb_outb(x,y) {printk("out %02x, %02x\n", x, y);outb(x,y);}
#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
#define outb outb_p
#endif
/*
* NOTES about DMA transfers:
*
* controller 1: channels 0-3, byte operations, ports 00-1F
* controller 2: channels 4-7, word operations, ports C0-DF
*
* - ALL registers are 8 bits only, regardless of transfer size
* - channel 4 is not used - cascades 1 into 2.
* - channels 0-3 are byte - addresses/counts are for physical bytes
* - channels 5-7 are word - addresses/counts are for physical words
* - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
* - transfer count loaded to registers is 1 less than actual count
* - controller 2 offsets are all even (2x offsets for controller 1)
* - page registers for 5-7 don't use data bit 0, represent 128K pages
* - page registers for 0-3 use bit 0, represent 64K pages
*
* DMA transfers are limited to the lower 16MB of _physical_ memory.
* Note that addresses loaded into registers must be _physical_ addresses,
* not logical addresses (which may differ if paging is active).
*
* Address mapping for channels 0-3:
*
* A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
* | ... | | ... | | ... |
* | ... | | ... | | ... |
* | ... | | ... | | ... |
* P7 ... P0 A7 ... A0 A7 ... A0
* | Page | Addr MSB | Addr LSB | (DMA registers)
*
* Address mapping for channels 5-7:
*
* A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
* | ... | \ \ ... \ \ \ ... \ \
* | ... | \ \ ... \ \ \ ... \ (not used)
* | ... | \ \ ... \ \ \ ... \
* P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
* | Page | Addr MSB | Addr LSB | (DMA registers)
*
* Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
* and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
* the hardware level, so odd-byte transfers aren't possible).
*
* Transfer count (_not # bytes_) is limited to 64K, represented as actual
* count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
* and up to 128K bytes may be transferred on channels 5-7 in one operation.
*
*/
#define MAX_DMA_CHANNELS 8
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
/* DMA controller registers */
#define DMA1_CMD_REG 0x08 /* command register (w) */
#define DMA1_STAT_REG 0x08 /* status register (r) */
#define DMA1_REQ_REG 0x09 /* request register (w) */
#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
#define DMA1_MODE_REG 0x0B /* mode register (w) */
#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
#define DMA2_CMD_REG 0xD0 /* command register (w) */
#define DMA2_STAT_REG 0xD0 /* status register (r) */
#define DMA2_REQ_REG 0xD2 /* request register (w) */
#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
#define DMA2_MODE_REG 0xD6 /* mode register (w) */
#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
#define DMA_ADDR_0 0x00 /* DMA address registers */
#define DMA_ADDR_1 0x02
#define DMA_ADDR_2 0x04
#define DMA_ADDR_3 0x06
#define DMA_ADDR_4 0xC0
#define DMA_ADDR_5 0xC4
#define DMA_ADDR_6 0xC8
#define DMA_ADDR_7 0xCC
#define DMA_CNT_0 0x01 /* DMA count registers */
#define DMA_CNT_1 0x03
#define DMA_CNT_2 0x05
#define DMA_CNT_3 0x07
#define DMA_CNT_4 0xC2
#define DMA_CNT_5 0xC6
#define DMA_CNT_6 0xCA
#define DMA_CNT_7 0xCE
#define DMA_PAGE_0 0x87 /* DMA page registers */
#define DMA_PAGE_1 0x83
#define DMA_PAGE_2 0x81
#define DMA_PAGE_3 0x82
#define DMA_PAGE_5 0x8B
#define DMA_PAGE_6 0x89
#define DMA_PAGE_7 0x8A
#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
/* enable/disable a specific DMA channel */
static __inline__ void enable_dma(unsigned int dmanr)
{
if (dmanr<=3)
deb_outb(dmanr, DMA1_MASK_REG)
else
deb_outb(dmanr & 3, DMA2_MASK_REG);
}
static __inline__ void disable_dma(unsigned int dmanr)
{
if (dmanr<=3)
deb_outb(dmanr | 4, DMA1_MASK_REG)
else
deb_outb((dmanr & 3) | 4, DMA2_MASK_REG);
}
/* Clear the 'DMA Pointer Flip Flop'.
* Write 0 for LSB/MSB, 1 for MSB/LSB access.
* Use this once to initialize the FF to a known state.
* After that, keep track of it. :-)
* --- In order to do that, the DMA routines below should ---
* --- only be used while interrupts are disabled! ---
*/
static __inline__ void clear_dma_ff(unsigned int dmanr)
{
if (dmanr<=3)
deb_outb(0, DMA1_CLEAR_FF_REG)
else
deb_outb(0, DMA2_CLEAR_FF_REG);
}
/* set mode (above) for a specific DMA channel */
static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
{
if (dmanr<=3)
deb_outb(mode | dmanr, DMA1_MODE_REG)
else
deb_outb(mode | (dmanr&3), DMA2_MODE_REG);
}
/* Set only the page register bits of the transfer address.
* This is used for successive transfers when we know the contents of
* the lower 16 bits of the DMA current address register, but a 64k boundary
* may have been crossed.
*/
static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
{
switch(dmanr) {
case 0:
deb_outb(pagenr, DMA_PAGE_0);
break;
case 1:
deb_outb(pagenr, DMA_PAGE_1);
break;
case 2:
deb_outb(pagenr, DMA_PAGE_2);
break;
case 3:
deb_outb(pagenr, DMA_PAGE_3);
break;
case 5:
deb_outb(pagenr & 0xfe, DMA_PAGE_5);
break;
case 6:
deb_outb(pagenr & 0xfe, DMA_PAGE_6);
break;
case 7:
deb_outb(pagenr & 0xfe, DMA_PAGE_7);
break;
}
}
/* Set transfer address & page bits for specific DMA channel.
* Assumes dma flipflop is clear.
*/
static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
{
set_dma_page(dmanr, a>>16);
if (dmanr <= 3) {
deb_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
deb_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE )
} else {
deb_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
deb_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
}
}
/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
* a specific DMA channel.
* You must ensure the parameters are valid.
* NOTE: from a manual: "the number of transfers is one more
* than the initial word count"! This is taken into account.
* Assumes dma flip-flop is clear.
* NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
*/
static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
{
count--;
if (dmanr <= 3) {
deb_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
deb_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
} else {
deb_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
deb_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
}
}
/* Get DMA residue count. After a DMA transfer, this
* should return zero. Reading this while a DMA transfer is
* still in progress will return unpredictable results.
* If called before the channel has been used, it may return 1.
* Otherwise, it returns the number of _bytes_ left to transfer.
*
* Assumes DMA flip-flop is clear.
*/
static __inline__ int get_dma_residue(unsigned int dmanr)
{
unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
: ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
/* using short to get 16-bit wrap around */
unsigned short count;
count = 1 + inb(io_port);
count += inb(io_port) << 8;
return (dmanr<=3)? count : (count<<1);
}
/* These are in kernel/dma.c: */
extern int request_dma(unsigned int dmanr,char * deviceID); /* reserve a DMA channel */
extern void free_dma(unsigned int dmanr); /* release it again */
#endif /* _ASM_DMA_H */
......@@ -147,6 +147,7 @@ static int sync_buffers(dev_t dev, int wait)
2) wait for completion by waiting for all buffers to unlock. */
repeat:
retry = 0;
repeat2:
ncount = 0;
/* We search all lists as a failsafe mechanism, not because we expect
there to be dirty buffers on any of the other lists. */
......@@ -170,6 +171,7 @@ static int sync_buffers(dev_t dev, int wait)
continue;
}
wait_on_buffer (bh);
goto repeat2;
}
/* If an unlocked buffer is not uptodate, there has
been an IO error. Skip it. */
......@@ -183,6 +185,9 @@ static int sync_buffers(dev_t dev, int wait)
on the third pass. */
if (!bh->b_dirt || pass>=2)
continue;
/* don't bother about locked buffers */
if (bh->b_lock)
continue;
bh->b_count++;
bh->b_flushtime = 0;
ll_rw_block(WRITE, 1, &bh);
......@@ -1735,31 +1740,37 @@ asmlinkage int sys_bdflush(int func, int data)
int ncount;
struct buffer_head * bh, *next;
if(!suser()) return -EPERM;
if (!suser())
return -EPERM;
if(func == 1)
if (func == 1)
return sync_old_buffers();
/* Basically func 0 means start, 1 means read param 1, 2 means write param 1, etc */
if(func >= 2){
if (func >= 2) {
i = (func-2) >> 1;
if (i < 0 || i >= N_PARAM) return -EINVAL;
if (i < 0 || i >= N_PARAM)
return -EINVAL;
if((func & 1) == 0) {
error = verify_area(VERIFY_WRITE, (void *) data, sizeof(int));
if(error) return error;
if (error)
return error;
put_fs_long(bdf_prm.data[i], data);
return 0;
};
if(data < bdflush_min[i] || data > bdflush_max[i]) return -EINVAL;
if (data < bdflush_min[i] || data > bdflush_max[i])
return -EINVAL;
bdf_prm.data[i] = data;
return 0;
};
if(bdflush_running++) return -EBUSY; /* Only one copy of this running at one time */
if (bdflush_running)
return -EBUSY; /* Only one copy of this running at one time */
bdflush_running++;
/* OK, from here on is the daemon */
while(1==1){
for (;;) {
#ifdef DEBUG
printk("bdflush() activated...");
#endif
......
......@@ -728,10 +728,10 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
if (!fn)
break;
retval = fn(&bprm, regs);
if (retval == 0) {
if (retval >= 0) {
iput(bprm.inode);
current->did_exec = 1;
return 0;
return retval;
}
if (retval != -ENOEXEC)
break;
......
......@@ -72,7 +72,7 @@ static int ext_readdir(struct inode * inode, struct file * filp,
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
if (filp->f_pos % 8 != 0)
if ((filp->f_pos & 7) != 0)
return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
......
......@@ -232,11 +232,13 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
{
off_t pos;
int written, c;
struct buffer_head * bh;
struct buffer_head * bh, *bufferlist[NBUF];
char * p;
struct super_block * sb;
int err;
int i,buffercount,write_error;
write_error = buffercount = 0;
if (!inode) {
printk("ext2_file_write: inode = NULL\n");
return -EINVAL;
......@@ -294,12 +296,32 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
buf += c;
bh->b_uptodate = 1;
mark_buffer_dirty(bh, 0);
if (filp->f_flags & O_SYNC) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
if (filp->f_flags & O_SYNC)
bufferlist[buffercount++] = bh;
else
brelse(bh);
if (buffercount == NBUF){
ll_rw_block(WRITE, buffercount, bufferlist);
for(i=0; i<buffercount; i++){
wait_on_buffer(bufferlist[i]);
if (!bufferlist[i]->b_uptodate)
write_error=1;
brelse(bufferlist[i]);
}
buffercount=0;
}
brelse (bh);
if(write_error)
break;
}
if ( buffercount ){
ll_rw_block(WRITE, buffercount, bufferlist);
for(i=0; i<buffercount; i++){
wait_on_buffer(bufferlist[i]);
if (!bufferlist[i]->b_uptodate)
write_error=1;
brelse(bufferlist[i]);
}
}
if (pos > inode->i_size)
inode->i_size = pos;
if (filp->f_flags & O_SYNC)
......
......@@ -92,7 +92,11 @@ struct hpfs_spare_block
{
unsigned magic; /* f991 1849 */
unsigned magic1; /* fa52 29c5, more magic? */
unsigned dirty; /* 0 clean, 1 "improperly stopped" */
unsigned dirty: 1; /* 0 clean, 1 "improperly stopped" */
unsigned flag1234: 4; /* unknown flags */
unsigned fast: 1; /* partition was fast formatted */
unsigned flag6to31: 26; /* unknown flags */
secno hotfix_map; /* info about remapped bad sectors */
unsigned n_spares_used; /* number of hotfixes */
......
......@@ -109,7 +109,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
return -EBADF;
error = verify_area(VERIFY_WRITE, l, sizeof(*l));
error = verify_area(VERIFY_READ, l, sizeof(*l));
if (error)
return error;
memcpy_fromfs(&flock, l, sizeof(flock));
......
......@@ -3,6 +3,12 @@
*
* Copyright (C) 1992 Rick Sladkey
*
* Changes Copyright (C) 1994 by Florian La Roche
* - Do not copy data too often around in the kernel.
* - In nfs_file_read the return value of kmalloc wasn't checked.
* - Put in a better version of read look-ahead buffering. Original idea
* and implementation by Wai S Kok elekokw@ee.nus.sg.
*
* nfs regular file handling functions
*/
......@@ -21,7 +27,6 @@
static int nfs_file_read(struct inode *, struct file *, char *, int);
static int nfs_file_write(struct inode *, struct file *, char *, int);
static int nfs_fsync(struct inode *, struct file *);
extern int nfs_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
static struct file_operations nfs_file_operations = {
NULL, /* lseek - default */
......@@ -53,6 +58,32 @@ struct inode_operations nfs_file_inode_operations = {
NULL /* truncate */
};
/* Once data is inserted, it can only be deleted, if (in_use==0). */
struct read_cache {
int in_use; /* currently in use? */
unsigned long inode_num; /* inode number */
off_t file_pos; /* file position */
int len; /* size of data */
unsigned long time; /* time, this entry was inserted */
char * buf; /* data */
int buf_size; /* size of buffer */
};
#define READ_CACHE_SIZE 5
#define EXPIRE_CACHE (HZ * 3) /* keep no longer than 3 seconds */
unsigned long num_requests = 0;
unsigned long num_cache_hits = 0;
static int tail = 0; /* next cache slot to replace */
static struct read_cache cache[READ_CACHE_SIZE] = {
{ 0, 0, -1, 0, 0, NULL, 0 },
{ 0, 0, -1, 0, 0, NULL, 0 },
{ 0, 0, -1, 0, 0, NULL, 0 },
{ 0, 0, -1, 0, 0, NULL, 0 },
{ 0, 0, -1, 0, 0, NULL, 0 } };
static int nfs_fsync(struct inode *inode, struct file *file)
{
return 0;
......@@ -61,10 +92,7 @@ static int nfs_fsync(struct inode *inode, struct file *file)
static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
int count)
{
int result;
int hunk;
int i;
int n;
int result, hunk, i, n, fs;
struct nfs_fattr fattr;
char *data;
off_t pos;
......@@ -79,46 +107,88 @@ static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
return -EINVAL;
}
pos = file->f_pos;
if (file->f_pos + count > inode->i_size)
if (pos + count > inode->i_size)
count = inode->i_size - pos;
if (count <= 0)
return 0;
++num_requests;
cli();
for (i = 0; i < READ_CACHE_SIZE; i++)
if ((cache[i].inode_num == inode->i_ino)
&& (cache[i].file_pos <= pos)
&& (cache[i].file_pos + cache[i].len >= pos + count)
&& (abs(jiffies - cache[i].time) <= EXPIRE_CACHE))
break;
if (i < READ_CACHE_SIZE) {
++cache[i].in_use;
sti();
++num_cache_hits;
memcpy_tofs(buf, cache[i].buf + pos - cache[i].file_pos, count);
--cache[i].in_use;
file->f_pos += count;
return count;
}
sti();
n = NFS_SERVER(inode)->rsize;
data = (char *) kmalloc(n, GFP_KERNEL);
for (i = 0; i < count; i += n) {
hunk = count - i;
if (hunk > n)
hunk = n;
for (i = 0; i < count - n; i += n) {
result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
pos, hunk, data, &fattr);
if (result < 0) {
kfree_s(data, n);
pos, n, buf, &fattr, 1);
if (result < 0)
return result;
}
memcpy_tofs(buf, data, result);
pos += result;
buf += result;
if (result < n) {
i += result;
break;
file->f_pos = pos;
nfs_refresh_inode(inode, &fattr);
return i + result;
}
}
file->f_pos = pos;
kfree_s(data, n);
fs = 0;
if (!(data = (char *)kmalloc(n, GFP_KERNEL))) {
data = buf;
fs = 1;
}
result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
pos, n, data, &fattr, fs);
if (result < 0) {
if (!fs)
kfree_s(data, n);
return result;
}
hunk = count - i;
if (result < hunk)
hunk = result;
if (fs) {
file->f_pos = pos + hunk;
nfs_refresh_inode(inode, &fattr);
return i + hunk;
}
memcpy_tofs(buf, data, hunk);
file->f_pos = pos + hunk;
nfs_refresh_inode(inode, &fattr);
return i;
cli();
if (cache[tail].in_use == 0) {
if (cache[tail].buf)
kfree_s(cache[tail].buf, cache[tail].buf_size);
cache[tail].buf = data;
cache[tail].buf_size = n;
cache[tail].inode_num = inode->i_ino;
cache[tail].file_pos = pos;
cache[tail].len = result;
cache[tail].time = jiffies;
if (++tail >= READ_CACHE_SIZE)
tail = 0;
} else
kfree_s(data, n);
sti();
return i + hunk;
}
static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
int count)
{
int result;
int hunk;
int i;
int n;
int result, hunk, i, n, pos;
struct nfs_fattr fattr;
char *data;
int pos;
if (!inode) {
printk("nfs_file_write: inode = NULL\n");
......@@ -135,18 +205,14 @@ static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
if (file->f_flags & O_APPEND)
pos = inode->i_size;
n = NFS_SERVER(inode)->wsize;
data = (char *) kmalloc(n, GFP_KERNEL);
for (i = 0; i < count; i += n) {
hunk = count - i;
if (hunk >= n)
hunk = n;
memcpy_fromfs(data, buf, hunk);
result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode),
pos, hunk, data, &fattr);
if (result < 0) {
kfree_s(data, n);
pos, hunk, buf, &fattr);
if (result < 0)
return result;
}
pos += hunk;
buf += hunk;
if (hunk < n) {
......@@ -155,7 +221,6 @@ static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
}
}
file->f_pos = pos;
kfree_s(data, n);
nfs_refresh_inode(inode, &fattr);
return i;
}
......
......@@ -54,7 +54,7 @@ static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area,
if (hunk > n)
hunk = n;
result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
pos, hunk, (char *) (page + i), &fattr);
pos, hunk, (char *) (page + i), &fattr, 0);
if (result < 0)
break;
pos += result;
......
This diff is collapsed.
......@@ -11,6 +11,11 @@
*
* An xid mismatch no longer causes the request to be trashed.
*
* Peter Eriksson - incorrect XID used to confuse Linux
* Florian La Roche - use the correct max size, if reading a packet and
* also verify, if the whole packet has been read...
* more checks should be done in proc.c...
*
*/
#include <linux/config.h>
......@@ -44,7 +49,7 @@ extern struct socket *socki_lookup(struct inode *inode);
* to the server socket.
*/
static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
{
struct file *file;
struct inode *inode;
......@@ -192,26 +197,23 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
#if 0
printk("nfs_rpc_call: XID mismatch\n");
#endif
goto re_select;
}
/* JEJB/JSP 2/7/94
*
* we have the correct xid, so read into the correct place and
* return it
*
* Here we need to know the size given to alloc, server->wsize for
* writes or server->rsize for reads. In practice these are the
* same.
*
* If they are not the same then a reply to a write request will be
* a small acknowledgment, so even if wsize < rsize we should never
* cause data to be written past the end of the buffer (unless some
* brain damaged implementation sends out a large write acknowledge).
*
* FIXME: I should really know how big a packet was alloc'd --
* should pass it to do_nfs_rpc. */
*/
result=sock->ops->recvfrom(sock, (void *)start,
server->rsize + NFS_SLACK_SPACE, 1, 0, NULL,
size + 1024, 1, 0, NULL,
/* Here is NFS_SLACK_SPACE..., hack */
&addrlen);
if (result < addrlen) {
printk("NFS: just caught a too small read memory size..., email to NET channel\n");
printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
result = -EIO;
}
current->blocked = old_mask;
set_fs(fs);
return result;
......@@ -223,14 +225,14 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
* RPC replies.
*/
int nfs_rpc_call(struct nfs_server *server, int *start, int *end)
int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
{
int result;
while (server->lock)
sleep_on(&server->wait);
server->lock = 1;
result = do_nfs_rpc_call(server, start, end);
result = do_nfs_rpc_call(server, start, end, size);
server->lock = 0;
wake_up(&server->wait);
return result;
......
......@@ -3,6 +3,8 @@
*
* Copyright (C) 1992 Rick Sladkey
*
* Optimization changes Copyright (C) 1994 Florian La Roche
*
* nfs symlink handling code
*/
......@@ -14,6 +16,7 @@
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/string.h>
static int nfs_readlink(struct inode *, char *, int);
static int nfs_follow_link(struct inode *, struct inode *, int, int,
......@@ -43,8 +46,9 @@ struct inode_operations nfs_symlink_inode_operations = {
static int nfs_follow_link(struct inode *dir, struct inode *inode,
int flag, int mode, struct inode **res_inode)
{
int error;
char *res;
int error, *mem;
unsigned int len;
char *res, *res2;
*res_inode = NULL;
if (!dir) {
......@@ -65,27 +69,33 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
iput(dir);
return -ELOOP;
}
res = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL);
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res);
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, NFS_MAXPATHLEN);
if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
printk("NFS: no memory in nfs_follow_link\n");
error = -EIO;
}
if (error) {
iput(inode);
iput(dir);
kfree_s(res, NFS_MAXPATHLEN + 1);
kfree(mem);
return error;
}
memcpy(res2, res, len);
res2[len] = '\0';
kfree(mem);
iput(inode);
current->link_count++;
error = open_namei(res, flag, mode, res_inode, dir);
error = open_namei(res2, flag, mode, res_inode, dir);
current->link_count--;
kfree_s(res, NFS_MAXPATHLEN + 1);
kfree_s(res2, NFS_MAXPATHLEN + 1);
return error;
}
static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
{
int i;
char c;
int error;
int error, *mem;
unsigned int len;
char *res;
if (!S_ISLNK(inode->i_mode)) {
......@@ -94,15 +104,14 @@ static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
}
if (buflen > NFS_MAXPATHLEN)
buflen = NFS_MAXPATHLEN;
res = (char *) kmalloc(buflen + 1, GFP_KERNEL);
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res);
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, buflen);
iput(inode);
if (error) {
kfree_s(res, buflen + 1);
return error;
if (! error) {
memcpy_tofs(buffer, res, len);
put_fs_byte('\0', buffer + len);
error = len;
}
for (i = 0; i < buflen && (c = res[i]); i++)
put_fs_byte(c,buffer++);
kfree_s(res, buflen + 1);
return i;
kfree(mem);
return error;
}
......@@ -20,14 +20,13 @@
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
extern struct file_operations * get_blkfops(unsigned int);
extern struct file_operations * get_chrfops(unsigned int);
extern void wait_for_keypress(void);
extern void fcntl_init_locks(void);
extern int floppy_grab_irq_and_dma(void);
extern int root_mountflags;
......@@ -296,23 +295,15 @@ static struct super_block * read_super(dev_t dev,char *name,int flags,
* filesystems which don't use real block-devices. -- jrs
*/
static char unnamed_dev_in_use[256];
static char unnamed_dev_in_use[256/8] = { 0, };
static dev_t get_unnamed_dev(void)
{
static int first_use = 0;
int i;
if (first_use == 0) {
first_use = 1;
memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
unnamed_dev_in_use[0] = 1; /* minor 0 (nodev) is special */
}
for (i = 0; i < sizeof unnamed_dev_in_use/sizeof unnamed_dev_in_use[0]; i++) {
if (!unnamed_dev_in_use[i]) {
unnamed_dev_in_use[i] = 1;
for (i = 1; i < 256; i++) {
if (!set_bit(i,unnamed_dev_in_use))
return (UNNAMED_MAJOR << 8) | i;
}
}
return 0;
}
......@@ -321,12 +312,11 @@ static void put_unnamed_dev(dev_t dev)
{
if (!dev)
return;
if (!unnamed_dev_in_use[dev]) {
printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
MAJOR(dev), MINOR(dev));
if (MAJOR(dev) == UNNAMED_MAJOR &&
clear_bit(MINOR(dev), unnamed_dev_in_use))
return;
}
unnamed_dev_in_use[dev] = 0;
printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
MAJOR(dev), MINOR(dev));
}
static int do_umount(dev_t dev)
......@@ -645,18 +635,35 @@ void mount_root(void)
{
struct file_system_type * fs_type;
struct super_block * sb;
struct inode * inode;
struct inode * inode, d_inode;
struct file filp;
int retval;
memset(super_blocks, 0, sizeof(super_blocks));
fcntl_init_locks();
if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
wait_for_keypress();
/* ugly, ugly */
if (floppy_grab_irq_and_dma())
printk("Unable to grab floppy IRQ/DMA for mounting root floppy\n");
}
memset(&filp, 0, sizeof(filp));
memset(&d_inode, 0, sizeof(d_inode));
d_inode.i_rdev = ROOT_DEV;
filp.f_inode = &d_inode;
if ( root_mountflags & MS_RDONLY)
filp.f_mode = 1; /* read only */
else
filp.f_mode = 3; /* read write */
retval = blkdev_open(&d_inode, &filp);
if(retval == -EROFS){
root_mountflags |= MS_RDONLY;
filp.f_mode = 1;
retval = blkdev_open(&d_inode, &filp);
}
for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if(retval)
break;
if (!fs_type->requires_dev)
continue;
sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
......
......@@ -4,7 +4,7 @@ It implements all of
- SystemV/386 FS,
- Coherent FS.
This is version beta 2.
This is version beta 3.
To install:
* Answer the 'System V and Coherent filesystem support' question with 'y'
......
......@@ -306,6 +306,10 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
/* Try to recognize SystemV superblock */
if ((found = detect_sysv4(sb,bh)) != NULL) {
sb->sv_block_base = offsets[i];
goto ok;
}
if ((found = detect_sysv2(sb,bh)) != NULL) {
sb->sv_block_base = offsets[i];
goto ok;
......
......@@ -228,10 +228,12 @@ struct floppy_raw_cmd {
/* flags */
#define FD_RAW_READ 1
#define FD_RAW_WRITE 2
#define FD_RAW_NO_MOTOR 4
#define FD_RAW_DISK_CHANGE 4
#define FD_RAW_INTR 8
#define FD_RAW_SPIN 16
#define FD_RAW_NO_MOTOR_AFTER 32
#define FD_RAW_NEED_DISK 64
#define FD_RAW_NEED_SEEK 128
#define FD_RAW_USER_SUPPLIED 256
#endif
......@@ -89,6 +89,8 @@
#define FD_READID 0xEA /* prints the header of a sector */
#define FD_UNLOCK 0x14 /* Fifo config unlock */
#define FD_LOCK 0x94 /* Fifo config lock */
#define FD_RSEEK_OUT 0x8f /* seek out (i.e. to lower tracks) */
#define FD_RSEEK_IN 0xcf /* seek in (i.e. to higher tracks) */
/* DMA commands */
#define DMA_READ 0x46
......
......@@ -79,7 +79,7 @@ struct hd_geometry {
struct hd_driveid {
unsigned short config; /* lots of obsolete bit flags */
unsigned short cyls; /* "physical" cyls */
unsigned short reserved0; /* reserved */
unsigned short reserved2; /* reserved (word 2) */
unsigned short heads; /* "physical" heads */
unsigned short track_bytes; /* unformatted bytes per track */
unsigned short sector_bytes; /* unformatted bytes per sector */
......@@ -97,13 +97,13 @@ struct hd_driveid {
unsigned char vendor3; /* vendor unique */
unsigned short dword_io; /* 0=not_implemented; 1=implemented */
unsigned char vendor4; /* vendor unique */
unsigned char capability; /* bit0:DMA, bit1:LBA */
unsigned short reserved1; /* reserved */
unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw 3:IORDYsup*/
unsigned short reserved50; /* reserved (word 50) */
unsigned char vendor5; /* vendor unique */
unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
unsigned char vendor6; /* vendor unique */
unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
unsigned short cur_valid; /* when (bit0==1) use logical geom */
unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
unsigned short cur_cyls; /* logical cylinders */
unsigned short cur_heads; /* logical heads */
unsigned short cur_sectors; /* logical sectors per track */
......@@ -114,7 +114,14 @@ struct hd_driveid {
unsigned int lba_capacity; /* total number of sectors */
unsigned short dma_1word; /* single-word dma info */
unsigned short dma_mword; /* multiple-word dma info */
/* unsigned short reserved2[64];*/ /* reserved */
/* unsigned short vendor7 [32];*/ /* vendor unique */
/* unsigned short reserved3[96];*/ /* reserved */
unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */
unsigned short eide_pio; /* min cycle time (ns), no IORDY */
unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
unsigned short reserved69; /* reserved (word 69) */
unsigned short reserved70; /* reserved (word 70) */
/* unsigned short reservedxx[57];*/ /* reserved (words 71-127) */
/* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */
/* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */
};
......@@ -90,19 +90,6 @@ struct lp_struct {
char *lp_buffer;
};
/* the BIOS manuals say there can be up to 4 lpt devices
* but I have not seen a board where the 4th address is listed
* if you have different hardware change the table below
* please let me know if you have different equipment
* if you have more than 3 printers, remember to increase LP_NO
*/
struct lp_struct lp_table[] = {
{ 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
{ 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
{ 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
};
#define LP_NO 3
/*
* bit defines for 8255 status port
* base + 1
......
#ifndef _LINUX_NCP_H_
#define _LINUX_NCP_H_
#define NCP_OPEN 0x1111
#define NCP_CLOSE 0x5555
#define NCP_REQUEST 0x2222
#define NCP_REPLY 0x3333
struct ncp_request
{
unsigned short p_type __attribute__ ((packed));
unsigned char seq __attribute__ ((packed));
unsigned char c_low __attribute__ ((packed));
unsigned char task __attribute__ ((packed));
unsigned char c_high __attribute__ ((packed));
unsigned char func __attribute__ ((packed));
};
struct ncp_request_sf
{
unsigned short p_type __attribute__ ((packed));
unsigned char seq __attribute__ ((packed));
unsigned char c_low __attribute__ ((packed));
unsigned char task __attribute__ ((packed));
unsigned char c_high __attribute__ ((packed));
unsigned char func __attribute__ ((packed));
unsigned short s_len __attribute__ ((packed));
unsigned char s_func __attribute__ ((packed));
};
struct ncp_reply
{
unsigned short p_type __attribute__ ((packed));
unsigned char seq __attribute__ ((packed));
unsigned char c_low __attribute__ ((packed));
unsigned char task __attribute__ ((packed));
unsigned char c_high __attribute__ ((packed));
unsigned char f_stat __attribute__ ((packed));
unsigned char c_stat __attribute__ ((packed));
};
#define OTYPE_USER 0x0001
#define OTYPE_GROUP 0x0002
#define OTYPE_PQUEUE 0x0003
#define OTYPE_FSERVER 0x0004
#define OTYPE_JSERVER 0x0005
#define OTYPE_PSERVER 0x0007
#define OTYPE_UNKNOWN_1 0x002E
#define OTYPE_ADV_PSERVER 0x0047
#define OTYPE_AFSERVER 0x0107
#define OTYPE_UNKNOWN_2 0x0143
#define OTYPE_UNKNOWN_3 0x01F5
#define OTYPE_UNKNOWN_4 0x023F
#define LIMIT_OBJNAME 47
struct bind_obj
{
unsigned long id __attribute__ ((packed));
unsigned short type __attribute__ ((packed));
char name[LIMIT_OBJNAME+1] __attribute__ ((packed));
};
struct get_bind_obj
{
unsigned short type __attribute__ ((packed));
unsigned char n_len __attribute__ ((packed));
char name[0] __attribute__ ((packed));
};
struct scan_bind_obj
{
unsigned long id __attribute__ ((packed));
unsigned short type __attribute__ ((packed));
unsigned char n_len __attribute__ ((packed));
char name[0] __attribute__ ((packed));
};
struct login_req
{
unsigned char password[8] __attribute__ ((packed));
unsigned short type __attribute__ ((packed));
unsigned char n_len __attribute__ ((packed));
char name[0] __attribute__ ((packed));
};
struct ncp_time
{
unsigned char year __attribute__ ((packed));
unsigned char month __attribute__ ((packed));
unsigned char day __attribute__ ((packed));
unsigned char hours __attribute__ ((packed));
unsigned char mins __attribute__ ((packed));
unsigned char secs __attribute__ ((packed));
unsigned char c_secs __attribute__ ((packed));
};
struct login_info
{
unsigned long id __attribute__ ((packed));
unsigned short un1 __attribute__ ((packed));
char name[LIMIT_OBJNAME+1] __attribute__ ((packed));
struct ncp_time time __attribute__ ((packed));
};
#endif
......@@ -57,10 +57,11 @@ extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir,
const char *name, struct nfs_fh *fhandle,
struct nfs_fattr *fattr);
extern int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
char *res);
int **p0, char **string, unsigned int *len,
unsigned int maxlen);
extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
int offset, int count, char *data,
struct nfs_fattr *fattr);
struct nfs_fattr *fattr, int fs);
extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
int offset, int count, char *data,
struct nfs_fattr *fattr);
......@@ -88,7 +89,7 @@ extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
/* linux/fs/nfs/sock.c */
extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end);
extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size);
/* linux/fs/nfs/inode.c */
......
......@@ -247,6 +247,7 @@ struct tty_struct {
#define TTY_EXCLUSIVE 3
#define TTY_DEBUG 4
#define TTY_DO_WRITE_WAKEUP 5
#define TTY_PUSH 6
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
......
......@@ -455,7 +455,15 @@ unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
} else {
printk ("bios32_init : multiple entries, mail drew@colorado.edu\n");
/*
* Jeremy Fitzhardinge reports at least one PCI BIOS
* with two different service directories, and as both
* worked for him, we'll just mention the fact, and
* not actually disallow it..
*/
#if 0
return memory_start;
#endif
}
}
#ifdef CONFIG_PCI
......
......@@ -112,15 +112,24 @@ asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerva
int error;
struct itimerval set_buffer, get_buffer;
if (!value)
memset((char *) &set_buffer, 0, sizeof(set_buffer));
else
if (value) {
error = verify_area(VERIFY_READ, value, sizeof(*value));
if (error)
return error;
memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
} else
memset((char *) &set_buffer, 0, sizeof(set_buffer));
if (ovalue) {
error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
if (error)
return error;
}
error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
if (error || !ovalue)
return error;
error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
if (!error)
memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
return error;
}
......@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/tqueue.h>
#include <linux/resource.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -675,6 +676,16 @@ static void do_timer(struct pt_regs * regs)
}
#endif
}
/*
* check the cpu time limit on the process.
*/
if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
(((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_cur))
send_sig(SIGXCPU, current, 1);
if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
(((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
send_sig(SIGKILL, current, 1);
if (current != task[0] && 0 > --current->counter) {
current->counter = 0;
need_resched = 1;
......
......@@ -697,12 +697,15 @@ asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
{
struct rlimit new_rlim, *old_rlim;
int err;
if (resource >= RLIM_NLIMITS)
return -EINVAL;
err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
if (err)
return err;
memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
old_rlim = current->rlim + resource;
new_rlim.rlim_cur = get_fs_long((unsigned long *) rlim);
new_rlim.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
(new_rlim.rlim_max > old_rlim->rlim_max)) &&
!suser())
......@@ -723,7 +726,6 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
{
int error;
struct rusage r;
unsigned long *lp, *lpend, *dest;
error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
if (error)
......@@ -755,11 +757,7 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
r.ru_majflt = p->mm->maj_flt + p->mm->cmaj_flt;
break;
}
lp = (unsigned long *) &r;
lpend = (unsigned long *) (&r+1);
dest = (unsigned long *) ru;
for (; lp < lpend; lp++, dest++)
put_fs_long(*lp, dest);
memcpy_tofs(ru, &r, sizeof(r));
return 0;
}
......
This diff is collapsed.
......@@ -97,6 +97,7 @@ void time_init(void)
if ((year += 1900) < 1970)
year += 100;
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_usec = 0;
}
/*
* The timezone where the local system is located. Used as a default by some
......@@ -118,12 +119,19 @@ asmlinkage int sys_time(long * tloc)
return i;
}
asmlinkage int sys_stime(long * tptr)
asmlinkage int sys_stime(unsigned long * tptr)
{
int error;
unsigned long value;
if (!suser())
return -EPERM;
error = verify_area(VERIFY_READ, tptr, sizeof(*tptr));
if (error)
return error;
value = get_fs_long(tptr);
cli();
xtime.tv_sec = get_fs_long((unsigned long *) tptr);
xtime.tv_sec = value;
xtime.tv_usec = 0;
time_status = TIME_BAD;
time_maxerror = 0x70000000;
......@@ -266,12 +274,25 @@ inline static void warp_clock(void)
asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
{
static int firsttime = 1;
struct timeval new_tv;
struct timezone new_tz;
if (!suser())
return -EPERM;
if (tv) {
int error = verify_area(VERIFY_READ, tv, sizeof(*tv));
if (error)
return error;
memcpy_fromfs(&new_tv, tv, sizeof(*tv));
}
if (tz) {
sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
int error = verify_area(VERIFY_READ, tz, sizeof(*tz));
if (error)
return error;
memcpy_fromfs(&new_tz, tz, sizeof(*tz));
}
if (tz) {
sys_tz = new_tz;
if (firsttime) {
firsttime = 0;
if (!tv)
......@@ -279,11 +300,6 @@ asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
}
}
if (tv) {
int sec, usec;
sec = get_fs_long((unsigned long *)tv);
usec = get_fs_long(((unsigned long *)tv)+1);
cli();
/* This is revolting. We need to set the xtime.tv_usec
* correctly. However, the value in this location is
......@@ -291,15 +307,14 @@ asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
usec -= do_gettimeoffset();
new_tv.tv_usec -= do_gettimeoffset();
if (usec < 0)
{
usec += 1000000;
sec--;
if (new_tv.tv_usec < 0) {
new_tv.tv_usec += 1000000;
new_tv.tv_sec--;
}
xtime.tv_sec = sec;
xtime.tv_usec = usec;
xtime = new_tv;
time_status = TIME_BAD;
time_maxerror = 0x70000000;
time_esterror = 0x70000000;
......
......@@ -169,6 +169,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
if (is_digit(*fmt))
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
field_width = va_arg(args, int);
if (field_width < 0) {
......@@ -184,6 +185,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
if (is_digit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
precision = va_arg(args, int);
}
......
......@@ -734,8 +734,12 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
if (!(from & PAGE_PRESENT))
return 0;
/* if it is private, it must be clean to be shared */
if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY))
return 0;
if (from & PAGE_DIRTY) {
if (from_area->vm_page_prot & PAGE_COW)
return 0;
if (!(from_area->vm_page_prot & PAGE_RW))
return 0;
}
/* is the page reasonable at all? */
if (from >= high_memory)
return 0;
......@@ -754,6 +758,8 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
if (in_swap_cache(from)) { /* implies PAGE_DIRTY */
if (from_area->vm_page_prot & PAGE_COW)
return 0;
if (!(from_area->vm_page_prot & PAGE_RW))
return 0;
}
copy_page((from & PAGE_MASK), newpage);
*(unsigned long *) to_page = newpage | to_area->vm_page_prot;
......@@ -763,6 +769,8 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
if (in_swap_cache(from)) {
if (from_area->vm_page_prot & PAGE_COW)
return 0;
if (!(from_area->vm_page_prot & PAGE_RW))
return 0;
from |= PAGE_DIRTY;
*(unsigned long *) from_page = from;
delete_from_swap_cache(from);
......
......@@ -209,7 +209,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
/*
* Send it and free it once sent.
*/
ip_queue_xmit(NULL, dev, skb, 1);
ip_queue_xmit(NULL, ndev, skb, 1);
}
......
/*
*
* Kernel support for NCP
*
* Mark Evans 1994
*
*/
#ifndef _NCP_H
#define _NCP_H
#include <linux/ncp.h>
struct ncp_info
{
unsigned short conn; /* connection number */
unsigned char seq; /* sequence number */
ipx_socket *ncp; /* ncp socket */
ipx_socket *watchdog; /* watchdog socket */
ipx_socket *mail; /* mail socket */
};
#define NCP_TIMEOUT (3*HZ)
#define MAX_TIMEOUT 15
#endif /* _NCP_H */
......@@ -325,7 +325,7 @@ void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
* Update the loopback route
*/
if (rt->rt_dev->flags & IFF_LOOPBACK)
if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
rt_loopback = rt;
/*
......
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