Commit ecda87c0 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.57

parent 186b0970
This diff is collapsed.
----------------------------------------------------------------------------
NOTE: See also README.arcnet-hardware in this directory for jumper-setting
NOTE: See also arcnet-hardware.txt in this directory for jumper-setting
and cabling information if you're like many of us and didn't happen to get a
manual with your ARCnet card.
----------------------------------------------------------------------------
......@@ -144,6 +144,9 @@ line. For example:
insmod arcnet.o io=0x300 irqnum=2 shmem=0xd0000
You can also add a num=1, num=2 etc for additional arcnet cards that will
use arc1, arc2 etc for their device names (instead of the default, arc0).
** NEWS FLASH! Starting with 2.30 ALPHA, the ARCnet driver can autoprobe
even as a module. So "insmod arcnet.o" by itself should work.
Using the Driver
......
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 56
SUBLEVEL = 57
ARCH = i386
......
......@@ -166,7 +166,7 @@ $(MX_OBJS): $(TOPDIR)/include/linux/modversions.h
$(LX_OBJS) $(OX_OBJS): $(TOPDIR)/include/linux/modversions.h
$(CC) $(CFLAGS) -DMODVERSIONS -DEXPORT_SYMTAB -c $(@:.o=.c)
dep fastdep: $(TOPDIR)/include/linux/modversions.h
dep fastdep $(M_OBJS): $(TOPDIR)/include/linux/modversions.h
endif
endif
......
......@@ -52,7 +52,7 @@ define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
bool 'Echo console messages on /dev/ttyS1' CONFIG_SERIAL_ECHO
if [ "$CONFIG_PCI" = "y" ]; then
bool 'TGA Console Support' CONFIG_TGA_CONSOLE
bool 'PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE
bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
fi
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
......
......@@ -207,7 +207,7 @@ static inline void unmask_irq(unsigned long irq)
} else {
cache_806 &= mask;
outb(cache_806, 0x806);
#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
#elif NR_IRQS == 32
} else if (irq < 24) {
cache_26 &= mask;
outb(cache_26, 0x26);
......
......@@ -15,6 +15,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <asm/system.h>
#include <asm/segment.h>
......
......@@ -316,7 +316,7 @@ void decompress_kernel()
lines = SCREEN_INFO.orig_video_lines;
cols = SCREEN_INFO.orig_video_cols;
if (EXT_MEM_K < 1024) error("<2M of mem\n");
if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
output_data = (char *)0x100000; /* Points to 1M */
makecrc();
......
......@@ -10,6 +10,7 @@ bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
MODULES=y
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
fi
mainmenu_option next_comment
......@@ -20,7 +21,7 @@ bool 'Networking support' CONFIG_NET
bool 'Limit memory to low 16MB' CONFIG_MAX_16M
bool 'PCI bios support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
bool ' PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE
bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
fi
bool 'System V IPC' CONFIG_SYSVIPC
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
......
......@@ -7,6 +7,7 @@
#
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
# CONFIG_KERNELD is not set
#
# General setup
......
......@@ -658,7 +658,7 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_writev)
.long SYMBOL_NAME(sys_getsid)
.long SYMBOL_NAME(sys_fdatasync)
.long 0
.long SYMBOL_NAME(sys_sysctl)
.long SYMBOL_NAME(sys_mlock) /* 150 */
.long SYMBOL_NAME(sys_munlock)
.long SYMBOL_NAME(sys_mlockall)
......
......@@ -15,6 +15,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <asm/system.h>
......
......@@ -44,7 +44,7 @@ bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
bool 'Networking support' CONFIG_NET
#bool 'PCI bios support' CONFIG_PCI
#if [ "$CONFIG_PCI" = "y" ]; then
# bool ' PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE
# bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
#fi
bool 'System V IPC' CONFIG_SYSVIPC
......
......@@ -29,7 +29,7 @@ bool 'Networking support' CONFIG_NET y
#bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
bool 'PCI bios support' CONFIG_PCI y
if [ "$CONFIG_PCI" = "y" ]; then
bool ' PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE n
bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE n
if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
bool ' PCI Triton IDE Bus Master DMA support' CONFIG_BLK_DEV_TRITON y
fi
......
......@@ -38,10 +38,13 @@ if [ "$CONFIG_APM" = "y" ]; then
fi
bool 'Watchdog Timer Support' CONFIG_WATCHDOG
if [ "$CONFIG_WATCHDOG" = "y" ]; then
# bool ' WDT501P Watchdog timer' CONFIG_WDT_501P
# if [ "$CONFIG_WDT_501P" = "y" ]; then
# bool ' Fan Tachomeeter' CONFIG_WDT_501P_TACHO
# fi
# bool ' WDT500P Watchdog timer' CONFIG_WDT_500P
bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG
bool ' WDT Watchdog timer' CONFIG_WDT
if [ "$CONFIG_WDT" = "y" ]; then
bool ' WDT501 features' CONFIG_WDT_501
if [ "$CONFIG_WDT_501" = "y" ]; then
bool ' Fan Tachometer' CONFIG_WDT_501_FAN
fi
else
bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG
fi
fi
/*
* Industrial Computer Source WDT500/501 driver for Linux 1.3.x
*
* (c) Copyright 1995 CymruNET Ltd
* Innovation Centre
* Singleton Park
* Swansea
* Wales
* UK
* SA2 8PP
*
* http://www.cymru.net
*
* This driver is provided under the GNU public license, incorporated
* herein by reference. The driver is provided without warranty or
* support.
*
* Release 0.04.
*
*/
#define WATCHDOG_MINOR 130 /* Watchdog timer */
#define TEMP_MINOR 131 /* Temperature Sensor */
#define WDT_COUNT0 (io+0)
#define WDT_COUNT1 (io+1)
#define WDT_COUNT2 (io+2)
#define WDT_CR (io+3)
#define WDT_SR (io+4)
#define WDT_RT (io+5)
#define WDT_UNUSED (io+6)
#define WDT_DC (io+7)
#define WDC_SR_WCCR 1 /* Active low */
#define WDC_SR_TGOOD 2
#define WDC_SR_ISOI0 4
#define WDC_SR_ISII1 8
#define WDC_SR_FANGOOD 16
#define WDC_SR_PSUOVER 32 /* Active low */
#define WDC_SR_PSUUNDR 64 /* Active low */
#define WDC_SR_IRQ 128 /* Active low */
/*
* Feature Map 1 is the active high inputs not supported on your card.
* Feature Map 2 is the active low inputs not supported on your card.
*/
#ifdef CONFIG_WDT_501 /* Full board */
#ifdef CONFIG_WDT501_FAN /* Full board, Fan has no tachometer */
#define FEATUREMAP1 0
#else
#define FEATUREMAP1 WDC_SR_FANGOOD
#endif
#define FEATUREMAP2 0
#endif
#ifdef CONFIG_WDT500 /* Minimal board */
#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD)
#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
#endif
#ifndef FEATUREMAP1
#error "Config option not set"
#endif
/*
* Industrial Computer Source WDT500/501 driver for Linux 1.3.x
*
* (c) Copyright 1995 CymruNET Ltd
* Innovation Centre
* Singleton Park
* Swansea
* Wales
* UK
* SA2 8PP
*
* http://www.cymru.net
*
* This driver is provided under the GNU public license, incorporated
* herein by reference. The driver is provided without warranty or
* support.
*
* Release 0.04.
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mouse.h>
#include "wd501p.h"
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
static int wdt_is_open=0;
/*
* You must set these - there is no sane way to probe for this board.
*/
int io=0x240;
int irq=14;
#define WD_TIMO (100*60) /* 1 minute */
/*
* Programming suppoort
*/
static void wdt_ctr_mode(int ctr, int mode)
{
ctr<<=6;
ctr|=0x30;
ctr|=(mode<<1);
outb_p(ctr, WDT_CR);
}
static void wdt_ctr_load(int ctr, int val)
{
outb_p(val&0xFF, WDT_COUNT0+ctr);
outb_p(val>>8, WDT_COUNT0+ctr);
}
/*
* Kernel methods.
*/
static void wdt_interrupt(int irq, struct pt_regs *regs)
{
/*
* Read the status register see what is up and
* then printk it.
*/
unsigned char status=inb_p(WDT_SR);
status|=FEATUREMAP1;
status&=~FEATUREMAP2;
printk(KERN_CRIT "WDT status %d\n", status);
if(!(status&WDC_SR_TGOOD))
printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
if(!(status&WDC_SR_PSUOVER))
printk(KERN_CRIT "PSU over voltage.\n");
if(!(status&WDC_SR_PSUUNDR))
printk(KERN_CRIT "PSU under voltage.\n");
if(!(status&WDC_SR_FANGOOD))
printk(KERN_CRIT "Possible fan fault.\n");
if(!(status&WDC_SR_WCCR))
#ifdef SOFTWARE_REBOOT
#ifdef ONLY_TESTING
printk(KERN_CRIT "Would Reboot.\n");
#else
printk(KERN_CRIT "Initiating system reboot.\n");
hard_reset_now();
#endif
#else
printk(KERN_CRIT "Reset in 5ms.\n");
#endif
}
static int wdt_lseek(struct inode *inode, struct file *file, off_t offset,
int origin)
{
return -ESPIPE;
}
static int wdt_write(struct inode *inode, struct file *file, char *buf, int count)
{
/* Write a watchdog value */
inb_p(WDT_DC);
wdt_ctr_mode(1,2);
wdt_ctr_load(1,WD_TIMO); /* Timeout */
outb_p(0, WDT_DC);
return count;
}
/*
* Read reports the temperature in farenheit
*/
static int wdt_read(struct inode *inode, struct file *file, char *buf, int count)
{
unsigned short c=inb_p(WDT_RT);
unsigned char cp;
int err;
switch(MINOR(inode->i_rdev))
{
case TEMP_MINOR:
err=verify_area(VERIFY_WRITE, buf, 1);
if(err)
return err;
c*=11;
c/=15;
cp=c;
memcpy_tofs(buf,&cp,1);
return 1;
default:
return -EINVAL;
}
}
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
return -EINVAL;
}
static int wdt_open(struct inode *inode, struct file *file)
{
switch(MINOR(inode->i_rdev))
{
case WATCHDOG_MINOR:
if(wdt_is_open)
return -EBUSY;
MOD_INC_USE_COUNT;
/*
* Activate
*/
wdt_is_open=1;
inb_p(WDT_DC); /* Disable */
wdt_ctr_mode(0,3);
wdt_ctr_mode(1,2);
wdt_ctr_mode(2,0);
wdt_ctr_load(0, 8948); /* count at 100Hz */
wdt_ctr_load(1,WD_TIMO); /* Timeout 120 seconds */
wdt_ctr_load(2,65535);
outb_p(0, WDT_DC); /* Enable */
return 0;
case TEMP_MINOR:
MOD_INC_USE_COUNT;
return 0;
default:
return -ENODEV;
}
}
static void wdt_release(struct inode *inode, struct file *file)
{
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
inb_p(WDT_DC); /* Disable counters */
wdt_ctr_load(2,0); /* 0 length reset pulses now */
wdt_is_open=0;
}
MOD_DEC_USE_COUNT;
}
/*
* Kernel Interfaces
*/
static struct file_operations wdt_fops = {
wdt_lseek,
wdt_read,
wdt_write,
NULL, /* No Readdir */
NULL, /* No Select */
wdt_ioctl,
NULL, /* No mmap */
wdt_open,
wdt_release
};
static struct mouse wdt_mouse=
{
WATCHDOG_MINOR,
"wdt",
&wdt_fops
};
static struct mouse temp_mouse=
{
TEMP_MINOR,
"temperature",
&wdt_fops
};
#ifdef MODULE
int init_module(void)
{
printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
{
printk("IRQ %d is not free.\n", irq);
return -EIO;
}
mouse_register(&wdt_mouse);
#ifdef CONFIG_WDT_501
mouse_register(&temp_mouse);
#endif
request_region(io, 8, "wdt501");
return 0;
}
void cleanup_module(void)
{
mouse_deregister(&wdt_mouse);
#ifdef CONFIG_WDT_501
mouse_deregister(&temp_mouse);
#endif
release_region(io,8);
free_irq(irq);
}
#else
int wdt_init(void)
{
printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
{
printk("IRQ %d is not free.\n", irq);
return -EIO;
}
mouse_register(&wdt_mouse);
mouse_register(&temp_mouse);
request_region(io, 8, "wdt501");
return 0;
}
#endif
This diff is collapsed.
......@@ -258,11 +258,13 @@ int register_netdev(struct device *dev)
}
}
sti(); /* device probes assume interrupts enabled */
if (dev->init(dev) != 0) {
if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
restore_flags(flags);
return -EIO;
}
cli();
/* Add device to end of chain */
if (dev_base) {
......@@ -345,6 +347,9 @@ void unregister_netdev(struct device *dev)
break;
}
}
restore_flags(flags);
/* You can i.e use a interfaces in a route though it is not up.
We call close_dev (which is changed: it will down a device even if
dev->flags==0 (but it will not call dev->stop if IFF_UP
......@@ -353,8 +358,6 @@ void unregister_netdev(struct device *dev)
dev_mc_discard(dev), ....
*/
dev_close(dev);
restore_flags(flags);
}
......
......@@ -1753,8 +1753,6 @@ static void set_multicast_list(struct device *dev)
}
} /* End of set_multicast_list() */
#endif
/*-
......
......@@ -20,9 +20,14 @@
* General Public License for more details.
*
*
* $Id: aha152x.c,v 1.12 1995/12/16 12:26:07 fischer Exp fischer $
* $Id: aha152x.c,v 1.13 1996/01/09 02:15:53 fischer Exp $
*
* $Log: aha152x.c,v $
* Revision 1.13 1996/01/09 02:15:53 fischer
* - some cleanups
* - moved request_irq behind controller initialization
* (to avoid spurious interrupts)
*
* Revision 1.12 1995/12/16 12:26:07 fischer
* - barrier()'s added
* - configurable RESET delay added
......@@ -299,6 +304,8 @@ struct proc_dir_entry proc_scsi_aha152x = {
extern long loops_per_sec;
#define DELAY_DEFAULT 100
/* some additional "phases" for getphase() */
#define P_BUSFREE 1
#define P_PARITY 2
......@@ -322,7 +329,6 @@ enum {
/* set by aha152x_setup according to the command line */
static int setup_count=0;
static struct aha152x_setup {
char *conf;
int io_port;
int irq;
int scsiid;
......@@ -333,6 +339,7 @@ static struct aha152x_setup {
#ifdef DEBUG_AHA152X
int debug;
#endif
char *conf;
} setup[2];
static struct Scsi_Host *aha152x_host[IRQS];
......@@ -566,7 +573,7 @@ void aha152x_setup(char *str, int *ints)
setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */;
setup[setup_count].delay = ints[0] >= 7 ? ints[7] : 100;
setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
#ifdef DEBUG_AHA152X
setup[setup_count].debug = ints[0] >= 8 ? ints[8] : DEBUG_DEFAULT;
if(ints[0]>8)
......@@ -745,7 +752,10 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
setup[setup_count].reconnect = conf.cf_tardisc;
setup[setup_count].parity = !conf.cf_parity;
setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */;
setup[setup_count].delay = DELAY_DEFAULT;
#ifdef DEBUG_AHA152X
setup[setup_count].debug = DEBUG_DEFAULT;
#endif
setup_count++;
}
}
......@@ -775,7 +785,9 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
HOSTDATA(shpnt)->parity = setup[i].parity;
HOSTDATA(shpnt)->synchronous = setup[i].synchronous;
HOSTDATA(shpnt)->delay = setup[i].delay;
#ifdef DEBUG_AHA152X
HOSTDATA(shpnt)->debug = setup[i].debug;
#endif
HOSTDATA(shpnt)->aborting = 0;
HOSTDATA(shpnt)->abortion_complete = 0;
......@@ -787,29 +799,6 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
for(j=0; j<8; j++)
HOSTDATA(shpnt)->syncrate[j] = 0;
ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
if(ok<0)
{
if(ok == -EINVAL)
{
printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq);
printk(" Contact author.\n");
}
else
if(ok == -EBUSY)
printk("aha152x%d: IRQ %d already in use. Configure another.\n",
i, setup[i].irq);
else
{
printk("\naha152x%d: Unexpected error code on"
" requesting IRQ %d.\n", i, setup[i].irq);
printk(" Contact author.\n");
}
printk("aha152x: driver needs an IRQ.\n");
continue;
}
SETPORT(SCSIID, setup[i].scsiid << 4);
shpnt->this_id=setup[i].scsiid;
......@@ -842,6 +831,29 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
SETPORT(SIMODE1, 0);
SETBITS(DMACNTRL0, INTEN);
ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
if(ok<0)
{
if(ok == -EINVAL)
{
printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq);
printk(" Contact author.\n");
}
else
if(ok == -EBUSY)
printk("aha152x%d: IRQ %d already in use. Configure another.\n",
i, setup[i].irq);
else
{
printk("\naha152x%d: Unexpected error code on"
" requesting IRQ %d.\n", i, setup[i].irq);
printk(" Contact author.\n");
}
printk("aha152x: driver needs an IRQ.\n");
continue;
}
}
return (setup_count>0);
......
......@@ -2,7 +2,7 @@
#define _AHA152X_H
/*
* $Id: aha152x.h,v 1.12 1995/12/07 01:03:48 fischer Exp fischer $
* $Id: aha152x.h,v 1.13 1995/12/16 12:27:23 fischer Exp $
*/
#if defined(__KERNEL__)
......@@ -23,7 +23,7 @@ int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int
(unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.12 $"
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.13 $"
extern struct proc_dir_entry proc_scsi_aha152x;
......
......@@ -5,9 +5,6 @@
* Development Sponsored by Killy Corp. NY NY
*
* Borrows code from st driver.
*
* Version from 1.3.51 modified by Rick Richardson to fix problem in
* detecting whether its a send or a recieve style command (see sg_write)
*/
#include <linux/module.h>
......@@ -295,9 +292,6 @@ static void sg_command_done(Scsi_Cmnd * SCpnt)
wake_up(&scsi_generics[dev].read_wait);
}
#define SG_SEND 0
#define SG_REC 1
static int sg_write(struct inode *inode,struct file *filp,const char *buf,int count)
{
int bsize,size,amt,i;
......@@ -305,7 +299,7 @@ static int sg_write(struct inode *inode,struct file *filp,const char *buf,int co
kdev_t devt = inode->i_rdev;
int dev = MINOR(devt);
struct scsi_generic * device=&scsi_generics[dev];
int direction;
int input_size;
unsigned char opcode;
Scsi_Cmnd * SCpnt;
......@@ -342,33 +336,43 @@ static int sg_write(struct inode *inode,struct file *filp,const char *buf,int co
device->complete=0;
memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
/*
* fix input size, and see if we are sending data.
*
* Mod by Rick Richardson (rick@dgii.com):
* The original test to see if its a SEND/REC was:
* if( device->header.pack_len > device->header.reply_len )
* I haven't a clue why the author thought this would work. Instead,
* I've changed it to see if there is any additional data in this
* packet beyond the length of the SCSI command itself.
*/
device->header.pack_len=count;
buf+=sizeof(struct sg_header);
size = COMMAND_SIZE(get_user(buf)) + sizeof(struct sg_header);
if( device->header.pack_len > size)
/*
* Now we need to grab the command itself from the user's buffer.
*/
opcode = get_user(buf);
size=COMMAND_SIZE(opcode);
if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
/*
* Determine buffer size.
*/
input_size = device->header.pack_len - size;
if( input_size > device->header.reply_len)
{
bsize = device->header.pack_len;
direction = SG_SEND;
bsize = input_size;
} else {
bsize = device->header.reply_len;
direction = SG_REC;
}
/*
* Don't include the command header itself in the size.
*/
bsize-=sizeof(struct sg_header);
input_size-=sizeof(struct sg_header);
/*
* Verify that the user has actually passed enough bytes for this command.
*/
if( input_size < 0 )
{
device->pending=0;
wake_up( &device->write_wait );
return -EIO;
}
/*
* Allocate a buffer that is large enough to hold the data
* that has been requested. Round up to an even number of sectors,
......@@ -409,37 +413,11 @@ static int sg_write(struct inode *inode,struct file *filp,const char *buf,int co
printk("device allocated\n");
#endif
/*
* Now we need to grab the command itself from the user's buffer.
*/
SCpnt->request.rq_dev = devt;
SCpnt->request.rq_status = RQ_ACTIVE;
SCpnt->sense_buffer[0]=0;
opcode = get_user(buf);
size=COMMAND_SIZE(opcode);
if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
SCpnt->cmd_len = size;
/*
* If we are writing data, subtract off the size
* of the command itself, to get the amount of actual data
* that we need to send to the device.
*/
if( direction == SG_SEND )
amt -= size;
/*
* Verify that the user has actually passed enough bytes for this command.
*/
if( count < (sizeof(struct sg_header) + size) )
{
device->pending=0;
wake_up( &device->write_wait );
sg_free( device->buff, device->buff_len );
device->buff = NULL;
return -EIO;
}
/*
* Now copy the SCSI command from the user's address space.
*/
......@@ -451,7 +429,7 @@ static int sg_write(struct inode *inode,struct file *filp,const char *buf,int co
* field also includes the length of the header and the command,
* so we need to subtract these off.
*/
if( direction == SG_SEND ) memcpy_fromfs(device->buff,buf, amt);
if (input_size > 0) memcpy_fromfs(device->buff, buf, input_size);
/*
* Set the LUN field in the command structure.
......
......@@ -26,6 +26,7 @@
#include <linux/errno.h>
#include <linux/malloc.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/swapctl.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
......@@ -1216,10 +1217,10 @@ static int grow_buffers(int pri, int size)
/* =========== Reduce the buffer memory ============= */
/*
* try_to_free() checks if all the buffers on this particular page
* try_to_free_buffer() checks if all the buffers on this particular page
* are unused, and free's the page if so.
*/
static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp,
int try_to_free_buffer(struct buffer_head * bh, struct buffer_head ** bhp,
int priority)
{
unsigned long page;
......@@ -1286,9 +1287,9 @@ static inline void age_buffer(struct buffer_head *bh)
clear_bit(BH_Has_aged, &bh->b_state);
if (touched)
touch_page((unsigned long) bh->b_data);
touch_page(mem_map + MAP_NR((unsigned long) bh->b_data));
else
age_page((unsigned long) bh->b_data);
age_page(mem_map + MAP_NR((unsigned long) bh->b_data));
}
/*
......@@ -1352,19 +1353,6 @@ static int maybe_shrink_lav_buffers(int size)
* that are in the 0 - limit address range, for DMA re-allocations.
* We ignore that right now.
*/
int shrink_buffers(unsigned int priority, unsigned long limit)
{
if (priority < 2) {
sync_buffers(0,0);
}
if(priority == 2) wakeup_bdflush(1);
if(maybe_shrink_lav_buffers(0)) return 1;
/* No good candidate size - take any size we can find */
return shrink_specific_buffers(priority, 0);
}
static int shrink_specific_buffers(unsigned int priority, int size)
{
......@@ -1388,7 +1376,7 @@ static int shrink_specific_buffers(unsigned int priority, int size)
!bh->b_this_page)
continue;
if (!age_of((unsigned long) bh->b_data) &&
try_to_free(bh, &bh, 6))
try_to_free_buffer(bh, &bh, 6))
return 1;
if(!bh) break;
/* Some interrupt must have used it after we
......@@ -1436,7 +1424,7 @@ static int shrink_specific_buffers(unsigned int priority, int size)
if ((age_of((unsigned long) bh->b_data) >>
(6-priority)) > 0)
continue;
if (try_to_free(bh, &bh, 0))
if (try_to_free_buffer(bh, &bh, 0))
return 1;
if(!bh) break;
}
......@@ -1855,7 +1843,7 @@ int bdflush(void * unused)
current->session = 1;
current->pgrp = 1;
sprintf(current->comm, "kernel bdflush");
sprintf(current->comm, "kflushd");
/*
* As a kernel thread we want to tamper with system buffers
......
......@@ -4,8 +4,11 @@
* (C) 1993 Matthias Urlichs -- collected common code and tables.
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Added kerneld support: Jacques Gelinas and Bjorn Ekwall
*/
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/string.h>
......@@ -14,6 +17,9 @@
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
struct device_struct {
const char * name;
......@@ -47,19 +53,53 @@ int get_device_list(char * page)
}
return len;
}
/*
Return the function table of a device.
Load the driver if needed.
*/
static struct file_operations * get_fops(
unsigned int major,
unsigned int maxdev,
const char *mangle, /* String to use to build the module name */
struct device_struct tb[])
{
struct file_operations *ret = NULL;
if (major < maxdev){
#ifdef CONFIG_KERNELD
/*
* I do get request for device 0. I have no idea why. It happen
* at shutdown time for one. Without the following test, the
* kernel will happily trigger a request_module() which will
* trigger kerneld and modprobe for nothing (since there
* is no device with major number == 0. And furthermore
* it locks the reboot process :-(
*
* Jacques Gelinas (jacques@solucorp.qc.ca)
*/
if (!tb[major].fops && major != 0) {
char name[20];
sprintf(name, mangle, major);
request_module(name);
}
#endif
ret = tb[major].fops;
}
return ret;
}
/*
Return the function table of a device.
Load the driver if needed.
*/
struct file_operations * get_blkfops(unsigned int major)
{
if (major >= MAX_BLKDEV)
return NULL;
return blkdevs[major].fops;
return get_fops (major,MAX_BLKDEV,"block-major-%d",blkdevs);
}
struct file_operations * get_chrfops(unsigned int major)
{
if (major >= MAX_CHRDEV)
return NULL;
return chrdevs[major].fops;
return get_fops (major,MAX_CHRDEV,"char-major-%d",chrdevs);
}
int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
......@@ -170,17 +210,24 @@ int check_disk_change(kdev_t dev)
*/
int blkdev_open(struct inode * inode, struct file * filp)
{
int i;
i = MAJOR(inode->i_rdev);
if (i >= MAX_BLKDEV || !blkdevs[i].fops)
return -ENODEV;
filp->f_op = blkdevs[i].fops;
if (filp->f_op->open)
return filp->f_op->open(inode,filp);
return 0;
int ret = -ENODEV;
filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
if (filp->f_op != NULL){
ret = 0;
if (filp->f_op->open != NULL)
ret = filp->f_op->open(inode,filp);
}
return ret;
}
void blkdev_release(struct inode * inode)
{
struct file_operations *fops = get_blkfops(MAJOR(inode->i_rdev));
if (fops && fops->release)
fops->release(inode,NULL);
}
/*
* Dummy default file-operations: the only thing this does
* is contain the open that then fills in the correct operations
......@@ -223,15 +270,14 @@ struct inode_operations blkdev_inode_operations = {
*/
int chrdev_open(struct inode * inode, struct file * filp)
{
int i;
i = MAJOR(inode->i_rdev);
if (i >= MAX_CHRDEV || !chrdevs[i].fops)
return -ENODEV;
filp->f_op = chrdevs[i].fops;
if (filp->f_op->open)
return filp->f_op->open(inode,filp);
return 0;
int ret = -ENODEV;
filp->f_op = get_chrfops(MAJOR(inode->i_rdev));
if (filp->f_op != NULL){
ret = 0;
if (filp->f_op->open != NULL)
ret = filp->f_op->open(inode,filp);
}
return ret;
}
/*
......
......@@ -44,6 +44,9 @@
#include <asm/pgtable.h>
#include <linux/config.h>
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
asmlinkage int sys_exit(int exit_code);
asmlinkage int sys_brk(unsigned long);
......@@ -616,6 +619,7 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
int i;
int retval;
int sh_bang = 0;
int try;
#ifdef __alpha__
int loader = 0;
#endif
......@@ -781,18 +785,29 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
}
bprm.sh_bang = sh_bang;
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
break;
retval = fn(&bprm, regs);
if (retval >= 0) {
iput(bprm.inode);
current->did_exec = 1;
return retval;
for (try=0; try<2; try++) {
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
break;
retval = fn(&bprm, regs);
if (retval >= 0) {
iput(bprm.inode);
current->did_exec = 1;
return retval;
}
if (retval != -ENOEXEC)
break;
}
if (retval != -ENOEXEC)
if (retval != -ENOEXEC) {
break;
#ifdef CONFIG_KERNELD
}else{
char modname[20];
sprintf(modname, "binfmt-%hd", *(short*)(&bprm.buf));
request_module(modname);
#endif
}
}
exec_error2:
iput(bprm.inode);
......
......@@ -16,6 +16,7 @@
*/
struct file * first_file = NULL;
int nr_files = 0;
int max_files = NR_FILE;
/*
* Insert a new file structure at the head of the list of available ones.
......@@ -116,7 +117,7 @@ struct file * get_empty_filp(void)
f->f_version = ++event;
return f;
}
} while (nr_files < NR_FILE && grow_files());
} while (nr_files < max_files && grow_files());
return NULL;
}
......
......@@ -19,7 +19,9 @@ static struct inode_hash_entry {
static struct inode * first_inode;
static struct wait_queue * inode_wait = NULL;
static int nr_inodes = 0, nr_free_inodes = 0;
/* Keep these next two contiguous in memory for sysctl.c */
int nr_inodes = 0, nr_free_inodes = 0;
int max_inodes = NR_INODE;
static inline int const hashfn(kdev_t dev, unsigned int i)
{
......@@ -455,7 +457,7 @@ struct inode * get_empty_inode(void)
unsigned long badness = 1000;
int i;
if (nr_inodes < NR_INODE && nr_free_inodes < (nr_inodes >> 1))
if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1))
grow_inodes();
repeat:
inode = first_inode;
......@@ -471,7 +473,7 @@ struct inode * get_empty_inode(void)
}
}
if (badness)
if (nr_inodes < NR_INODE) {
if (nr_inodes < max_inodes) {
if (grow_inodes() == 0)
goto repeat;
}
......
......@@ -81,9 +81,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
*check = 'n';
*conversion = 'b';
/* Please leave dotsOK as 1, and contact Albert Cahalan if */
/* it causes any problems for you. <albert@ccs.neu.edu> */
*dotsOK =1; /* see note above, and report problems */
*dotsOK = 0;
*uid = current->uid;
*gid = current->gid;
*umask = current->fs->umask;
......@@ -108,6 +106,12 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
else if (!strcmp(value,"auto")) *conversion = 'a';
else return 0;
}
else if (!strcmp(this_char,"dots")) {
*dotsOK = 1;
}
else if (!strcmp(this_char,"nodots")) {
*dotsOK = 0;
}
else if (!strcmp(this_char,"dotsOK") && value) {
if (!strcmp(value,"yes")) *dotsOK = 1;
else if (!strcmp(value,"no")) *dotsOK = 0;
......
......@@ -675,7 +675,7 @@ static struct file nfs_file; /* File descriptor containing socket */
static struct inode nfs_inode; /* Inode containing socket */
static int *rpc_packet = NULL; /* RPC packet */
extern asmlinkage int sys_socketcall(int call, unsigned long *args);
extern asmlinkage int sys_socket(int family, int type, int protocol);
/*
......@@ -684,10 +684,9 @@ extern asmlinkage int sys_socketcall(int call, unsigned long *args);
static int root_nfs_open(void)
{
struct file *filp;
unsigned long opt[] = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };
/* Open the socket */
if ((nfs_data.fd = sys_socketcall(SYS_SOCKET, opt)) < 0) {
if ((nfs_data.fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
printk(KERN_ERR "NFS: Cannot open UDP socket\n");
return -1;
}
......
......@@ -81,13 +81,13 @@ nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
if (result == -ETIMEDOUT) {
if (server->flags & NFS_MOUNT_SOFT) {
printk("NFS server %s not responding, "
"still trying.\n", server->hostname);
"timed out.\n", server->hostname);
result = -EIO;
break;
}
if (!major_timeout_seen) {
printk("NFS server %s not responding, "
"timed out.\n", server->hostname);
"still trying.\n", server->hostname);
major_timeout_seen = 1;
}
if ((timeout.init_timeout <<= 1) >= maxtimeo)
......
......@@ -45,6 +45,7 @@
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif
#include <linux/swap.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
......
......@@ -16,6 +16,7 @@
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif
#include <asm/bitops.h>
/*
* Offset of the first process in the /proc root directory..
......@@ -25,6 +26,8 @@
static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
/*
* These are the generic /proc directory operations. They
* use the in-memory "struct proc_dir_entry" tree to parse
......@@ -49,7 +52,7 @@ static struct file_operations proc_dir_operations = {
/*
* proc directories can do almost nothing..
*/
static struct inode_operations proc_dir_inode_operations = {
struct inode_operations proc_dir_inode_operations = {
&proc_dir_operations, /* default net directory file-ops */
NULL, /* create */
proc_lookup, /* lookup */
......@@ -139,6 +142,15 @@ struct proc_dir_entry proc_scsi = {
NULL, &proc_root, NULL
};
struct proc_dir_entry proc_sys_root = {
PROC_SYS, 3, "sys", /* inode, name */
S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, /* mode, nlink, uid, gid */
0, &proc_dir_inode_operations, /* size, ops */
NULL, NULL, /* get_info, fill_inode */
NULL, /* next */
NULL, NULL /* parent, subdir */
};
int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
dp->next = dir->subdir;
......@@ -159,6 +171,10 @@ int proc_unregister(struct proc_dir_entry * dir, int ino)
dp->next = NULL;
if (S_ISDIR(dp->mode))
dir->nlink--;
if (ino >= PROC_DYNAMIC_FIRST &&
ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
clear_bit(ino-PROC_DYNAMIC_FIRST,
(void *) proc_alloc_map);
return 0;
}
p = &dp->next;
......@@ -166,6 +182,30 @@ int proc_unregister(struct proc_dir_entry * dir, int ino)
return -EINVAL;
}
static int make_inode_number(void)
{
int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
if (i<0 || i>=PROC_NDYNAMIC)
return -1;
set_bit(i, (void *) proc_alloc_map);
return PROC_DYNAMIC_FIRST + i;
}
int proc_register_dynamic(struct proc_dir_entry * dir,
struct proc_dir_entry * dp)
{
int i = make_inode_number();
if (i < 0)
return -EAGAIN;
dp->low_ino = i;
dp->next = dir->subdir;
dp->parent = dir;
dir->subdir = dp;
if (S_ISDIR(dp->mode))
dir->nlink++;
return 0;
}
/*
* /proc/self:
*/
......@@ -262,6 +302,8 @@ void proc_root_init(void)
proc_register(&proc_root, &proc_scsi);
#endif
proc_register(&proc_root, &proc_sys_root);
#ifdef CONFIG_DEBUG_MALLOC
proc_register(&proc_root, &(struct proc_dir_entry) {
PROC_MALLOC, 6, "malloc",
......
......@@ -9,6 +9,8 @@
* - umount systemcall
*
* GK 2/5/95 - Changed to support mounting the root fs via NFS
*
* Added kerneld support: Jacques Gelinas and Bjorn Ekwall
*/
#include <stdarg.h>
......@@ -28,11 +30,14 @@
#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);
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
extern void wait_for_keypress(void);
extern struct file_operations * get_blkfops(unsigned int major);
extern void blkdev_release (struct inode *);
extern int root_mountflags;
......@@ -278,11 +283,15 @@ struct file_system_type *get_fs_type(const char *name)
if (!name)
return fs;
while (fs) {
if (!strcmp(name,fs->name))
break;
fs = fs->next;
for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
;
#ifdef CONFIG_KERNELD
if (!fs && (request_module(name) == 0)) {
for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
;
}
#endif
return fs;
}
......@@ -525,7 +534,6 @@ asmlinkage int sys_umount(char * name)
kdev_t dev;
int retval;
struct inode dummy_inode;
struct file_operations * fops;
if (!suser())
return -EPERM;
......@@ -557,9 +565,7 @@ asmlinkage int sys_umount(char * name)
return -ENXIO;
}
if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
fops = get_blkfops(MAJOR(dev));
if (fops && fops->release)
fops->release(inode,NULL);
blkdev_release (inode);
if (MAJOR(dev) == UNNAMED_MAJOR)
put_unnamed_dev(dev);
}
......
......@@ -36,26 +36,28 @@ __ntohl(unsigned long int x)
{
unsigned long int res, t1, t2;
__asm__
("bis %3,%3,%0 # %0 is result; %0=aabbccdd
extlh %0,5,%1 # %1 = dd000000
zap %0,0xfd,%2 # %2 = 0000cc00
sll %2,5,%2 # %2 = 00198000
s8addl %2,%1,%1 # %1 = ddcc0000
zap %0,0xfb,%2 # %2 = 00bb0000
srl %2,8,%2 # %2 = 0000bb00
extbl %0,3,%0 # %0 = 000000aa
or %1,%0,%0 # %0 = ddcc00aa
or %2,%0,%0 # %0 = ddccbbaa"
: "r="(res), "r="(t1), "r="(t2) : "r"(x));
__asm__(
"# bswap input: %0 (aabbccdd)
# output: %0, used %1 %2
extlh %0,5,%1 # %1 = dd000000
zap %0,0xfd,%2 # %2 = 0000cc00
sll %2,5,%2 # %2 = 00198000
s8addq %2,%1,%1 # %1 = ddcc0000
zap %0,0xfb,%2 # %2 = 00bb0000
srl %2,8,%2 # %2 = 0000bb00
extbl %0,3,%0 # %0 = 000000aa
or %1,%0,%0 # %0 = ddcc00aa
or %2,%0,%0 # %0 = ddccbbaa"
: "r="(res), "r="(t1), "r="(t2)
: "0" (x & 0xffffffffUL));
return res;
}
#define __constant_ntohl(x) \
((unsigned int)((((unsigned int)(x) & 0x000000ffU) << 24) | \
(((unsigned int)(x) & 0x0000ff00U) << 8) | \
(((unsigned int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned int)(x) & 0xff000000U) >> 24)))
((unsigned long int)((((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24)))
extern __inline__ unsigned short int
__ntohs(unsigned short int x)
......
#ifndef __LINUX_SMPLOCK_H
#define __LINUX_SMPLOCK_H
#ifndef __I386_SMPLOCK_H
#define __I386_SMPLOCK_H
#ifdef __SMP__
......
......@@ -154,6 +154,7 @@
#define __NR_writev 146
#define __NR_getsid 147
#define __NR_fdatasync 148
#define __NR__sysctl 149
#define __NR_mlock 150
#define __NR_munlock 151
......
......@@ -23,16 +23,22 @@
* Some programs (notably those using select()) may have to be
* recompiled to take full advantage of the new limits..
*/
/* Fixed constants first: */
#undef NR_OPEN
#define NR_OPEN 256
#define NR_INODE 2048 /* this should be bigger than NR_FILE */
#define NR_FILE 1024 /* this can well be larger on a larger system */
#define NR_SUPER 32
#define NR_SUPER 64
#define NR_IHASH 131
#define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10
/* And dynamically-tunable limits and defaults: */
extern int max_inodes, nr_inodes;
extern int max_files, nr_files;
#define NR_INODE 2048 /* this should be bigger than NR_FILE */
#define NR_FILE 1024 /* this can well be larger on a larger system */
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
......@@ -483,10 +489,10 @@ extern struct file *first_file;
extern int nr_files;
extern struct super_block super_blocks[NR_SUPER];
extern int shrink_buffers(unsigned int priority, unsigned long limit);
extern void refile_buffer(struct buffer_head * buf);
extern void set_writetime(struct buffer_head * buf, int flag);
extern void refill_freelist(int size);
extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**, int);
extern struct buffer_head ** buffer_pages;
extern int nr_buffers;
......
#ifndef _LINUX_KERNELD_H
#define _LINUX_KERNELD_H
#define KERNELD_SYSTEM 1
#define KERNELD_REQUEST_MODULE 2 /* "insmod" */
#define KERNELD_RELEASE_MODULE 3 /* "rmmod" */
#define KERNELD_DELAYED_RELEASE_MODULE 4 /* "rmmod" */
#define KERNELD_CANCEL_RELEASE_MODULE 5 /* "rmmod" */
#define KERNELD_REQUEST_ROUTE 6 /* from net/ipv4/route.c */
#define KERNELD_BLANKER 7 /* from drivers/char/console.c */
#define IPC_KERNELD 00040000 /* use the kerneld message channel */
#define KERNELD_MAXCMD 0x7ffeffff
#define KERNELD_MINSEQ 0x7fff0000 /* "commands" legal up to 0x7ffeffff */
#define KERNELD_WAIT 0x80000000
#define KERNELD_NOWAIT 0
struct kerneld_msg {
long mtype;
long id;
#ifdef __KERNEL__
char *text;
#else
char text[1];
#endif /* __KERNEL__ */
};
#ifdef __KERNEL__
extern int kerneld_send(int msgtype, int ret_size, int msgsz,
const char *text, const char *ret_val);
/*
* Request that a module should be loaded.
* Wait for the exit status from insmod/modprobe.
* If it fails, it fails... at least we tried...
*/
static inline int request_module(const char *name)
{
return kerneld_send(KERNELD_REQUEST_MODULE,
0 | KERNELD_WAIT,
strlen(name), name, NULL);
}
/*
* Request the removal of a module, maybe don't wait for it.
* It doesn't matter if the removal fails, now does it?
*/
static inline int release_module(const char *name, int waitflag)
{
return kerneld_send(KERNELD_RELEASE_MODULE,
0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT),
strlen(name), name, NULL);
}
/*
* Request a delayed removal of a module, but don't wait for it.
* The delay is done by kerneld (default: 60 seconds)
*/
static inline int delayed_release_module(const char *name)
{
return kerneld_send(KERNELD_DELAYED_RELEASE_MODULE,
0 | KERNELD_NOWAIT,
strlen(name), name, NULL);
}
/*
* Attempt to cancel a previous request for removal of a module,
* but don't wait for it.
* This call can be made if the kernel wants to prevent a delayed
* unloading of a module.
*/
static inline int cancel_release_module(const char *name)
{
return kerneld_send(KERNELD_CANCEL_RELEASE_MODULE,
0 | KERNELD_NOWAIT,
strlen(name), name, NULL);
}
/*
* Perform an "inverted" system call, maybe return the exit status
*/
static inline int ksystem(const char *cmd, int waitflag)
{
return kerneld_send(KERNELD_SYSTEM,
0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT),
strlen(cmd), cmd, NULL);
}
/*
* Try to create a route, possibly by opening a ppp-connection
*/
static inline int kerneld_route(const char *ip_route)
{
return kerneld_send(KERNELD_REQUEST_ROUTE,
0 | KERNELD_WAIT,
strlen(ip_route), ip_route, NULL);
}
/*
* Handle an external screen blanker
*/
static inline int kerneld_blanker(int on_off) /* 0 => "off", else "on" */
{
return kerneld_send(KERNELD_BLANKER,
0 | (on_off?KERNELD_NOWAIT:KERNELD_WAIT),
strlen(on_off?"on":"off"), on_off?"on":"off", NULL);
}
#endif /* __KERNEL__ */
#endif
/*
* lists.h: Simple list macros for Linux
*/
#define DLNODE(ptype) \
struct { \
ptype * dl_prev; \
ptype * dl_next; \
}
#define DNODE_SINGLE(node) {(node),(node)}
#define DNODE_NULL {0,0}
#define DLIST_INIT(listnam) \
(listnam).dl_prev = &(listnam); \
(listnam).dl_last = &(listnam);
#define DLIST_NEXT(listnam) listnam.dl_next
#define DLIST_PREV(listnam) listnam.dl_prev
#define DLIST_INSERT_AFTER(node, new, listnam) do { \
(new)->listnam.dl_prev = (node); \
(new)->listnam.dl_next = (node)->listnam.dl_next; \
(node)->listnam.dl_next->listnam.dl_prev = (new); \
(node)->listnam.dl_next = (new); \
} while (0)
#define DLIST_INSERT_BEFORE(node, new, listnam) do { \
(new)->listnam.dl_next = (node); \
(new)->listnam.dl_prev = (node)->listnam.dl_prev; \
(node)->listnam.dl_prev->listnam.dl_next = (new); \
(node)->listnam.dl_prev = (new); \
} while (0)
#define DLIST_DELETE(node, listnam) do { \
node->listnam.dl_prev->listnam.dl_next = \
node->listnam.dl_next; \
node->listnam.dl_next->listnam.dl_prev = \
node->listnam.dl_prev; \
} while (0)
......@@ -111,7 +111,8 @@ typedef struct page {
age:8,
uptodate:1,
error:1,
unused:5,
referenced:1,
unused:4,
reserved:1;
unsigned long offset;
struct inode *inode;
......@@ -127,10 +128,6 @@ extern mem_map_t * mem_map;
* Free area management
*/
extern int nr_swap_pages;
extern int nr_free_pages;
extern int min_free_pages;
#define NR_MEM_LISTS 6
struct mem_list {
......@@ -197,15 +194,6 @@ extern void * vremap(unsigned long offset, unsigned long size);
extern void vfree(void * addr);
extern int vread(char *buf, char *addr, int count);
/* swap.c */
extern void swap_free(unsigned long);
extern void swap_duplicate(unsigned long);
extern void swap_in(struct task_struct *, struct vm_area_struct *, pte_t *, unsigned long id, int write_access);
extern void si_swapinfo(struct sysinfo * val);
extern void rw_swap_page(int rw, unsigned long nr, char * buf);
/* mmap.c */
extern unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long off);
......@@ -221,11 +209,6 @@ extern unsigned long get_unmapped_area(unsigned long, unsigned long);
extern unsigned long page_unuse(unsigned long);
extern int shrink_mmap(int, unsigned long);
#define read_swap_page(nr,buf) \
rw_swap_page(READ,(nr),(buf))
#define write_swap_page(nr,buf) \
rw_swap_page(WRITE,(nr),(buf))
#define GFP_BUFFER 0x00
#define GFP_ATOMIC 0x01
#define GFP_USER 0x02
......@@ -291,69 +274,6 @@ static inline struct vm_area_struct * find_vma_intersection (struct task_struct
return vma;
}
/*
* vm_ops not present page codes for shared memory.
*
* Will go away eventually..
*/
#define SHM_SWP_TYPE 0x40
extern void shm_no_page (ulong *);
/*
* swap cache stuff (in swap.c)
*/
#define SWAP_CACHE_INFO
extern unsigned long * swap_cache;
#ifdef SWAP_CACHE_INFO
extern unsigned long swap_cache_add_total;
extern unsigned long swap_cache_add_success;
extern unsigned long swap_cache_del_total;
extern unsigned long swap_cache_del_success;
extern unsigned long swap_cache_find_total;
extern unsigned long swap_cache_find_success;
#endif
extern inline unsigned long in_swap_cache(unsigned long addr)
{
return swap_cache[MAP_NR(addr)];
}
extern inline long find_in_swap_cache (unsigned long addr)
{
unsigned long entry;
#ifdef SWAP_CACHE_INFO
swap_cache_find_total++;
#endif
entry = xchg(swap_cache + MAP_NR(addr), 0);
#ifdef SWAP_CACHE_INFO
if (entry)
swap_cache_find_success++;
#endif
return entry;
}
extern inline int delete_from_swap_cache(unsigned long addr)
{
unsigned long entry;
#ifdef SWAP_CACHE_INFO
swap_cache_del_total++;
#endif
entry= xchg(swap_cache + MAP_NR(addr), 0);
if (entry) {
#ifdef SWAP_CACHE_INFO
swap_cache_del_success++;
#endif
swap_free(entry);
return 1;
}
return 0;
}
#endif /* __KERNEL__ */
#endif
......@@ -26,6 +26,9 @@
/* maximum length of module name */
#define MOD_MAX_NAME 64
/* magic marker for modules inserted from kerneld, to be auto-reaped */
#define MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */
/* maximum length of symbol name */
#define SYM_MAX_NAME 60
......@@ -90,7 +93,7 @@ extern int register_symtab(struct symbol_table *);
extern long mod_use_count_;
#define MOD_INC_USE_COUNT mod_use_count_++
#define MOD_DEC_USE_COUNT mod_use_count_--
#define MOD_IN_USE (mod_use_count_ != 0)
#define MOD_IN_USE ((mod_use_count_ & ~MOD_AUTOCLEAN) != 0)
#ifndef __NO_VERSION__
#include <linux/version.h>
......
......@@ -39,16 +39,6 @@ static inline unsigned long _page_hashfn(struct inode * inode, unsigned long off
#define page_hash(inode,offset) page_hash_table[_page_hashfn(inode,offset)]
static inline int page_age_update(struct page * page, int accessed)
{
unsigned int age = page->age;
if (accessed)
age |= PAGE_AGE_VALUE << 1;
age >>= 1;
page->age = age;
return age > (PAGE_AGE_VALUE >> 1);
}
static inline struct page * find_page(struct inode * inode, unsigned long offset)
{
struct page *page;
......@@ -58,7 +48,7 @@ static inline struct page * find_page(struct inode * inode, unsigned long offset
continue;
if (page->offset != offset)
continue;
page->age = PAGE_AGE_VALUE | (page->age >> 1);
page->referenced = 1;
page->count++;
break;
}
......@@ -84,6 +74,7 @@ static inline void add_page_to_hash_queue(struct inode * inode, struct page * pa
struct page **p = &page_hash(inode,page->offset);
page_cache_size++;
page->referenced = 1;
page->age = PAGE_AGE_VALUE;
page->prev_hash = NULL;
if ((page->next_hash = *p) != NULL)
......
......@@ -36,7 +36,8 @@ enum root_directory_inos {
PROC_IOPORTS,
PROC_APM,
PROC_PROFILE, /* whether enabled or not */
PROC_CMDLINE
PROC_CMDLINE,
PROC_SYS
};
enum pid_directory_inos {
......@@ -123,6 +124,11 @@ enum scsi_directory_inos {
PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */
}; /* 16 HBAs in one machine */
/* Finally, the dynamically allocatable proc entries are reserved: */
#define PROC_DYNAMIC_FIRST 4096
#define PROC_NDYNAMIC 4096
#define PROC_SUPER_MAGIC 0x9fa0
/*
......@@ -153,11 +159,13 @@ struct proc_dir_entry {
int (*get_info)(char *, char **, off_t, int, int);
void (*fill_inode)(struct inode *);
struct proc_dir_entry *next, *parent, *subdir;
void *data;
};
extern struct proc_dir_entry proc_root;
extern struct proc_dir_entry proc_net;
extern struct proc_dir_entry proc_scsi;
extern struct proc_dir_entry proc_sys;
extern struct proc_dir_entry proc_pid;
extern struct proc_dir_entry proc_pid_fd;
......@@ -168,6 +176,8 @@ extern void proc_base_init(void);
extern void proc_net_init(void);
extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
extern int proc_register_dynamic(struct proc_dir_entry *,
struct proc_dir_entry *);
extern int proc_unregister(struct proc_dir_entry *, int);
static inline int proc_net_register(struct proc_dir_entry * x)
......@@ -229,10 +239,12 @@ extern int proc_match(int, const char *, struct proc_dir_entry *);
extern int proc_readdir(struct inode *, struct file *, void *, filldir_t);
extern int proc_lookup(struct inode *, const char *, int, struct inode **);
extern struct inode_operations proc_dir_inode_operations;
extern struct inode_operations proc_net_inode_operations;
extern struct inode_operations proc_netdir_inode_operations;
extern struct inode_operations proc_scsi_inode_operations;
extern struct inode_operations proc_mem_inode_operations;
extern struct inode_operations proc_sys_inode_operations;
extern struct inode_operations proc_array_inode_operations;
extern struct inode_operations proc_arraylong_inode_operations;
extern struct inode_operations proc_kcore_inode_operations;
......
......@@ -5,4 +5,134 @@
#define SWAP_FLAG_PRIO_MASK 0x7fff
#define SWAP_FLAG_PRIO_SHIFT 0
#define MAX_SWAPFILES 8
#ifdef __KERNEL__
#define SWP_USED 1
#define SWP_WRITEOK 3
struct swap_info_struct {
unsigned int flags;
kdev_t swap_device;
struct inode * swap_file;
unsigned char * swap_map;
unsigned char * swap_lockmap;
int lowest_bit;
int highest_bit;
int prio; /* swap priority */
int pages;
unsigned long max;
int next; /* next entry on swap list */
};
extern int nr_swap_pages;
extern int nr_free_pages;
extern int min_free_pages;
extern int free_pages_low;
extern int free_pages_high;
/* Incomplete types for prototype declarations: */
struct task_struct;
struct vm_area_struct;
struct sysinfo;
/* linux/ipc/shm.c */
extern int shm_swap (int, unsigned long);
/* linux/mm/swap_clock.c */
extern int try_to_free_page(int, unsigned long);
/* linux/mm/swap_io.c */
extern void rw_swap_page(int, unsigned long, char *);
#define read_swap_page(nr,buf) \
rw_swap_page(READ,(nr),(buf))
#define write_swap_page(nr,buf) \
rw_swap_page(WRITE,(nr),(buf))
/* linux/mm/swap_mman.c */
extern void swap_in(struct task_struct *, struct vm_area_struct *,
pte_t *, unsigned long, int);
/* linux/mm/swap_state.c */
extern void show_swap_cache_info(void);
extern int add_to_swap_cache(unsigned long, unsigned long);
extern unsigned long init_swap_cache(unsigned long, unsigned long);
extern void swap_duplicate(unsigned long);
/* linux/mm/swapfile.c */
extern int nr_swapfiles;
extern struct swap_info_struct swap_info[];
void si_swapinfo(struct sysinfo *);
unsigned long get_swap_page(void);
extern void swap_free(unsigned long);
/*
* vm_ops not present page codes for shared memory.
*
* Will go away eventually..
*/
#define SHM_SWP_TYPE 0x40
extern void shm_no_page (ulong *);
/*
* swap cache stuff (in linux/mm/swap_state.c)
*/
#define SWAP_CACHE_INFO
extern unsigned long * swap_cache;
#ifdef SWAP_CACHE_INFO
extern unsigned long swap_cache_add_total;
extern unsigned long swap_cache_add_success;
extern unsigned long swap_cache_del_total;
extern unsigned long swap_cache_del_success;
extern unsigned long swap_cache_find_total;
extern unsigned long swap_cache_find_success;
#endif
extern inline unsigned long in_swap_cache(unsigned long addr)
{
return swap_cache[MAP_NR(addr)];
}
extern inline long find_in_swap_cache (unsigned long addr)
{
unsigned long entry;
#ifdef SWAP_CACHE_INFO
swap_cache_find_total++;
#endif
entry = xchg(swap_cache + MAP_NR(addr), 0);
#ifdef SWAP_CACHE_INFO
if (entry)
swap_cache_find_success++;
#endif
return entry;
}
extern inline int delete_from_swap_cache(unsigned long addr)
{
unsigned long entry;
#ifdef SWAP_CACHE_INFO
swap_cache_del_total++;
#endif
entry= xchg(swap_cache + MAP_NR(addr), 0);
if (entry) {
#ifdef SWAP_CACHE_INFO
swap_cache_del_success++;
#endif
swap_free(entry);
return 1;
}
return 0;
}
#endif /* __KERNEL__*/
#endif /* _LINUX_SWAP_H */
......@@ -28,11 +28,20 @@ typedef struct swap_control_v5
int sc_nr_pages_to_free;
enum RCL_POLICY sc_policy;
} swap_control_v5;
typedef struct swap_control_v5 swap_control_t;
extern swap_control_t swap_control;
typedef struct kswapd_control_v1
{
int maxpages;
int pages_buff;
int pages_shm;
int pages_mmap;
int pages_swap;
} kswapd_control_v1;
typedef kswapd_control_v1 kswapd_control_t;
extern kswapd_control_t kswapd_ctl;
#define SC_VERSION 1
#define SC_MAX_VERSION 1
......@@ -79,24 +88,20 @@ static inline int AGE_CLUSTER_SIZE(int resources)
return n;
}
static inline void touch_page(unsigned long addr)
static inline void touch_page(struct page *page)
{
unsigned char age = mem_map[MAP_NR(addr)].age;
if (age < (MAX_PAGE_AGE - PAGE_ADVANCE))
age += PAGE_ADVANCE;
if (page->age < (MAX_PAGE_AGE - PAGE_ADVANCE))
page->age += PAGE_ADVANCE;
else
age = MAX_PAGE_AGE;
mem_map[MAP_NR(addr)].age = age;
page->age = MAX_PAGE_AGE;
}
static inline void age_page(unsigned long addr)
static inline void age_page(struct page *page)
{
unsigned char age = mem_map[MAP_NR(addr)].age;
if (age > PAGE_DECLINE)
age -= PAGE_DECLINE;
if (page->age > PAGE_DECLINE)
page->age -= PAGE_DECLINE;
else
age = 0;
mem_map[MAP_NR(addr)].age = age;
page->age = 0;
}
static inline int age_of(unsigned long addr)
......
This diff is collapsed.
......@@ -14,6 +14,8 @@
* BEEP_TIMER console beep timer
*
* RS_TIMER timer for the RS-232 ports
*
* SWAP_TIMER timer for the background pageout daemon
*
* HD_TIMER harddisk timer
*
......@@ -40,6 +42,7 @@
#define BLANK_TIMER 0
#define BEEP_TIMER 1
#define RS_TIMER 2
#define SWAP_TIMER 3
#define HD_TIMER 16
#define FLOPPY_TIMER 17
......
......@@ -185,6 +185,9 @@ extern __inline__ void ip_rt_put(struct rtable * rt)
;
#endif
#ifdef CONFIG_KERNELD
extern struct rtable * ip_rt_route(__u32 daddr, int local);
#else
extern __inline__ struct rtable * ip_rt_route(__u32 daddr, int local)
#ifndef MODULE
{
......@@ -208,6 +211,7 @@ extern __inline__ struct rtable * ip_rt_route(__u32 daddr, int local)
#else
;
#endif
#endif
extern __inline__ struct rtable * ip_check_route(struct rtable ** rp,
__u32 daddr, int local)
......
......@@ -44,6 +44,7 @@ extern int console_loglevel;
static int init(void *);
extern int bdflush(void *);
extern int kswapd(void *);
extern void init_IRQ(void);
extern void init_modules(void);
......@@ -51,6 +52,7 @@ extern long console_init(long, long);
extern long kmalloc_init(long,long);
extern void sock_init(void);
extern long pci_init(long, long);
extern void sysctl_init(void);
extern void swap_setup(char *str, int *ints);
extern void buff_setup(char *str, int *ints);
......@@ -108,7 +110,7 @@ static void load_ramdisk(char *str, int *ints);
static void prompt_ramdisk(char *str, int *ints);
#endif CONFIG_BLK_DEV_RAM
#ifdef CONFIG_SYSVIPC
#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
extern void ipc_init(void);
#endif
......@@ -626,7 +628,7 @@ asmlinkage void start_kernel(void)
mem_init(memory_start,memory_end);
buffer_init();
sock_init();
#ifdef CONFIG_SYSVIPC
#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
ipc_init();
#endif
#ifdef CONFIG_APM
......@@ -640,6 +642,7 @@ asmlinkage void start_kernel(void)
#ifdef __SMP__
smp_init();
#endif
sysctl_init();
/*
* We count on the initial thread going ok
* Like idlers init is an unlocked kernel thread, which will
......@@ -693,6 +696,8 @@ static int init(void * unused)
/* Launch bdflush from here, instead of the old syscall way. */
kernel_thread(bdflush, NULL, 0);
/* Start the background pageout daemon. */
kernel_thread(kswapd, NULL, 0);
setup();
......
......@@ -10,6 +10,10 @@
O_TARGET := ipc.o
O_OBJS := util.o
ifdef CONFIG_KERNELD
CONFIG_SYSVIPC=1
endif
ifdef CONFIG_SYSVIPC
O_OBJS += msg.o sem.o shm.o
endif
......
This diff is collapsed.
......@@ -12,6 +12,7 @@
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/malloc.h>
#include <linux/swap.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
......
......@@ -13,7 +13,7 @@
#include <linux/shm.h>
#include <linux/stat.h>
#ifdef CONFIG_SYSVIPC
#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
extern void sem_init (void), msg_init (void), shm_init (void);
......
......@@ -13,7 +13,7 @@
O_TARGET := kernel.o
O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
module.o exit.o signal.o itimer.o info.o time.o softirq.o \
resource.o
resource.o sysctl.o
ifeq ($(CONFIG_MODULES),y)
OX_OBJS = ksyms.o
......
......@@ -18,6 +18,7 @@
#include <asm/segment.h>
extern void sem_exit (void);
extern void kerneld_exit(void);
int getrusage(struct task_struct *, int, struct rusage *);
......@@ -511,6 +512,7 @@ NORET_TYPE void do_exit(long code)
current->flags |= PF_EXITING;
del_timer(&current->real_timer);
sem_exit();
kerneld_exit();
exit_mm();
__exit_files(current);
__exit_fs(current);
......
......@@ -13,6 +13,7 @@
#include <linux/unistd.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/swap.h>
asmlinkage int sys_sysinfo(struct sysinfo *info)
{
......
This diff is collapsed.
This diff is collapsed.
......@@ -18,6 +18,7 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <asm/segment.h>
#include <asm/io.h>
......
This diff is collapsed.
......@@ -8,7 +8,8 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
O_OBJS := memory.o swap.o mmap.o filemap.o mprotect.o mlock.o \
kmalloc.o vmalloc.o
O_OBJS := memory.o mmap.o filemap.o mprotect.o mlock.o \
kmalloc.o vmalloc.o \
swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o
include $(TOPDIR)/Rules.make
This diff is collapsed.
......@@ -43,6 +43,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <asm/system.h>
#include <asm/segment.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment