Commit 50198be8 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.20

parent ec010c86
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 19 SUBLEVEL = 20
all: Version zImage all: Version zImage
......
...@@ -80,7 +80,7 @@ if [ "$CONFIG_SLIP" = "y" ]; then ...@@ -80,7 +80,7 @@ if [ "$CONFIG_SLIP" = "y" ]; then
# bool ' SLIP debugging on' SL_DUMP y # bool ' SLIP debugging on' SL_DUMP y
fi fi
bool 'PPP (point-to-point) support' CONFIG_PPP n bool 'PPP (point-to-point) support' CONFIG_PPP n
bool 'Load balancing support (very experimental)' CONFIG_SLAVE_BALANCING n bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
bool 'PLIP (parallel port) support' CONFIG_PLIP n bool 'PLIP (parallel port) support' CONFIG_PLIP n
bool 'NE2000/NE1000 support' CONFIG_NE2000 n bool 'NE2000/NE1000 support' CONFIG_NE2000 n
bool 'WD80*3 support' CONFIG_WD80x3 n bool 'WD80*3 support' CONFIG_WD80x3 n
...@@ -95,6 +95,7 @@ bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n ...@@ -95,6 +95,7 @@ bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n
bool 'AT1700 support' CONFIG_AT1700 n bool 'AT1700 support' CONFIG_AT1700 n
#bool 'Zenith Z-Note support' CONFIG_ZNET n #bool 'Zenith Z-Note support' CONFIG_ZNET n
#bool 'EtherExpress support' CONFIG_EEXPRESS n #bool 'EtherExpress support' CONFIG_EEXPRESS n
#bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n
bool 'DEPCA support' CONFIG_DEPCA n bool 'DEPCA support' CONFIG_DEPCA n
#bool 'NI52EE support' CONFIG_NI52 n #bool 'NI52EE support' CONFIG_NI52 n
#bool 'NI65EE support' CONFIG_NI65 n #bool 'NI65EE support' CONFIG_NI65 n
...@@ -107,7 +108,7 @@ fi ...@@ -107,7 +108,7 @@ fi
comment 'CD-ROM drivers' comment 'CD-ROM drivers'
bool 'Sony CDU31A CDROM driver support' CONFIG_CDU31A n bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n
bool 'Mitsumi CDROM driver support' CONFIG_MCD n bool 'Mitsumi CDROM driver support' CONFIG_MCD n
bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
......
This diff is collapsed.
...@@ -103,6 +103,7 @@ static int mmap_mem(struct inode * inode, struct file * file, ...@@ -103,6 +103,7 @@ static int mmap_mem(struct inode * inode, struct file * file,
mpnt->vm_start = addr; mpnt->vm_start = addr;
mpnt->vm_end = addr + len; mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot; mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = inode; mpnt->vm_inode = inode;
inode->i_count++; inode->i_count++;
...@@ -197,6 +198,7 @@ static int mmap_zero(struct inode * inode, struct file * file, ...@@ -197,6 +198,7 @@ static int mmap_zero(struct inode * inode, struct file * file,
mpnt->vm_start = addr; mpnt->vm_start = addr;
mpnt->vm_end = addr + len; mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot; mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = NULL; mpnt->vm_inode = NULL;
mpnt->vm_offset = off; mpnt->vm_offset = off;
......
...@@ -291,8 +291,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -291,8 +291,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
if (el_debug > 2) if (el_debug > 2)
printk(" queued xmit.\n"); printk(" queued xmit.\n");
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
return 0; return 0;
} }
...@@ -514,9 +513,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs) ...@@ -514,9 +513,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
#ifdef MODULE #ifdef MODULE
char kernel_version[] = UTS_RELEASE; char kernel_version[] = UTS_RELEASE;
static struct device dev_3c501 = { static struct device dev_3c501 = {
"" /*"3c501"*/, " " /*"3c501"*/,
0, 0, 0, 0, 0, 0, 0, 0,
0x280, 7, 0x280, 5,
0, 0, 0, NULL, el1_probe }; 0, 0, 0, NULL, el1_probe };
int int
......
...@@ -479,8 +479,7 @@ el16_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -479,8 +479,7 @@ el16_send_packet(struct sk_buff *skb, struct device *dev)
outb(0x84, ioaddr + MISC_CTRL); outb(0x84, ioaddr + MISC_CTRL);
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */ /* You might need to clean up and record Tx statistics here. */
......
...@@ -388,8 +388,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -388,8 +388,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
outw(0x9000 + 1536, ioaddr + EL3_CMD); outw(0x9000 + 1536, ioaddr + EL3_CMD);
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
/* Clear the Tx status stack. */ /* Clear the Tx status stack. */
{ {
...@@ -669,7 +668,7 @@ el3_close(struct device *dev) ...@@ -669,7 +668,7 @@ el3_close(struct device *dev)
#ifdef MODULE #ifdef MODULE
char kernel_version[] = UTS_RELEASE; char kernel_version[] = UTS_RELEASE;
static struct device dev_3c509 = { static struct device dev_3c509 = {
"" /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe }; " " /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe };
int int
init_module(void) init_module(void)
......
...@@ -230,8 +230,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -230,8 +230,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->irqlock = 0; ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR); outb_p(ENISR_ALL, e8390_base + EN0_IMR);
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
return 0; return 0;
} }
...@@ -556,7 +555,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs) ...@@ -556,7 +555,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
rely on higher-level filtering for now. */ rely on higher-level filtering for now. */
outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR); outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
} else if (num_addrs < 0) } else if (num_addrs < 0)
outb_p(E8390_RXCONFIG | 0x10, ioaddr + EN0_RXCR); outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
else else
outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR); outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
} }
......
...@@ -136,6 +136,9 @@ ifdef CONFIG_AC3200 ...@@ -136,6 +136,9 @@ ifdef CONFIG_AC3200
NETDRV_OBJS := $(NETDRV_OBJS) net.a(ac3200.o) NETDRV_OBJS := $(NETDRV_OBJS) net.a(ac3200.o)
CONFIG_8390 = CONFIG_8390 CONFIG_8390 = CONFIG_8390
endif endif
ifdef CONFIG_APRICOT
NETDRV_OBJS := $(NETDRV_OBJS) net.a(apricot.o)
endif
ifdef CONFIG_8390 ifdef CONFIG_8390
NETDRV_OBJS := $(NETDRV_OBJS) net.a(8390.o) NETDRV_OBJS := $(NETDRV_OBJS) net.a(8390.o)
......
This diff is collapsed.
...@@ -406,8 +406,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -406,8 +406,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
/* Turn on Tx interrupts back on. */ /* Turn on Tx interrupts back on. */
outb(0x82, ioaddr + TX_INTR); outb(0x82, ioaddr + TX_INTR);
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
return 0; return 0;
} }
......
...@@ -471,8 +471,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -471,8 +471,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
write_reg_high(ioaddr, IMR, ISRh_RxErr); write_reg_high(ioaddr, IMR, ISRh_RxErr);
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
return 0; return 0;
} }
......
...@@ -453,8 +453,7 @@ de600_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -453,8 +453,7 @@ de600_start_xmit(struct sk_buff *skb, struct device *dev)
sti(); /* interrupts back on */ sti(); /* interrupts back on */
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
return 0; return 0;
} }
...@@ -751,7 +750,7 @@ de600_rspace(struct sock *sk) ...@@ -751,7 +750,7 @@ de600_rspace(struct sock *sk)
#ifdef MODULE #ifdef MODULE
char kernel_version[] = UTS_RELEASE; char kernel_version[] = UTS_RELEASE;
static struct device de600_dev = { static struct device de600_dev = {
"" /*"de600"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe }; " " /*"de600"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
int int
init_module(void) init_module(void)
......
...@@ -914,9 +914,7 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -914,9 +914,7 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev)
dev->tbusy=0; dev->tbusy=0;
} }
if (skb->free) { dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
}
} }
return 0; return 0;
......
...@@ -89,8 +89,7 @@ dummy_xmit(struct sk_buff *skb, struct device *dev) ...@@ -89,8 +89,7 @@ dummy_xmit(struct sk_buff *skb, struct device *dev)
if (skb == NULL || dev == NULL) if (skb == NULL || dev == NULL)
return 0; return 0;
if (skb->free) dev_kfree_skb(skb, FREE_WRITE);
kfree_skb(skb, FREE_WRITE);
#if DUMMY_STATS #if DUMMY_STATS
stats = (struct enet_statistics *)dev->priv; stats = (struct enet_statistics *)dev->priv;
......
...@@ -494,8 +494,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -494,8 +494,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev)
outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ); outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ);
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */ /* You might need to clean up and record Tx statistics here. */
lp->stats.tx_aborted_errors++; lp->stats.tx_aborted_errors++;
......
...@@ -555,14 +555,8 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -555,14 +555,8 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len); memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
lp->tx_ring[entry].base = lp->tx_ring[entry].base =
(int)(lp->tx_bounce_buffs + entry) | 0x83000000; (int)(lp->tx_bounce_buffs + entry) | 0x83000000;
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
} else { } else {
/* We can't free the packet yet, so we inform the memory management
code that we are still using it. */
skb_kept_by_device(skb);
lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000; lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000;
} }
lp->cur_tx++; lp->cur_tx++;
...@@ -650,7 +644,7 @@ lance_interrupt(int reg_ptr) ...@@ -650,7 +644,7 @@ lance_interrupt(int reg_ptr)
if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE]) if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE])
|| databuff < (void*)(lp->tx_bounce_buffs)) { || databuff < (void*)(lp->tx_bounce_buffs)) {
struct sk_buff *skb = ((struct sk_buff *)databuff) - 1; struct sk_buff *skb = ((struct sk_buff *)databuff) - 1;
skb_device_release(skb,FREE_WRITE); dev_kfree_skb(skb,FREE_WRITE);
/* Warning: skb may well vanish at the point you call /* Warning: skb may well vanish at the point you call
device_release! */ device_release! */
......
...@@ -57,8 +57,11 @@ loopback_xmit(struct sk_buff *skb, struct device *dev) ...@@ -57,8 +57,11 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
dev->tbusy = 1; dev->tbusy = 1;
sti(); sti();
/* FIXME: Optimise so buffers with skb->free=1 are not copied but
instead are lobbed from tx queue to rx queue */
done = dev_rint(skb->data, skb->len, 0, dev); done = dev_rint(skb->data, skb->len, 0, dev);
if (skb->free) kfree_skb(skb, FREE_WRITE); dev_kfree_skb(skb, FREE_WRITE);
while (done != 1) { while (done != 1) {
done = dev_rint(NULL, 0, 0, dev); done = dev_rint(NULL, 0, 0, dev);
......
...@@ -52,6 +52,9 @@ ...@@ -52,6 +52,9 @@
static struct device *ethdev_index[MAX_ETH_CARDS]; static struct device *ethdev_index[MAX_ETH_CARDS];
unsigned long lance_init(unsigned long mem_start, unsigned long mem_end); unsigned long lance_init(unsigned long mem_start, unsigned long mem_end);
unsigned long pi_init(unsigned long mem_start, unsigned long mem_end);
unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end);
/* /*
net_dev_init() is our network device initialization routine. net_dev_init() is our network device initialization routine.
...@@ -67,6 +70,9 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end) ...@@ -67,6 +70,9 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end)
#endif #endif
#if defined(CONFIG_PI) #if defined(CONFIG_PI)
mem_start = pi_init(mem_start, mem_end); mem_start = pi_init(mem_start, mem_end);
#endif
#if defined(CONFIG_APRICOT)
mem_start = apricot_init(mem_start, mem_end);
#endif #endif
return mem_start; return mem_start;
} }
......
This diff is collapsed.
...@@ -1798,8 +1798,7 @@ ppp_xmit(struct sk_buff *skb, struct device *dev) ...@@ -1798,8 +1798,7 @@ ppp_xmit(struct sk_buff *skb, struct device *dev)
ppp_kick_tty(ppp); ppp_kick_tty(ppp);
done: done:
if (skb->free) dev_kfree_skb(skb, FREE_WRITE);
kfree_skb(skb, FREE_WRITE);
return 0; return 0;
} }
......
...@@ -292,8 +292,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -292,8 +292,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
hardware_send_packet(ioaddr, buf, length); hardware_send_packet(ioaddr, buf, length);
dev->trans_start = jiffies; dev->trans_start = jiffies;
} }
if (skb->free) dev_kfree_skb (skb, FREE_WRITE);
kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */ /* You might need to clean up and record Tx statistics here. */
if (inw(ioaddr) == /*RU*/81) if (inw(ioaddr) == /*RU*/81)
......
...@@ -464,41 +464,11 @@ sl_xmit(struct sk_buff *skb, struct device *dev) ...@@ -464,41 +464,11 @@ sl_xmit(struct sk_buff *skb, struct device *dev)
/* We were not, so we are now... :-) */ /* We were not, so we are now... :-) */
if (skb != NULL) { if (skb != NULL) {
#if 0
#ifdef CONFIG_AX25
if(sl->mode & SL_MODE_AX25)
{
if(!skb->arp && dev->rebuild_header(skb->data,dev))
{
skb->dev=dev;
arp_queue(skb);
return 0;
}
skb->arp=1;
}
#endif
#endif
sl_lock(sl); sl_lock(sl);
size=skb->len; size=skb->len;
#if 0
if(!(sl->mode&SL_MODE_AX25))
{
if(size<sizeof(struct iphdr))
{
printk("Runt IP frame fed to slip!\n");
}
else
{
size=((struct iphdr *)(skb->data))->tot_len;
size=ntohs(size);
/* sl_hex_dump(skb->data,skb->len);*/
}
}
#endif
sl_encaps(sl, skb->data, size); sl_encaps(sl, skb->data, size);
if (skb->free) dev_kfree_skb(skb, FREE_WRITE);
kfree_skb(skb, FREE_WRITE);
} }
return(0); return(0);
} }
......
...@@ -147,7 +147,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) ...@@ -147,7 +147,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
Scsi_Cmnd * SCpnt; Scsi_Cmnd * SCpnt;
unsigned char opcode; unsigned char opcode;
int inlen, outlen, cmdlen; int inlen, outlen, cmdlen;
int needed; int needed, buf_needed;
int result; int result;
if (!buffer) if (!buffer)
...@@ -159,11 +159,11 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) ...@@ -159,11 +159,11 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
cmd_in = (char *) ( ((int *)buffer) + 2); cmd_in = (char *) ( ((int *)buffer) + 2);
opcode = get_fs_byte(cmd_in); opcode = get_fs_byte(cmd_in);
needed = (inlen > outlen ? inlen : outlen); needed = buf_needed = (inlen > outlen ? inlen : outlen);
if(needed){ if(buf_needed){
needed = (needed + 511) & ~511; buf_needed = (buf_needed + 511) & ~511;
if (needed > MAX_BUF) needed = MAX_BUF; if (buf_needed > MAX_BUF) buf_needed = MAX_BUF;
buf = (char *) scsi_malloc(needed); buf = (char *) scsi_malloc(buf_needed);
if (!buf) return -ENOMEM; if (!buf) return -ENOMEM;
} else } else
buf = NULL; buf = NULL;
...@@ -202,7 +202,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) ...@@ -202,7 +202,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer)
}; };
result = SCpnt->result; result = SCpnt->result;
SCpnt->request.dev = -1; /* Mark as not busy */ SCpnt->request.dev = -1; /* Mark as not busy */
if (buf) scsi_free(buf, needed); if (buf) scsi_free(buf, buf_needed);
if(scsi_devices[SCpnt->index].scsi_request_fn) if(scsi_devices[SCpnt->index].scsi_request_fn)
(*scsi_devices[SCpnt->index].scsi_request_fn)(); (*scsi_devices[SCpnt->index].scsi_request_fn)();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
/* /*
* TODO: * TODO:
* 1. Find out why scatter/gather is limited to 16 requests per command. * 1. Find out why scatter/gather is limited to 16 requests per command.
* This is fixed, at least on the 24F, as of version 1.12 - CAE.
* 2. Look at command linking (mscp.command_link and * 2. Look at command linking (mscp.command_link and
* mscp.command_link_id). (Does not work with many disks, * mscp.command_link_id). (Does not work with many disks,
* and no performance increase. ERY). * and no performance increase. ERY).
...@@ -38,6 +39,15 @@ ...@@ -38,6 +39,15 @@
* unfinished, questionable, or wrong. * unfinished, questionable, or wrong.
*/ */
/* Changes from version 1.11 alpha to 1.12
*
* Increased the size of the scatter-gather list to 33 entries for
* the 24F adapter (it was 16). I don't have the specs for the 14F
* or the 34F, so they may support larger s-g lists as well.
*
* Caleb Epstein <cae@jpmorgan.com>
*/
/* Changes from version 1.9 to 1.11 /* Changes from version 1.9 to 1.11
* *
* Patches to bring this driver up to speed with the default kernel * Patches to bring this driver up to speed with the default kernel
...@@ -138,7 +148,7 @@ ...@@ -138,7 +148,7 @@
#define ULTRASTOR_DEBUG (UD_ABORT|UD_CSIR|UD_RESET) #define ULTRASTOR_DEBUG (UD_ABORT|UD_CSIR|UD_RESET)
#endif #endif
#define VERSION "1.11 alpha" #define VERSION "1.12"
#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
...@@ -183,7 +193,7 @@ struct mscp { ...@@ -183,7 +193,7 @@ struct mscp {
the MSCP structure because they are associated with SCSI requests. */ the MSCP structure because they are associated with SCSI requests. */
void (*done)(Scsi_Cmnd *); void (*done)(Scsi_Cmnd *);
Scsi_Cmnd *SCint; Scsi_Cmnd *SCint;
ultrastor_sg_list sglist[ULTRASTOR_14F_MAX_SG]; ultrastor_sg_list sglist[ULTRASTOR_24F_MAX_SG]; /* use larger size for 24F */
}; };
...@@ -504,6 +514,7 @@ static int ultrastor_14f_detect(int hostnum) ...@@ -504,6 +514,7 @@ static int ultrastor_14f_detect(int hostnum)
static int ultrastor_24f_detect(int hostnum) static int ultrastor_24f_detect(int hostnum)
{ {
register int i; register int i;
struct Scsi_Host * shpnt = NULL;
#if (ULTRASTOR_DEBUG & UD_DETECT) #if (ULTRASTOR_DEBUG & UD_DETECT)
printk("US24F: detect"); printk("US24F: detect");
...@@ -580,7 +591,12 @@ static int ultrastor_24f_detect(int hostnum) ...@@ -580,7 +591,12 @@ static int ultrastor_24f_detect(int hostnum)
config.host_number = hostnum; config.host_number = hostnum;
scsi_hosts[hostnum].this_id = config.ha_scsi_id; scsi_hosts[hostnum].this_id = config.ha_scsi_id;
scsi_hosts[hostnum].unchecked_isa_dma = 0; scsi_hosts[hostnum].unchecked_isa_dma = 0;
scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_14F_MAX_SG; scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_24F_MAX_SG;
shpnt = scsi_register(hostnum, 0);
shpnt->irq = config.interrupt;
shpnt->dma_channel = config.dma_channel;
shpnt->io_port = config.port_address;
#if ULTRASTOR_MAX_CMDS > 1 #if ULTRASTOR_MAX_CMDS > 1
config.mscp_free = ~0; config.mscp_free = ~0;
...@@ -594,7 +610,7 @@ static int ultrastor_24f_detect(int hostnum) ...@@ -594,7 +610,7 @@ static int ultrastor_24f_detect(int hostnum)
outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12)); outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12));
outb(0x02, SYS_DOORBELL_MASK(addr+12)); outb(0x02, SYS_DOORBELL_MASK(addr+12));
printk("UltraStor driver version " VERSION ". Using %d SG lists.\n", printk("UltraStor driver version " VERSION ". Using %d SG lists.\n",
ULTRASTOR_14F_MAX_SG); scsi_hosts[hostnum].sg_tablesize);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
...@@ -810,6 +826,10 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -810,6 +826,10 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
if(config.slot) if(config.slot)
return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */ return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */
/* Simple consistency checking */
if(!SCpnt->host_scribble)
return SCSI_ABORT_NOT_RUNNING;
mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp; mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp;
if (mscp_index >= ULTRASTOR_MAX_CMDS) if (mscp_index >= ULTRASTOR_MAX_CMDS)
panic("Ux4F aborting invalid MSCP"); panic("Ux4F aborting invalid MSCP");
...@@ -899,7 +919,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -899,7 +919,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
#if ULTRASTOR_DEBUG & UD_ABORT #if ULTRASTOR_DEBUG & UD_ABORT
if (config.mscp[mscp_index].SCint != SCpnt) if (config.mscp[mscp_index].SCint != SCpnt)
printk("abort: command mismatch, %x != %x\n", printk("abort: command mismatch, %p != %p\n",
config.mscp[mscp_index].SCint, SCpnt); config.mscp[mscp_index].SCint, SCpnt);
#endif #endif
if (config.mscp[mscp_index].SCint == 0) if (config.mscp[mscp_index].SCint == 0)
...@@ -915,7 +935,6 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -915,7 +935,6 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
/* Need to set a timeout here in case command never completes. */ /* Need to set a timeout here in case command never completes. */
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
int ultrastor_reset(Scsi_Cmnd * SCpnt) int ultrastor_reset(Scsi_Cmnd * SCpnt)
......
...@@ -21,6 +21,8 @@ int ultrastor_reset(Scsi_Cmnd *); ...@@ -21,6 +21,8 @@ int ultrastor_reset(Scsi_Cmnd *);
int ultrastor_biosparam(int, int, int *); int ultrastor_biosparam(int, int, int *);
#define ULTRASTOR_14F_MAX_SG 16 #define ULTRASTOR_14F_MAX_SG 16
#define ULTRASTOR_24F_MAX_SG 33
#define ULTRASTOR_MAX_CMDS_PER_LUN 5 #define ULTRASTOR_MAX_CMDS_PER_LUN 5
#define ULTRASTOR_MAX_CMDS 16 #define ULTRASTOR_MAX_CMDS 16
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/personality.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -55,12 +56,15 @@ extern void shm_exit (void); ...@@ -55,12 +56,15 @@ extern void shm_exit (void);
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(int fd); static int load_aout_library(int fd);
static int aout_core_dump(long signr, struct pt_regs * regs);
/* /*
* Here are the actual binaries that will be accepted: * Here are the actual binaries that will be accepted:
* add more with "register_binfmt()".. * add more with "register_binfmt()"..
*/ */
static struct linux_binfmt aout_format = { NULL, load_aout_binary, load_aout_library }; static struct linux_binfmt aout_format = {
NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
};
static struct linux_binfmt *formats = &aout_format; static struct linux_binfmt *formats = &aout_format;
int register_binfmt(struct linux_binfmt * fmt) int register_binfmt(struct linux_binfmt * fmt)
...@@ -154,7 +158,7 @@ if (file.f_op->lseek) { \ ...@@ -154,7 +158,7 @@ if (file.f_op->lseek) { \
* field, which also makes sure the core-dumps won't be recursive if the * field, which also makes sure the core-dumps won't be recursive if the
* dumping of the process results in another error.. * dumping of the process results in another error..
*/ */
int core_dump(long signr, struct pt_regs * regs) static int aout_core_dump(long signr, struct pt_regs * regs)
{ {
struct inode * inode = NULL; struct inode * inode = NULL;
struct file file; struct file file;
...@@ -318,12 +322,12 @@ unsigned long * create_tables(char * p,int argc,int envc,int ibcs) ...@@ -318,12 +322,12 @@ unsigned long * create_tables(char * p,int argc,int envc,int ibcs)
mpnt->vm_start = PAGE_MASK & (unsigned long) p; mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE; mpnt->vm_end = TASK_SIZE;
mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY; mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
mpnt->vm_flags = VM_GROWSDOWN;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = NULL; mpnt->vm_inode = NULL;
mpnt->vm_offset = 0; mpnt->vm_offset = 0;
mpnt->vm_ops = NULL; mpnt->vm_ops = NULL;
insert_vm_struct(current, mpnt); insert_vm_struct(current, mpnt);
current->mm->stk_vma = mpnt;
} }
sp = (unsigned long *) (0xfffffffc & (unsigned long) p); sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
sp -= envc+1; sp -= envc+1;
...@@ -529,7 +533,6 @@ void flush_old_exec(struct linux_binprm * bprm) ...@@ -529,7 +533,6 @@ void flush_old_exec(struct linux_binprm * bprm)
mpnt = current->mm->mmap; mpnt = current->mm->mmap;
current->mm->mmap = NULL; current->mm->mmap = NULL;
current->mm->stk_vma = NULL;
while (mpnt) { while (mpnt) {
mpnt1 = mpnt->vm_next; mpnt1 = mpnt->vm_next;
if (mpnt->vm_ops && mpnt->vm_ops->close) if (mpnt->vm_ops && mpnt->vm_ops->close)
...@@ -571,9 +574,6 @@ void flush_old_exec(struct linux_binprm * bprm) ...@@ -571,9 +574,6 @@ void flush_old_exec(struct linux_binprm * bprm)
if (last_task_used_math == current) if (last_task_used_math == current)
last_task_used_math = NULL; last_task_used_math = NULL;
current->used_math = 0; current->used_math = 0;
current->personality = 0;
current->lcall7 = no_lcall7;
current->signal_map = current->signal_invmap = ident_map;
} }
/* /*
...@@ -764,25 +764,6 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -764,25 +764,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
return error; return error;
} }
/*
* signal mapping: this is the default identity mapping used for normal
* linux binaries (it's both the reverse and the normal map, of course)
*/
unsigned long ident_map[33] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32
};
/*
* default lcall7 handler.. The native linux stuff doesn't
* use it at all, so we just segfault on it.
*/
asmlinkage void no_lcall7(struct pt_regs * regs)
{
send_sig(SIGSEGV, current, 1);
}
static void set_brk(unsigned long start, unsigned long end) static void set_brk(unsigned long start, unsigned long end)
{ {
start = PAGE_ALIGN(start); start = PAGE_ALIGN(start);
...@@ -805,6 +786,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -805,6 +786,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
struct file * file; struct file * file;
int fd, error; int fd, error;
unsigned long p = bprm->p; unsigned long p = bprm->p;
unsigned long fd_offset;
ex = *((struct exec *) bprm->buf); /* exec-header */ ex = *((struct exec *) bprm->buf); /* exec-header */
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
...@@ -814,14 +796,16 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -814,14 +796,16 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return -ENOEXEC; return -ENOEXEC;
} }
if (N_MAGIC(ex) == ZMAGIC && current->personality = PER_LINUX;
(N_TXTOFF(ex) < bprm->inode->i_sb->s_blocksize)) { fd_offset = N_TXTOFF(ex);
printk("N_TXTOFF < BLOCK_SIZE. Please convert binary."); if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
return -ENOEXEC; return -ENOEXEC;
} }
if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) == ZMAGIC) { if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
printk("N_TXTOFF != BLOCK_SIZE. See a.out.h."); (fd_offset < bprm->inode->i_sb->s_blocksize)) {
printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
return -ENOEXEC; return -ENOEXEC;
} }
...@@ -845,7 +829,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -845,7 +829,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data); read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
} else { } else {
if (ex.a_text & 0xfff || ex.a_data & 0xfff) if (ex.a_text & 0xfff || ex.a_data & 0xfff)
printk("%s: executable not page aligned\n", current->comm); printk(KERN_NOTICE "executable not page aligned\n");
fd = open_inode(bprm->inode, O_RDONLY); fd = open_inode(bprm->inode, O_RDONLY);
...@@ -857,23 +841,26 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -857,23 +841,26 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
do_mmap(NULL, 0, ex.a_text+ex.a_data, do_mmap(NULL, 0, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0); MAP_FIXED|MAP_PRIVATE, 0);
read_exec(bprm->inode, N_TXTOFF(ex), read_exec(bprm->inode, fd_offset,
(char *) N_TXTADDR(ex), ex.a_text+ex.a_data); (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
goto beyond_if; goto beyond_if;
} }
if (ex.a_text) {
error = do_mmap(file, N_TXTADDR(ex), ex.a_text, error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_SHARED, N_TXTOFF(ex)); MAP_FIXED | MAP_SHARED, fd_offset);
if (error != N_TXTADDR(ex)) { if (error != N_TXTADDR(ex)) {
sys_close(fd); sys_close(fd);
send_sig(SIGSEGV, current, 0); send_sig(SIGSEGV, current, 0);
return 0; return 0;
}; };
}
error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data, error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, N_TXTOFF(ex) + ex.a_text); MAP_FIXED | MAP_PRIVATE, fd_offset + ex.a_text);
sys_close(fd); sys_close(fd);
if (error != N_TXTADDR(ex) + ex.a_text) { if (error != N_TXTADDR(ex) + ex.a_text) {
send_sig(SIGSEGV, current, 0); send_sig(SIGSEGV, current, 0);
...@@ -883,11 +870,24 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -883,11 +870,24 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->inode->i_count++; bprm->inode->i_count++;
} }
beyond_if: beyond_if:
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)++;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
set_brk(current->mm->start_brk, current->mm->brk); set_brk(current->mm->start_brk, current->mm->brk);
p += change_ldt(ex.a_text,bprm->page); p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE; p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc,0); p = (unsigned long)create_tables((char *)p,
bprm->argc, bprm->envc,
current->personality != PER_LINUX);
current->mm->start_stack = p; current->mm->start_stack = p;
regs->eip = ex.a_entry; /* eip, magic happens :-) */ regs->eip = ex.a_entry; /* eip, magic happens :-) */
regs->esp = p; /* stack pointer */ regs->esp = p; /* stack pointer */
......
...@@ -63,46 +63,59 @@ static struct super_operations isofs_sops = { ...@@ -63,46 +63,59 @@ static struct super_operations isofs_sops = {
NULL NULL
}; };
struct iso9660_options{
char map;
char rock;
char cruft;
unsigned char conversion;
unsigned int blocksize;
gid_t gid;
uid_t uid;
};
static int parse_options(char *options, struct iso9660_options * popt)
static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft, unsigned int * blocksize)
{ {
char *this_char,*value; char *this_char,*value;
*map = 'n'; popt->map = 'n';
*rock = 'y'; popt->rock = 'y';
*cruft = 'n'; popt->cruft = 'n';
*conversion = 'a'; popt->conversion = 'a';
*blocksize = 1024; popt->blocksize = 1024;
popt->gid = 0;
popt->uid = 0;
if (!options) return 1; if (!options) return 1;
for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
if (strncmp(this_char,"norock",6) == 0) { if (strncmp(this_char,"norock",6) == 0) {
*rock = 'n'; popt->rock = 'n';
continue; continue;
}; };
if (strncmp(this_char,"cruft",5) == 0) { if (strncmp(this_char,"cruft",5) == 0) {
*cruft = 'y'; popt->cruft = 'y';
continue; continue;
}; };
if ((value = strchr(this_char,'=')) != NULL) if ((value = strchr(this_char,'=')) != NULL)
*value++ = 0; *value++ = 0;
if (!strcmp(this_char,"map") && value) { if (!strcmp(this_char,"map") && value) {
if (value[0] && !value[1] && strchr("on",*value)) if (value[0] && !value[1] && strchr("on",*value))
*map = *value; popt->map = *value;
else if (!strcmp(value,"off")) *map = 'o'; else if (!strcmp(value,"off")) popt->map = 'o';
else if (!strcmp(value,"normal")) *map = 'n'; else if (!strcmp(value,"normal")) popt->map = 'n';
else return 0; else return 0;
} }
else if (!strcmp(this_char,"conv") && value) { else if (!strcmp(this_char,"conv") && value) {
if (value[0] && !value[1] && strchr("bta",*value)) if (value[0] && !value[1] && strchr("bta",*value))
*conversion = *value; popt->conversion = *value;
else if (!strcmp(value,"binary")) *conversion = 'b'; else if (!strcmp(value,"binary")) popt->conversion = 'b';
else if (!strcmp(value,"text")) *conversion = 't'; else if (!strcmp(value,"text")) popt->conversion = 't';
else if (!strcmp(value,"mtext")) *conversion = 'm'; else if (!strcmp(value,"mtext")) popt->conversion = 'm';
else if (!strcmp(value,"auto")) *conversion = 'a'; else if (!strcmp(value,"auto")) popt->conversion = 'a';
else return 0; else return 0;
} }
else if (!strcmp(this_char,"block") && value) { else if (value &&
(!strcmp(this_char,"block") ||
!strcmp(this_char,"uid") ||
!strcmp(this_char,"gid"))) {
char * vpnt = value; char * vpnt = value;
unsigned int ivalue; unsigned int ivalue;
ivalue = 0; ivalue = 0;
...@@ -112,8 +125,18 @@ static int parse_options(char *options,char *map,char *conversion, char * rock, ...@@ -112,8 +125,18 @@ static int parse_options(char *options,char *map,char *conversion, char * rock,
vpnt++; vpnt++;
}; };
if (*vpnt) return 0; if (*vpnt) return 0;
switch(*this_char) {
case 'b':
if (ivalue != 1024 && ivalue != 2048) return 0; if (ivalue != 1024 && ivalue != 2048) return 0;
*blocksize = ivalue; popt->blocksize = ivalue;
break;
case 'g':
popt->uid = ivalue;
break;
case 'u':
popt->gid = ivalue;
break;
}
} }
else return 0; else return 0;
} }
...@@ -125,7 +148,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -125,7 +148,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
{ {
struct buffer_head *bh; struct buffer_head *bh;
int iso_blknum; int iso_blknum;
unsigned int blocksize, blocksize_bits; unsigned int blocksize_bits;
int high_sierra; int high_sierra;
int dev=s->s_dev; int dev=s->s_dev;
struct iso_volume_descriptor *vdp; struct iso_volume_descriptor *vdp;
...@@ -136,29 +159,39 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -136,29 +159,39 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
struct iso_directory_record *rootp; struct iso_directory_record *rootp;
char map, conversion, rock, cruft; struct iso9660_options opt;
if (!parse_options((char *) data,&map,&conversion, &rock, &cruft, &blocksize)) { if (!parse_options((char *) data,&opt)) {
s->s_dev = 0; s->s_dev = 0;
return NULL; return NULL;
} }
#if 0
printk("map = %c\n", opt.map);
printk("rock = %c\n", opt.rock);
printk("cruft = %c\n", opt.cruft);
printk("conversion = %c\n", opt.conversion);
printk("blocksize = %d\n", opt.blocksize);
printk("gid = %d\n", opt.gid);
printk("uid = %d\n", opt.uid);
#endif
blocksize_bits = 0; blocksize_bits = 0;
{ {
int i = blocksize; int i = opt.blocksize;
while (i != 1){ while (i != 1){
blocksize_bits++; blocksize_bits++;
i >>=1; i >>=1;
}; };
}; };
set_blocksize(dev, blocksize); set_blocksize(dev, opt.blocksize);
lock_super(s); lock_super(s);
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */ s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) { for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), blocksize))) { if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
s->s_dev=0; s->s_dev=0;
printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n", printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
dev, iso_blknum); dev, iso_blknum);
...@@ -178,7 +211,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -178,7 +211,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->u.isofs_sb.s_high_sierra = 1; s->u.isofs_sb.s_high_sierra = 1;
high_sierra = 1; high_sierra = 1;
rock = 'n'; opt.rock = 'n';
h_pri = (struct hs_primary_descriptor *)vdp; h_pri = (struct hs_primary_descriptor *)vdp;
break; break;
}; };
...@@ -235,7 +268,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -235,7 +268,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
to allow suid. (suid or devices will not show up unless we have to allow suid. (suid or devices will not show up unless we have
Rock Ridge extensions) */ Rock Ridge extensions) */
s->s_flags = MS_RDONLY /* | MS_NODEV | MS_NOSUID */; s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) { if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
printk("1 <<Block bits != Block size\n"); printk("1 <<Block bits != Block size\n");
...@@ -256,11 +289,13 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -256,11 +289,13 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->s_dev = dev; s->s_dev = dev;
s->s_op = &isofs_sops; s->s_op = &isofs_sops;
s->u.isofs_sb.s_mapping = map; s->u.isofs_sb.s_mapping = opt.map;
s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0); s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
s->u.isofs_sb.s_conversion = conversion; s->u.isofs_sb.s_conversion = opt.conversion;
s->u.isofs_sb.s_cruft = cruft; s->u.isofs_sb.s_cruft = opt.cruft;
s->s_blocksize = blocksize; s->u.isofs_sb.s_uid = opt.uid;
s->u.isofs_sb.s_gid = opt.gid;
s->s_blocksize = opt.blocksize;
s->s_blocksize_bits = blocksize_bits; s->s_blocksize_bits = blocksize_bits;
s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS); s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
unlock_super(s); unlock_super(s);
...@@ -389,8 +424,8 @@ void isofs_read_inode(struct inode * inode) ...@@ -389,8 +424,8 @@ void isofs_read_inode(struct inode * inode)
if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
inode->i_mode |= S_IXUGO; /* execute permission */ inode->i_mode |= S_IXUGO; /* execute permission */
} }
inode->i_uid = 0; inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
inode->i_gid = 0; inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
inode->i_size = isonum_733 (raw_inode->size); inode->i_size = isonum_733 (raw_inode->size);
/* There are defective discs out there - we do this to protect /* There are defective discs out there - we do this to protect
...@@ -416,15 +451,6 @@ void isofs_read_inode(struct inode * inode) ...@@ -416,15 +451,6 @@ void isofs_read_inode(struct inode * inode)
inode->i_size = 0; inode->i_size = 0;
} }
#ifdef DEBUG
/* I have no idea what extended attributes are used for, so
we will flag it for now */
if(raw_inode->ext_attr_length[0] != 0){
printk("Extended attributes present for ISO file (%ld).\n",
inode->i_ino);
}
#endif
/* I have no idea what file_unit_size is used for, so /* I have no idea what file_unit_size is used for, so
we will flag it for now */ we will flag it for now */
if(raw_inode->file_unit_size[0] != 0){ if(raw_inode->file_unit_size[0] != 0){
...@@ -446,7 +472,9 @@ void isofs_read_inode(struct inode * inode) ...@@ -446,7 +472,9 @@ void isofs_read_inode(struct inode * inode)
inode->i_mtime = inode->i_atime = inode->i_ctime = inode->i_mtime = inode->i_atime = inode->i_ctime =
iso_date(raw_inode->date, high_sierra); iso_date(raw_inode->date, high_sierra);
inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) << inode->u.isofs_i.i_first_extent =
(isonum_733 (raw_inode->extent) +
isonum_711 (raw_inode->ext_attr_length)) <<
(ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode)); (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode));
inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */ inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
......
...@@ -73,6 +73,7 @@ int nfs_mmap(struct inode * inode, struct file * file, ...@@ -73,6 +73,7 @@ int nfs_mmap(struct inode * inode, struct file * file,
mpnt->vm_start = addr; mpnt->vm_start = addr;
mpnt->vm_end = addr + len; mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot; mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = inode; mpnt->vm_inode = inode;
inode->i_count++; inode->i_count++;
......
/* /*
* linux/fs/binfmt_elf.c * linux/fs/binfmt_elf.c
*
* These are the functions used to load ELF format executables as used
* on SVr4 machines. Information on the format may be found in the book
* "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
* Tools".
*
* Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -14,6 +21,7 @@ ...@@ -14,6 +21,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/personality.h>
#include <asm/segment.h> #include <asm/segment.h>
...@@ -139,7 +147,7 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex, ...@@ -139,7 +147,7 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
if((interp_elf_ex->e_type != ET_EXEC && if((interp_elf_ex->e_type != ET_EXEC &&
interp_elf_ex->e_type != ET_DYN) || interp_elf_ex->e_type != ET_DYN) ||
(interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) || (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
(!interpreter_inode->i_op || !interpreter_inode->i_op->bmap || (!interpreter_inode->i_op ||
!interpreter_inode->i_op->default_file_ops->mmap)){ !interpreter_inode->i_op->default_file_ops->mmap)){
return 0xffffffff; return 0xffffffff;
}; };
...@@ -251,7 +259,7 @@ static unsigned int load_aout_interp(struct exec * interp_ex, ...@@ -251,7 +259,7 @@ static unsigned int load_aout_interp(struct exec * interp_ex,
#define INTERPRETER_AOUT 1 #define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2 #define INTERPRETER_ELF 2
int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{ {
struct elfhdr elf_ex; struct elfhdr elf_ex;
struct elfhdr interp_elf_ex; struct elfhdr interp_elf_ex;
...@@ -496,8 +504,17 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -496,8 +504,17 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(elf_phdata); kfree(elf_phdata);
if(!elf_interpreter) sys_close(elf_exec_fileno); if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno);
current->elf_executable = 1;
/* The following 3 lines need a little bit of work if we are loading
an iBCS2 binary. We should initially load it this way, and if
we get a lcall7, then we should look to see if the iBCS2 execution
profile is present. If it is, then switch to that, otherwise
bomb. */
current->personality = PER_LINUX;
current->lcall7 = no_lcall7;
current->signal_map = current->signal_invmap = ident_map;
current->executable = bprm->inode; current->executable = bprm->inode;
bprm->inode->i_count++; bprm->inode->i_count++;
#ifdef LOW_ELF_STACK #ifdef LOW_ELF_STACK
...@@ -545,7 +562,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -545,7 +562,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* This is really simpleminded and specialized - we are loading an /* This is really simpleminded and specialized - we are loading an
a.out library that is given an ELF header. */ a.out library that is given an ELF header. */
int load_elf_library(int fd){ static int load_elf_library(int fd){
struct file * file; struct file * file;
struct elfhdr elf_ex; struct elfhdr elf_ex;
struct elf_phdr *elf_phdata = NULL; struct elf_phdr *elf_phdata = NULL;
...@@ -576,7 +593,7 @@ int load_elf_library(int fd){ ...@@ -576,7 +593,7 @@ int load_elf_library(int fd){
/* First of all, some simple consistency checks */ /* First of all, some simple consistency checks */
if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
(elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
(!inode->i_op || !inode->i_op->bmap || (!inode->i_op ||
!inode->i_op->default_file_ops->mmap)){ !inode->i_op->default_file_ops->mmap)){
return -ENOEXEC; return -ENOEXEC;
}; };
...@@ -634,3 +651,5 @@ int load_elf_library(int fd){ ...@@ -634,3 +651,5 @@ int load_elf_library(int fd){
kfree(elf_phdata); kfree(elf_phdata);
return 0; return 0;
} }
struct linux_binfmt elf_format = { NULL, load_elf_binary, load_elf_library };
...@@ -30,8 +30,10 @@ struct linux_binprm{ ...@@ -30,8 +30,10 @@ struct linux_binprm{
*/ */
struct linux_binfmt { struct linux_binfmt {
struct linux_binfmt * next; struct linux_binfmt * next;
int *use_count;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(int fd); int (*load_shlib)(int fd);
int (*core_dump)(long signr, struct pt_regs * regs);
}; };
extern int register_binfmt(struct linux_binfmt *); extern int register_binfmt(struct linux_binfmt *);
......
...@@ -135,6 +135,7 @@ ...@@ -135,6 +135,7 @@
#define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03) #define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03)
#define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04) #define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04)
#define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08) #define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08)
#define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10)
#define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6) #define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6)
#define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01) #define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01)
#define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02) #define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02)
......
...@@ -60,7 +60,7 @@ struct ifaddr { ...@@ -60,7 +60,7 @@ struct ifaddr {
/* /*
* Device mapping structure. I'd just gone off and designed a * Device mapping structure. I'd just gone off and designed a
* beautiful scheme using only loadable modules with arguments * beautiful scheme using only loadable modules with arguments
* for driver options and along come the PCMICA people 8) * for driver options and along come the PCMCIA people 8)
* *
* Ah well. The get() side of this is good for WDSETUP, and it'll * Ah well. The get() side of this is good for WDSETUP, and it'll
* be handy for debugging things. The set side is fine for now and * be handy for debugging things. The set side is fine for now and
......
/*
* NET3 PLIP tuning facilities for the new Niibe PLIP.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#ifndef _LINUX_IF_PLIP_H
#define _LINUX_IF_PLIP_H
#include <linux/sockios.h>
#define SIOCDEVPLIP SIOCDEVPRIVATE
struct plipconf
{
unsigned short pcmd;
unsigned long nibble;
unsigned long trigger;
};
#define PLIP_GET_TIMEOUT 0x1
#define PLIP_SET_TIMEOUT 0x2
#endif
...@@ -18,6 +18,10 @@ struct isofs_sb_info { ...@@ -18,6 +18,10 @@ struct isofs_sb_info {
unsigned char s_cruft; /* Broken disks with high unsigned char s_cruft; /* Broken disks with high
byte of length containing byte of length containing
junk */ junk */
unsigned char s_nosuid;
unsigned char s_nodev;
gid_t s_gid;
uid_t s_uid;
}; };
#endif #endif
......
...@@ -19,6 +19,7 @@ struct modify_ldt_ldt_s { ...@@ -19,6 +19,7 @@ struct modify_ldt_ldt_s {
unsigned int contents:2; unsigned int contents:2;
unsigned int read_exec_only:1; unsigned int read_exec_only:1;
unsigned int limit_in_pages:1; unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
}; };
#define MODIFY_LDT_CONTENTS_DATA 0 #define MODIFY_LDT_CONTENTS_DATA 0
......
...@@ -9,18 +9,7 @@ ...@@ -9,18 +9,7 @@
#define VERIFY_READ 0 #define VERIFY_READ 0
#define VERIFY_WRITE 1 #define VERIFY_WRITE 1
int __verify_write(unsigned long addr, unsigned long count); extern int verify_area(int, const void *, unsigned long);
extern inline int verify_area(int type, const void * addr, unsigned long size)
{
if (TASK_SIZE <= (unsigned long) addr)
return -EFAULT;
if (size > TASK_SIZE - (unsigned long) addr)
return -EFAULT;
if (wp_works_ok || type == VERIFY_READ || !size)
return 0;
return __verify_write((unsigned long) addr,size);
}
/* /*
* Linux kernel virtual memory manager primitives. * Linux kernel virtual memory manager primitives.
...@@ -42,6 +31,7 @@ struct vm_area_struct { ...@@ -42,6 +31,7 @@ struct vm_area_struct {
unsigned long vm_start; unsigned long vm_start;
unsigned long vm_end; unsigned long vm_end;
unsigned short vm_page_prot; unsigned short vm_page_prot;
unsigned short vm_flags;
struct vm_area_struct * vm_next; /* linked list */ struct vm_area_struct * vm_next; /* linked list */
struct vm_area_struct * vm_share; /* linked list */ struct vm_area_struct * vm_share; /* linked list */
struct inode * vm_inode; struct inode * vm_inode;
...@@ -49,6 +39,12 @@ struct vm_area_struct { ...@@ -49,6 +39,12 @@ struct vm_area_struct {
struct vm_operations_struct * vm_ops; struct vm_operations_struct * vm_ops;
}; };
/*
* vm_flags..
*/
#define VM_GROWSDOWN 0x01
#define VM_GROWSUP 0x02
/* /*
* These are the virtual MM functions - opening of an area, closing it (needed to * These are the virtual MM functions - opening of an area, closing it (needed to
* keep files on disk up-to-date etc), pointer to the functions called when a * keep files on disk up-to-date etc), pointer to the functions called when a
......
...@@ -22,14 +22,6 @@ ...@@ -22,14 +22,6 @@
#define NFS_READDIR_CACHE_SIZE 64 #define NFS_READDIR_CACHE_SIZE 64
/*
* WARNING! The I/O buffer size cannot be bigger than about 3900 for now.
* It needs to fit inside a 4096-byte page and leave room for the RPC and
* NFS headers. But it ought to at least be a multiple of 512 and probably
* should be a power of 2. I don't think Linux TCP/IP can handle more than
* about 1800 yet.
*/
#define NFS_MAX_FILE_IO_BUFFER_SIZE (7*512) #define NFS_MAX_FILE_IO_BUFFER_SIZE (7*512)
#define NFS_DEF_FILE_IO_BUFFER_SIZE 1024 #define NFS_DEF_FILE_IO_BUFFER_SIZE 1024
......
#ifndef _PERSONALITY_H
#define _PERSONALITY_H
#include <linux/linkage.h>
#include <linux/ptrace.h>
/* Flags for bug emulation. These occupy the top three bytes. */ /* Flags for bug emulation. These occupy the top three bytes. */
#define STICKY_TIMEOUTS 0x8000000 #define STICKY_TIMEOUTS 0x4000000
#define WHOLE_SECONDS 0x4000000 #define WHOLE_SECONDS 0x2000000
/* Personality types. These go in the low byte. */ /* Personality types. These go in the low byte. Avoid using the top bit,
* it will conflict with error returns.
*/
#define PER_MASK (0x00ff) #define PER_MASK (0x00ff)
#define PER_LINUX (0x0000) #define PER_LINUX (0x0000)
#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) #define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
...@@ -10,3 +19,33 @@ ...@@ -10,3 +19,33 @@
#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) #define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) #define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) #define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
#define PER_BSD (0x0006)
/* Prototype for an lcall7 syscall handler. */
typedef asmlinkage void (*lcall7_func)(struct pt_regs *);
/* Description of an execution domain - personality range supported,
* lcall7 syscall handler, start up / shut down functions etc.
* N.B. The name and lcall7 handler must be where they are since the
* offset of the handler is hard coded in kernel/sys_call.S.
*/
struct exec_domain {
char *name;
lcall7_func handler;
unsigned char pers_low, pers_high;
unsigned long * signal_map;
unsigned long * signal_invmap;
int *use_count;
struct exec_domain *next;
};
extern struct exec_domain default_exec_domain;
extern struct exec_domain *lookup_exec_domain(unsigned long personality);
extern int register_exec_domain(struct exec_domain *it);
extern int unregister_exec_domain(struct exec_domain *it);
extern asmlinkage int sys_personality(unsigned long personality);
#endif /* _PERSONALITY_H */
...@@ -36,6 +36,8 @@ __asm__ __volatile__("decl _intr_count") ...@@ -36,6 +36,8 @@ __asm__ __volatile__("decl _intr_count")
extern int EISA_bus; extern int EISA_bus;
#define MCA_bus 0 #define MCA_bus 0
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/tasks.h> #include <linux/tasks.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -228,7 +230,6 @@ struct mm_struct { ...@@ -228,7 +230,6 @@ struct mm_struct {
short swap_page; /* current page */ short swap_page; /* current page */
#endif NEW_SWAP #endif NEW_SWAP
struct vm_area_struct * mmap; struct vm_area_struct * mmap;
struct vm_area_struct * stk_vma;
}; };
#define INIT_MM { \ #define INIT_MM { \
...@@ -240,7 +241,7 @@ struct mm_struct { ...@@ -240,7 +241,7 @@ struct mm_struct {
/* ?_flt */ 0, 0, 0, 0, \ /* ?_flt */ 0, 0, 0, 0, \
0, \ 0, \
/* swap */ 0, 0, 0, 0, 0, \ /* swap */ 0, 0, 0, 0, 0, \
NULL, NULL } NULL }
struct task_struct { struct task_struct {
/* these are hardcoded - don't touch */ /* these are hardcoded - don't touch */
...@@ -252,12 +253,11 @@ struct task_struct { ...@@ -252,12 +253,11 @@ struct task_struct {
unsigned long flags; /* per process flags, defined below */ unsigned long flags; /* per process flags, defined below */
int errno; int errno;
int debugreg[8]; /* Hardware debugging registers */ int debugreg[8]; /* Hardware debugging registers */
asmlinkage void (*lcall7)(struct pt_regs *); struct exec_domain *exec_domain;
/* various fields */ /* various fields */
struct linux_binfmt *binfmt;
struct task_struct *next_task, *prev_task; struct task_struct *next_task, *prev_task;
struct sigaction sigaction[32]; struct sigaction sigaction[32];
unsigned long * signal_map;
unsigned long * signal_invmap;
unsigned long saved_kernel_stack; unsigned long saved_kernel_stack;
unsigned long kernel_stack_page; unsigned long kernel_stack_page;
int exit_code, exit_signal; int exit_code, exit_signal;
...@@ -326,9 +326,10 @@ struct task_struct { ...@@ -326,9 +326,10 @@ struct task_struct {
#define INIT_TASK \ #define INIT_TASK \
/* state etc */ { 0,15,15,0,0,0,0, \ /* state etc */ { 0,15,15,0,0,0,0, \
/* debugregs */ { 0, }, \ /* debugregs */ { 0, }, \
/* lcall 7 */ no_lcall7, \ /* exec domain */&default_exec_domain, \
/* binfmt */ NULL, \
/* schedlink */ &init_task,&init_task, \ /* schedlink */ &init_task,&init_task, \
/* signals */ {{ 0, },}, ident_map, ident_map, \ /* signals */ {{ 0, },}, \
/* stack */ 0,(unsigned long) &init_kernel_stack, \ /* stack */ 0,(unsigned long) &init_kernel_stack, \
/* ec,brk... */ 0,0,0,0,0, \ /* ec,brk... */ 0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \
...@@ -361,9 +362,6 @@ extern unsigned long itimer_next; ...@@ -361,9 +362,6 @@ extern unsigned long itimer_next;
extern struct timeval xtime; extern struct timeval xtime;
extern int need_resched; extern int need_resched;
extern unsigned long ident_map[33];
extern asmlinkage void no_lcall7(struct pt_regs *);
#define CURRENT_TIME (xtime.tv_sec) #define CURRENT_TIME (xtime.tv_sec)
extern void sleep_on(struct wait_queue ** p); extern void sleep_on(struct wait_queue ** p);
......
...@@ -108,11 +108,11 @@ extern void skb_append(struct sk_buff *old,struct sk_buff *newsk); ...@@ -108,11 +108,11 @@ extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_unlink(struct sk_buff *buf); extern void skb_unlink(struct sk_buff *buf);
extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list); extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
extern struct sk_buff * alloc_skb(unsigned int size, int priority); extern struct sk_buff * alloc_skb(unsigned int size, int priority);
extern void kfree_skbmem(void *mem, unsigned size); extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
extern void skb_kept_by_device(struct sk_buff *skb); extern void skb_device_lock(struct sk_buff *skb);
extern void skb_device_release(struct sk_buff *skb, extern void skb_device_unlock(struct sk_buff *skb);
int mode); extern void dev_kfree_skb(struct sk_buff *skb, int mode);
extern int skb_device_locked(struct sk_buff *skb); extern int skb_device_locked(struct sk_buff *skb);
/* /*
* Peek an sk_buff. Unlike most other operations you _MUST_ * Peek an sk_buff. Unlike most other operations you _MUST_
......
...@@ -33,12 +33,15 @@ struct linger { ...@@ -33,12 +33,15 @@ struct linger {
#define AF_AX25 3 #define AF_AX25 3
#define AF_IPX 4 #define AF_IPX 4
#define AF_MAX 8 /* For now.. */
/* Protocol families, same as address families. */ /* Protocol families, same as address families. */
#define PF_UNIX AF_UNIX #define PF_UNIX AF_UNIX
#define PF_INET AF_INET #define PF_INET AF_INET
#define PF_AX25 AF_AX25 #define PF_AX25 AF_AX25
#define PF_IPX AF_IPX #define PF_IPX AF_IPX
#define PF_MAX AF_MAX
/* Flags we can use with send/ and recv. */ /* Flags we can use with send/ and recv. */
#define MSG_OOB 1 #define MSG_OOB 1
#define MSG_PEEK 2 #define MSG_PEEK 2
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#define FIOGETOWN 0x8903 #define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904 #define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905 #define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8096 /* Get stamp */ #define SIOCGSTAMP 0x8906 /* Get stamp */
/* Routing table calls. */ /* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */ #define SIOCADDRT 0x890B /* add routing table entry */
......
#ifndef _LINUX_UN_H #ifndef _LINUX_UN_H
#define _LINUX_UN_H #define _LINUX_UN_H
#define UNIX_PATH_MAX 108
struct sockaddr_un { struct sockaddr_un {
unsigned short sun_family; /* AF_UNIX */ unsigned short sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */ char sun_path[UNIX_PATH_MAX]; /* pathname */
}; };
#endif /* _LINUX_UN_H */ #endif /* _LINUX_UN_H */
...@@ -142,6 +142,7 @@ ...@@ -142,6 +142,7 @@
#define __NR_fchdir 133 #define __NR_fchdir 133
#define __NR_bdflush 134 #define __NR_bdflush 134
#define __NR_sysfs 135 #define __NR_sysfs 135
#define __NR_personality 136
extern int errno; extern int errno;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
.c.o: .c.o:
$(CC) $(CFLAGS) -c $< $(CC) $(CFLAGS) -c $<
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \ OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o exec_domain.o \
panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \ panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \
signal.o ptrace.o ioport.o itimer.o \ signal.o ptrace.o ioport.o itimer.o \
info.o ldt.o time.o tqueue.o vm86.o info.o ldt.o time.o tqueue.o vm86.o
......
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/sched.h>
static asmlinkage void no_lcall7(struct pt_regs * regs);
static unsigned long ident_map[32] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31
};
struct exec_domain default_exec_domain = {
"Linux", /* name */
no_lcall7, /* lcall7 causes a seg fault. */
0, 0xff, /* All personalities. */
ident_map, /* Identiy map signals. */
ident_map, /* - both ways. */
NULL, /* No usage counter. */
NULL /* Nothing after this in the list. */
};
static struct exec_domain *exec_domains = &default_exec_domain;
static asmlinkage void no_lcall7(struct pt_regs * regs)
{
send_sig(SIGSEGV, current, 1);
}
struct exec_domain *lookup_exec_domain(unsigned long personality)
{
unsigned long pers = personality & PER_MASK;
struct exec_domain *it;
for (it=exec_domains; it; it=it->next)
if (pers >= it->pers_low
&& pers <= it->pers_high)
return it;
/* Should never get this far. */
printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
return NULL;
}
int register_exec_domain(struct exec_domain *it)
{
struct exec_domain *tmp;
if (!it)
return -EINVAL;
if (it->next)
return -EBUSY;
for (tmp=exec_domains; tmp; tmp=tmp->next)
if (tmp == it)
return -EBUSY;
it->next = exec_domains;
exec_domains = it;
return 0;
}
int unregister_exec_domain(struct exec_domain *it)
{
struct exec_domain ** tmp;
tmp = &exec_domains;
while (*tmp) {
if (it == *tmp) {
*tmp = it->next;
it->next = NULL;
return 0;
}
tmp = &(*tmp)->next;
}
return -EINVAL;
}
asmlinkage int sys_personality(unsigned long personality)
{
struct exec_domain *it;
unsigned long old_personality;
if (personality == 0xffffffff)
return current->personality;
it = lookup_exec_domain(personality);
if (!it)
return -EINVAL;
old_personality = current->personality;
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
current->personality = personality;
current->exec_domain = it;
if (current->exec_domain->use_count)
(*current->exec_domain->use_count)++;
return old_personality;
}
...@@ -483,6 +483,10 @@ NORET_TYPE void do_exit(long code) ...@@ -483,6 +483,10 @@ NORET_TYPE void do_exit(long code)
#ifdef DEBUG_PROC_TREE #ifdef DEBUG_PROC_TREE
audit_ptree(); audit_ptree();
#endif #endif
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
schedule(); schedule();
/* /*
* In order to get rid of the "volatile function does return" message * In order to get rid of the "volatile function does return" message
......
...@@ -94,7 +94,6 @@ static int dup_mmap(struct task_struct * tsk) ...@@ -94,7 +94,6 @@ static int dup_mmap(struct task_struct * tsk)
struct vm_area_struct * mpnt, **p, *tmp; struct vm_area_struct * mpnt, **p, *tmp;
tsk->mm->mmap = NULL; tsk->mm->mmap = NULL;
tsk->mm->stk_vma = NULL;
p = &tsk->mm->mmap; p = &tsk->mm->mmap;
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
tmp = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL); tmp = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
...@@ -107,8 +106,6 @@ static int dup_mmap(struct task_struct * tsk) ...@@ -107,8 +106,6 @@ static int dup_mmap(struct task_struct * tsk)
tmp->vm_inode->i_count++; tmp->vm_inode->i_count++;
*p = tmp; *p = tmp;
p = &tmp->vm_next; p = &tmp->vm_next;
if (current->mm->stk_vma == mpnt)
tsk->mm->stk_vma = tmp;
} }
return 0; return 0;
} }
...@@ -184,6 +181,12 @@ asmlinkage int sys_fork(struct pt_regs regs) ...@@ -184,6 +181,12 @@ asmlinkage int sys_fork(struct pt_regs regs)
goto bad_fork_free; goto bad_fork_free;
task[nr] = p; task[nr] = p;
*p = *current; *p = *current;
if (p->exec_domain && p->exec_domain->use_count)
(*p->exec_domain->use_count)++;
if (p->binfmt && p->binfmt->use_count)
(*p->binfmt->use_count)++;
p->did_exec = 0; p->did_exec = 0;
p->kernel_stack_page = 0; p->kernel_stack_page = 0;
p->state = TASK_UNINTERRUPTIBLE; p->state = TASK_UNINTERRUPTIBLE;
......
...@@ -306,7 +306,7 @@ void free_irq(unsigned int irq) ...@@ -306,7 +306,7 @@ void free_irq(unsigned int irq)
static void math_error_irq(int cpl) static void math_error_irq(int cpl)
{ {
outb(0,0xF0); outb(0,0xF0);
if (ignore_irq13) if (ignore_irq13 || !hard_math)
return; return;
math_error(); math_error();
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/personality.h>
#ifdef CONFIG_INET #ifdef CONFIG_INET
#include <linux/netdevice.h> #include <linux/netdevice.h>
#endif #endif
...@@ -61,7 +62,7 @@ struct { ...@@ -61,7 +62,7 @@ struct {
X(wp_works_ok), X(wp_works_ok),
/* process memory management */ /* process memory management */
X(__verify_write), X(verify_area),
X(do_mmap), X(do_mmap),
X(do_munmap), X(do_munmap),
X(insert_vm_struct), X(insert_vm_struct),
...@@ -97,6 +98,11 @@ struct { ...@@ -97,6 +98,11 @@ struct {
X(register_binfmt), X(register_binfmt),
X(unregister_binfmt), X(unregister_binfmt),
/* execution environment registration */
X(lookup_exec_domain),
X(register_exec_domain),
X(unregister_exec_domain),
/* interrupt handling */ /* interrupt handling */
X(request_irq), X(request_irq),
X(free_irq), X(free_irq),
......
...@@ -58,8 +58,10 @@ static int write_ldt(void * ptr, unsigned long bytecount) ...@@ -58,8 +58,10 @@ static int write_ldt(void * ptr, unsigned long bytecount)
limit *= PAGE_SIZE; limit *= PAGE_SIZE;
limit += base; limit += base;
#ifdef NOTDEF_KLUDGE
if (limit < base || limit >= 0xC0000000) if (limit < base || limit >= 0xC0000000)
return -EINVAL; return -EINVAL;
#endif
if (!current->ldt) { if (!current->ldt) {
for (i=1 ; i<NR_TASKS ; i++) { for (i=1 ; i<NR_TASKS ; i++) {
...@@ -88,7 +90,8 @@ static int write_ldt(void * ptr, unsigned long bytecount) ...@@ -88,7 +90,8 @@ static int write_ldt(void * ptr, unsigned long bytecount)
((ldt_info.read_exec_only ^ 1) << 9) | ((ldt_info.read_exec_only ^ 1) << 9) |
(ldt_info.seg_32bit << 22) | (ldt_info.seg_32bit << 22) |
(ldt_info.limit_in_pages << 23) | (ldt_info.limit_in_pages << 23) |
0xf000; ((ldt_info.seg_not_present ^1) << 15) |
0x7000;
return 0; return 0;
} }
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
extern int core_dump(long signr,struct pt_regs * regs);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs); asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset) asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
...@@ -246,7 +244,10 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon ...@@ -246,7 +244,10 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon
do_exit(SIGSEGV); do_exit(SIGSEGV);
/* set up the "normal" stack seen by the signal handler (iBCS2) */ /* set up the "normal" stack seen by the signal handler (iBCS2) */
put_fs_long(__CODE,frame); put_fs_long(__CODE,frame);
put_fs_long(current->signal_invmap[signr], frame+1); if (current->exec_domain && current->exec_domain->signal_invmap)
put_fs_long(current->exec_domain->signal_invmap[signr], frame+1);
else
put_fs_long(signr, frame+1);
put_fs_long(regs->gs, frame+2); put_fs_long(regs->gs, frame+2);
put_fs_long(regs->fs, frame+3); put_fs_long(regs->fs, frame+3);
put_fs_long(regs->es, frame+4); put_fs_long(regs->es, frame+4);
...@@ -348,8 +349,10 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) ...@@ -348,8 +349,10 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
case SIGQUIT: case SIGILL: case SIGTRAP: case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV: case SIGIOT: case SIGFPE: case SIGSEGV:
if (core_dump(signr,regs)) if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80; signr |= 0x80;
}
/* fall through */ /* fall through */
default: default:
current->signal |= _S(signr & 0x7f); current->signal |= _S(signr & 0x7f);
......
...@@ -39,6 +39,9 @@ asmlinkage int sys_idle(void) ...@@ -39,6 +39,9 @@ asmlinkage int sys_idle(void)
{ {
int i; int i;
if (current->pid != 0)
return -EPERM;
/* Map out the low memory: it's no longer needed */ /* Map out the low memory: it's no longer needed */
for (i = 0 ; i < 768 ; i++) for (i = 0 ; i < 768 ; i++)
swapper_pg_dir[i] = 0; swapper_pg_dir[i] = 0;
......
...@@ -78,7 +78,7 @@ flags = 20 ...@@ -78,7 +78,7 @@ flags = 20
errno = 24 errno = 24
dbgreg6 = 52 dbgreg6 = 52
dbgreg7 = 56 dbgreg7 = 56
lcall7 = 60 exec_domain = 60
ENOSYS = 38 ENOSYS = 38
...@@ -144,7 +144,8 @@ _lcall7: ...@@ -144,7 +144,8 @@ _lcall7:
movl %esp,%eax movl %esp,%eax
movl _current,%edx movl _current,%edx
pushl %eax pushl %eax
movl lcall7(%edx),%edx movl exec_domain(%edx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
call *%edx call *%edx
popl %eax popl %eax
jmp ret_from_sys_call jmp ret_from_sys_call
...@@ -535,5 +536,6 @@ _sys_call_table: ...@@ -535,5 +536,6 @@ _sys_call_table:
.long _sys_fchdir .long _sys_fchdir
.long _sys_bdflush .long _sys_bdflush
.long _sys_sysfs /* 135 */ .long _sys_sysfs /* 135 */
.long _sys_personality
.space (NR_syscalls-135)*4 .space (NR_syscalls-136)*4
...@@ -40,7 +40,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -40,7 +40,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
} }
#define get_seg_byte(seg,addr) ({ \ #define get_seg_byte(seg,addr) ({ \
register char __res; \ register unsigned char __res; \
__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \ :"=a" (__res):"0" (seg),"m" (*(addr))); \
__res;}) __res;})
...@@ -123,21 +123,30 @@ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current) ...@@ -123,21 +123,30 @@ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
DO_ERROR(11, SIGSEGV, "segment not present", segment_not_present, current) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGSEGV, "stack segment", stack_segment, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
DO_ERROR(15, SIGSEGV, "reserved", reserved, current) DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{ {
int signr = SIGSEGV;
if (regs->eflags & VM_MASK) { if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct vm86_regs *) regs, error_code); handle_vm86_fault((struct vm86_regs *) regs, error_code);
return; return;
} }
die_if_kernel("general protection",regs,error_code);
switch (get_seg_byte(regs->cs, (char *)regs->eip)) {
case 0xCD: /* INT */
case 0xF4: /* HLT */
case 0xFA: /* CLI */
case 0xFB: /* STI */
signr = SIGILL;
}
current->tss.error_code = error_code; current->tss.error_code = error_code;
current->tss.trap_no = 13; current->tss.trap_no = 13;
send_sig(SIGSEGV, current, 1); send_sig(signr, current, 1);
die_if_kernel("general protection",regs,error_code);
} }
asmlinkage void do_nmi(struct pt_regs * regs, long error_code) asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
......
...@@ -59,6 +59,7 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ ...@@ -59,6 +59,7 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */
extern void sound_mem_init(void); extern void sound_mem_init(void);
extern void die_if_kernel(char *,struct pt_regs *,long); extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
/* /*
* The free_area_list arrays point to the queue heads of the free areas * The free_area_list arrays point to the queue heads of the free areas
...@@ -78,11 +79,11 @@ unsigned short * mem_map = NULL; ...@@ -78,11 +79,11 @@ unsigned short * mem_map = NULL;
/* /*
* oom() prints a message (so that the user knows why the process died), * oom() prints a message (so that the user knows why the process died),
* and gives the process an untrappable SIGSEGV. * and gives the process an untrappable SIGKILL.
*/ */
void oom(struct task_struct * task) void oom(struct task_struct * task)
{ {
printk("\nout of memory\n"); printk("\nOut of memory.\n");
task->sigaction[SIGKILL-1].sa_handler = NULL; task->sigaction[SIGKILL-1].sa_handler = NULL;
task->blocked &= ~(1<<(SIGKILL-1)); task->blocked &= ~(1<<(SIGKILL-1));
send_sig(SIGKILL,task,1); send_sig(SIGKILL,task,1);
...@@ -660,7 +661,7 @@ void do_wp_page(unsigned long error_code, unsigned long address, ...@@ -660,7 +661,7 @@ void do_wp_page(unsigned long error_code, unsigned long address,
*pg_table = 0; *pg_table = 0;
} }
int __verify_write(unsigned long start, unsigned long size) static int __verify_write(unsigned long start, unsigned long size)
{ {
size--; size--;
size += start & ~PAGE_MASK; size += start & ~PAGE_MASK;
...@@ -673,6 +674,38 @@ int __verify_write(unsigned long start, unsigned long size) ...@@ -673,6 +674,38 @@ int __verify_write(unsigned long start, unsigned long size)
return 0; return 0;
} }
int verify_area(int type, const void * addr, unsigned long size)
{
struct vm_area_struct * vma;
for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
if (!vma)
goto bad_area;
if (vma->vm_end > (unsigned long) addr)
break;
}
if (vma->vm_start <= (unsigned long) addr)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
if (vma->vm_end - (unsigned long) addr > current->rlim[RLIMIT_STACK].rlim_cur)
goto bad_area;
good_area:
while (vma->vm_end - (unsigned long) addr < size) {
struct vm_area_struct * next = vma->vm_next;
if (!next)
goto bad_area;
if (vma->vm_end != next->vm_start)
goto bad_area;
vma = next;
}
if (wp_works_ok || type == VERIFY_READ || !size)
return 0;
return __verify_write((unsigned long) addr,size);
bad_area:
return -EFAULT;
}
static inline void get_empty_page(struct task_struct * tsk, unsigned long address) static inline void get_empty_page(struct task_struct * tsk, unsigned long address)
{ {
unsigned long tmp; unsigned long tmp;
...@@ -843,8 +876,8 @@ void do_no_page(unsigned long error_code, unsigned long address, ...@@ -843,8 +876,8 @@ void do_no_page(unsigned long error_code, unsigned long address,
tmp = *(unsigned long *) page; tmp = *(unsigned long *) page;
if (tmp & PAGE_PRESENT) if (tmp & PAGE_PRESENT)
return; return;
++tsk->mm->rss;
if (tmp) { if (tmp) {
++tsk->mm->rss;
++tsk->mm->maj_flt; ++tsk->mm->maj_flt;
swap_in((unsigned long *) page); swap_in((unsigned long *) page);
return; return;
...@@ -859,10 +892,12 @@ void do_no_page(unsigned long error_code, unsigned long address, ...@@ -859,10 +892,12 @@ void do_no_page(unsigned long error_code, unsigned long address,
continue; continue;
} }
if (!mpnt->vm_ops || !mpnt->vm_ops->nopage) { if (!mpnt->vm_ops || !mpnt->vm_ops->nopage) {
++tsk->mm->rss;
++tsk->mm->min_flt; ++tsk->mm->min_flt;
get_empty_page(tsk,address); get_empty_page(tsk,address);
return; return;
} }
++tsk->mm->rss;
mpnt->vm_ops->nopage(error_code, mpnt, address); mpnt->vm_ops->nopage(error_code, mpnt, address);
return; return;
} }
...@@ -870,7 +905,7 @@ void do_no_page(unsigned long error_code, unsigned long address, ...@@ -870,7 +905,7 @@ void do_no_page(unsigned long error_code, unsigned long address,
goto ok_no_page; goto ok_no_page;
if (address >= tsk->mm->end_data && address < tsk->mm->brk) if (address >= tsk->mm->end_data && address < tsk->mm->brk)
goto ok_no_page; goto ok_no_page;
if (mpnt && mpnt == tsk->mm->stk_vma && if (mpnt && (mpnt->vm_flags & VM_GROWSDOWN) &&
address - tmp > mpnt->vm_start - address && address - tmp > mpnt->vm_start - address &&
tsk->rlim[RLIMIT_STACK].rlim_cur > mpnt->vm_end - address) { tsk->rlim[RLIMIT_STACK].rlim_cur > mpnt->vm_end - address) {
mpnt->vm_start = address; mpnt->vm_start = address;
...@@ -883,6 +918,7 @@ void do_no_page(unsigned long error_code, unsigned long address, ...@@ -883,6 +918,7 @@ void do_no_page(unsigned long error_code, unsigned long address,
if (error_code & 4) /* user level access? */ if (error_code & 4) /* user level access? */
return; return;
ok_no_page: ok_no_page:
++tsk->mm->rss;
++tsk->mm->min_flt; ++tsk->mm->min_flt;
get_empty_page(tsk,address); get_empty_page(tsk,address);
} }
...@@ -1021,6 +1057,7 @@ void show_mem(void) ...@@ -1021,6 +1057,7 @@ void show_mem(void)
printk("%d reserved pages\n",reserved); printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared); printk("%d pages shared\n",shared);
show_buffers(); show_buffers();
show_net_buffers();
} }
extern unsigned long free_area_init(unsigned long, unsigned long); extern unsigned long free_area_init(unsigned long, unsigned long);
......
...@@ -340,6 +340,7 @@ int generic_mmap(struct inode * inode, struct file * file, ...@@ -340,6 +340,7 @@ int generic_mmap(struct inode * inode, struct file * file,
mpnt->vm_start = addr; mpnt->vm_start = addr;
mpnt->vm_end = addr + len; mpnt->vm_end = addr + len;
mpnt->vm_page_prot = prot; mpnt->vm_page_prot = prot;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = inode; mpnt->vm_inode = inode;
inode->i_count++; inode->i_count++;
...@@ -459,6 +460,7 @@ static int anon_map(struct inode *ino, struct file * file, ...@@ -459,6 +460,7 @@ static int anon_map(struct inode *ino, struct file * file,
mpnt->vm_start = addr; mpnt->vm_start = addr;
mpnt->vm_end = addr + len; mpnt->vm_end = addr + len;
mpnt->vm_page_prot = mask; mpnt->vm_page_prot = mask;
mpnt->vm_flags = 0;
mpnt->vm_share = NULL; mpnt->vm_share = NULL;
mpnt->vm_inode = NULL; mpnt->vm_inode = NULL;
mpnt->vm_offset = 0; mpnt->vm_offset = 0;
......
This is snapshot 014 This is snapshot 015
Changes for the 015 snapshot
o All read/write buffers are validated at the top level _only_
o All address structures are moved to and from user mode at the top
level. Thus you can now issue proto->bind(....) calls and related
functions such as connect from another kernel task. All thats left
to fix now is a kernel alloc_socket()/free_socket() and accompanying
proto->make_kernel(socket)
o Small fixes to address behaviour caused by the above
o Max NFS size of 16K bytes
o Added the apricot driver as a test (#'ed out in config.in)
o Fixed a missing function definition in net_init.c
o Added G4KLX ax25_router code
o Added Niibe's PLIP driver and altered it to support timer
configuration and IRQ/port setting. Added if_plip.h. Comments and
feedback appreciated on this (both to Niibe and me).
o Added AF_MAX/PF_MAX defines
o Added a note that the DE600 driver also works for a noname 'PE1200'.
o Network buffer statistics on shift-scroll_lock
o Fixed a serious race in the device driver code. This was causing odd
crashes with the Lance drivers, lockups with the ne2000 cards and
a few other 'bad' goings on. All drivers are effected. See
README.DEV if porting a driver to this revision.
If you see entries in your 'free while locked' count, those would
typically have crashed a pre 1.20 kernel.
o TCP keeps the timers above 0.2sec round-trip time because of the use of
delayed ACK's by BSD style kernels.
o Fixed a small BSD error in the return from datagram socket
recv/recvfrom() calls when data is truncated. BSD returns the true
length of the message, Linux returned the amount copied which broke
programs that did a MSG_PEEK with a small buffer and grew it if need
be (some of the AV/RTP stuff notably).
o Added TIOCINQ/OUTQ to AX.25 and IPX.
o Added driver ioctl() calls to IPX.
o Corrected the skb->len==0 in the tcp_data reset on shutdown to check
skb->copied_seq.
o IP options reflect onto SO_PRIORITY.
o When a driver is downed its ARP entries are flushed. Should solve
the occasional crash when taking out a modular driver.
o Added Donald's multicast reception while promiscuous fix for the
8390 drivers.
o Potential ARP TCP-retransmit clear race fixed. Incredibly
unlikely to occur but no doubt it will 8(.
To Do
o Fast path the tcp for packets in order with no flags set - we ought
to hit cable speed on slower machines if we fix that and the below.
(under test - define TCP_FASTPATH in tcp.c if you want to be brave
and report any findings.)
o Include the HP onboard lance fixes.
o Fix Unix domain sockets.
o Fix the _SLOW_ TCP window calculation junk in tcp_data/tcp_ack.
o Make the dev_add_proto() list hashed by protocol type.
o Remove the call to dev->header_type - load it into the skbuff.
instead to avoid the extra calls and cache misses.
o Include new sk_buff skb_push() code and move toward using it.
o Fix the PI driver so pi0a can be down when pi0b is up without getting
crashes. Also fix the stuff to allow piconfig to set the parameters.
o Make AX.25 set the packet type - certainly before it hits IP.
o sk_buff building at the top level - pure kernel interfaces to the
protocol layers
o Clean up NFS, merge NFS/TCP code.
o SIGIO
o IP forwarding use of options properly (needs new sk_buff code)
o Reroute TCP retransmits if needed (needs new sk_buffs)
Fixes added for 1.1.19
o Unix domain bind error code.
o skb->localroute starts cleared.
o Compiles with networking disabled
Fixes added for 1.1.18
o Dummy driver includes correctly.
o PPP fixes from A.L.
o ifslave fixes
o Small error causing nfsd to coredump fixed by Linus.
Fixes added for 1.1.17 Fixes added for 1.1.17
...@@ -10,10 +93,12 @@ o Module fixes by Bj0rn. ...@@ -10,10 +93,12 @@ o Module fixes by Bj0rn.
o PLIP fix by Tanabe. o PLIP fix by Tanabe.
Fixes added for 1.1.16 Fixes added for 1.1.16
o Charles Hedricks fixes to TCP. o Charles Hedricks fixes to TCP.
o Small fixes all over the place. o Small fixes all over the place.
Fixes added for 1.1.15 Fixes added for 1.1.15
o Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's o Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's
(sort of). (sort of).
o Integrated new AX.25 - this will be ready for the big time in a few o Integrated new AX.25 - this will be ready for the big time in a few
......
...@@ -379,7 +379,9 @@ static int inet_setsockopt(struct socket *sock, int level, int optname, ...@@ -379,7 +379,9 @@ static int inet_setsockopt(struct socket *sock, int level, int optname,
return sk->prot->setsockopt(sk,level,optname,optval,optlen); return sk->prot->setsockopt(sk,level,optname,optval,optlen);
} }
/*
* Get a socket option on an AF_INET socket.
*/
static int inet_getsockopt(struct socket *sock, int level, int optname, static int inet_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen) char *optval, int *optlen)
...@@ -393,6 +395,9 @@ static int inet_getsockopt(struct socket *sock, int level, int optname, ...@@ -393,6 +395,9 @@ static int inet_getsockopt(struct socket *sock, int level, int optname,
return sk->prot->getsockopt(sk,level,optname,optval,optlen); return sk->prot->getsockopt(sk,level,optname,optval,optlen);
} }
/*
* Automatically bind an unbound socket.
*/
static int inet_autobind(struct sock *sk) static int inet_autobind(struct sock *sk)
{ {
...@@ -408,6 +413,10 @@ static int inet_autobind(struct sock *sk) ...@@ -408,6 +413,10 @@ static int inet_autobind(struct sock *sk)
return 0; return 0;
} }
/*
* Move a socket into listening state.
*/
static int inet_listen(struct socket *sock, int backlog) static int inet_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = (struct sock *) sock->data; struct sock *sk = (struct sock *) sock->data;
...@@ -728,10 +737,9 @@ static int inet_release(struct socket *sock, struct socket *peer) ...@@ -728,10 +737,9 @@ static int inet_release(struct socket *sock, struct socket *peer)
static int inet_bind(struct socket *sock, struct sockaddr *uaddr, static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
int addr_len) int addr_len)
{ {
struct sockaddr_in addr; struct sockaddr_in *addr=(struct sockaddr_in *)uaddr;
struct sock *sk=(struct sock *)sock->data, *sk2; struct sock *sk=(struct sock *)sock->data, *sk2;
unsigned short snum; unsigned short snum;
int err;
int chk_addr_ret; int chk_addr_ret;
/* check this error. */ /* check this error. */
...@@ -740,12 +748,10 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, ...@@ -740,12 +748,10 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
if (sk->num != 0) if (sk->num != 0)
return(-EINVAL); return(-EINVAL);
err=verify_area(VERIFY_READ, uaddr, addr_len); if(addr_len<sizeof(struct sockaddr_in))
if(err) return -EINVAL;
return err;
memcpy_fromfs(&addr, uaddr, min(sizeof(addr), addr_len));
snum = ntohs(addr.sin_port); snum = ntohs(addr->sin_port);
/* /*
* We can't just leave the socket bound wherever it is, it might * We can't just leave the socket bound wherever it is, it might
...@@ -759,12 +765,12 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, ...@@ -759,12 +765,12 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
if (snum < PROT_SOCK && !suser()) if (snum < PROT_SOCK && !suser())
return(-EACCES); return(-EACCES);
chk_addr_ret = ip_chk_addr(addr.sin_addr.s_addr); chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
if (addr.sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR) if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR)
return(-EADDRNOTAVAIL); /* Source address MUST be ours! */ return(-EADDRNOTAVAIL); /* Source address MUST be ours! */
if (chk_addr_ret || addr.sin_addr.s_addr == 0) if (chk_addr_ret || addr->sin_addr.s_addr == 0)
sk->saddr = addr.sin_addr.s_addr; sk->saddr = addr->sin_addr.s_addr;
/* Make sure we are allowed to bind here. */ /* Make sure we are allowed to bind here. */
cli(); cli();
...@@ -841,7 +847,7 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr, ...@@ -841,7 +847,7 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
} }
if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK)) if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK))
return -EALREADY; /* Connecting is currently in progress */ return -EINPROGRESS; /* Connecting is currently in progress */
if (sock->state != SS_CONNECTING) if (sock->state != SS_CONNECTING)
{ {
...@@ -985,46 +991,27 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -985,46 +991,27 @@ static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
static int inet_getname(struct socket *sock, struct sockaddr *uaddr, static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer) int *uaddr_len, int peer)
{ {
struct sockaddr_in sin; struct sockaddr_in *sin=(struct sockaddr_in *)uaddr;
struct sock *sk; struct sock *sk;
int len;
int err;
err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long));
if(err)
return err;
len=get_fs_long(uaddr_len);
err = verify_area(VERIFY_WRITE, uaddr, len);
if(err)
return err;
/* Check this error. */
if (len < sizeof(sin))
return(-EINVAL);
sin.sin_family = AF_INET; sin->sin_family = AF_INET;
sk = (struct sock *) sock->data; sk = (struct sock *) sock->data;
if (peer) if (peer)
{ {
if (!tcp_connected(sk->state)) if (!tcp_connected(sk->state))
return(-ENOTCONN); return(-ENOTCONN);
sin.sin_port = sk->dummy_th.dest; sin->sin_port = sk->dummy_th.dest;
sin.sin_addr.s_addr = sk->daddr; sin->sin_addr.s_addr = sk->daddr;
} }
else else
{ {
sin.sin_port = sk->dummy_th.source; sin->sin_port = sk->dummy_th.source;
if (sk->saddr == 0) if (sk->saddr == 0)
sin.sin_addr.s_addr = ip_my_addr(); sin->sin_addr.s_addr = ip_my_addr();
else else
sin.sin_addr.s_addr = sk->saddr; sin->sin_addr.s_addr = sk->saddr;
} }
len = sizeof(sin); *uaddr_len = sizeof(*sin);
memcpy_tofs(uaddr, &sin, sizeof(sin));
put_fs_long(len, uaddr_len);
return(0); return(0);
} }
...@@ -1033,40 +1020,46 @@ static int inet_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -1033,40 +1020,46 @@ static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
* The assorted BSD I/O operations * The assorted BSD I/O operations
*/ */
static int inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
static int inet_recv(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags, struct sockaddr *sin, int *addr_len )
unsigned flags)
{ {
struct sock *sk = (struct sock *) sock->data; struct sock *sk = (struct sock *) sock->data;
int err;
if (sk->prot->recvfrom == NULL)
return(-EOPNOTSUPP);
if(sk->err) if(sk->err)
return inet_error(sk); return inet_error(sk);
if(size<0)
return -EINVAL;
if(size==0)
return 0;
err=verify_area(VERIFY_WRITE,ubuf,size);
if(err)
return err;
/* We may need to bind the socket. */ /* We may need to bind the socket. */
if(inet_autobind(sk)) if(inet_autobind(sk)!=0)
return(-EAGAIN); return(-EAGAIN);
return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, flags)); return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags,
(struct sockaddr_in*)sin, addr_len));
} }
static int inet_recv(struct socket *sock, void *ubuf, int size, int noblock,
unsigned flags)
{
/* BSD explicitly states these are the same - so we do it this way to be sure */
return inet_recvfrom(sock,ubuf,size,noblock,flags,NULL,NULL);
}
static int inet_read(struct socket *sock, char *ubuf, int size, int noblock) static int inet_read(struct socket *sock, char *ubuf, int size, int noblock)
{ {
return inet_recv(sock,ubuf,size,noblock,0); struct sock *sk = (struct sock *) sock->data;
if(sk->err)
return inet_error(sk);
/* We may need to bind the socket. */
if(inet_autobind(sk))
return(-EAGAIN);
return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, 0));
} }
static int inet_send(struct socket *sock, void *ubuf, int size, int noblock, static int inet_send(struct socket *sock, void *ubuf, int size, int noblock,
unsigned flags) unsigned flags)
{ {
struct sock *sk = (struct sock *) sock->data; struct sock *sk = (struct sock *) sock->data;
int err;
if (sk->shutdown & SEND_SHUTDOWN) if (sk->shutdown & SEND_SHUTDOWN)
{ {
send_sig(SIGPIPE, current, 1); send_sig(SIGPIPE, current, 1);
...@@ -1074,13 +1067,6 @@ static int inet_send(struct socket *sock, void *ubuf, int size, int noblock, ...@@ -1074,13 +1067,6 @@ static int inet_send(struct socket *sock, void *ubuf, int size, int noblock,
} }
if(sk->err) if(sk->err)
return inet_error(sk); return inet_error(sk);
if(size<0)
return -EINVAL;
if(size==0)
return 0;
err=verify_area(VERIFY_READ,ubuf,size);
if(err)
return err;
/* We may need to bind the socket. */ /* We may need to bind the socket. */
if(inet_autobind(sk)!=0) if(inet_autobind(sk)!=0)
return(-EAGAIN); return(-EAGAIN);
...@@ -1095,7 +1081,6 @@ static int inet_write(struct socket *sock, char *ubuf, int size, int noblock) ...@@ -1095,7 +1081,6 @@ static int inet_write(struct socket *sock, char *ubuf, int size, int noblock)
static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock,
unsigned flags, struct sockaddr *sin, int addr_len) unsigned flags, struct sockaddr *sin, int addr_len)
{ {
int err;
struct sock *sk = (struct sock *) sock->data; struct sock *sk = (struct sock *) sock->data;
if (sk->shutdown & SEND_SHUTDOWN) if (sk->shutdown & SEND_SHUTDOWN)
{ {
...@@ -1106,16 +1091,7 @@ static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, ...@@ -1106,16 +1091,7 @@ static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock,
return(-EOPNOTSUPP); return(-EOPNOTSUPP);
if(sk->err) if(sk->err)
return inet_error(sk); return inet_error(sk);
if(size<0)
return -EINVAL;
if(size==0)
return 0;
err=verify_area(VERIFY_READ,ubuf,size);
if(err)
return err;
/* We may need to bind the socket. */ /* We may need to bind the socket. */
if(inet_autobind(sk)!=0) if(inet_autobind(sk)!=0)
return -EAGAIN; return -EAGAIN;
return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags, return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags,
...@@ -1123,32 +1099,6 @@ static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, ...@@ -1123,32 +1099,6 @@ static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock,
} }
static int inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
unsigned flags, struct sockaddr *sin, int *addr_len )
{
struct sock *sk = (struct sock *) sock->data;
int err;
if (sk->prot->recvfrom == NULL)
return(-EOPNOTSUPP);
if(sk->err)
return inet_error(sk);
if(size<0)
return -EINVAL;
if(size==0)
return 0;
err=verify_area(VERIFY_WRITE,ubuf,size);
if(err)
return err;
/* We may need to bind the socket. */
if(inet_autobind(sk)!=0)
return(-EAGAIN);
return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags,
(struct sockaddr_in*)sin, addr_len));
}
static int inet_shutdown(struct socket *sock, int how) static int inet_shutdown(struct socket *sock, int how)
{ {
struct sock *sk=(struct sock*)sock->data; struct sock *sk=(struct sock*)sock->data;
...@@ -1352,7 +1302,8 @@ void inet_proto_init(struct net_proto *pro) ...@@ -1352,7 +1302,8 @@ void inet_proto_init(struct net_proto *pro)
struct inet_protocol *p; struct inet_protocol *p;
int i; int i;
printk("Swansea University Computer Society NET3.014\n");
printk("NET3 TCP/IP protcols stack v016\n");
/* /*
* Tell SOCKET that we are alive... * Tell SOCKET that we are alive...
......
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
extern void arp_init(void); extern void arp_init(void);
extern void arp_destroy(unsigned long paddr, int force); extern void arp_destroy(unsigned long paddr, int force);
extern void arp_device_down(struct device *dev);
extern int arp_rcv(struct sk_buff *skb, struct device *dev, extern int arp_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt); struct packet_type *pt);
extern int arp_find(unsigned char *haddr, unsigned long paddr, extern int arp_find(unsigned char *haddr, unsigned long paddr,
......
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.
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