Commit 75bcc1d5 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.0

parent cd534a05
VERSION = 1 VERSION = 1
PATCHLEVEL = 0 PATCHLEVEL = 1
SUBLEVEL = 6 SUBLEVEL = 0
all: Version zImage all: Version zImage
...@@ -9,6 +9,7 @@ all: Version zImage ...@@ -9,6 +9,7 @@ all: Version zImage
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \ else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi) else echo sh; fi ; fi)
ROOT := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
# #
# Make "config" the default target if there is no configuration file or # Make "config" the default target if there is no configuration file or
...@@ -76,7 +77,7 @@ AS =as ...@@ -76,7 +77,7 @@ AS =as
LD =ld LD =ld
LDFLAGS =#-qmagic LDFLAGS =#-qmagic
HOSTCC =gcc HOSTCC =gcc
CC =gcc -D__KERNEL__ CC =gcc -D__KERNEL__ -I$(ROOT)/include
MAKE =make MAKE =make
CPP =$(CC) -E CPP =$(CC) -E
AR =ar AR =ar
......
...@@ -42,12 +42,9 @@ struct request { ...@@ -42,12 +42,9 @@ struct request {
* This is used in the elevator algorithm: Note that * This is used in the elevator algorithm: Note that
* reads always go before writes. This is natural: reads * reads always go before writes. This is natural: reads
* are much more time-critical than writes. * are much more time-critical than writes.
*
* Update: trying with writes being preferred due to test
* by Alessandro Rubini..
*/ */
#define IN_ORDER(s1,s2) \ #define IN_ORDER(s1,s2) \
((s1)->cmd > (s2)->cmd || ((s1)->cmd == (s2)->cmd && \ ((s1)->cmd < (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \ ((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \
(s1)->sector < (s2)->sector))))) (s1)->sector < (s2)->sector)))))
......
...@@ -476,9 +476,23 @@ printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF); ...@@ -476,9 +476,23 @@ printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
#endif #endif
return 0; return 0;
case CDROMEJECT: /* Eject the drive - N/A */ case CDROMEJECT:
/* all drives can atleast stop! */
if (audioStatus == CDROM_AUDIO_PLAY) {
outb(MCMD_STOP, MCDPORT(0));
i = getMcdStatus(MCD_STATUS_DELAY);
}
audioStatus = CDROM_AUDIO_NO_STATUS;
outb(MCMD_EJECT, MCDPORT(0));
/*
* the status (i) shows failure on all but the FX drives.
* But nothing we can do about that in software!
* So just read the status and forget it. - Jon.
*/
i = getMcdStatus(MCD_STATUS_DELAY);
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
......
/* /*
* This file contains the driver for an XT hard disk controller (at least the DTC 5150X) for Linux. * This file contains the driver for an XT hard disk controller
* (at least the DTC 5150X) for Linux.
* *
* Author: Pat Mackinlay, smackinla@cc.curtin.edu.au * Author: Pat Mackinlay, pat@it.com.au
* Date: 29/09/92 * Date: 29/09/92
* *
* Revised: 01/01/93, ... * Revised: 01/01/93, ...
* *
* Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, kevinf@agora.rain.com) * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler,
* Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and Wim Van Dorst. * kevinf@agora.rain.com)
* Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and
* Wim Van Dorst.
*
* Revised: 04/04/94 by Risto Kankkunen
* Moved the detection code from xd_init() to xd_geninit() as it needed
* interrupts enabled and Linus didn't want to enable them in that first
* phase. xd_geninit() is the place to do these kinds of things anyway,
* he says.
*/ */
...@@ -53,8 +62,8 @@ XD_INFO xd_info[XD_MAXDRIVES]; ...@@ -53,8 +62,8 @@ XD_INFO xd_info[XD_MAXDRIVES];
should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */ should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
static XD_SIGNATURE xd_sigs[] = { static XD_SIGNATURE xd_sigs[] = {
{ 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */ { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
{ 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */ { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
{ 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */ { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
{ 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */ { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */ { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
...@@ -70,21 +79,42 @@ static u_char *xd_bases[] = ...@@ -70,21 +79,42 @@ static u_char *xd_bases[] =
}; };
static struct hd_struct xd[XD_MAXDRIVES << 6]; static struct hd_struct xd[XD_MAXDRIVES << 6];
static int xd_sizes[XD_MAXDRIVES << 6],xd_access[XD_MAXDRIVES] = { 0,0 }; static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
static int xd_blocksizes[XD_MAXDRIVES << 6]; static int xd_blocksizes[XD_MAXDRIVES << 6];
static struct gendisk xd_gendisk = { MAJOR_NR,"xd",6,1 << 6,XD_MAXDRIVES,xd_geninit,xd,xd_sizes,0,(void *) xd_info,NULL }; static struct gendisk xd_gendisk = {
static struct file_operations xd_fops = { NULL,block_read,block_write,NULL,NULL,xd_ioctl,NULL,xd_open,xd_release,block_fsync }; MAJOR_NR, /* Major number */
"xd", /* Major name */
static struct wait_queue *xd_wait_int = NULL,*xd_wait_open = NULL; 6, /* Bits to shift to get real from partition */
1 << 6, /* Number of partitions per real */
XD_MAXDRIVES, /* maximum number of real */
xd_geninit, /* init function */
xd, /* hd struct */
xd_sizes, /* block sizes */
0, /* number */
(void *) xd_info, /* internal */
NULL /* next */
};
static struct file_operations xd_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
NULL, /* select */
xd_ioctl, /* ioctl */
NULL, /* mmap */
xd_open, /* open */
xd_release, /* release */
block_fsync /* fsync */
};
static struct wait_queue *xd_wait_int = NULL, *xd_wait_open = NULL;
static u_char xd_valid[XD_MAXDRIVES] = { 0,0 }; static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
static u_char xd_drives = 0,xd_irq = 0,xd_dma = 0,xd_maxsectors,xd_override = 0,xd_type = 0; static u_char xd_drives = 0, xd_irq = 0, xd_dma = 0, xd_maxsectors;
static u_char xd_override = 0, xd_type = 0;
static u_short xd_iobase = 0; static u_short xd_iobase = 0;
/* xd_init: grab the IRQ and DMA channel and initialise the drives */ /* xd_init: register the block device number and set up pointer tables */
u_long xd_init (u_long mem_start,u_long mem_end) u_long xd_init (u_long mem_start,u_long mem_end)
{ {
u_char i,controller,*address;
if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
printk("xd_init: unable to get major number %d\n",MAJOR_NR); printk("xd_init: unable to get major number %d\n",MAJOR_NR);
return (mem_start); return (mem_start);
...@@ -94,26 +124,6 @@ u_long xd_init (u_long mem_start,u_long mem_end) ...@@ -94,26 +124,6 @@ u_long xd_init (u_long mem_start,u_long mem_end)
xd_gendisk.next = gendisk_head; xd_gendisk.next = gendisk_head;
gendisk_head = &xd_gendisk; gendisk_head = &xd_gendisk;
if (xd_detect(&controller,&address)) {
printk("xd_init: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
if (controller)
xd_sigs[controller].init_controller(address);
xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
printk("xd_init: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
for (i = 0; i < xd_drives; i++)
printk("xd_init: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
if (!request_irq(xd_irq,xd_interrupt_handler)) {
if (request_dma(xd_dma)) {
printk("xd_init: unable to get DMA%d\n",xd_dma);
free_irq(xd_irq);
}
}
else
printk("xd_init: unable to get IRQ%d\n",xd_irq);
}
return mem_start; return mem_start;
} }
...@@ -139,10 +149,32 @@ static u_char xd_detect (u_char *controller,u_char **address) ...@@ -139,10 +149,32 @@ static u_char xd_detect (u_char *controller,u_char **address)
return (found); return (found);
} }
/* xd_geninit: set up the "raw" device entries in the table */ /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
/* and set up the "raw" device entries in the table */
static void xd_geninit (void) static void xd_geninit (void)
{ {
u_char i; u_char i,controller,*address;
if (xd_detect(&controller,&address)) {
printk("xd_geninit: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
if (controller)
xd_sigs[controller].init_controller(address);
xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
printk("xd_geninit: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
for (i = 0; i < xd_drives; i++)
printk("xd_geninit: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
if (!request_irq(xd_irq,xd_interrupt_handler)) {
if (request_dma(xd_dma)) {
printk("xd_geninit: unable to get DMA%d\n",xd_dma);
free_irq(xd_irq);
}
}
else
printk("xd_geninit: unable to get IRQ%d\n",xd_irq);
}
for (i = 0; i < xd_drives; i++) { for (i = 0; i < xd_drives; i++) {
xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors; xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
...@@ -188,10 +220,12 @@ static void do_xd_request (void) ...@@ -188,10 +220,12 @@ static void do_xd_request (void)
switch (CURRENT->cmd) { switch (CURRENT->cmd) {
case READ: case READ:
case WRITE: for (retry = 0; (retry < XD_RETRIES) && !code; retry++) case WRITE:
code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count); for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
break; code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
default: printk("do_xd_request: unknown request\n"); break; break;
default:
printk("do_xd_request: unknown request\n"); break;
} }
} }
end_request(code); /* wrap up, 0 = fail, 1 = success */ end_request(code); /* wrap up, 0 = fail, 1 = success */
...@@ -206,25 +240,27 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) ...@@ -206,25 +240,27 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
if (inode && (dev < xd_drives)) if (inode && (dev < xd_drives))
switch (cmd) { switch (cmd) {
case HDIO_GETGEO: if (arg) { case HDIO_GETGEO:
if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry)))) if (arg) {
return (err); if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads); return (err);
put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors); put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads);
put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders); put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors);
put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start); put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders);
put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start);
return (0);
} return (0);
break; }
case BLKGETSIZE: if (arg) { break;
if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)))) case BLKGETSIZE:
return (err); if (arg) {
put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg); if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
return (err);
return (0); put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
}
break; return (0);
}
break;
case BLKFLSBUF: case BLKFLSBUF:
if(!suser()) return -EACCES; if(!suser()) return -EACCES;
if(!inode->i_rdev) return -EINVAL; if(!inode->i_rdev) return -EINVAL;
...@@ -232,7 +268,8 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) ...@@ -232,7 +268,8 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
invalidate_buffers(inode->i_rdev); invalidate_buffers(inode->i_rdev);
return 0; return 0;
case BLKRRPART: return (xd_reread_partitions(inode->i_rdev)); case BLKRRPART:
return (xd_reread_partitions(inode->i_rdev));
RO_IOCTLS(inode->i_rdev,arg); RO_IOCTLS(inode->i_rdev,arg);
} }
return (-EINVAL); return (-EINVAL);
...@@ -303,8 +340,12 @@ static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block, ...@@ -303,8 +340,12 @@ static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,
xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control); xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) { switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) {
case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive); return (0); case 1:
case 2: switch ((sense[0] & 0x30) >> 4) { printk("xd_readwrite: timeout, recalibrating drive\n");
xd_recalibrate(drive);
return (0);
case 2:
switch ((sense[0] & 0x30) >> 4) {
case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break; case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break;
case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break; case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break;
case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break; case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break;
...@@ -412,28 +453,31 @@ static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outd ...@@ -412,28 +453,31 @@ static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outd
if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout)) if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
return (1); return (1);
switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) { switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
case 0: if (mode == DMA_MODE) { case 0:
enable_dma(xd_dma); if (mode == DMA_MODE) {
sleep_on(&xd_wait_int); enable_dma(xd_dma);
disable_dma(xd_dma); sleep_on(&xd_wait_int);
} disable_dma(xd_dma);
else } else
outb(outdata ? *outdata++ : 0,XD_DATA); outb(outdata ? *outdata++ : 0,XD_DATA);
break; break;
case STAT_INPUT: if (mode == DMA_MODE) { case STAT_INPUT:
enable_dma(xd_dma); if (mode == DMA_MODE) {
sleep_on(&xd_wait_int); enable_dma(xd_dma);
disable_dma(xd_dma); sleep_on(&xd_wait_int);
} disable_dma(xd_dma);
else } else
if (indata) if (indata)
*indata++ = inb(XD_DATA); *indata++ = inb(XD_DATA);
else else
inb(XD_DATA); inb(XD_DATA);
break; break;
case STAT_COMMAND: outb(command ? *command++ : 0,XD_DATA); break; case STAT_COMMAND:
case STAT_COMMAND outb(command ? *command++ : 0,XD_DATA);
| STAT_INPUT: complete = 1; break; break;
case STAT_COMMAND | STAT_INPUT:
complete = 1;
break;
} }
} }
csb = inb(XD_DATA); csb = inb(XD_DATA);
...@@ -460,7 +504,7 @@ static u_char xd_initdrives (void (*init_drive)(u_char drive)) ...@@ -460,7 +504,7 @@ static u_char xd_initdrives (void (*init_drive)(u_char drive))
for (i = 0; i < XD_MAXDRIVES; i++) { for (i = 0; i < XD_MAXDRIVES; i++) {
xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0); xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) { if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
init_drive(count); init_drive(count);
count++; count++;
} }
......
...@@ -39,6 +39,16 @@ extern __inline__ int clear_bit(int nr, void * addr) ...@@ -39,6 +39,16 @@ extern __inline__ int clear_bit(int nr, void * addr)
return oldbit; return oldbit;
} }
extern __inline__ int change_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"r" (nr));
return oldbit;
}
/* /*
* This routine doesn't need to be atomic, but it's faster to code it * This routine doesn't need to be atomic, but it's faster to code it
* this way. * this way.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
/* Structure defining a queue for a network interface. */ /* Structure defining a queue for a network interface. */
#ifdef not_yet_in_linux
struct ifnet { struct ifnet {
char *if_name; /* name, e.g. ``en'' or ``lo'' */ char *if_name; /* name, e.g. ``en'' or ``lo'' */
short if_unit; /* sub-unit for device driver */ short if_unit; /* sub-unit for device driver */
...@@ -33,13 +34,11 @@ struct ifnet { ...@@ -33,13 +34,11 @@ struct ifnet {
int if_metric; /* routing metric (not used) */ int if_metric; /* routing metric (not used) */
struct ifaddr *if_addrlist; /* linked list of addrs per if */ struct ifaddr *if_addrlist; /* linked list of addrs per if */
struct ifqueue { struct ifqueue {
#ifdef not_yet_in_linux
struct mbuf *ifq_head; struct mbuf *ifq_head;
struct mbuf *ifq_tail; struct mbuf *ifq_tail;
int ifq_len; int ifq_len;
int ifq_maxlen; int ifq_maxlen;
int ifq_drops; int ifq_drops;
#endif
} if_snd; /* output queue */ } if_snd; /* output queue */
/* Procedure handles. */ /* Procedure handles. */
...@@ -59,6 +58,7 @@ struct ifnet { ...@@ -59,6 +58,7 @@ struct ifnet {
/* Linked list: pointer to next interface. */ /* Linked list: pointer to next interface. */
struct ifnet *if_next; struct ifnet *if_next;
}; };
#endif
/* Standard interface flags. */ /* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */ #define IFF_UP 0x1 /* interface is up */
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define MCD_STATUS_DELAY 100 #define MCD_STATUS_DELAY 100
/* number of times to retry a command before giving up */ /* number of times to retry a command before giving up */
#define MCD_RETRY_ATTEMPTS 3 #define MCD_RETRY_ATTEMPTS 5
/* port access macro */ /* port access macro */
#define MCDPORT(x) (mcd_port + (x)) #define MCDPORT(x) (mcd_port + (x))
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#define MCMD_SET_VOLUME 0xAE /* set audio level */ #define MCMD_SET_VOLUME 0xAE /* set audio level */
#define MCMD_PLAY_READ 0xC0 /* play or read data */ #define MCMD_PLAY_READ 0xC0 /* play or read data */
#define MCMD_GET_VERSION 0xDC #define MCMD_GET_VERSION 0xDC
#define MCMD_EJECT 0xF6 /* eject (FX drive) */
/* borrowed from hd.c */ /* borrowed from hd.c */
......
...@@ -92,22 +92,31 @@ struct page_info { ...@@ -92,22 +92,31 @@ struct page_info {
}; };
/* end of planning stage */ /* end of planning stage */
extern volatile short free_page_ptr; /* used by malloc and tcp/ip. */ /*
* Free area management
*/
extern int nr_swap_pages; extern int nr_swap_pages;
extern int nr_free_pages; extern int nr_free_pages;
extern unsigned long free_page_list;
extern int nr_secondary_pages;
extern unsigned long secondary_page_list;
#define MAX_SECONDARY_PAGES 20 #define MAX_SECONDARY_PAGES 20
#define NR_MEM_LISTS 6
struct mem_list {
struct mem_list * next;
struct mem_list * prev;
};
extern struct mem_list free_area_list[NR_MEM_LISTS];
extern unsigned char * free_area_map[NR_MEM_LISTS];
/* /*
* This is timing-critical - most of the time in getting a new page * This is timing-critical - most of the time in getting a new page
* goes to clearing the page. If you want a page without the clearing * goes to clearing the page. If you want a page without the clearing
* overhead, just use __get_free_page() directly.. * overhead, just use __get_free_page() directly..
*/ */
extern unsigned long __get_free_page(int priority); #define __get_free_page(priority) __get_free_pages((priority),0)
extern unsigned long __get_free_pages(int priority, unsigned long gfporder);
extern inline unsigned long get_free_page(int priority) extern inline unsigned long get_free_page(int priority)
{ {
unsigned long page; unsigned long page;
...@@ -121,9 +130,12 @@ extern inline unsigned long get_free_page(int priority) ...@@ -121,9 +130,12 @@ extern inline unsigned long get_free_page(int priority)
return page; return page;
} }
/* memory.c */ /* memory.c & swap.c*/
#define free_page(addr) free_pages((addr),0)
extern void free_pages(unsigned long addr, unsigned long order);
extern void free_page(unsigned long addr); extern void show_free_areas(void);
extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page, extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
unsigned long address); unsigned long address);
extern void free_page_tables(struct task_struct * tsk); extern void free_page_tables(struct task_struct * tsk);
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
/* /*
* This string-include defines all string functions as inline * This string-include defines all string functions as inline
* functions. Use gcc. It also assumes ds=es=data space, this should be * functions. Use gcc. It also assumes ds=es=data space, this should be
...@@ -416,4 +420,8 @@ __asm__("cld\n\t" ...@@ -416,4 +420,8 @@ __asm__("cld\n\t"
return s; return s;
} }
#ifdef __cplusplus
}
#endif
#endif #endif
#ifndef _LINUX_SYS_H #ifndef _LINUX_SYS_H
#define _LINUX_SYS_H #define _LINUX_SYS_H
/* /*
* system call entry points * system call entry points ... but not all are defined
*/ */
#define NR_syscalls 256
#define sys_clone sys_fork /*
* These are system calls with the same entry-point
#ifdef __cplusplus */
extern "C" { #define _sys_clone _sys_fork
#endif
extern int sys_setup(); /* 0 */
extern int sys_exit();
extern int sys_fork();
extern int sys_read();
extern int sys_write();
extern int sys_open(); /* 5 */
extern int sys_close();
extern int sys_waitpid();
extern int sys_creat();
extern int sys_link();
extern int sys_unlink(); /* 10 */
extern int sys_execve();
extern int sys_chdir();
extern int sys_time();
extern int sys_mknod();
extern int sys_chmod(); /* 15 */
extern int sys_chown();
extern int sys_break();
extern int sys_stat();
extern int sys_lseek();
extern int sys_getpid(); /* 20 */
extern int sys_mount();
extern int sys_umount();
extern int sys_setuid();
extern int sys_getuid();
extern int sys_stime(); /* 25 */
extern int sys_ptrace();
extern int sys_alarm();
extern int sys_fstat();
extern int sys_pause();
extern int sys_utime(); /* 30 */
extern int sys_stty();
extern int sys_gtty();
extern int sys_access();
extern int sys_nice();
extern int sys_ftime(); /* 35 */
extern int sys_sync();
extern int sys_kill();
extern int sys_rename();
extern int sys_mkdir();
extern int sys_rmdir(); /* 40 */
extern int sys_dup();
extern int sys_pipe();
extern int sys_times();
extern int sys_prof();
extern int sys_brk(); /* 45 */
extern int sys_setgid();
extern int sys_getgid();
extern int sys_signal();
extern int sys_geteuid();
extern int sys_getegid(); /* 50 */
extern int sys_acct();
extern int sys_phys();
extern int sys_lock();
extern int sys_ioctl();
extern int sys_fcntl(); /* 55 */
extern int sys_mpx();
extern int sys_setpgid();
extern int sys_ulimit();
extern int sys_uname();
extern int sys_umask(); /* 60 */
extern int sys_chroot();
extern int sys_ustat();
extern int sys_dup2();
extern int sys_getppid();
extern int sys_getpgrp(); /* 65 */
extern int sys_setsid();
extern int sys_sigaction();
extern int sys_sgetmask();
extern int sys_ssetmask();
extern int sys_setreuid(); /* 70 */
extern int sys_setregid();
extern int sys_sigpending();
extern int sys_sigsuspend();
extern int sys_sethostname();
extern int sys_setrlimit(); /* 75 */
extern int sys_getrlimit();
extern int sys_getrusage();
extern int sys_gettimeofday();
extern int sys_settimeofday();
extern int sys_getgroups(); /* 80 */
extern int sys_setgroups();
extern int sys_select();
extern int sys_symlink();
extern int sys_lstat();
extern int sys_readlink(); /* 85 */
extern int sys_uselib();
extern int sys_swapon();
extern int sys_reboot();
extern int sys_readdir();
extern int sys_mmap(); /* 90 */
extern int sys_munmap();
extern int sys_truncate();
extern int sys_ftruncate();
extern int sys_fchmod();
extern int sys_fchown(); /* 95 */
extern int sys_getpriority();
extern int sys_setpriority();
extern int sys_profil();
extern int sys_statfs();
extern int sys_fstatfs(); /* 100 */
extern int sys_ioperm();
extern int sys_socketcall();
extern int sys_syslog();
extern int sys_getitimer();
extern int sys_setitimer(); /* 105 */
extern int sys_newstat();
extern int sys_newlstat();
extern int sys_newfstat();
extern int sys_newuname();
extern int sys_iopl(); /* 110 */
extern int sys_vhangup();
extern int sys_idle();
extern int sys_vm86();
extern int sys_wait4();
extern int sys_swapoff(); /* 115 */
extern int sys_sysinfo();
extern int sys_ipc();
extern int sys_fsync();
extern int sys_sigreturn();
extern int sys_setdomainname(); /* 120 */
extern int sys_olduname();
extern int sys_old_syscall();
extern int sys_modify_ldt();
extern int sys_adjtimex();
extern int sys_mprotect(); /* 125 */
extern int sys_sigprocmask();
extern int sys_create_module();
extern int sys_init_module();
extern int sys_delete_module();
extern int sys_get_kernel_syms(); /* 130 */
extern int sys_quotactl();
extern int sys_getpgid();
extern int sys_fchdir();
extern int sys_bdflush();
/* /*
* These are system calls that will be removed at some time * These are system calls that will be removed at some time
* due to newer versions existing.. * due to newer versions existing..
*/ */
#ifdef notdef #ifdef notdef
#define sys_waitpid sys_old_syscall /* sys_wait4 */ #define _sys_waitpid _sys_old_syscall /* _sys_wait4 */
#define sys_olduname sys_old_syscall /* sys_newuname */ #define _sys_olduname _sys_old_syscall /* _sys_newuname */
#define sys_uname sys_old_syscall /* sys_newuname */ #define _sys_uname _sys_old_syscall /* _sys_newuname */
#define sys_stat sys_old_syscall /* sys_newstat */ #define _sys_stat _sys_old_syscall /* _sys_newstat */
#define sys_fstat sys_old_syscall /* sys_newfstat */ #define _sys_fstat _sys_old_syscall /* _sys_newfstat */
#define sys_lstat sys_old_syscall /* sys_newlstat */ #define _sys_lstat _sys_old_syscall /* _sys_newlstat */
#define sys_signal sys_old_syscall /* sys_sigaction */ #define _sys_signal _sys_old_syscall /* _sys_sigaction */
#define sys_sgetmask sys_old_syscall /* sys_sigprocmask */ #define _sys_sgetmask _sys_old_syscall /* _sys_sigprocmask */
#define sys_ssetmask sys_old_syscall /* sig_sigprocmask */ #define _sys_ssetmask _sys_old_syscall /* _sys_sigprocmask */
#endif #endif
/* /*
* These are system calls that haven't been implemented yet * These are system calls that haven't been implemented yet
* but have an entry in the table for future expansion.. * but have an entry in the table for future expansion..
*/ */
#define _sys_quotactl _sys_ni_syscall
#define sys_quotactl sys_ni_syscall #define _sys_bdflush _sys_ni_syscall
#define sys_bdflush sys_ni_syscall
typedef int (*fn_ptr)();
#ifdef __cplusplus
}
#endif
#endif #endif
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* /*
* This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X). * This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X).
* *
* Author: Pat Mackinlay, smackinla@cc.curtin.edu.au * Author: Pat Mackinlay, pat@it.com.au
* Date: 29/09/92 * Date: 29/09/92
* *
* Revised: 01/01/93, ... * Revised: 01/01/93, ...
......
...@@ -78,7 +78,6 @@ extern void floppy_init(void); ...@@ -78,7 +78,6 @@ extern void floppy_init(void);
extern void sock_init(void); extern void sock_init(void);
extern long rd_init(long mem_start, int length); extern long rd_init(long mem_start, int length);
unsigned long net_dev_init(unsigned long, unsigned long); unsigned long net_dev_init(unsigned long, unsigned long);
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern void hd_setup(char *str, int *ints); extern void hd_setup(char *str, int *ints);
extern void bmouse_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints);
...@@ -267,7 +266,7 @@ static void parse_options(char *line) ...@@ -267,7 +266,7 @@ static void parse_options(char *line)
{ {
char *next; char *next;
char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
int devnums[] = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xC00, 0xC40, 0}; int devnums[] = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
int args, envs; int args, envs;
if (!*line) if (!*line)
......
...@@ -34,14 +34,6 @@ sys_call.o: sys_call.s ...@@ -34,14 +34,6 @@ sys_call.o: sys_call.s
sched.o: sched.c sched.o: sched.c
$(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $< $(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $<
ksyms.lst: ksyms.S ../include/linux/autoconf.h
$(CPP) $(CFLAGS) $< > $@
ksyms.s: ksyms.sh ksyms.lst
sh $< > $@
ksyms.o: ksyms.s
dep: dep:
$(CPP) -M *.c > .depend $(CPP) -M *.c > .depend
......
#include <linux/autoconf.h>
/*
* Herein lies all the functions/variables that are "exported" for linkage
* With dynamically loaded kernel modules. Could do with making this a bit
* cleaner!
*
* Jon.
*/
_register_chrdev
_unregister_chrdev
_register_blkdev
_unregister_blkdev
_wake_up_interruptible
_wp_works_ok
___verify_write
_current
_jiffies
_printk
_schedule
#ifdef CONFIG_FTAPE
#
# The next labels are needed for ftape driver.
#
_ftape_big_buffer
_do_floppy
#endif
/*
* Herein lies all the functions/variables that are "exported" for linkage
* with dynamically loaded kernel modules.
* Jon.
*/
#include <linux/autoconf.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#define X(name) { (void *) &name, #name }
struct {
void *addr;
const char *name;
} symbol_table[] = {
X(register_chrdev),
X(unregister_chrdev),
X(register_blkdev),
X(unregister_blkdev),
X(wake_up_interruptible),
X(wp_works_ok),
X(__verify_write),
X(current),
X(jiffies),
X(printk),
X(schedule),
#ifdef CONFIG_FTAPE
/* The next labels are needed for ftape driver. */
X(ftape_big_buffer),
X(do_floppy),
#endif
};
int symbol_table_size = sizeof (symbol_table) / sizeof (symbol_table[0]);
# This program will construct ksyms.s. Ksyms.s contains a symbol table
# for all the kernel symbols included in the file ksyms.lst. The following
# variables are defined in ksym.s:
#
# int symbol_table_size; /* number of symbols */
# struct {
# void *value; /* value of symbol */
# char *name; /* name of symbol */
# } symbol_table[];
#
#
trap "rm -f ksyms.tmp ksyms.lst ; exit 1" 1 2
sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort > ksyms.tmp
echo ' .data
.globl _symbol_table_size, _symbol_table
_symbol_table_size:'
echo " .long" `wc -l < ksyms.tmp`
echo '
_symbol_table:'
awk 'BEGIN {stringloc = 0}
{print " .long " $1; print " .long strings+" stringloc; \
stringloc += length($1) + 1;}' ksyms.tmp
echo '
strings:'
awk '{print " .ascii \"" $1 "\\0\""}' ksyms.tmp
rm -f ksyms.tmp
#
# Alternativly, if the kernel is c++ compiled:
# By using gsub() we can forse all function names to appear as extern "C".
# This allows linkable drivers written in C or C++ - Jon
# awk '{gsub(/__F.*/, "") ; print " .ascii \"" $0 "\\0\""}' ksyms.tmp
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/sys.h>
#include <linux/fdreg.h> #include <linux/fdreg.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/time.h> #include <linux/time.h>
...@@ -102,55 +101,7 @@ struct { ...@@ -102,55 +101,7 @@ struct {
short b; short b;
} stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS }; } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
struct kernel_stat kstat = struct kernel_stat kstat = { 0 };
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*
* int 0x80 entry points.. Moved away from the header file, as
* iBCS2 may also want to use the '<linux/sys.h>' headers..
*/
#ifdef __cplusplus
extern "C" {
#endif
int sys_ni_syscall(void)
{
return -EINVAL;
}
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_olduname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_truncate,
sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
sys_newfstat, sys_uname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
sys_getpgid, sys_fchdir, sys_bdflush };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
#ifdef __cplusplus
}
#endif
/* /*
* 'math_state_restore()' saves the current math information in the * 'math_state_restore()' saves the current math information in the
......
...@@ -30,6 +30,11 @@ extern void adjust_clock(void); ...@@ -30,6 +30,11 @@ extern void adjust_clock(void);
#define PZERO 15 #define PZERO 15
asmlinkage int sys_ni_syscall(void)
{
return -EINVAL;
}
static int proc_sel(struct task_struct *p, int which, int who) static int proc_sel(struct task_struct *p, int which, int who)
{ {
switch (which) { switch (which) {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
*/ */
#include <linux/segment.h> #include <linux/segment.h>
#include <linux/sys.h>
EBX = 0x00 EBX = 0x00
ECX = 0x04 ECX = 0x04
...@@ -87,7 +88,7 @@ ENOSYS = 38 ...@@ -87,7 +88,7 @@ ENOSYS = 38
.globl _invalid_TSS,_segment_not_present,_stack_segment .globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_reserved .globl _general_protection,_reserved
.globl _alignment_check,_page_fault .globl _alignment_check,_page_fault
.globl ret_from_sys_call .globl ret_from_sys_call, _sys_call_table
#define SAVE_ALL \ #define SAVE_ALL \
cld; \ cld; \
...@@ -163,8 +164,11 @@ _system_call: ...@@ -163,8 +164,11 @@ _system_call:
pushl %eax # save orig_eax pushl %eax # save orig_eax
SAVE_ALL SAVE_ALL
movl $-ENOSYS,EAX(%esp) movl $-ENOSYS,EAX(%esp)
cmpl _NR_syscalls,%eax cmpl $(NR_syscalls),%eax
jae ret_from_sys_call jae ret_from_sys_call
movl _sys_call_table(,%eax,4),%eax
testl %eax,%eax
je ret_from_sys_call
movl _current,%ebx movl _current,%ebx
andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
movl $0,errno(%ebx) movl $0,errno(%ebx)
...@@ -172,7 +176,7 @@ _system_call: ...@@ -172,7 +176,7 @@ _system_call:
movl %edx,dbgreg6(%ebx) # save current hardware debugging status movl %edx,dbgreg6(%ebx) # save current hardware debugging status
testb $0x20,flags(%ebx) # PF_TRACESYS testb $0x20,flags(%ebx) # PF_TRACESYS
jne 1f jne 1f
call _sys_call_table(,%eax,4) call *%eax
movl %eax,EAX(%esp) # save the return value movl %eax,EAX(%esp) # save the return value
movl errno(%ebx),%edx movl errno(%ebx),%edx
negl %edx negl %edx
...@@ -388,3 +392,144 @@ _alignment_check: ...@@ -388,3 +392,144 @@ _alignment_check:
_page_fault: _page_fault:
pushl $_do_page_fault pushl $_do_page_fault
jmp error_code jmp error_code
.data
.align 4
_sys_call_table:
.long _sys_setup /* 0 */
.long _sys_exit
.long _sys_fork
.long _sys_read
.long _sys_write
.long _sys_open /* 5 */
.long _sys_close
.long _sys_waitpid
.long _sys_creat
.long _sys_link
.long _sys_unlink /* 10 */
.long _sys_execve
.long _sys_chdir
.long _sys_time
.long _sys_mknod
.long _sys_chmod /* 15 */
.long _sys_chown
.long _sys_break
.long _sys_stat
.long _sys_lseek
.long _sys_getpid /* 20 */
.long _sys_mount
.long _sys_umount
.long _sys_setuid
.long _sys_getuid
.long _sys_stime /* 25 */
.long _sys_ptrace
.long _sys_alarm
.long _sys_fstat
.long _sys_pause
.long _sys_utime /* 30 */
.long _sys_stty
.long _sys_gtty
.long _sys_access
.long _sys_nice
.long _sys_ftime /* 35 */
.long _sys_sync
.long _sys_kill
.long _sys_rename
.long _sys_mkdir
.long _sys_rmdir /* 40 */
.long _sys_dup
.long _sys_pipe
.long _sys_times
.long _sys_prof
.long _sys_brk /* 45 */
.long _sys_setgid
.long _sys_getgid
.long _sys_signal
.long _sys_geteuid
.long _sys_getegid /* 50 */
.long _sys_acct
.long _sys_phys
.long _sys_lock
.long _sys_ioctl
.long _sys_fcntl /* 55 */
.long _sys_mpx
.long _sys_setpgid
.long _sys_ulimit
.long _sys_olduname
.long _sys_umask /* 60 */
.long _sys_chroot
.long _sys_ustat
.long _sys_dup2
.long _sys_getppid
.long _sys_getpgrp /* 65 */
.long _sys_setsid
.long _sys_sigaction
.long _sys_sgetmask
.long _sys_ssetmask
.long _sys_setreuid /* 70 */
.long _sys_setregid
.long _sys_sigsuspend
.long _sys_sigpending
.long _sys_sethostname
.long _sys_setrlimit /* 75 */
.long _sys_getrlimit
.long _sys_getrusage
.long _sys_gettimeofday
.long _sys_settimeofday
.long _sys_getgroups /* 80 */
.long _sys_setgroups
.long _sys_select
.long _sys_symlink
.long _sys_lstat
.long _sys_readlink /* 85 */
.long _sys_uselib
.long _sys_swapon
.long _sys_reboot
.long _sys_readdir
.long _sys_mmap /* 90 */
.long _sys_munmap
.long _sys_truncate
.long _sys_ftruncate
.long _sys_fchmod
.long _sys_fchown /* 95 */
.long _sys_getpriority
.long _sys_setpriority
.long _sys_profil
.long _sys_statfs
.long _sys_fstatfs /* 100 */
.long _sys_ioperm
.long _sys_socketcall
.long _sys_syslog
.long _sys_setitimer
.long _sys_getitimer /* 105 */
.long _sys_newstat
.long _sys_newlstat
.long _sys_newfstat
.long _sys_uname
.long _sys_iopl /* 110 */
.long _sys_vhangup
.long _sys_idle
.long _sys_vm86
.long _sys_wait4
.long _sys_swapoff /* 115 */
.long _sys_sysinfo
.long _sys_ipc
.long _sys_fsync
.long _sys_sigreturn
.long _sys_clone /* 120 */
.long _sys_setdomainname
.long _sys_newuname
.long _sys_modify_ldt
.long _sys_adjtimex
.long _sys_mprotect /* 125 */
.long _sys_sigprocmask
.long _sys_create_module
.long _sys_init_module
.long _sys_delete_module
.long _sys_get_kernel_syms /* 130 */
.long _sys_quotactl
.long _sys_getpgid
.long _sys_fchdir
.long _sys_bdflush
.space (NR_syscalls-130)*4
...@@ -10,7 +10,19 @@ ...@@ -10,7 +10,19 @@
#include <linux/types.h> #include <linux/types.h>
#ifdef __cplusplus
#define C_BEGIN extern "C" {
#define C_END }
#else
#define C_BEGIN
#define C_END
#endif
#undef __cplusplus
#define extern #define extern
#define inline #define inline
#define __LIBRARY__ #define __LIBRARY__
C_BEGIN
#include <linux/string.h> #include <linux/string.h>
C_END
...@@ -7,6 +7,11 @@ ...@@ -7,6 +7,11 @@
* *
*/ */
/*
* Modified by Alex Bligh (alex@cconcepts.co.uk) 4 Apr 1994 to use multiple
* pages. So for 'page' throughout, read 'area'.
*/
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/system.h> #include <asm/system.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -17,7 +22,7 @@ ...@@ -17,7 +22,7 @@
I want this number to be increased in the near future: I want this number to be increased in the near future:
loadable device drivers should use this function to get memory */ loadable device drivers should use this function to get memory */
#define MAX_KMALLOC_K 4 #define MAX_KMALLOC_K ((PAGE_SIZE<<(NUM_AREA_ORDERS-1))>>10)
/* This defines how many times we should try to allocate a free page before /* This defines how many times we should try to allocate a free page before
...@@ -86,25 +91,35 @@ struct size_descriptor { ...@@ -86,25 +91,35 @@ struct size_descriptor {
int nfrees; int nfrees;
int nbytesmalloced; int nbytesmalloced;
int npages; int npages;
unsigned long gfporder; /* number of pages in the area required */
}; };
/*
* For now it is unsafe to allocate bucket sizes between n & n=16 where n is
* 4096 * any power of two
*/
struct size_descriptor sizes[] = { struct size_descriptor sizes[] = {
{ NULL, 32,127, 0,0,0,0 }, { NULL, 32,127, 0,0,0,0, 0},
{ NULL, 64, 63, 0,0,0,0 }, { NULL, 64, 63, 0,0,0,0, 0 },
{ NULL, 128, 31, 0,0,0,0 }, { NULL, 128, 31, 0,0,0,0, 0 },
{ NULL, 252, 16, 0,0,0,0 }, { NULL, 252, 16, 0,0,0,0, 0 },
{ NULL, 508, 8, 0,0,0,0 }, { NULL, 508, 8, 0,0,0,0, 0 },
{ NULL,1020, 4, 0,0,0,0 }, { NULL,1020, 4, 0,0,0,0, 0 },
{ NULL,2040, 2, 0,0,0,0 }, { NULL,2040, 2, 0,0,0,0, 0 },
{ NULL,4080, 1, 0,0,0,0 }, { NULL,4096-16, 1, 0,0,0,0, 0 },
{ NULL, 0, 0, 0,0,0,0 } { NULL,8192-16, 1, 0,0,0,0, 1 },
{ NULL,16384-16, 1, 0,0,0,0, 2 },
{ NULL,32768-16, 1, 0,0,0,0, 3 },
{ NULL,65536-16, 1, 0,0,0,0, 4 },
{ NULL,131072-16, 1, 0,0,0,0, 5 },
{ NULL, 0, 0, 0,0,0,0, 0 }
}; };
#define NBLOCKS(order) (sizes[order].nblocks) #define NBLOCKS(order) (sizes[order].nblocks)
#define BLOCKSIZE(order) (sizes[order].size) #define BLOCKSIZE(order) (sizes[order].size)
#define AREASIZE(order) (PAGE_SIZE<<(sizes[order].gfporder))
long kmalloc_init (long start_mem,long end_mem) long kmalloc_init (long start_mem,long end_mem)
...@@ -118,12 +133,12 @@ long kmalloc_init (long start_mem,long end_mem) ...@@ -118,12 +133,12 @@ long kmalloc_init (long start_mem,long end_mem)
for (order = 0;BLOCKSIZE(order);order++) for (order = 0;BLOCKSIZE(order);order++)
{ {
if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) > if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) >
PAGE_SIZE) AREASIZE(order))
{ {
printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n", printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
NBLOCKS (order) * BLOCKSIZE(order) + NBLOCKS (order) * BLOCKSIZE(order) +
sizeof (struct page_descriptor), sizeof (struct page_descriptor),
(int) PAGE_SIZE, (int) AREASIZE(order),
BLOCKSIZE (order)); BLOCKSIZE (order));
panic ("This only happens if someone messes with kmalloc"); panic ("This only happens if someone messes with kmalloc");
} }
...@@ -161,12 +176,6 @@ void * kmalloc (size_t size, int priority) ...@@ -161,12 +176,6 @@ void * kmalloc (size_t size, int priority)
priority = GFP_ATOMIC; priority = GFP_ATOMIC;
} }
} }
if (size > MAX_KMALLOC_K * 1024)
{
printk ("kmalloc: I refuse to allocate %d bytes (for now max = %d).\n",
size,MAX_KMALLOC_K*1024);
return (NULL);
}
order = get_order (size); order = get_order (size);
if (order < 0) if (order < 0)
...@@ -215,7 +224,7 @@ while (tries --) ...@@ -215,7 +224,7 @@ while (tries --)
sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */ sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */
/* This can be done with ints on: This is private to this invocation */ /* This can be done with ints on: This is private to this invocation */
page = (struct page_descriptor *) __get_free_page (priority & GFP_LEVEL_MASK); page = (struct page_descriptor *) __get_free_pages (priority & GFP_LEVEL_MASK, sizes[order].gfporder);
if (!page) { if (!page) {
static unsigned long last = 0; static unsigned long last = 0;
if (last + 10*HZ < jiffies) { if (last + 10*HZ < jiffies) {
...@@ -339,10 +348,15 @@ if (page->nfree == NBLOCKS (page->order)) ...@@ -339,10 +348,15 @@ if (page->nfree == NBLOCKS (page->order))
else else
printk ("Ooops. page %p doesn't show on freelist.\n", page); printk ("Ooops. page %p doesn't show on freelist.\n", page);
} }
free_page ((long)page); /* FIXME: I'm sure we should do something with npages here (like npages--) */
free_pages ((long)page, sizes[order].gfporder);
} }
restore_flags(flags); restore_flags(flags);
/* FIXME: ?? Are these increment & decrement operations guaranteed to be
* atomic? Could an IRQ not occur between the read & the write?
* Maybe yes on a x86 with GCC...??
*/
sizes[order].nfrees++; /* Noncritical (monitoring) admin stuff */ sizes[order].nfrees++; /* Noncritical (monitoring) admin stuff */
sizes[order].nbytesmalloced -= size; sizes[order].nbytesmalloced -= size;
} }
/* /*
* linux/mm/memory.c * linux/mm/memory.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
*/ */
/* /*
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* 20.12.91 - Ok, making the swap-device changeable like the root. * 20.12.91 - Ok, making the swap-device changeable like the root.
*/ */
/*
* 05.04.94 - Multi-page memory management added for v1.1.
* Idea by Alex Bligh (alex@cconcepts.co.uk)
*/
#include <asm/system.h> #include <asm/system.h>
#include <linux/config.h> #include <linux/config.h>
...@@ -48,17 +53,14 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ ...@@ -48,17 +53,14 @@ 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);
int nr_swap_pages = 0;
int nr_free_pages = 0;
unsigned long free_page_list = 0;
/* /*
* The secondary free_page_list is used for malloc() etc things that * The free_area_list arrays point to the queue heads of the free areas
* may need pages during interrupts etc. Normal get_free_page() operations * of different sizes
* don't touch it, so it stays as a kind of "panic-list", that can be
* accessed when all other mm tricks have failed.
*/ */
int nr_secondary_pages = 0; int nr_swap_pages = 0;
unsigned long secondary_page_list = 0; int nr_free_pages = 0;
struct mem_list free_area_list[NR_MEM_LISTS];
unsigned char * free_area_map[NR_MEM_LISTS];
#define copy_page(from,to) \ #define copy_page(from,to) \
__asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si") __asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si")
...@@ -978,8 +980,7 @@ void show_mem(void) ...@@ -978,8 +980,7 @@ void show_mem(void)
int shared = 0; int shared = 0;
printk("Mem-info:\n"); printk("Mem-info:\n");
printk("Free pages: %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10)); show_free_areas();
printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
i = high_memory >> PAGE_SHIFT; i = high_memory >> PAGE_SHIFT;
while (i-- > 0) { while (i-- > 0) {
...@@ -1052,7 +1053,7 @@ void mem_init(unsigned long start_low_mem, ...@@ -1052,7 +1053,7 @@ void mem_init(unsigned long start_low_mem,
int codepages = 0; int codepages = 0;
int reservedpages = 0; int reservedpages = 0;
int datapages = 0; int datapages = 0;
unsigned long tmp; unsigned long tmp, mask;
unsigned short * p; unsigned short * p;
extern int etext; extern int etext;
...@@ -1067,22 +1068,34 @@ void mem_init(unsigned long start_low_mem, ...@@ -1067,22 +1068,34 @@ void mem_init(unsigned long start_low_mem,
start_mem = (unsigned long) p; start_mem = (unsigned long) p;
while (p > mem_map) while (p > mem_map)
*--p = MAP_PAGE_RESERVED; *--p = MAP_PAGE_RESERVED;
/* set up the free-area data structures */
for (mask = PAGE_MASK, tmp = 0 ; tmp < NR_MEM_LISTS ; tmp++, mask <<= 1) {
unsigned long bitmap_size;
free_area_list[tmp].prev = free_area_list[tmp].next = &free_area_list[tmp];
end_mem = (end_mem + ~mask) & mask;
bitmap_size = end_mem >> (PAGE_SHIFT + tmp);
bitmap_size = (bitmap_size + 7) >> 3;
free_area_map[tmp] = (unsigned char *) start_mem;
memset((void *) start_mem, 0, bitmap_size);
start_mem += bitmap_size;
}
/* mark usable pages in the mem_map[] */
start_low_mem = PAGE_ALIGN(start_low_mem); start_low_mem = PAGE_ALIGN(start_low_mem);
start_mem = PAGE_ALIGN(start_mem); start_mem = PAGE_ALIGN(start_mem);
while (start_low_mem < 0xA0000) { while (start_low_mem < 0xA0000) {
mem_map[MAP_NR(start_low_mem)] = 0; mem_map[MAP_NR(start_low_mem)] = 0;
start_low_mem += PAGE_SIZE; start_low_mem += PAGE_SIZE;
} }
while (start_mem < end_mem) { while (start_mem < high_memory) {
mem_map[MAP_NR(start_mem)] = 0; mem_map[MAP_NR(start_mem)] = 0;
start_mem += PAGE_SIZE; start_mem += PAGE_SIZE;
} }
#ifdef CONFIG_SOUND #ifdef CONFIG_SOUND
sound_mem_init(); sound_mem_init();
#endif #endif
free_page_list = 0; for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
nr_free_pages = 0;
for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) {
if (mem_map[MAP_NR(tmp)]) { if (mem_map[MAP_NR(tmp)]) {
if (tmp >= 0xA0000 && tmp < 0x100000) if (tmp >= 0xA0000 && tmp < 0x100000)
reservedpages++; reservedpages++;
...@@ -1092,14 +1105,13 @@ void mem_init(unsigned long start_low_mem, ...@@ -1092,14 +1105,13 @@ void mem_init(unsigned long start_low_mem,
datapages++; datapages++;
continue; continue;
} }
*(unsigned long *) tmp = free_page_list; mem_map[MAP_NR(tmp)] = 1;
free_page_list = tmp; free_page(tmp);
nr_free_pages++;
} }
tmp = nr_free_pages << PAGE_SHIFT; tmp = nr_free_pages << PAGE_SHIFT;
printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
tmp >> 10, tmp >> 10,
end_mem >> 10, high_memory >> 10,
codepages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10)); datapages << (PAGE_SHIFT-10));
......
/* /*
* linux/mm/swap.c * linux/mm/swap.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
*/ */
/* /*
...@@ -45,7 +45,6 @@ static struct swap_info_struct { ...@@ -45,7 +45,6 @@ static struct swap_info_struct {
unsigned long max; unsigned long max;
} swap_info[MAX_SWAPFILES]; } swap_info[MAX_SWAPFILES];
extern unsigned long free_page_list;
extern int shm_swap (int); extern int shm_swap (int);
/* /*
...@@ -486,16 +485,18 @@ static int try_to_free_page(void) ...@@ -486,16 +485,18 @@ static int try_to_free_page(void)
return 0; return 0;
} }
/* static inline void add_mem_queue(struct mem_list * head, struct mem_list * entry)
* Note that this must be atomic, or bad things will happen when {
* pages are requested in interrupts (as malloc can do). Thus the entry->prev = head;
* cli/sti's. entry->next = head->next;
*/ entry->next->prev = entry;
static inline void add_mem_queue(unsigned long addr, unsigned long * queue) head->next = entry;
}
static inline void remove_mem_queue(struct mem_list * head, struct mem_list * entry)
{ {
addr &= PAGE_MASK; entry->next->prev = entry->prev;
*(unsigned long *) addr = *queue; entry->prev->next = entry->next;
*queue = addr;
} }
/* /*
...@@ -509,27 +510,40 @@ static inline void add_mem_queue(unsigned long addr, unsigned long * queue) ...@@ -509,27 +510,40 @@ static inline void add_mem_queue(unsigned long addr, unsigned long * queue)
* With the above two rules, you get a straight-line execution path * With the above two rules, you get a straight-line execution path
* for the normal case, giving better asm-code. * for the normal case, giving better asm-code.
*/ */
void free_page(unsigned long addr)
/*
* Buddy system. Hairy. You really aren't expected to understand this
*/
static inline void free_pages_ok(unsigned long addr, unsigned long order)
{
unsigned long index = addr >> (PAGE_SHIFT + 1 + order);
unsigned long mask = PAGE_MASK << order;
addr &= mask;
nr_free_pages += 1 << order;
while (order < NR_MEM_LISTS-1) {
if (!change_bit(index, free_area_map[order]))
break;
remove_mem_queue(free_area_list+order, (struct mem_list *) (addr ^ (1+~mask)));
order++;
index >>= 1;
mask <<= 1;
addr &= mask;
}
add_mem_queue(free_area_list+order, (struct mem_list *) addr);
}
void free_pages(unsigned long addr, unsigned long order)
{ {
if (addr < high_memory) { if (addr < high_memory) {
unsigned long flag;
unsigned short * map = mem_map + MAP_NR(addr); unsigned short * map = mem_map + MAP_NR(addr);
if (*map) { if (*map) {
if (!(*map & MAP_PAGE_RESERVED)) { if (!(*map & MAP_PAGE_RESERVED)) {
unsigned long flag;
save_flags(flag); save_flags(flag);
cli(); cli();
if (!--*map) { if (!--*map)
if (nr_secondary_pages < MAX_SECONDARY_PAGES) { free_pages_ok(addr, order);
add_mem_queue(addr,&secondary_page_list);
nr_secondary_pages++;
restore_flags(flag);
return;
}
add_mem_queue(addr,&free_page_list);
nr_free_pages++;
}
restore_flags(flag); restore_flags(flag);
} }
return; return;
...@@ -541,57 +555,43 @@ void free_page(unsigned long addr) ...@@ -541,57 +555,43 @@ void free_page(unsigned long addr)
} }
/* /*
* This is one ugly macro, but it simplifies checking, and makes * Some ugly macros to speed up __get_free_pages()..
* this speed-critical place reasonably fast, especially as we have
* to do things with the interrupt flag etc.
*
* Note that this #define is heavily optimized to give fast code
* for the normal case - the if-statements are ordered so that gcc-2.2.2
* will make *no* jumps for the normal code. Don't touch unless you
* know what you are doing.
*/
#define REMOVE_FROM_MEM_QUEUE(queue,nr) \
cli(); \
if ((result = queue) != 0) { \
if (!(result & ~PAGE_MASK) && result < high_memory) { \
queue = *(unsigned long *) result; \
if (!mem_map[MAP_NR(result)]) { \
mem_map[MAP_NR(result)] = 1; \
nr--; \
last_free_pages[index = (index + 1) & (NR_LAST_FREE_PAGES - 1)] = result; \
restore_flags(flag); \
return result; \
} \
printk("Free page %08lx has mem_map = %d\n", \
result,mem_map[MAP_NR(result)]); \
} else \
printk("Result = 0x%08lx - memory map destroyed\n", result); \
queue = 0; \
nr = 0; \
} else if (nr) { \
printk(#nr " is %d, but " #queue " is empty\n",nr); \
nr = 0; \
} \
restore_flags(flag)
/*
* Get physical address of first (actually last :-) free page, and mark it
* used. If no free pages left, return 0.
*
* Note that this is one of the most heavily called functions in the kernel,
* so it's a bit timing-critical (especially as we have to disable interrupts
* in it). See the above macro which does most of the work, and which is
* optimized for a fast normal path of execution.
*/ */
unsigned long __get_free_page(int priority) #define RMQUEUE(order) \
do { struct mem_list * queue = free_area_list+order; \
unsigned long new_order = order; \
do { struct mem_list *next = queue->next; \
if (queue != next) { \
queue->next = next->next; \
next->next->prev = queue; \
mark_used((unsigned long) next, new_order); \
nr_free_pages -= 1 << order; \
restore_flags(flags); \
EXPAND(next, order, new_order); \
return (unsigned long) next; \
} new_order++; queue++; \
} while (new_order < NR_MEM_LISTS); \
} while (0)
static inline int mark_used(unsigned long addr, unsigned long order)
{ {
unsigned long result, flag; return change_bit(addr >> (PAGE_SHIFT+1+order), free_area_map[order]);
static unsigned long index = 0; }
/* this routine can be called at interrupt time via #define EXPAND(addr,low,high) \
malloc. We want to make sure that the critical do { unsigned long size = PAGE_SIZE << high; \
sections of code have interrupts disabled. -RAB while (high > low) { \
Is this code reentrant? */ high--; size >>= 1; cli(); \
add_mem_queue(free_area_list+high, addr); \
mark_used((unsigned long) addr, high); \
restore_flags(flags); \
addr = (void *) (size + (unsigned long) addr); \
} mem_map[MAP_NR((unsigned long) addr)] = 1; \
} while (0)
unsigned long __get_free_pages(int priority, unsigned long order)
{
unsigned long flags;
if (intr_count && priority != GFP_ATOMIC) { if (intr_count && priority != GFP_ATOMIC) {
static int count = 0; static int count = 0;
...@@ -601,18 +601,46 @@ unsigned long __get_free_page(int priority) ...@@ -601,18 +601,46 @@ unsigned long __get_free_page(int priority)
priority = GFP_ATOMIC; priority = GFP_ATOMIC;
} }
} }
save_flags(flag); save_flags(flags);
repeat: repeat:
REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages); cli();
if (priority == GFP_BUFFER) if ((priority==GFP_ATOMIC) || nr_free_pages > MAX_SECONDARY_PAGES) {
RMQUEUE(order);
restore_flags(flags);
return 0; return 0;
if (priority != GFP_ATOMIC) }
if (try_to_free_page()) restore_flags(flags);
goto repeat; if (priority != GFP_BUFFER && try_to_free_page())
REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages); goto repeat;
return 0; return 0;
} }
/*
* Show free area list (used inside shift_scroll-lock stuff)
* We also calculate the percentage fragmentation. We do this by counting the
* memory on each free list with the exception of the first item on the list.
*/
void show_free_areas(void)
{
unsigned long order, flags;
unsigned long total = 0;
printk("Free pages: %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10));
save_flags(flags);
cli();
for (order=0 ; order < NR_MEM_LISTS; order++) {
struct mem_list * tmp;
unsigned long nr = 0;
for (tmp = free_area_list[order].next ; tmp != free_area_list + order ; tmp = tmp->next) {
nr ++;
}
total += nr * (4 << order);
printk("%lu*%ukB ", nr, 4 << order);
}
restore_flags(flags);
printk("= %lukB)\n", total);
}
/* /*
* Trying to stop swapping from a file is fraught with races, so * Trying to stop swapping from a file is fraught with races, so
* we repeat quite a bit here when we have to pause. swapoff() * we repeat quite a bit here when we have to pause. swapoff()
......
...@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format) ...@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format)
if (timer_active) if (timer_active)
add_timer(&sp->timer); add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */ /* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80) { if (pos > buffer+PAGE_SIZE-90) {
printk("oops, too many %s sockets for netinfo.\n", printk("oops, too many %s sockets for netinfo.\n",
pro->name); pro->name);
return(strlen(buffer)); return(strlen(buffer));
......
...@@ -244,14 +244,6 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -244,14 +244,6 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
} }
skb->len = tmp + len; skb->len = tmp + len;
if(dev!=NULL && skb->len > 4095)
{
kfree_skb(skb, FREE_WRITE);
release_sock(sk);
return(-EMSGSIZE);
}
sk->prot->queue_xmit(sk, dev, skb, 1); sk->prot->queue_xmit(sk, dev, skb, 1);
release_sock(sk); release_sock(sk);
return(len); return(len);
......
...@@ -458,7 +458,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority) ...@@ -458,7 +458,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority)
void kfree_skbmem(void *mem,unsigned size) void kfree_skbmem(void *mem,unsigned size)
{ {
struct sk_buff *x=mem; struct sk_buff *x=(struct sk_buff *) mem;
IS_SKB(x); IS_SKB(x);
if(x->magic_debug_cookie==SK_GOOD_SKB) if(x->magic_debug_cookie==SK_GOOD_SKB)
{ {
......
...@@ -79,7 +79,7 @@ struct sk_buff { ...@@ -79,7 +79,7 @@ struct sk_buff {
unsigned char data[0]; unsigned char data[0];
}; };
#define SK_WMEM_MAX 8192 #define SK_WMEM_MAX 32767
#define SK_RMEM_MAX 32767 #define SK_RMEM_MAX 32767
#define SK_FREED_SKB 0x0DE2C0DE #define SK_FREED_SKB 0x0DE2C0DE
......
...@@ -1655,7 +1655,7 @@ sock_wfree(struct sock *sk, void *mem, unsigned long size) ...@@ -1655,7 +1655,7 @@ sock_wfree(struct sock *sk, void *mem, unsigned long size)
{ {
DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
IS_SKB(mem); IS_SKB((struct sk_buff *) mem);
kfree_skbmem(mem, size); kfree_skbmem(mem, size);
if (sk) { if (sk) {
sk->wmem_alloc -= size; sk->wmem_alloc -= size;
...@@ -1675,7 +1675,7 @@ void ...@@ -1675,7 +1675,7 @@ void
sock_rfree(struct sock *sk, void *mem, unsigned long size) sock_rfree(struct sock *sk, void *mem, unsigned long size)
{ {
DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
IS_SKB(mem); IS_SKB((struct sk_buff *) mem);
kfree_skbmem(mem, size); kfree_skbmem(mem, size);
if (sk) { if (sk) {
sk->rmem_alloc -= size; sk->rmem_alloc -= size;
......
...@@ -152,22 +152,6 @@ get_firstr(struct sock *sk) ...@@ -152,22 +152,6 @@ get_firstr(struct sock *sk)
return skb_dequeue(&sk->rqueue); return skb_dequeue(&sk->rqueue);
} }
/*
* Difference between two values in tcp ack terms.
*/
static long
diff(unsigned long seq1, unsigned long seq2)
{
long d;
d = seq1 - seq2;
if (d > 0) return(d);
/* I hope this returns what I want. */
return(~d+1);
}
/* This routine picks a TCP windows for a socket based on /* This routine picks a TCP windows for a socket based on
the following constraints the following constraints
......
...@@ -263,21 +263,6 @@ udp_send(struct sock *sk, struct sockaddr_in *sin, ...@@ -263,21 +263,6 @@ udp_send(struct sock *sk, struct sockaddr_in *sin,
skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */ skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */
skb->dev = dev; skb->dev = dev;
#ifdef OLD
/*
* This code used to hack in some form of fragmentation.
* I removed that, since it didn't work anyway, and it made the
* code a bad thing to read and understand. -FvK
*/
if (len > dev->mtu) {
#else
if (skb->len > 4095)
{
#endif
printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
return(-EMSGSIZE);
}
/* Fill in the UDP header. */ /* Fill in the UDP header. */
uh = (struct udphdr *) buff; uh = (struct udphdr *) buff;
......
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