diff -u --recursive --new-file v1.0.6/linux/Makefile linux/Makefile --- v1.0.6/linux/Makefile Tue Apr 5 07:23:05 1994 +++ linux/Makefile Tue Apr 5 07:41:50 1994 @@ -1,6 +1,6 @@ VERSION = 1 -PATCHLEVEL = 0 -SUBLEVEL = 6 +PATCHLEVEL = 1 +SUBLEVEL = 0 all: Version zImage @@ -9,6 +9,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ 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 @@ -76,7 +77,7 @@ LD =ld LDFLAGS =#-qmagic HOSTCC =gcc -CC =gcc -D__KERNEL__ +CC =gcc -D__KERNEL__ -I$(ROOT)/include MAKE =make CPP =$(CC) -E AR =ar diff -u --recursive --new-file v1.0.6/linux/drivers/block/blk.h linux/drivers/block/blk.h --- v1.0.6/linux/drivers/block/blk.h Tue Apr 5 07:23:05 1994 +++ linux/drivers/block/blk.h Wed Apr 6 10:40:57 1994 @@ -42,12 +42,9 @@ * This is used in the elevator algorithm: Note that * reads always go before writes. This is natural: reads * are much more time-critical than writes. - * - * Update: trying with writes being preferred due to test - * by Alessandro Rubini.. */ #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)->sector < (s2)->sector))))) diff -u --recursive --new-file v1.0.6/linux/drivers/block/mcd.c linux/drivers/block/mcd.c --- v1.0.6/linux/drivers/block/mcd.c Sun Mar 6 16:12:04 1994 +++ linux/drivers/block/mcd.c Wed Apr 6 11:18:19 1994 @@ -476,9 +476,23 @@ #endif 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; - default: return -EINVAL; } diff -u --recursive --new-file v1.0.6/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v1.0.6/linux/drivers/block/xd.c Sat Feb 12 18:27:33 1994 +++ linux/drivers/block/xd.c Tue Apr 5 07:24:51 1994 @@ -1,13 +1,22 @@ /* - * 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 * * Revised: 01/01/93, ... * - * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, kevinf@agora.rain.com) - * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and Wim Van Dorst. + * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, + * 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 @@ 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[] = { - { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* 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, 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, 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,"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 */ @@ -70,21 +79,42 @@ }; 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 struct gendisk xd_gendisk = { MAJOR_NR,"xd",6,1 << 6,XD_MAXDRIVES,xd_geninit,xd,xd_sizes,0,(void *) xd_info,NULL }; -static struct file_operations xd_fops = { NULL,block_read,block_write,NULL,NULL,xd_ioctl,NULL,xd_open,xd_release,block_fsync }; - -static struct wait_queue *xd_wait_int = NULL,*xd_wait_open = NULL; +static struct gendisk xd_gendisk = { + MAJOR_NR, /* Major number */ + "xd", /* Major name */ + 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_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; -/* 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_char i,controller,*address; - if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd_init: unable to get major number %d\n",MAJOR_NR); return (mem_start); @@ -94,26 +124,6 @@ xd_gendisk.next = gendisk_head; 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; } @@ -139,11 +149,33 @@ 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) { - 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++) { xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors; xd_valid[i] = 1; @@ -188,10 +220,12 @@ switch (CURRENT->cmd) { case READ: - case WRITE: for (retry = 0; (retry < XD_RETRIES) && !code; retry++) - code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count); - break; - default: printk("do_xd_request: unknown request\n"); break; + case WRITE: + for (retry = 0; (retry < XD_RETRIES) && !code; retry++) + code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count); + break; + default: + printk("do_xd_request: unknown request\n"); break; } } end_request(code); /* wrap up, 0 = fail, 1 = success */ @@ -206,25 +240,27 @@ if (inode && (dev < xd_drives)) switch (cmd) { - case HDIO_GETGEO: if (arg) { - if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry)))) - return (err); - put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads); - put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors); - 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); - } - break; - case BLKGETSIZE: if (arg) { - if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)))) - return (err); - put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg); - - return (0); - } - break; + case HDIO_GETGEO: + if (arg) { + if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry)))) + return (err); + put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads); + put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors); + 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); + } + break; + case BLKGETSIZE: + if (arg) { + if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)))) + return (err); + put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg); + + return (0); + } + break; case BLKFLSBUF: if(!suser()) return -EACCES; if(!inode->i_rdev) return -EINVAL; @@ -232,7 +268,8 @@ invalidate_buffers(inode->i_rdev); 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); } return (-EINVAL); @@ -303,8 +340,12 @@ 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)) { - case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive); return (0); - case 2: switch ((sense[0] & 0x30) >> 4) { + case 1: + 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 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; @@ -412,28 +453,31 @@ if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout)) return (1); switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) { - case 0: if (mode == DMA_MODE) { - enable_dma(xd_dma); - sleep_on(&xd_wait_int); - disable_dma(xd_dma); - } - else - outb(outdata ? *outdata++ : 0,XD_DATA); - break; - case STAT_INPUT: if (mode == DMA_MODE) { - enable_dma(xd_dma); - sleep_on(&xd_wait_int); - disable_dma(xd_dma); - } - else - if (indata) - *indata++ = inb(XD_DATA); - else - inb(XD_DATA); - break; - case STAT_COMMAND: outb(command ? *command++ : 0,XD_DATA); break; - case STAT_COMMAND - | STAT_INPUT: complete = 1; break; + case 0: + if (mode == DMA_MODE) { + enable_dma(xd_dma); + sleep_on(&xd_wait_int); + disable_dma(xd_dma); + } else + outb(outdata ? *outdata++ : 0,XD_DATA); + break; + case STAT_INPUT: + if (mode == DMA_MODE) { + enable_dma(xd_dma); + sleep_on(&xd_wait_int); + disable_dma(xd_dma); + } else + if (indata) + *indata++ = inb(XD_DATA); + else + inb(XD_DATA); + break; + case STAT_COMMAND: + outb(command ? *command++ : 0,XD_DATA); + break; + case STAT_COMMAND | STAT_INPUT: + complete = 1; + break; } } csb = inb(XD_DATA); @@ -460,7 +504,7 @@ for (i = 0; i < XD_MAXDRIVES; i++) { 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); count++; } diff -u --recursive --new-file v1.0.6/linux/include/asm/bitops.h linux/include/asm/bitops.h --- v1.0.6/linux/include/asm/bitops.h Fri Feb 11 09:25:54 1994 +++ linux/include/asm/bitops.h Tue Apr 5 11:38:58 1994 @@ -39,6 +39,16 @@ 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 way. diff -u --recursive --new-file v1.0.6/linux/include/linux/if.h linux/include/linux/if.h --- v1.0.6/linux/include/linux/if.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/if.h Tue Apr 5 08:14:29 1994 @@ -24,6 +24,7 @@ /* Structure defining a queue for a network interface. */ +#ifdef not_yet_in_linux struct ifnet { char *if_name; /* name, e.g. ``en'' or ``lo'' */ short if_unit; /* sub-unit for device driver */ @@ -33,13 +34,11 @@ int if_metric; /* routing metric (not used) */ struct ifaddr *if_addrlist; /* linked list of addrs per if */ struct ifqueue { -#ifdef not_yet_in_linux struct mbuf *ifq_head; struct mbuf *ifq_tail; int ifq_len; int ifq_maxlen; int ifq_drops; -#endif } if_snd; /* output queue */ /* Procedure handles. */ @@ -59,6 +58,7 @@ /* Linked list: pointer to next interface. */ struct ifnet *if_next; }; +#endif /* Standard interface flags. */ #define IFF_UP 0x1 /* interface is up */ diff -u --recursive --new-file v1.0.6/linux/include/linux/mcd.h linux/include/linux/mcd.h --- v1.0.6/linux/include/linux/mcd.h Mon Jan 3 08:19:44 1994 +++ linux/include/linux/mcd.h Wed Apr 6 11:18:19 1994 @@ -31,7 +31,7 @@ #define MCD_STATUS_DELAY 100 /* number of times to retry a command before giving up */ -#define MCD_RETRY_ATTEMPTS 3 +#define MCD_RETRY_ATTEMPTS 5 /* port access macro */ #define MCDPORT(x) (mcd_port + (x)) @@ -64,6 +64,7 @@ #define MCMD_SET_VOLUME 0xAE /* set audio level */ #define MCMD_PLAY_READ 0xC0 /* play or read data */ #define MCMD_GET_VERSION 0xDC +#define MCMD_EJECT 0xF6 /* eject (FX drive) */ /* borrowed from hd.c */ diff -u --recursive --new-file v1.0.6/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.0.6/linux/include/linux/mm.h Mon Mar 21 20:42:09 1994 +++ linux/include/linux/mm.h Wed Apr 6 11:39:19 1994 @@ -92,22 +92,31 @@ }; /* 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_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 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 * goes to clearing the page. If you want a page without the clearing * 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) { unsigned long page; @@ -121,9 +130,12 @@ 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, unsigned long address); extern void free_page_tables(struct task_struct * tsk); diff -u --recursive --new-file v1.0.6/linux/include/linux/string.h linux/include/linux/string.h --- v1.0.6/linux/include/linux/string.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/string.h Tue Apr 5 07:37:24 1994 @@ -7,6 +7,10 @@ #define NULL ((void *) 0) #endif +#ifdef __cplusplus +extern "C" { +#endif + /* * This string-include defines all string functions as inline * functions. Use gcc. It also assumes ds=es=data space, this should be @@ -415,5 +419,9 @@ :"cx","di","memory"); return s; } + +#ifdef __cplusplus +} +#endif #endif diff -u --recursive --new-file v1.0.6/linux/include/linux/sys.h linux/include/linux/sys.h --- v1.0.6/linux/include/linux/sys.h Mon Jan 31 16:31:24 1994 +++ linux/include/linux/sys.h Tue Apr 5 09:00:20 1994 @@ -1,179 +1,37 @@ #ifndef _LINUX_SYS_H #define _LINUX_SYS_H + /* - * system call entry points + * system call entry points ... but not all are defined */ - -#define sys_clone sys_fork - -#ifdef __cplusplus -extern "C" { -#endif +#define NR_syscalls 256 -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 with the same entry-point + */ +#define _sys_clone _sys_fork /* * These are system calls that will be removed at some time * due to newer versions existing.. */ #ifdef notdef -#define sys_waitpid sys_old_syscall /* sys_wait4 */ -#define sys_olduname sys_old_syscall /* sys_newuname */ -#define sys_uname sys_old_syscall /* sys_newuname */ -#define sys_stat sys_old_syscall /* sys_newstat */ -#define sys_fstat sys_old_syscall /* sys_newfstat */ -#define sys_lstat sys_old_syscall /* sys_newlstat */ -#define sys_signal sys_old_syscall /* sys_sigaction */ -#define sys_sgetmask sys_old_syscall /* sys_sigprocmask */ -#define sys_ssetmask sys_old_syscall /* sig_sigprocmask */ +#define _sys_waitpid _sys_old_syscall /* _sys_wait4 */ +#define _sys_olduname _sys_old_syscall /* _sys_newuname */ +#define _sys_uname _sys_old_syscall /* _sys_newuname */ +#define _sys_stat _sys_old_syscall /* _sys_newstat */ +#define _sys_fstat _sys_old_syscall /* _sys_newfstat */ +#define _sys_lstat _sys_old_syscall /* _sys_newlstat */ +#define _sys_signal _sys_old_syscall /* _sys_sigaction */ +#define _sys_sgetmask _sys_old_syscall /* _sys_sigprocmask */ +#define _sys_ssetmask _sys_old_syscall /* _sys_sigprocmask */ #endif /* * These are system calls that haven't been implemented yet * but have an entry in the table for future expansion.. */ - -#define sys_quotactl sys_ni_syscall -#define sys_bdflush sys_ni_syscall - -typedef int (*fn_ptr)(); - -#ifdef __cplusplus -} -#endif +#define _sys_quotactl _sys_ni_syscall +#define _sys_bdflush _sys_ni_syscall #endif diff -u --recursive --new-file v1.0.6/linux/include/linux/xd.h linux/include/linux/xd.h --- v1.0.6/linux/include/linux/xd.h Sat Feb 12 18:27:32 1994 +++ linux/include/linux/xd.h Tue Apr 5 07:24:51 1994 @@ -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). * - * Author: Pat Mackinlay, smackinla@cc.curtin.edu.au + * Author: Pat Mackinlay, pat@it.com.au * Date: 29/09/92 * * Revised: 01/01/93, ... diff -u --recursive --new-file v1.0.6/linux/init/main.c linux/init/main.c --- v1.0.6/linux/init/main.c Sun Apr 3 14:58:24 1994 +++ linux/init/main.c Tue Apr 5 07:37:24 1994 @@ -78,7 +78,6 @@ extern void sock_init(void); extern long rd_init(long mem_start, int length); 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 bmouse_setup(char *str, int *ints); @@ -267,7 +266,7 @@ { char *next; 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; if (!*line) diff -u --recursive --new-file v1.0.6/linux/kernel/Makefile linux/kernel/Makefile --- v1.0.6/linux/kernel/Makefile Fri Dec 17 08:14:28 1993 +++ linux/kernel/Makefile Tue Apr 5 07:37:24 1994 @@ -34,14 +34,6 @@ sched.o: sched.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: $(CPP) -M *.c > .depend diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.S linux/kernel/ksyms.S --- v1.0.6/linux/kernel/ksyms.S Wed Feb 16 09:30:21 1994 +++ linux/kernel/ksyms.S @@ -1,30 +0,0 @@ -#include -/* - * 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 diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.0.6/linux/kernel/ksyms.c +++ linux/kernel/ksyms.c Wed Apr 6 11:38:21 1994 @@ -0,0 +1,40 @@ +/* + * Herein lies all the functions/variables that are "exported" for linkage + * with dynamically loaded kernel modules. + * Jon. + */ + +#include +#include +#include +#include + +#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]); diff -u --recursive --new-file v1.0.6/linux/kernel/ksyms.sh linux/kernel/ksyms.sh --- v1.0.6/linux/kernel/ksyms.sh Fri Feb 18 16:54:02 1994 +++ linux/kernel/ksyms.sh @@ -1,37 +0,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 diff -u --recursive --new-file v1.0.6/linux/kernel/sched.c linux/kernel/sched.c --- v1.0.6/linux/kernel/sched.c Tue Apr 5 07:23:07 1994 +++ linux/kernel/sched.c Tue Apr 5 08:49:45 1994 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -102,55 +101,7 @@ short b; } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS }; -struct kernel_stat kstat = - { 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 '' 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 +struct kernel_stat kstat = { 0 }; /* * 'math_state_restore()' saves the current math information in the diff -u --recursive --new-file v1.0.6/linux/kernel/sys.c linux/kernel/sys.c --- v1.0.6/linux/kernel/sys.c Mon Mar 21 20:42:10 1994 +++ linux/kernel/sys.c Tue Apr 5 08:32:36 1994 @@ -30,6 +30,11 @@ #define PZERO 15 +asmlinkage int sys_ni_syscall(void) +{ + return -EINVAL; +} + static int proc_sel(struct task_struct *p, int which, int who) { switch (which) { diff -u --recursive --new-file v1.0.6/linux/kernel/sys_call.S linux/kernel/sys_call.S --- v1.0.6/linux/kernel/sys_call.S Wed Dec 1 14:44:15 1993 +++ linux/kernel/sys_call.S Tue Apr 5 09:01:38 1994 @@ -41,6 +41,7 @@ */ #include +#include EBX = 0x00 ECX = 0x04 @@ -87,7 +88,7 @@ .globl _invalid_TSS,_segment_not_present,_stack_segment .globl _general_protection,_reserved .globl _alignment_check,_page_fault -.globl ret_from_sys_call +.globl ret_from_sys_call, _sys_call_table #define SAVE_ALL \ cld; \ @@ -163,8 +164,11 @@ pushl %eax # save orig_eax SAVE_ALL movl $-ENOSYS,EAX(%esp) - cmpl _NR_syscalls,%eax + cmpl $(NR_syscalls),%eax jae ret_from_sys_call + movl _sys_call_table(,%eax,4),%eax + testl %eax,%eax + je ret_from_sys_call movl _current,%ebx andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors movl $0,errno(%ebx) @@ -172,7 +176,7 @@ movl %edx,dbgreg6(%ebx) # save current hardware debugging status testb $0x20,flags(%ebx) # PF_TRACESYS jne 1f - call _sys_call_table(,%eax,4) + call *%eax movl %eax,EAX(%esp) # save the return value movl errno(%ebx),%edx negl %edx @@ -388,3 +392,144 @@ _page_fault: pushl $_do_page_fault 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 diff -u --recursive --new-file v1.0.6/linux/lib/string.c linux/lib/string.c --- v1.0.6/linux/lib/string.c Wed Dec 1 14:44:15 1993 +++ linux/lib/string.c Tue Apr 5 09:51:29 1994 @@ -10,7 +10,19 @@ #include +#ifdef __cplusplus +#define C_BEGIN extern "C" { +#define C_END } +#else +#define C_BEGIN +#define C_END +#endif + +#undef __cplusplus #define extern #define inline #define __LIBRARY__ + +C_BEGIN #include +C_END diff -u --recursive --new-file v1.0.6/linux/mm/kmalloc.c linux/mm/kmalloc.c --- v1.0.6/linux/mm/kmalloc.c Tue Apr 5 07:23:08 1994 +++ linux/mm/kmalloc.c Tue Apr 5 14:52:20 1994 @@ -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 #include #include @@ -17,7 +22,7 @@ I want this number to be increased in the near future: 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 @@ -86,25 +91,35 @@ int nfrees; int nbytesmalloced; 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[] = { - { NULL, 32,127, 0,0,0,0 }, - { NULL, 64, 63, 0,0,0,0 }, - { NULL, 128, 31, 0,0,0,0 }, - { NULL, 252, 16, 0,0,0,0 }, - { NULL, 508, 8, 0,0,0,0 }, - { NULL,1020, 4, 0,0,0,0 }, - { NULL,2040, 2, 0,0,0,0 }, - { NULL,4080, 1, 0,0,0,0 }, - { NULL, 0, 0, 0,0,0,0 } + { NULL, 32,127, 0,0,0,0, 0}, + { NULL, 64, 63, 0,0,0,0, 0 }, + { NULL, 128, 31, 0,0,0,0, 0 }, + { NULL, 252, 16, 0,0,0,0, 0 }, + { NULL, 508, 8, 0,0,0,0, 0 }, + { NULL,1020, 4, 0,0,0,0, 0 }, + { NULL,2040, 2, 0,0,0,0, 0 }, + { NULL,4096-16, 1, 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 BLOCKSIZE(order) (sizes[order].size) - +#define AREASIZE(order) (PAGE_SIZE<<(sizes[order].gfporder)) long kmalloc_init (long start_mem,long end_mem) @@ -118,12 +133,12 @@ for (order = 0;BLOCKSIZE(order);order++) { 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", NBLOCKS (order) * BLOCKSIZE(order) + sizeof (struct page_descriptor), - (int) PAGE_SIZE, + (int) AREASIZE(order), BLOCKSIZE (order)); panic ("This only happens if someone messes with kmalloc"); } @@ -161,12 +176,6 @@ 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); if (order < 0) @@ -215,7 +224,7 @@ 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 */ - 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) { static unsigned long last = 0; if (last + 10*HZ < jiffies) { @@ -339,10 +348,15 @@ else 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); +/* 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].nbytesmalloced -= size; } diff -u --recursive --new-file v1.0.6/linux/mm/memory.c linux/mm/memory.c --- v1.0.6/linux/mm/memory.c Wed Feb 23 10:36:51 1994 +++ linux/mm/memory.c Wed Apr 6 11:47:17 1994 @@ -1,7 +1,7 @@ /* * linux/mm/memory.c * - * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ /* @@ -28,6 +28,11 @@ * 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 #include @@ -48,17 +53,14 @@ extern void sound_mem_init(void); 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 - * may need pages during interrupts etc. Normal get_free_page() operations - * don't touch it, so it stays as a kind of "panic-list", that can be - * accessed when all other mm tricks have failed. + * The free_area_list arrays point to the queue heads of the free areas + * of different sizes */ -int nr_secondary_pages = 0; -unsigned long secondary_page_list = 0; +int nr_swap_pages = 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) \ __asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si") @@ -978,8 +980,7 @@ int shared = 0; printk("Mem-info:\n"); - printk("Free pages: %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10)); - printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10)); + show_free_areas(); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); i = high_memory >> PAGE_SHIFT; while (i-- > 0) { @@ -1052,7 +1053,7 @@ int codepages = 0; int reservedpages = 0; int datapages = 0; - unsigned long tmp; + unsigned long tmp, mask; unsigned short * p; extern int etext; @@ -1067,22 +1068,34 @@ start_mem = (unsigned long) p; while (p > mem_map) *--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_mem = PAGE_ALIGN(start_mem); while (start_low_mem < 0xA0000) { mem_map[MAP_NR(start_low_mem)] = 0; start_low_mem += PAGE_SIZE; } - while (start_mem < end_mem) { + while (start_mem < high_memory) { mem_map[MAP_NR(start_mem)] = 0; start_mem += PAGE_SIZE; } #ifdef CONFIG_SOUND sound_mem_init(); #endif - free_page_list = 0; - nr_free_pages = 0; - for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) { + for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) { if (mem_map[MAP_NR(tmp)]) { if (tmp >= 0xA0000 && tmp < 0x100000) reservedpages++; @@ -1092,14 +1105,13 @@ datapages++; continue; } - *(unsigned long *) tmp = free_page_list; - free_page_list = tmp; - nr_free_pages++; + mem_map[MAP_NR(tmp)] = 1; + free_page(tmp); } tmp = nr_free_pages << PAGE_SHIFT; printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", tmp >> 10, - end_mem >> 10, + high_memory >> 10, codepages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10)); diff -u --recursive --new-file v1.0.6/linux/mm/swap.c linux/mm/swap.c --- v1.0.6/linux/mm/swap.c Tue Apr 5 07:23:08 1994 +++ linux/mm/swap.c Wed Apr 6 11:48:16 1994 @@ -1,7 +1,7 @@ /* * linux/mm/swap.c * - * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ /* @@ -45,7 +45,6 @@ unsigned long max; } swap_info[MAX_SWAPFILES]; -extern unsigned long free_page_list; extern int shm_swap (int); /* @@ -486,16 +485,18 @@ return 0; } -/* - * Note that this must be atomic, or bad things will happen when - * pages are requested in interrupts (as malloc can do). Thus the - * cli/sti's. - */ -static inline void add_mem_queue(unsigned long addr, unsigned long * queue) -{ - addr &= PAGE_MASK; - *(unsigned long *) addr = *queue; - *queue = addr; +static inline void add_mem_queue(struct mem_list * head, struct mem_list * entry) +{ + entry->prev = head; + entry->next = head->next; + entry->next->prev = entry; + head->next = entry; +} + +static inline void remove_mem_queue(struct mem_list * head, struct mem_list * entry) +{ + entry->next->prev = entry->prev; + entry->prev->next = entry->next; } /* @@ -509,27 +510,40 @@ * With the above two rules, you get a straight-line execution path * 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) { + unsigned long flag; unsigned short * map = mem_map + MAP_NR(addr); - if (*map) { if (!(*map & MAP_PAGE_RESERVED)) { - unsigned long flag; - save_flags(flag); cli(); - if (!--*map) { - if (nr_secondary_pages < MAX_SECONDARY_PAGES) { - add_mem_queue(addr,&secondary_page_list); - nr_secondary_pages++; - restore_flags(flag); - return; - } - add_mem_queue(addr,&free_page_list); - nr_free_pages++; - } + if (!--*map) + free_pages_ok(addr, order); restore_flags(flag); } return; @@ -541,57 +555,43 @@ } /* - * This is one ugly macro, but it simplifies checking, and makes - * 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) + * Some ugly macros to speed up __get_free_pages().. + */ +#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) +{ + return change_bit(addr >> (PAGE_SHIFT+1+order), free_area_map[order]); +} + +#define EXPAND(addr,low,high) \ +do { unsigned long size = PAGE_SIZE << high; \ + while (high > low) { \ + 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) -/* - * 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) -{ - unsigned long result, flag; - static unsigned long index = 0; - - /* this routine can be called at interrupt time via - malloc. We want to make sure that the critical - sections of code have interrupts disabled. -RAB - Is this code reentrant? */ +unsigned long __get_free_pages(int priority, unsigned long order) +{ + unsigned long flags; if (intr_count && priority != GFP_ATOMIC) { static int count = 0; @@ -601,16 +601,44 @@ priority = GFP_ATOMIC; } } - save_flags(flag); + save_flags(flags); repeat: - REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages); - if (priority == GFP_BUFFER) + cli(); + if ((priority==GFP_ATOMIC) || nr_free_pages > MAX_SECONDARY_PAGES) { + RMQUEUE(order); + restore_flags(flags); return 0; - if (priority != GFP_ATOMIC) - if (try_to_free_page()) - goto repeat; - REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages); + } + restore_flags(flags); + if (priority != GFP_BUFFER && try_to_free_page()) + goto repeat; 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); } /* diff -u --recursive --new-file v1.0.6/linux/net/inet/proc.c linux/net/inet/proc.c --- v1.0.6/linux/net/inet/proc.c Wed Mar 2 11:11:16 1994 +++ linux/net/inet/proc.c Mon Apr 4 09:23:07 1994 @@ -95,7 +95,7 @@ if (timer_active) add_timer(&sp->timer); /* 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", pro->name); return(strlen(buffer)); diff -u --recursive --new-file v1.0.6/linux/net/inet/raw.c linux/net/inet/raw.c --- v1.0.6/linux/net/inet/raw.c Sun Feb 6 12:17:40 1994 +++ linux/net/inet/raw.c Tue Apr 5 10:17:16 1994 @@ -244,14 +244,6 @@ } 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); release_sock(sk); return(len); diff -u --recursive --new-file v1.0.6/linux/net/inet/skbuff.c linux/net/inet/skbuff.c --- v1.0.6/linux/net/inet/skbuff.c Tue Apr 5 07:23:08 1994 +++ linux/net/inet/skbuff.c Tue Apr 5 07:37:25 1994 @@ -458,7 +458,7 @@ void kfree_skbmem(void *mem,unsigned size) { - struct sk_buff *x=mem; + struct sk_buff *x=(struct sk_buff *) mem; IS_SKB(x); if(x->magic_debug_cookie==SK_GOOD_SKB) { diff -u --recursive --new-file v1.0.6/linux/net/inet/skbuff.h linux/net/inet/skbuff.h --- v1.0.6/linux/net/inet/skbuff.h Tue Mar 1 13:11:55 1994 +++ linux/net/inet/skbuff.h Tue Apr 5 07:30:48 1994 @@ -79,7 +79,7 @@ unsigned char data[0]; }; -#define SK_WMEM_MAX 8192 +#define SK_WMEM_MAX 32767 #define SK_RMEM_MAX 32767 #define SK_FREED_SKB 0x0DE2C0DE diff -u --recursive --new-file v1.0.6/linux/net/inet/sock.c linux/net/inet/sock.c --- v1.0.6/linux/net/inet/sock.c Tue Apr 5 07:23:08 1994 +++ linux/net/inet/sock.c Tue Apr 5 07:37:25 1994 @@ -1655,7 +1655,7 @@ { 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); if (sk) { sk->wmem_alloc -= size; @@ -1675,7 +1675,7 @@ 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)); - IS_SKB(mem); + IS_SKB((struct sk_buff *) mem); kfree_skbmem(mem, size); if (sk) { sk->rmem_alloc -= size; diff -u --recursive --new-file v1.0.6/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.0.6/linux/net/inet/tcp.c Fri Mar 18 10:21:35 1994 +++ linux/net/inet/tcp.c Tue Apr 5 09:52:28 1994 @@ -152,22 +152,6 @@ 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 the following constraints diff -u --recursive --new-file v1.0.6/linux/net/inet/udp.c linux/net/inet/udp.c --- v1.0.6/linux/net/inet/udp.c Tue Jan 25 08:51:48 1994 +++ linux/net/inet/udp.c Tue Apr 5 10:16:24 1994 @@ -263,21 +263,6 @@ skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */ 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. */ uh = (struct udphdr *) buff;