diff -u --recursive --new-file v1.1.93/linux/Makefile linux/Makefile --- v1.1.93/linux/Makefile Mon Feb 20 21:34:53 1995 +++ linux/Makefile Mon Feb 20 21:33:03 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 93 +SUBLEVEL = 94 ARCH = i386 diff -u --recursive --new-file v1.1.93/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v1.1.93/linux/arch/alpha/kernel/entry.S Wed Feb 1 09:23:04 1995 +++ linux/arch/alpha/kernel/entry.S Wed Feb 22 12:27:52 1995 @@ -145,6 +145,18 @@ rti .end entUna +.align 5 +.globl entSys +.ent entSys +entSys: + SAVE_ALL + bis $30,$30,$19 + lda $27,do_entSys + jsr $26,($27),do_entSys + RESTORE_ALL + rti +.end entSys + .align 5 .globl sys_call_table sys_call_table: diff -u --recursive --new-file v1.1.93/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v1.1.93/linux/arch/alpha/kernel/process.c Wed Feb 15 10:36:37 1995 +++ linux/arch/alpha/kernel/process.c Wed Feb 22 12:27:52 1995 @@ -60,19 +60,19 @@ } /* - * This needs lots of work still.. + * This needs some work still.. */ -unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs) +void copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; - p->tss.usp = rdusp(); + p->tss.usp = usp; childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1; *childregs = *regs; p->tss.ksp = (unsigned long) childregs; /* p->tss.pc = XXXX; */ - halt(); - return clone_flags; + panic("copy_thread not implemented"); } /* @@ -84,9 +84,51 @@ /* * sys_execve() executes a new program. + * + * This works due to the alpha calling sequence: the first 6 args + * are gotten from registers, while the rest is on the stack, so + * we get a0-a5 for free, and then magically find "struct pt_regs" + * on the stack for us.. + * + * Don't do this at home. */ -asmlinkage int sys_execve(struct pt_regs regs) +asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) { - halt(); - return 0; + int error; + char * filename; + + error = getname((char *) a0, &filename); + if (error) + return error; + error = do_execve(filename, (char **) a1, (char **) a2, ®s); + putname(filename); + return error; +} + +/* + * sys_fork() does the obvious thing, but not the obvious way. + * See sys_execve() above. + */ +asmlinkage int sys_fork(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) +{ + return do_fork(COPYVM | SIGCHLD, rdusp(), ®s); +} + +asmlinkage int sys_clone(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) +{ + unsigned long clone_flags = a0; + unsigned long newsp; + + newsp = rdusp(); + if (newsp == a1 || !a1) + clone_flags |= COPYVM; + else + newsp = a1; + return do_fork(clone_flags, newsp, ®s); } diff -u --recursive --new-file v1.1.93/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c --- v1.1.93/linux/arch/alpha/kernel/traps.c Mon Jan 30 08:53:05 1995 +++ linux/arch/alpha/kernel/traps.c Wed Feb 22 12:27:52 1995 @@ -38,10 +38,28 @@ die_if_kernel("Unaligned", regs, 0); } +/* + * DEC means people to use the "retsys" instruction for return from + * a system call, but they are clearly misguided about this. We use + * "rti" in all cases, and fill in the stack with the return values. + * That should make signal handling etc much cleaner. + * + * Even more horribly, DEC doesn't allow system calls from kernel mode. + * "Security" features letting the user do something the kernel can't + * are a thinko. DEC palcode is strange. The PAL-code designers probably + * got terminally tainted by VMS at some point. + */ +asmlinkage void do_entSys(unsigned long sysnr, unsigned long arg1, unsigned long arg2, struct pt_regs *regs) +{ + printk("System call %ld(%ld,%ld)\n", sysnr, arg1, arg2); + die_if_kernel("Syscall", regs, 0); +} + extern asmlinkage void entMM(void); extern asmlinkage void entIF(void); extern asmlinkage void entArith(void); extern asmlinkage void entUna(void); +extern asmlinkage void entSys(void); void trap_init(void) { @@ -59,4 +77,5 @@ wrent(entMM, 2); wrent(entIF, 3); wrent(entUna, 4); + wrent(entSys, 5); } diff -u --recursive --new-file v1.1.93/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v1.1.93/linux/arch/i386/kernel/process.c Wed Feb 15 10:36:37 1995 +++ linux/arch/i386/kernel/process.c Wed Feb 22 12:27:52 1995 @@ -150,9 +150,8 @@ current->debugreg[i] = 0; } -#define IS_CLONE (regs->orig_eax == __NR_clone) - -unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs) +void copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + struct task_struct * p, struct pt_regs * regs) { int i; struct pt_regs * childregs; @@ -171,15 +170,9 @@ p->tss.eip = (unsigned long) ret_from_sys_call; *childregs = *regs; childregs->eax = 0; + childregs->esp = esp; p->tss.back_link = 0; p->tss.eflags = regs->eflags & 0xffffcfff; /* iopl is always 0 for a new process */ - if (IS_CLONE) { - if (regs->ebx) - childregs->esp = regs->ebx; - clone_flags = regs->ecx; - if (childregs->esp == regs->esp) - clone_flags |= COPYVM; - } p->tss.ldt = _LDT(nr); if (p->ldt) { p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); @@ -196,7 +189,6 @@ p->tss.io_bitmap[i] = ~0; if (last_task_used_math == current) __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387)); - return clone_flags; } /* @@ -236,6 +228,25 @@ convert it into standard 387 format first.. */ dump->u_fpvalid = 0; } +} + +asmlinkage int sys_fork(struct pt_regs regs) +{ + return do_fork(COPYVM | SIGCHLD, regs.esp, ®s); +} + +asmlinkage int sys_clone(struct pt_regs regs) +{ + unsigned long clone_flags; + unsigned long newsp; + + newsp = regs.ebx; + clone_flags = regs.ecx; + if (!newsp) + newsp = regs.esp; + if (newsp == regs.esp) + clone_flags |= COPYVM; + return do_fork(clone_flags, newsp, ®s); } /* diff -u --recursive --new-file v1.1.93/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v1.1.93/linux/arch/i386/kernel/ptrace.c Wed Feb 1 09:23:04 1995 +++ linux/arch/i386/kernel/ptrace.c Mon Feb 20 21:29:53 1995 @@ -1,3 +1,4 @@ +#define THREE_LEVEL /* ptrace.c */ /* By Ross Biro 1/23/92 */ /* edited by Linus Torvalds */ @@ -86,11 +87,12 @@ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr) { pgd_t * pgdir; + pmd_t * pgmiddle; pte_t * pgtable; unsigned long page; repeat: - pgdir = PAGE_DIR_OFFSET(vma->vm_task, addr); + pgdir = pgd_offset(vma->vm_task, addr); if (pgd_none(*pgdir)) { do_no_page(vma, addr, 0); goto repeat; @@ -100,7 +102,17 @@ pgd_clear(pgdir); return 0; } - pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + do_no_page(vma, addr, 0); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return 0; + } + pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { do_no_page(vma, addr, 0); goto repeat; @@ -126,11 +138,12 @@ unsigned long data) { pgd_t *pgdir; + pmd_t *pgmiddle; pte_t *pgtable; unsigned long page; repeat: - pgdir = PAGE_DIR_OFFSET(vma->vm_task, addr); + pgdir = pgd_offset(vma->vm_task, addr); if (!pgd_present(*pgdir)) { do_no_page(vma, addr, 1); goto repeat; @@ -140,7 +153,17 @@ pgd_clear(pgdir); return; } - pgtable = (pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + do_no_page(vma, addr, 0); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return; + } + pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { do_no_page(vma, addr, 1); goto repeat; diff -u --recursive --new-file v1.1.93/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- v1.1.93/linux/arch/sparc/mm/fault.c Sun Feb 5 19:31:51 1995 +++ linux/arch/sparc/mm/fault.c Wed Feb 22 08:47:40 1995 @@ -14,11 +14,6 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ extern void die_if_kernel(char *,struct pt_regs *,long); -/* Sparc stuff... I know this is a ugly place to put the PROM vector, don't - * remind me. - */ -extern unsigned int trapbase[]; -extern unsigned int end[], etext[], msgbuf[]; struct linux_romvec *romvec; /* foo */ diff -u --recursive --new-file v1.1.93/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v1.1.93/linux/arch/sparc/mm/init.c Mon Feb 20 21:34:54 1995 +++ linux/arch/sparc/mm/init.c Wed Feb 22 08:47:40 1995 @@ -160,7 +160,7 @@ * self-modifying code. */ - a= (unsigned long) etext; + a= (unsigned long) &etext; mask=~(PTE_NC|PTE_W); /* make cacheable + not writable */ printk("changing kernel text perms...\n"); @@ -173,7 +173,7 @@ for(i=0; i<8; i++) { - b=PAGE_ALIGN((unsigned long) trapbase); + b=PAGE_ALIGN((unsigned long) &trapbase); switch_to_context(i); diff -u --recursive --new-file v1.1.93/linux/drivers/block/sonycd535.c linux/drivers/block/sonycd535.c --- v1.1.93/linux/drivers/block/sonycd535.c Fri Feb 17 11:20:12 1995 +++ linux/drivers/block/sonycd535.c Wed Feb 22 08:46:46 1995 @@ -4,7 +4,7 @@ * This is a modified version of the CDU-31A device driver (see below). * Changes were made using documentation for the CDU-531 (which Sony * assures me is very similar to the 535) and partial disassembly of the - * DOS driver. I used Minyard's driver and replaced the the CDU-31A + * DOS driver. I used Minyard's driver and replaced the the CDU-31A * commands with the CDU-531 commands. This was complicated by a different * interface protocol with the drive. The driver is still polled. * @@ -23,18 +23,23 @@ * * Things to do: * - handle errors and status better, put everything into a single word - * - use interrupts, DMA + * - use interrupts (code mostly there, but a big hole still missing) + * - handle multi-session CDs? + * - use DMA? * * Known Bugs: * - * + * Ken Pizzini (ken@halcyon.com) + * + * Original by: * Ron Jeppesen (ronj.an@site007.saic.com) * * *------------------------------------------------------------------------ * Sony CDROM interface device driver. * - * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to ronj above) + * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above) * * Colossians 3:17 * @@ -99,6 +104,9 @@ # include # include # include +# ifndef CONFIG_MODVERSIONS + char kernel_version[]= UTS_RELEASE; +# endif #endif #include @@ -137,9 +145,11 @@ * proper address. */ #ifndef CDU535_ADDRESS -# define CDU535_ADDRESS (0x340) +# define CDU535_ADDRESS 0x340 +#endif +#ifndef CDU535_INTERRUPT +# define CDU535_INTERRUPT 0 #endif - #ifndef CDU535_HANDLE # define CDU535_HANDLE "cdu535" #endif @@ -171,7 +181,9 @@ * if LOCK_DOORS is defined then the eject button is disabled while * the device is open. */ -#define LOCK_DOORS +#ifndef NO_LOCK_DOORS +# define LOCK_DOORS +#endif static int read_subcode(void); static void sony_get_toc(void); @@ -179,11 +191,14 @@ static inline unsigned int int_to_bcd(unsigned int val); static unsigned int bcd_to_int(unsigned int bcd); static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2], - Byte * response, int nResponse, int ignoreStatusBit7); + Byte * response, int n_response, int ignoreStatusBit7); /* The base I/O address of the Sony Interface. This is a variable (not a #define) so it can be easily changed via some future ioctl() */ -static unsigned short sony_cd_base_io = CDU535_ADDRESS; +#ifndef MODULE +static +#endif +unsigned short sony535_cd_base_io = CDU535_ADDRESS; /* * The following are I/O addresses of the various registers for the drive. The @@ -217,10 +232,10 @@ static struct s535_sony_subcode *last_sony_subcode; /* Points to the last subcode address read */ #ifndef MODULE -static unsigned char *sony_buffer; /* Points to the read-ahead buffer */ +static Byte *sony_buffer; /* Points to the read-ahead buffer */ #else -static unsigned char **sony_buffer; /* Points to the pointers - to the sector buffers */ +static Byte **sony_buffer; /* Points to the pointers + to the sector buffers */ #endif static int sony_inuse = 0; /* is the drive in use? Only one open at a time allowed */ @@ -240,8 +255,17 @@ * I just kept the CDU-31A driver behavior rather than using the PAUSE * command on the CDU-535. */ -static unsigned char cur_pos_msf[3] = {0, 0, 0}; -static unsigned char final_pos_msf[3] = {0, 0, 0}; +static Byte cur_pos_msf[3] = {0, 0, 0}; +static Byte final_pos_msf[3] = {0, 0, 0}; + +/* What IRQ is the drive using? 0 if none. */ +#ifndef MODULE +static +#endif +int sony535_irq_used = CDU535_INTERRUPT; + +/* The interrupt handler will wake this queue up when it gets an interrupt. */ +static struct wait_queue *cdu535_irq_wait = NULL; /* @@ -251,10 +275,10 @@ static int cdu535_check_media_change(dev_t full_dev) { - int retval; + int retval; if (MINOR(full_dev) != 0) { - printk("Sony CD-ROM request error: invalid device.\n"); + printk(CDU535_MESSAGE_NAME " request error: invalid device.\n"); return 0; } @@ -264,18 +288,64 @@ return retval; } +static inline void +enable_interrupts(void) +{ +#ifdef USE_IRQ + /* this code snarfed from cdu31a.c; it will not + * directly work for the cdu535 as written... + */ + curr_control_reg |= ( SONY_ATTN_INT_EN_BIT + | SONY_RES_RDY_INT_EN_BIT + | SONY_DATA_RDY_INT_EN_BIT); + outb(curr_control_reg, sony_cd_control_reg); +#endif +} + +static inline void +disable_interrupts(void) +{ +#ifdef USE_IRQ + /* this code snarfed from cdu31a.c; it will not + * directly work for the cdu535 as written... + */ + curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT + | SONY_RES_RDY_INT_EN_BIT + | SONY_DATA_RDY_INT_EN_BIT); + outb(curr_control_reg, sony_cd_control_reg); +#endif +} + +static void +cdu535_interrupt(int irq, struct pt_regs *regs) +{ + disable_interrupts(); + if (cdu535_irq_wait != NULL) + wake_up(&cdu535_irq_wait); + else + printk(CDU535_MESSAGE_NAME + ": Got an interrupt but nothing was waiting\n"); +} + /* * Wait a little while (used for polling the drive). If in initialization, - * setting a timeout doesn't work, so just loop for a while (we trust - * that the sony_sleep() call is protected by a test for proper jiffies count). + * setting a timeout doesn't work, so just loop for a while. (We trust + * that the sony_sleep() call is protected by a test for proper jiffies count.) */ static inline void sony_sleep(void) { - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies; - schedule(); + if (sony535_irq_used <= 0) { /* poll */ + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies; + schedule(); + } else { /* Interrupt driven */ + cli(); + enable_interrupts(); + interruptible_sleep_on(&cdu535_irq_wait); + sti(); + } } /*------------------start of SONY CDU535 very specific ---------------------*/ @@ -293,23 +363,24 @@ } /*************************************************************************** - * int read_result_reg( unsigned char *data_ptr ) + * int read_result_reg( Byte *data_ptr ) * * Read a result byte from the Sony CDU controller, store in location pointed * to by data_ptr. Return zero on success, TIME_OUT if we did not receive * data. ***************************************************************************/ static int -read_result_reg(unsigned char *data_ptr) +read_result_reg(Byte *data_ptr) { - int retry_count; - int read_status; + int retry_count; + int read_status; retry_count = jiffies + SONY_JIFFIES_TIMEOUT; while (jiffies < retry_count) { if (((read_status = inb(read_status_reg)) & SONY535_RESULT_NOT_READY_BIT) == 0) { #if DEBUG > 1 - printk("read_result_reg(): readStatReg = 0x%x\n", read_status); + printk(CDU535_MESSAGE_NAME + ": read_result_reg(): readStatReg = 0x%x\n", read_status); #endif *data_ptr = inb(result_reg); return 0; @@ -317,14 +388,14 @@ sony_sleep(); } } - printk(" Sony CDROM read_result_reg: TIME OUT!\n"); + printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n"); return TIME_OUT; } /**************************************************************************** * int read_exec_status( Byte status[2] ) * - * Read the execution status of the last command and put into status. + * Read the execution status of the last command and put into status. * Handles reading second status word if available. Returns 0 on success, * TIME_OUT on failure. ****************************************************************************/ @@ -339,10 +410,8 @@ return TIME_OUT; } #if DEBUG > 1 - printk("read_exec_status: read 0x%x\n", status[0]); - if (status[0] & 0x80) - printk(" and 0x%x\n", status[1]); - printk("\n"); + printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n", + status[0], status[1]); #endif return 0; } @@ -357,9 +426,9 @@ static int check_drive_status(void) { - Byte status, e_status[2]; - int CDD, ATN; - unsigned char cmd; + Byte status, e_status[2]; + int CDD, ATN; + Byte cmd; select_unit(0); if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */ @@ -387,7 +456,7 @@ return TIME_OUT; #if DEBUG > 1 - printk("--check_drive_status() got 0x%x\n", status); + printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status); #endif if (status == 0) @@ -401,17 +470,17 @@ break; /* go on to CDD stuff */ case SONY535_ATN_BUSY: if (initialized) - printk("Sony CDROM error, drive busy\n"); + printk(CDU535_MESSAGE_NAME " error: drive busy\n"); return CD_BUSY; case SONY535_ATN_EJECT_IN_PROGRESS: - printk("Sony CDROM error, eject in progress\n"); + printk(CDU535_MESSAGE_NAME " error: eject in progress\n"); sony_audio_status = CDROM_AUDIO_INVALID; return CD_BUSY; case SONY535_ATN_RESET_OCCURRED: case SONY535_ATN_DISC_CHANGED: case SONY535_ATN_RESET_AND_DISC_CHANGED: #if DEBUG > 0 - printk("Sony CDROM, reset occurred or disc changed\n"); + printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n"); #endif sony_disc_changed = 1; sony_toc_read = 0; @@ -425,16 +494,17 @@ } return 0; default: - printk("Sony CDROM error, drive busy (ATN=0x%x)\n", ATN); + printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN); return CD_BUSY; } - switch (CDD) { /* the 531 docs are not helpful in decoding this */ - case 0x0: /* just use the values from the DOS driver */ + switch (CDD) { /* the 531 docs are not helpful in decoding this */ + case 0x0: /* just use the values from the DOS driver */ case 0x2: case 0xa: - break; /* no error */ + break; /* no error */ case 0xc: - printk("check_drive_status(): CDD = 0xc! Not properly handled!\n"); + printk(CDU535_MESSAGE_NAME + ": check_drive_status(): CDD = 0xc! Not properly handled!\n"); return CD_BUSY; /* ? */ default: return CD_BUSY; @@ -443,14 +513,14 @@ } /* check_drive_status() */ /***************************************************************************** - * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2], + * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2], * Byte *response, int n_response, int ignore_status_bit7 ) * * Generic routine for executing commands. The command and its parameters * should be placed in the cmd[] array, number of bytes in the command is * stored in nCmd. The response from the command will be stored in the * response array. The number of bytes you expect back (excluding status) - * should be passed in nResponse. Finally, some + * should be passed in n_response. Finally, some * commands set bit 7 of the return status even when there is no second * status byte, on these commands set ignoreStatusBit7 TRUE. * If the command was sent and data received back, then we return 0, @@ -462,7 +532,7 @@ do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2], Byte * response, int n_response, int ignore_status_bit7) { - int i; + int i; /* write out the command */ for (i = 0; i < n_cmd; i++) @@ -471,7 +541,7 @@ /* read back the status */ if (read_result_reg(status) != 0) return TIME_OUT; - if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) { + if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) { /* get second status byte */ if (read_result_reg(status + 1) != 0) return TIME_OUT; @@ -479,7 +549,8 @@ status[1] = 0; } #if DEBUG > 2 - printk("do_sony_cmd %x: %x %x\n", *cmd, status[0], status[1]); + printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n", + *cmd, status[0], status[1]); #endif /* do not know about when I should read set of data and when not to */ @@ -502,7 +573,8 @@ static int set_drive_mode(int mode, Byte status[2]) { - Byte cmd_buff[2], ret_buff[1]; + Byte cmd_buff[2]; + Byte ret_buff[1]; cmd_buff[0] = SONY535_SET_DRIVE_MODE; cmd_buff[1] = mode; @@ -510,7 +582,7 @@ } /*************************************************************************** - * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2], + * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2], * Byte *data_buff, int buff_size ) * * Read n_blocks of data from the CDROM starting at position params[0:2], @@ -527,19 +599,19 @@ Byte * data_buff, int buf_size) #else seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], - unsigned char **buff, int buf_size) + Byte **buff, int buf_size) #endif { - int i; const int block_size = 2048; - Byte cmd_buff[7]; - int read_status; - int retry_count; -#ifdef MODULE - Byte *data_buff; - int sector_count = 0; + Byte cmd_buff[7]; + int i; + int read_status; + int retry_count; +#ifndef MODULE + Byte *start_pos = data_buff; #else - Byte *start_pos = data_buff; + Byte *data_buff; + int sector_count = 0; #endif if (buf_size < ((long)block_size) * n_blocks) @@ -598,11 +670,11 @@ static int request_toc_data(Byte status[2], struct s535_sony_toc *toc) { - int to_status; - int i, j, n_tracks, track_no; - Byte cmd_no = 0xb2; - Byte track_address_buffer[5]; - int first_track_num, last_track_num; + int to_status; + int i, j, n_tracks, track_no; + int first_track_num, last_track_num; + Byte cmd_no = 0xb2; + Byte track_address_buffer[5]; /* read the fixed portion of the table of contents */ if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0) @@ -636,19 +708,19 @@ static int spin_up_drive(Byte status[2]) { - Byte cmd_buff[1]; + Byte cmd; /* first see if the drive is already spinning */ - cmd_buff[0] = SONY535_REQUEST_DRIVE_STATUS_1; - if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) + cmd = SONY535_REQUEST_DRIVE_STATUS_1; + if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0) return TIME_OUT; if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0) - return 0; /* its already spinning */ + return 0; /* its already spinning */ - /* else, give the spin-up command */ - cmd_buff[0] = SONY535_SPIN_UP; - return do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); -} /* spin_up_drive() */ + /* otherwise, give the spin-up command */ + cmd = SONY535_SPIN_UP; + return do_sony_cmd(&cmd, 1, status, NULL, 0, 0); +} /*--------------------end of SONY CDU535 very specific ---------------------*/ @@ -656,8 +728,7 @@ static inline unsigned int int_to_bcd(unsigned int val) { - int retval; - + int retval; retval = (val / 10) << 4; retval = retval | val % 10; @@ -678,7 +749,7 @@ * a block device) to an MSF format. */ static void -log_to_msf(unsigned int log, unsigned char *msf) +log_to_msf(unsigned int log, Byte *msf) { log = log + LOG_START_OFFSET; msf[0] = int_to_bcd(log / 4500); @@ -692,7 +763,7 @@ * Convert an MSF format to a logical sector. */ static unsigned int -msf_to_log(unsigned char *msf) +msf_to_log(Byte *msf) { unsigned int log; @@ -711,8 +782,7 @@ * the drive would want to see a number-of-sector value. */ static void -size_to_buf(unsigned int size, - unsigned char *buf) +size_to_buf(unsigned int size, Byte *buf) { buf[0] = size / 65536; size = size % 65536; @@ -731,14 +801,15 @@ static void do_cdu535_request(void) { - int block; unsigned int dev; - int nsect; - unsigned char params[10]; - int copyoff; - int spin_up_retry; unsigned int read_size; - unsigned char status[2], cmd[2]; + int block; + int nsect; + int copyoff; + int spin_up_retry; + Byte params[10]; + Byte status[2]; + Byte cmd[2]; if (!sony_inuse) { @@ -798,33 +869,37 @@ size_to_buf(read_size, ¶ms[3]); /* - * Read the data. If the drive was not spinning, spin it up and try - * once more. I know, the goto is ugly, but I am too lazy to fix it. + * Read the data. If the drive was not spinning, + * spin it up and try once more. */ spin_up_retry = 0; - try_read_again: + for (;;) { #if DEBUG > 1 - if (check_drive_status() != 0) { /* drive not ready */ - sony_first_block = -1; - sony_last_block = -1; - end_request(0); - return; - } + if (check_drive_status() != 0) { + /* drive not ready */ + sony_first_block = -1; + sony_last_block = -1; + end_request(0); + return; + } #endif - if (seek_and_read_N_blocks(params, read_size, status, sony_buffer, - (read_size * 2048)) < 0) { - if ((status[0] & SONY535_STATUS1_NOT_SPINNING) && (!spin_up_retry)) { - printk(" Sony535 Debug -- calling spin up when reading data!\n"); - cmd[0] = SONY535_SPIN_UP; - do_sony_cmd(cmd, 1, status, NULL, 0, 0); - spin_up_retry = 1; - goto try_read_again; + if (0 <= seek_and_read_N_blocks(params, read_size, + status, sony_buffer, (read_size * 2048))) + break; + if (!(status[0] & SONY535_STATUS1_NOT_SPINNING) || + spin_up_retry) { + printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n", + status[0]); + sony_first_block = -1; + sony_last_block = -1; + end_request(0); + return; } - printk("Sony CDROM Read error: 0x%.2x\n", status[0]); - sony_first_block = -1; - sony_last_block = -1; - end_request(0); - return; + printk(CDU535_MESSAGE_NAME + " debug: calling spin up when reading data!\n"); + cmd[0] = SONY535_SPIN_UP; + do_sony_cmd(cmd, 1, status, NULL, 0, 0); + spin_up_retry = 1; } } /* @@ -866,7 +941,7 @@ static void sony_get_toc(void) { - unsigned char status[2]; + Byte status[2]; if (!sony_toc_read) { /* do not call check_drive_status() from here since it can call this routine */ if (request_toc_data(status, sony_toc) < 0) @@ -884,8 +959,8 @@ static int find_track(int track) { - int i; - int num_tracks; + int i; + int num_tracks; num_tracks = bcd_to_int(sony_toc->last_track_num) - @@ -905,16 +980,17 @@ static int read_subcode(void) { - Byte cmd = SONY535_REQUEST_SUB_Q_DATA, status[2]; - int dsc_status; + Byte cmd = SONY535_REQUEST_SUB_Q_DATA; + Byte status[2]; + int dsc_status; if (check_drive_status() != 0) return -EIO; if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode, - sizeof (struct s535_sony_subcode), 1)) != 0) { - printk("Sony CDROM error 0x%.2x, %d (read_subcode)\n", status[0], - dsc_status); + sizeof(struct s535_sony_subcode), 1)) != 0) { + printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n", + status[0], dsc_status); return -EIO; } return 0; @@ -942,9 +1018,9 @@ if (!sony_toc_read) { return -EIO; } - verify_area(VERIFY_WRITE /* and read */ , (char *)arg, sizeof (schi)); + verify_area(VERIFY_WRITE /* and read */ , (char *)arg, sizeof schi); - memcpy_fromfs(&schi, (char *)arg, sizeof (schi)); + memcpy_fromfs(&schi, (char *)arg, sizeof schi); switch (sony_audio_status) { case CDROM_AUDIO_PLAY: @@ -959,7 +1035,7 @@ case CDROM_AUDIO_NO_STATUS: schi.cdsc_audiostatus = sony_audio_status; - memcpy_tofs((char *)arg, &schi, sizeof (schi)); + memcpy_tofs((char *)arg, &schi, sizeof schi); return 0; break; @@ -986,7 +1062,7 @@ schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf); schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf); } - memcpy_tofs((char *)arg, &schi, sizeof (schi)); + memcpy_tofs((char *)arg, &schi, sizeof schi); return 0; } @@ -1001,9 +1077,9 @@ unsigned long arg) { unsigned int dev; - unsigned char status[2]; - unsigned char cmd_buff[10], params[10]; - int i, dsc_status; + Byte status[2]; + Byte cmd_buff[10], params[10]; + int i, dsc_status; if (!inode) { @@ -1019,7 +1095,8 @@ switch (cmd) { case CDROMSTART: /* Spin up the drive */ if (spin_up_drive(status) < 0) { - printk("Sony CDROM error 0x%.2x (CDROMSTART)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n", + status[0]); return -EIO; } return 0; @@ -1038,7 +1115,8 @@ dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) || ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) { - printk("Sony CDROM error 0x%.2x (CDROMSTOP)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n", + status[0]); return -EIO; } return 0; @@ -1047,7 +1125,8 @@ case CDROMPAUSE: /* Pause the drive */ cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */ if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) { - printk("Sony CDROM error 0x%.2x (CDROMPAUSE)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n", + status[0]); return -EIO; } /* Get the current position and save it for resuming */ @@ -1082,7 +1161,8 @@ cmd_buff[9] = final_pos_msf[2]; if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { - printk("Sony CDROM error 0x%.2x (CDROMRESUME)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n", + status[0]); return -EIO; } sony_audio_status = CDROM_AUDIO_PLAY; @@ -1108,7 +1188,8 @@ /* cmd_buff[7-9] are filled in for loop above */ if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { - printk("Sony CDROM error 0x%.2x (CDROMPLAYMSF)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n", + status[0]); return -EIO; } /* Save the final position for pauses and resumes */ @@ -1128,10 +1209,10 @@ if (!sony_toc_read) return -EIO; hdr = (struct cdrom_tochdr *)arg; - verify_area(VERIFY_WRITE, hdr, sizeof (*hdr)); + verify_area(VERIFY_WRITE, hdr, sizeof *hdr); loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num); loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num); - memcpy_tofs(hdr, &loc_hdr, sizeof (*hdr)); + memcpy_tofs(hdr, &loc_hdr, sizeof *hdr); } return 0; break; @@ -1140,17 +1221,17 @@ { struct cdrom_tocentry *entry; struct cdrom_tocentry loc_entry; - int track_idx; - unsigned char *msf_val = NULL; + int track_idx; + Byte *msf_val = NULL; sony_get_toc(); if (!sony_toc_read) { return -EIO; } entry = (struct cdrom_tocentry *)arg; - verify_area(VERIFY_WRITE /* and read */ , entry, sizeof (*entry)); + verify_area(VERIFY_WRITE /* and read */ , entry, sizeof *entry); - memcpy_fromfs(&loc_entry, entry, sizeof (loc_entry)); + memcpy_fromfs(&loc_entry, entry, sizeof loc_entry); /* Lead out is handled separately since it is special. */ if (loc_entry.cdte_track == CDROM_LEADOUT) { @@ -1174,7 +1255,7 @@ loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1)); loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2)); } - memcpy_tofs(entry, &loc_entry, sizeof (*entry)); + memcpy_tofs(entry, &loc_entry, sizeof *entry); } return 0; break; @@ -1182,14 +1263,14 @@ case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ { struct cdrom_ti ti; - int track_idx; + int track_idx; sony_get_toc(); if (!sony_toc_read) return -EIO; - verify_area(VERIFY_READ, (char *)arg, sizeof (ti)); + verify_area(VERIFY_READ, (char *)arg, sizeof ti); - memcpy_fromfs(&ti, (char *)arg, sizeof (ti)); + memcpy_fromfs(&ti, (char *)arg, sizeof ti); if ((ti.cdti_trk0 < sony_toc->first_track_num) || (sony_toc->last_track_num < ti.cdti_trk0) || (ti.cdti_trk1 < ti.cdti_trk0)) { @@ -1234,9 +1315,11 @@ cmd_buff[9] = params[6]; if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { - printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1], - params[2], params[3], params[4], params[5], params[6]); - printk("Sony CDROM error 0x%.2x (CDROMPLAYTRKIND)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n", + status[0]); + printk("... Params: %x %x %x %x %x %x %x\n", + params[0], params[1], params[2], + params[3], params[4], params[5], params[6]); return -EIO; } /* Save the final position for pauses and resumes */ @@ -1254,14 +1337,15 @@ { struct cdrom_volctrl volctrl; - verify_area(VERIFY_READ, (char *)arg, sizeof (volctrl)); + verify_area(VERIFY_READ, (char *)arg, sizeof volctrl); - memcpy_fromfs(&volctrl, (char *)arg, sizeof (volctrl)); + memcpy_fromfs(&volctrl, (char *)arg, sizeof volctrl); cmd_buff[0] = SONY535_SET_VOLUME; cmd_buff[1] = volctrl.channel0; cmd_buff[2] = volctrl.channel1; if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) { - printk("Sony CDROM error 0x%.2x (CDROMVOLCTRL)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n", + status[0]); return -EIO; } } @@ -1276,7 +1360,8 @@ sony_audio_status = CDROM_AUDIO_INVALID; cmd_buff[0] = SONY535_EJECT_CADDY; if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) { - printk("Sony CDROM error 0x%.2x (CDROMEJECT)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n", + status[0]); return -EIO; } return 0; @@ -1296,7 +1381,7 @@ cdu_open(struct inode *inode, struct file *filp) { - unsigned char status[2], cmd_buff[2]; + Byte status[2], cmd_buff[2]; if (sony_inuse) @@ -1307,7 +1392,8 @@ MOD_INC_USE_COUNT; if (spin_up_drive(status) != 0) { - printk("Sony CDROM error 0x%.2x (cdu_open, spin up)\n", status[0]); + printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n", + status[0]); sony_inuse = 0; MOD_DEC_USE_COUNT; return -EIO; @@ -1343,7 +1429,7 @@ cdu_release(struct inode *inode, struct file *filp) { - unsigned char status[2], cmd_no; + Byte status[2], cmd_no; sony_inuse = 0; MOD_DEC_USE_COUNT; @@ -1392,28 +1478,44 @@ unsigned long sony535_init(unsigned long mem_start, unsigned long mem_end) #else -int +int init_module(void) #endif { struct s535_sony_drive_config drive_config; - unsigned char cmd_buff[3], ret_buff[2]; - unsigned char status[2]; - int retry_count; + Byte cmd_buff[3]; + Byte ret_buff[2]; + Byte status[2]; + int retry_count; + int tmp_irq; #ifdef MODULE - int i; + int i; #endif + /* Setting the base I/O address to 0xffff will disable it. */ + if (sony535_cd_base_io == 0xffff) + goto bail; + /* Set up all the register locations */ - result_reg = sony_cd_base_io; - command_reg = sony_cd_base_io; - data_reg = sony_cd_base_io + 1; - read_status_reg = sony_cd_base_io + 2; - select_unit_reg = sony_cd_base_io + 3; - - printk("sonycd535: probing base address %03X\n", sony_cd_base_io); - if (check_region(sony_cd_base_io,4)) { - printk("sonycd535: my base address is not free!\n"); + result_reg = sony535_cd_base_io; + command_reg = sony535_cd_base_io; + data_reg = sony535_cd_base_io + 1; + read_status_reg = sony535_cd_base_io + 2; + select_unit_reg = sony535_cd_base_io + 3; + +#ifndef USE_IRQ + sony535_irq_used = 0; /* polling only until this is ready... */ +#endif + /* we need to poll until things get initialized */ + tmp_irq = sony535_irq_used; + sony535_irq_used = 0; + +#if DEBUG > 0 + printk(CDU535_MESSAGE_NAME ": probing base address %03X\n", + sony535_cd_base_io); +#endif + if (check_region(sony535_cd_base_io,4)) { + printk(CDU535_MESSAGE_NAME ": my base address is not free!\n"); #ifndef MODULE return mem_start; #else @@ -1433,19 +1535,46 @@ select_unit(0); if (inb(result_reg) != 0xff) break; - sony_sleep(); /* about 1-2 ms on my machine */ + sony_sleep(); } if ((jiffies < retry_count) && (check_drive_status() != TIME_OUT)) { /* CD-ROM drive responded -- get the drive configuration */ cmd_buff[0] = SONY535_INQUIRY; - if (do_sony_cmd(cmd_buff, 1, status, (Byte *) & drive_config, 28, 1) == 0) { - /* was able to get the configuration, set drive mode as rest of init */ + if (do_sony_cmd(cmd_buff, 1, status, + (Byte *)&drive_config, 28, 1) == 0) { + /* was able to get the configuration, + * set drive mode as rest of init + */ #if DEBUG > 0 /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */ if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 ) - printk("Inquiry command returned status = 0x%x\n", status[0]); + printk(CDU535_MESSAGE_NAME + "Inquiry command returned status = 0x%x\n", status[0]); #endif + /* now ready to use interrupts, if available */ + sony535_irq_used = tmp_irq; +#ifndef MODULE +/* This code is not in MODULEs by default, since the autoirq stuff might + * not be in the module-accessable symbol table. + */ + /* A negative sony535_irq_used will attempt an autoirq. */ + if (sony535_irq_used < 0) { + autoirq_setup(0); + enable_interrupts(); + outb(0, read_status_reg); /* does a reset? */ + sony535_irq_used = autoirq_report(10); + disable_interrupts(); + } +#endif + if (sony535_irq_used > 0) { + if (request_irq(sony535_irq_used, cdu535_interrupt, + SA_INTERRUPT, CDU535_HANDLE)) { + printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME + " driver; polling instead.\n", sony535_irq_used); + sony535_irq_used = 0; + } + } cmd_buff[0] = SONY535_SET_DRIVE_MODE; cmd_buff[1] = 0x0; /* default audio */ if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) { @@ -1453,11 +1582,14 @@ sony_buffer_size = SONY535_BUFFER_SIZE; sony_buffer_sectors = sony_buffer_size / 2048; - printk("Sony I/F CDROM : %8.8s %16.16s %4.4s", + printk(CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s", drive_config.vendor_id, drive_config.product_id, drive_config.product_rev_level); - printk(" using %d byte buffer\n", sony_buffer_size); + printk(" base address %03X, ", sony535_cd_base_io); + if (tmp_irq > 0) + printk("IRQ%d, ", tmp_irq); + printk("using %d byte buffer\n", sony_buffer_size); if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { printk("Unable to get major %d for %s\n", @@ -1473,21 +1605,21 @@ #ifndef MODULE sony_toc = (struct s535_sony_toc *)mem_start; - mem_start += sizeof (*sony_toc); + mem_start += sizeof *sony_toc; last_sony_subcode = (struct s535_sony_subcode *)mem_start; - mem_start += sizeof (*last_sony_subcode); - sony_buffer = (unsigned char *)mem_start; + mem_start += sizeof *last_sony_subcode; + sony_buffer = (Byte *)mem_start; mem_start += sony_buffer_size; #else /* MODULE */ sony_toc = (struct s535_sony_toc *) - kmalloc(sizeof (*sony_toc), GFP_KERNEL); + kmalloc(sizeof *sony_toc, GFP_KERNEL); last_sony_subcode = (struct s535_sony_subcode *) - kmalloc(sizeof (*last_sony_subcode), GFP_KERNEL); - sony_buffer = (unsigned char **) + kmalloc(sizeof *last_sony_subcode, GFP_KERNEL); + sony_buffer = (Byte **) kmalloc(4 * sony_buffer_sectors, GFP_KERNEL); for (i = 0; i < sony_buffer_sectors; i++) - sony_buffer[i] = (unsigned char *)kmalloc(2048, GFP_KERNEL); + sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL); #endif /* MODULE */ initialized = 1; } @@ -1500,8 +1632,9 @@ return -EIO; #endif } else { - request_region(sony_cd_base_io, 4, CDU535_HANDLE); + request_region(sony535_cd_base_io, 4, CDU535_HANDLE); } +bail: #ifndef MODULE return mem_start; #else @@ -1511,7 +1644,7 @@ #ifndef MODULE /* - * accept "kernel command line" parameters + * accept "kernel command line" parameters * (added by emoenke@gwdg.de) * * use: tell LILO: @@ -1522,33 +1655,35 @@ void sonycd535_setup(char *strings, int *ints) { + /* if IRQ change and default io base desired, + * then call with io base of 0 + */ if (ints[0] > 0) - sony_cd_base_io = ints[1]; -#if 0 /* placeholder for future use */ + if (ints[0] != 0) + sony535_cd_base_io = ints[1]; if (ints[0] > 1) - irq_used = ints[2]; -#endif + sony535_irq_used = ints[2]; if ((strings != NULL) && (*strings != '\0')) - printk("%s: Warning: Unknown interface type: %s\n", - strings, CDU535_MESSAGE_NAME); + printk(CDU535_MESSAGE_NAME + ": Warning: Unknown interface type: %s\n", strings); } #else /* MODULE */ -void +void cleanup_module(void) { int i; if (MOD_IN_USE) { - printk("Sony 535 module in use, cannot remove\n"); + printk(CDU535_HANDLE " module in use, cannot remove\n"); return; } - release_region(sony_cd_base_io, 4); - kfree_s(sony_toc, sizeof (*sony_toc)); - kfree_s(last_sony_subcode, sizeof (*last_sony_subcode)); + release_region(sony535_cd_base_io, 4); for (i = 0; i < sony_buffer_sectors; i++) kfree_s(sony_buffer[i], 2048); kfree_s(sony_buffer, 4 * sony_buffer_sectors); + kfree_s(last_sony_subcode, sizeof *last_sony_subcode); + kfree_s(sony_toc, sizeof *sony_toc); if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); else diff -u --recursive --new-file v1.1.93/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v1.1.93/linux/drivers/char/ChangeLog Thu Feb 9 10:18:50 1995 +++ linux/drivers/char/ChangeLog Mon Feb 20 21:29:52 1995 @@ -1,3 +1,75 @@ +Sat Feb 18 12:13:51 1995 Theodore Y. Ts'o (tytso@rt-11) + + * tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear + current->tty_old_pgrp field when a session leader + acquires a controlling tty, and after a session leader + has disassociated from a controlling tty. + +Fri Feb 17 09:34:09 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_interrupt_single, rs_interrupt, rs_interrupt_multi): + Change the the number of passes made from 64 to be 256, + configurable with the #define RS_ISR_PASS_LIMIT. + + * serial.c (rs_init, set_serial_info, get_serial_info, rs_close): + Remove support for closing_wait2. Instead, set + tty->closing and rely on the line dispcline to prevent + echo wars. + + * n_tty.c (n_tty_receive_char): IEXTEN does not need to be + enabled in order for IXANY to be active. + + If tty->closing is set, then only process XON and XOFF + characters. + +Sun Feb 12 23:57:48 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_timer): Change the interrupt poll time from 60 + seconds to 10 seconds, configurable with the #define + RS_STROBE_TIME. + + * serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl, + set_multiport_struct, get_multiport_struct): Add + provisions for a new type of interrutp service routine, + which better supports multiple serial ports on a single + IRQ. + +Sun Feb 5 19:35:11 1995 Theodore Y. Ts'o (tytso@rt-11) + + * tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent): + * serial.c (rs_ioctl, rs_close): + * cyclades.c (cy_ioctl, cy_close): + * n_tty.c (n_tty_close): Rename wait_until_sent to + tty_wait_until_sent, so that it's a better name to export + in ksyms.c. + +Sat Feb 4 23:36:20 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_close): Added missing check for closing_wait2 being + ASYNC_CLOSING_WAIT_NONE. + +Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_init, set_serial_info, get_serial_info, + rs_close): Support close_wait in the serial driver. + This is helpful for slow devices (like serial + plotters) so that their outputs don't get flushed upon + device close. This has to be configurable because + normally we don't want ports to be hung up for long + periods of time during a close when they are not + connected to a device, or the device is powered off. + + The default is to wait 30 seconds; in the case of a + very slow device, the close_wait timeout should be + lengthed. If it is set to 0, the kernel will wait + forever for all of the data to be transmitted. + +Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (startup, change_speed, rs_init): Add support to detect + the StarTech 16650 chip. Treat it as a 16450 for now, + because of its FIFO bugs. + Thu Jan 5 21:21:57 1995 * serial.c: (receive_char): Added counter to prevent infinite loop diff -u --recursive --new-file v1.1.93/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v1.1.93/linux/drivers/char/n_tty.c Thu Feb 9 10:18:51 1995 +++ linux/drivers/char/n_tty.c Mon Feb 20 21:29:52 1995 @@ -345,7 +345,7 @@ return; } - if (tty->stopped && I_IXON(tty) && I_IXANY(tty) && L_IEXTEN(tty)) { + if (tty->stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); return; } @@ -355,6 +355,16 @@ if (I_IUCLC(tty) && L_IEXTEN(tty)) c=tolower(c); + if (tty->closing) { + if (I_IXON(tty)) { + if (c == START_CHAR(tty)) + start_tty(tty); + else if (c == STOP_CHAR(tty)) + stop_tty(tty); + } + return; + } + /* * If the previous character was LNEXT, or we know that this * character is not one of the characters that we'll have to @@ -690,6 +700,7 @@ memset(tty->read_flags, 0, sizeof(tty->read_flags)); n_tty_set_termios(tty, 0); tty->minimum_to_wake = 1; + tty->closing = 0; return 0; } diff -u --recursive --new-file v1.1.93/linux/drivers/char/selection.c linux/drivers/char/selection.c --- v1.1.93/linux/drivers/char/selection.c Fri Feb 17 11:20:12 1995 +++ linux/drivers/char/selection.c Wed Feb 22 12:27:52 1995 @@ -3,10 +3,10 @@ * * This module exports the functions: * - * 'int set_selection(const int arg)' + * 'int set_selection(const unsigned long arg)' * 'void clear_selection(void)' * 'int paste_selection(struct tty_struct *tty)' - * 'int sel_loadlut(const int arg)' + * 'int sel_loadlut(const unsigned long arg)' * * Now that /dev/vcs exists, most of this can disappear again. */ @@ -15,6 +15,9 @@ #include #include #include + +#include + #include "vt_kern.h" #include "consolemap.h" #include "selection.h" @@ -82,7 +85,7 @@ } /* set inwordLut contents. Invoked by ioctl(). */ -int sel_loadlut(const int arg) +int sel_loadlut(const unsigned long arg) { int i = verify_area(VERIFY_READ, (char *) arg, 36); if (i) @@ -107,7 +110,7 @@ } /* set the current selection. Invoked by ioctl(). */ -int set_selection(const int arg, struct tty_struct *tty) +int set_selection(const unsigned long arg, struct tty_struct *tty) { int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; diff -u --recursive --new-file v1.1.93/linux/drivers/char/selection.h linux/drivers/char/selection.h --- v1.1.93/linux/drivers/char/selection.h Fri Feb 17 11:20:13 1995 +++ linux/drivers/char/selection.h Wed Feb 22 12:27:52 1995 @@ -6,9 +6,9 @@ extern int sel_cons; extern void clear_selection(void); -extern int set_selection(const int arg, struct tty_struct *tty); +extern int set_selection(const unsigned long arg, struct tty_struct *tty); extern int paste_selection(struct tty_struct *tty); -extern int sel_loadlut(const int arg); +extern int sel_loadlut(const unsigned long arg); extern int mouse_reporting(void); extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); @@ -33,7 +33,9 @@ /* how to access screen memory */ #ifdef __alpha__ - + +#include + static inline void scr_writew(unsigned short val, unsigned short * addr) { if ((long) addr < 0) diff -u --recursive --new-file v1.1.93/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v1.1.93/linux/drivers/char/serial.c Thu Feb 9 10:18:51 1995 +++ linux/drivers/char/serial.c Mon Feb 20 21:29:52 1995 @@ -67,12 +67,14 @@ #define SERIAL_PARANOIA_CHECK #define CONFIG_SERIAL_NOPAUSE_IO #define SERIAL_DO_RESTART -#define CONFIG_SERIAL_NEW_ISR #undef SERIAL_DEBUG_INTR #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + #define _INLINE_ inline /* @@ -81,6 +83,7 @@ */ static struct async_struct *IRQ_ports[16]; +static struct rs_multiport_struct rs_multiport[16]; static int IRQ_timeout[16]; static volatile int rs_irq_triggered; static volatile int rs_triggered; @@ -420,9 +423,7 @@ if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif return; } @@ -445,9 +446,7 @@ if (info->xmit_cnt <= 0) { info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif } } @@ -480,9 +479,7 @@ #endif info->tty->hw_stopped = 0; info->IER |= UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); return; } @@ -493,15 +490,12 @@ #endif info->tty->hw_stopped = 1; info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif } } } } -#ifdef CONFIG_SERIAL_NEW_ISR /* * This is the serial driver's generic interrupt routine */ @@ -511,6 +505,8 @@ struct async_struct * info; int pass_counter = 0; struct async_struct *end_mark = 0; + int first_multi = 0; + struct rs_multiport_struct *multi; #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt(%d)...", irq); @@ -520,6 +516,10 @@ if (!info) return; + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); + do { if (!info->tty || (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) { @@ -545,7 +545,7 @@ info = info->next_port; if (!info) { info = IRQ_ports[irq]; - if (pass_counter++ > 64) { + if (pass_counter++ > RS_ISR_PASS_LIMIT) { #if 0 printk("rs loop break\n"); #endif @@ -554,6 +554,9 @@ continue; } } while (end_mark != info); + if (multi->port_monitor) + printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, inb(multi->port_monitor)); #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif @@ -566,7 +569,9 @@ { int status; int pass_counter = 0; + int first_multi = 0; struct async_struct * info; + struct rs_multiport_struct *multi; #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d)...", irq); @@ -576,6 +581,10 @@ if (!info || !info->tty) return; + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); + do { status = serial_inp(info, UART_LSR) & info->read_status_mask; #ifdef SERIAL_DEBUG_INTR @@ -586,7 +595,7 @@ check_modem_status(info); if (status & UART_LSR_THRE) transmit_chars(info, 0); - if (pass_counter++ > 64) { + if (pass_counter++ > RS_ISR_PASS_LIMIT) { #if 0 printk("rs_single loop break.\n"); #endif @@ -594,102 +603,95 @@ } } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); info->last_active = jiffies; + if (multi->port_monitor) + printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, inb(multi->port_monitor)); #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif } -#else /* CONFIG_SERIAL_NEW_ISR */ - /* - * This is the serial driver's generic interrupt routine + * This is the serial driver's for multiport boards */ -static void rs_interrupt(int irq, struct pt_regs * regs) +static void rs_interrupt_multi(int irq, struct pt_regs * regs) { int status; struct async_struct * info; - int done = 1, pass_counter = 0; + int pass_counter = 0; + int first_multi= 0; + struct rs_multiport_struct *multi; - #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt(%d)...", irq); + printk("rs_interrupt_multi(%d)...", irq); #endif info = IRQ_ports[irq]; if (!info) return; + multi = &rs_multiport[irq]; + if (!multi->port1) { + /* Should never happen */ + printk("rs_interrupt_multi: NULL port1!\n"); + return; + } + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); while (1) { - if (!info->tty) + if (!info->tty || + (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) goto next; - serial_outp(info, UART_IER, 0); + info->last_active = jiffies; + status = serial_inp(info, UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) { +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) receive_chars(info, &status); - done = 0; - } check_modem_status(info); if (status & UART_LSR_THRE) - transmit_chars(info, &done); + transmit_chars(info, 0); next: - info = info->next_port; - if (!info) { - info = IRQ_ports[irq]; - if (done) - break; - done = 1; - if (pass_counter++ > 64) { -#if 0 - printk("rs loop break\n"); -#endif - break; /* Prevent infinite loops */ - } - } - } - - /* - * Reset the IER registers; info is already set up from the - * above while loop. - */ - do - serial_outp(info, UART_IER, info->IER); - while ((info = info->next_port) != NULL); -} - -/* - * This is the serial driver's interrupt routine for a single port - */ -static void rs_interrupt_single(int irq, struct pt_regs * regs) -{ - int status; - struct async_struct * info; + info = info->next_port; + if (info) + continue; - + info = IRQ_ports[irq]; + if (pass_counter++ > RS_ISR_PASS_LIMIT) { +#if 1 + printk("rs_multi loop break\n"); +#endif + break; /* Prevent infinite loops */ + } + if (multi->port_monitor) + printk("rs port monitor irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, + inb(multi->port_monitor)); + if ((inb(multi->port1) & multi->mask1) != multi->match1) + continue; + if (!multi->port2) + break; + if ((inb(multi->port2) & multi->mask2) != multi->match2) + continue; + if (!multi->port3) + break; + if ((inb(multi->port3) & multi->mask3) != multi->match3) + continue; + if (!multi->port4) + break; + if ((inb(multi->port4) & multi->mask4) == multi->match4) + continue; + break; + } #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); + printk("end.\n"); #endif - - info = IRQ_ports[irq]; - if (!info || !info->tty) - return; - - serial_outp(info, UART_IER, 0); - status = serial_inp(info, UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) - receive_chars(info, &status); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - - /* - * Reset the IER register - */ - serial_outp(info, UART_IER, info->IER); } -#endif /* CONFIG_SERIAL_NEW_ISR */ /* * ------------------------------------------------------------------- @@ -747,7 +749,7 @@ struct async_struct *info; unsigned int i; - if ((jiffies - last_strobe) >= 60*HZ) { + if ((jiffies - last_strobe) >= RS_STROBE_TIME*HZ) { for (i=1; i < 16; i++) { info = IRQ_ports[i]; if (!info) @@ -760,14 +762,17 @@ serial_out(info, UART_IER, info->IER); info = info->next_port; } while (info); - rs_interrupt(i, NULL); + if (rs_multiport[i].port1) + rs_interrupt_multi(i, NULL); + else + rs_interrupt(i, NULL); } else rs_interrupt_single(i, NULL); sti(); } } last_strobe = jiffies; - timer_table[RS_TIMER].expires = jiffies + 60 * HZ; + timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME * HZ; timer_active |= 1 << RS_TIMER; if (IRQ_ports[0]) { @@ -877,7 +882,11 @@ * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) */ - if (info->type == PORT_16550A) { + if (info->type == PORT_16650) { + serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + info->xmit_fifo_size = 1; /* disabled for now */ + } else if (info->type == PORT_16550A) { serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); info->xmit_fifo_size = 16; @@ -906,7 +915,10 @@ !IRQ_ports[info->irq]->next_port)) { if (IRQ_ports[info->irq]) { free_irq(info->irq); - handler = rs_interrupt; + if (rs_multiport[info->irq].port1) + handler = rs_interrupt_multi; + else + handler = rs_interrupt; } else handler = rs_interrupt_single; @@ -1148,6 +1160,18 @@ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } else if (info->type == PORT_16650) { + /* + * On the 16650, we disable the FIFOs altogether + * because of a design bug in how the implement + * things. We could support it by completely changing + * how we handle the interrupt driver, but not today.... + * + * N.B. Because there's no way to set a FIFO trigger + * at 1 char, we'd probably disable at speed below + * 2400 baud anyway... + */ + fcr = 0; } else fcr = 0; @@ -1404,6 +1428,7 @@ tmp.flags = info->flags; tmp.baud_base = info->baud_base; tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; tmp.hub6 = info->hub6; memcpy_tofs(retinfo,&tmp,sizeof(*retinfo)); @@ -1471,6 +1496,7 @@ info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; release_region(info->port,8); if (change_port || change_irq) { @@ -1676,6 +1702,101 @@ return wild_interrupts; } +static int get_multiport_struct(struct async_struct * info, + struct serial_multiport_struct *retinfo) +{ + struct serial_multiport_struct ret; + struct rs_multiport_struct *multi; + + multi = &rs_multiport[info->irq]; + + ret.port_monitor = multi->port_monitor; + + ret.port1 = multi->port1; + ret.mask1 = multi->mask1; + ret.match1 = multi->match1; + + ret.port2 = multi->port2; + ret.mask2 = multi->mask2; + ret.match2 = multi->match2; + + ret.port3 = multi->port3; + ret.mask3 = multi->mask3; + ret.match3 = multi->match3; + + ret.port4 = multi->port4; + ret.mask4 = multi->mask4; + ret.match4 = multi->match4; + + ret.irq = info->irq; + + memcpy_tofs(retinfo,&ret,sizeof(*retinfo)); + return 0; + +} + +static int set_multiport_struct(struct async_struct * info, + struct serial_multiport_struct *in_multi) +{ + struct serial_multiport_struct new_multi; + struct rs_multiport_struct *multi; + int was_multi, now_multi; + int retval; + void (*handler)(int, struct pt_regs *); + + if (!suser()) + return -EPERM; + if (!in_multi) + return -EFAULT; + memcpy_fromfs(&new_multi, in_multi, + sizeof(struct serial_multiport_struct)); + + if (new_multi.irq != info->irq || info->irq == 0 || + !IRQ_ports[info->irq]) + return -EINVAL; + + multi = &rs_multiport[info->irq]; + was_multi = (multi->port1 != 0); + + multi->port_monitor = new_multi.port_monitor; + + multi->port1 = new_multi.port1; + multi->mask1 = new_multi.mask1; + multi->match1 = new_multi.match1; + + multi->port2 = new_multi.port2; + multi->mask2 = new_multi.mask2; + multi->match2 = new_multi.match2; + + multi->port3 = new_multi.port3; + multi->mask3 = new_multi.mask3; + multi->match3 = new_multi.match3; + + multi->port4 = new_multi.port4; + multi->mask4 = new_multi.mask4; + multi->match4 = new_multi.match4; + + now_multi = (multi->port1 != 0); + + if (IRQ_ports[info->irq]->next_port && + (was_multi != now_multi)) { + free_irq(info->irq); + if (now_multi) + handler = rs_interrupt_multi; + else + handler = rs_interrupt; + + retval = request_irq(info->irq, handler, SA_INTERRUPT, + "serial"); + if (retval) { + printk("Couldn't reallocate serial interrupt " + "driver!!\n"); + } + } + + return 0; +} + static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { @@ -1778,6 +1899,16 @@ info, sizeof(struct async_struct)); return 0; + case TIOCSERGETMULTI: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_multiport_struct)); + if (error) + return error; + return get_multiport_struct(info, + (struct serial_multiport_struct *) arg); + case TIOCSERSETMULTI: + return set_multiport_struct(info, + (struct serial_multiport_struct *) arg); default: return -ENOIOCTLCMD; } @@ -1872,6 +2003,13 @@ if (info->flags & ASYNC_CALLOUT_ACTIVE) info->callout_termios = *tty->termios; /* + * Now we wait for the trnasmit buffer to clear; and we notify + * the line discpline only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the @@ -1881,7 +2019,6 @@ info->read_status_mask &= ~UART_LSR_DR; if (info->flags & ASYNC_INITIALIZED) { serial_out(info, UART_IER, info->IER); - tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1901,6 +2038,7 @@ tty->driver.flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); + tty->closing = 0; info->event = 0; info->tty = 0; if (tty->ldisc.num != ldiscs[N_TTY].num) { @@ -2155,7 +2293,7 @@ */ static void show_serial_version(void) { - printk("Serial driver version 4.00 with"); + printk("Serial driver version 4.11 with"); #ifdef CONFIG_HUB6 printk(" HUB-6"); #define SERIAL_OPT @@ -2329,6 +2467,10 @@ if (info->flags & ASYNC_AUTO_IRQ) info->irq = do_auto_irq(info); + scratch2 = serial_in(info, UART_LCR); + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ + serial_outp(info, UART_LCR, scratch2); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(info, UART_IIR) >> 6; info->xmit_fifo_size = 1; @@ -2343,8 +2485,15 @@ info->type = PORT_16550; break; case 3: - info->type = PORT_16550A; - info->xmit_fifo_size = 16; + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + if (serial_in(info, UART_EFR) == 0) { + info->type = PORT_16650; + info->xmit_fifo_size = 32; + } else { + info->type = PORT_16550A; + info->xmit_fifo_size = 16; + } + serial_outp(info, UART_LCR, scratch2); break; } if (info->type == PORT_16450) { @@ -2398,6 +2547,7 @@ for (i = 0; i < 16; i++) { IRQ_ports[i] = 0; IRQ_timeout[i] = 0; + memset(&rs_multiport[i], 0, sizeof(struct rs_multiport_struct)); } show_serial_version(); @@ -2458,6 +2608,7 @@ info->type = PORT_UNKNOWN; info->custom_divisor = 0; info->close_delay = 50; + info->closing_wait = 3000; info->x_char = 0; info->event = 0; info->count = 0; @@ -2492,6 +2643,9 @@ break; case PORT_16550A: printk(" is a 16550A\n"); + break; + case PORT_16650: + printk(" is a 16650\n"); break; default: printk("\n"); diff -u --recursive --new-file v1.1.93/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.1.93/linux/drivers/char/tty_io.c Fri Feb 17 11:20:13 1995 +++ linux/drivers/char/tty_io.c Mon Feb 20 21:29:52 1995 @@ -452,6 +452,7 @@ kill_pg(tty->pgrp, SIGCONT, priv); } + current->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; @@ -1165,6 +1166,7 @@ !current->tty && tty->session == 0) { current->tty = tty; + current->tty_old_pgrp = 0; tty->session = current->session; tty->pgrp = current->pgrp; } @@ -1393,6 +1395,7 @@ return -EPERM; } current->tty = tty; + current->tty_old_pgrp = 0; tty->session = current->session; tty->pgrp = current->pgrp; return 0; diff -u --recursive --new-file v1.1.93/linux/drivers/net/README.wavelan linux/drivers/net/README.wavelan --- v1.1.93/linux/drivers/net/README.wavelan Sun Feb 5 19:31:52 1995 +++ linux/drivers/net/README.wavelan Wed Feb 22 16:25:04 1995 @@ -1,13 +1,8 @@ #if defined(CONFIG_WAVELAN) -Tue Jan 31 10:42:35 EST 1995 +Thu Feb 23 00:10:31 EST 1995 -0. This document refers to Version 5 of the Linux WaveLAN device driver software. - It has been tested successfully under the 1.1.87 release of the Linux - kernel. It is `beta-test' software, so caveat emptor. Please report bugs - to me so that I can fix them quickly. - -1. At present the driver only autoprobes for a WaveLAN card at I/O address 0x390. +1. At present the driver autoprobes for a WaveLAN card only at I/O address 0x390. The version of the card that I use (NCR) supports four I/O addresses (selectable via a pair of DIP switches). If you want the driver to autoprobe a different subset of the four valid addresses then you will need to edit @@ -28,20 +23,7 @@ append ="ether=0,0x390,0x4321,eth0" .. -3. The files that comprise this software must be incorporated into the Linux - kernel source tree (usually rooted at /usr/src/linux). Following that a - "make clean; make config; make dep; make zImage" should produce a Linux - kernel incorporating the WaveLAN driver, ready for installation. - The files: - drivers/net/wavelan.[ch] - drivers/net/i82586.h - are unique to this package and simply may be moved into place. The - others are modified versions of pre-existing files and must - be incorporated more carefully. However, the regions of modified code - within these files are small and are bracketed by the preprocessor - symbol CONFIG_WAVELAN, so incorporation should be straightforward. - -4. If you encounter any problems send me some email. +3. If you encounter any problems send me some email. Good luck, Bruce Janson (bruce@cs.usyd.edu.au) diff -u --recursive --new-file v1.1.93/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v1.1.93/linux/drivers/net/wavelan.c Wed Feb 1 09:23:06 1995 +++ linux/drivers/net/wavelan.c Wed Feb 22 16:25:04 1995 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +71,7 @@ extern int wavelan_probe(device *); /* See Space.c */ -static char *version = "wavelan.c:v5 31/1/95\n"; +static char *version = "wavelan.c:v6 22/2/95\n"; /* * Entry point forward declarations. @@ -104,14 +105,6 @@ static net_local *first_wavelan = (net_local *)0; static -void -busy_loop(int i) -{ - while (i-- > 0) - ; -} - -static unsigned long wavelan_splhi(void) { @@ -150,7 +143,7 @@ { hacr_write(ioaddr, hacr); /* delay might only be needed sometimes */ - busy_loop(1000); + udelay(1000); } /* @@ -444,11 +437,13 @@ set_chan_attn(ioaddr, lp->hacr); - for (i = 1000000; i > 0; i--) + for (i = 1000; i > 0; i--) { obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); if (scb_cs == 0) break; + + udelay(1000); } if (i <= 0) @@ -477,11 +472,13 @@ set_chan_attn(ioaddr, lp->hacr); - for (i = 64000; i > 0; i--) + for (i = 64; i > 0; i--) { obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); if (cb.ac_status & AC_SFLD_C) break; + + udelay(1000); } if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) @@ -557,23 +554,27 @@ set_chan_attn(ioaddr, lp->hacr); - for (i = 1000000; i > 0; i--) + for (i = 1000; i > 0; i--) { obram_read(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); if (iscp.iscp_busy == (unsigned short)0) break; + + udelay(1000); } if (i <= 0) printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name); - for (i = 15000; i > 0; i--) + for (i = 15; i > 0; i--) { obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) break; + + udelay(1000); } if (i <= 0) @@ -970,11 +971,13 @@ set_chan_attn(ioaddr, lp->hacr); - for (i = 1000000; i > 0; i--) + for (i = 1000; i > 0; i--) { obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); if (scb_cs == 0) break; + + udelay(1000); } if (i <= 0) @@ -1049,11 +1052,13 @@ set_chan_attn(ioaddr, lp->hacr); - for (i = 1000000; i > 0; i--) + for (i = 1000; i > 0; i--) { obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); if (scb_cs == 0) break; + + udelay(1000); } if (i <= 0) @@ -1849,6 +1854,7 @@ wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs) { net_local *lp; + unsigned long x; lp = (net_local *)dev->priv; @@ -1859,7 +1865,9 @@ * Promiscuous mode: receive all packets. */ lp->promiscuous = 1; + x = wavelan_splhi(); (void)wavelan_hardware_reset(dev); + wavelan_splx(x); break; case 0: @@ -1868,7 +1876,9 @@ * clear multicast list. */ lp->promiscuous = 0; + x = wavelan_splhi(); (void)wavelan_hardware_reset(dev); + wavelan_splx(x); break; default: @@ -2319,9 +2329,9 @@ * Allan Creighton (allanc@cs.usyd.edu.au), * Matthew Geier (matthew@cs.usyd.edu.au), * Remo di Giovanni (remo@cs.usyd.edu.au), + * Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de), * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), * Tim Nicholson (tim@cs.usyd.edu.au), - * Jeff Noxon (jeff@oylpatch.sccsi.com), * Ian Parkin (ian@cs.usyd.edu.au), * John Rosenberg (johnr@cs.usyd.edu.au), * George Rossi (george@phm.gov.au), diff -u --recursive --new-file v1.1.93/linux/fs/buffer.c linux/fs/buffer.c --- v1.1.93/linux/fs/buffer.c Thu Jan 26 07:49:07 1995 +++ linux/fs/buffer.c Mon Feb 20 16:10:32 1995 @@ -1363,7 +1363,7 @@ if(priority > 3 && nlist == BUF_SHARED) continue; bh = lru_list[nlist]; if(!bh) continue; - i = nr_buffers_type[nlist] >> priority; + i = 2*nr_buffers_type[nlist] >> priority; for ( ; i-- > 0 ; bh = bh->b_next_free) { /* We may have stalled while waiting for I/O to complete. */ if(bh->b_list != nlist) goto repeat1; diff -u --recursive --new-file v1.1.93/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v1.1.93/linux/fs/isofs/dir.c Thu Jan 26 07:49:07 1995 +++ linux/fs/isofs/dir.c Wed Feb 22 08:15:14 1995 @@ -183,14 +183,17 @@ is no Rock Ridge NM field. */ else { - /* Do not report hidden or associated files */ - high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; - if (de->flags[-high_sierra] & 5) { - if (cpnt) { - kfree(cpnt); - cpnt = NULL; - }; - continue; + if (inode->i_sb->u.isofs_sb.s_unhide=='n') + { + /* Do not report hidden or associated files */ + high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; + if (de->flags[-high_sierra] & 5) { + if (cpnt) { + kfree(cpnt); + cpnt = NULL; + }; + continue; + } } dlen = de->name_len[0]; dpnt = de->name; diff -u --recursive --new-file v1.1.93/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v1.1.93/linux/fs/isofs/inode.c Thu Feb 9 10:18:53 1995 +++ linux/fs/isofs/inode.c Wed Feb 22 08:15:14 1995 @@ -63,6 +63,7 @@ char map; char rock; char cruft; + char unhide; unsigned char conversion; unsigned int blocksize; mode_t mode; @@ -77,6 +78,7 @@ popt->map = 'n'; popt->rock = 'y'; popt->cruft = 'n'; + popt->unhide = 'n'; popt->conversion = 'a'; popt->blocksize = 1024; popt->mode = S_IRUGO; @@ -88,6 +90,10 @@ popt->rock = 'n'; continue; }; + if (strncmp(this_char,"unhide",6) == 0) { + popt->unhide = 'y'; + continue; + }; if (strncmp(this_char,"cruft",5) == 0) { popt->cruft = 'y'; continue; @@ -214,6 +220,7 @@ printk("map = %c\n", opt.map); printk("rock = %c\n", opt.rock); printk("cruft = %c\n", opt.cruft); + printk("unhide = %c\n", opt.unhide); printk("conversion = %c\n", opt.conversion); printk("blocksize = %d\n", opt.blocksize); printk("gid = %d\n", opt.gid); @@ -353,6 +360,7 @@ s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0); s->u.isofs_sb.s_conversion = opt.conversion; s->u.isofs_sb.s_cruft = opt.cruft; + s->u.isofs_sb.s_unhide = opt.unhide; s->u.isofs_sb.s_uid = opt.uid; s->u.isofs_sb.s_gid = opt.gid; /* diff -u --recursive --new-file v1.1.93/linux/fs/isofs/namei.c linux/fs/isofs/namei.c --- v1.1.93/linux/fs/isofs/namei.c Thu Jan 26 07:49:07 1995 +++ linux/fs/isofs/namei.c Wed Feb 22 08:15:14 1995 @@ -73,7 +73,6 @@ unsigned int old_offset; unsigned int backlink; int dlen, rrflag, match; - int high_sierra = 0; char * dpnt; struct iso_directory_record * de; char c; @@ -155,16 +154,6 @@ backlink = 0; } - /* Do not report hidden or associated files */ - high_sierra = dir->i_sb->u.isofs_sb.s_high_sierra; - if (de->flags[-high_sierra] & 5) { - if (cpnt) { - kfree(cpnt); - cpnt = NULL; - }; - continue; - } - dlen = de->name_len[0]; dpnt = de->name; /* Now convert the filename in the buffer to lower case */ diff -u --recursive --new-file v1.1.93/linux/fs/locks.c linux/fs/locks.c --- v1.1.93/linux/fs/locks.c Fri Feb 17 11:20:16 1995 +++ linux/fs/locks.c Wed Feb 22 09:43:10 1995 @@ -7,7 +7,7 @@ * Deadlock Detection added by Kelly Carmichael, kelly@[142.24.8.65] * September 17, 1994. * - * FIXME: one thing isn't handled yet: + * FIXME: one thing isn't handled yet: * - mandatory locks (requires lots of changes elsewhere) * * Edited by Kai Petzke, wpp@marie.physik.tu-berlin.de @@ -22,7 +22,11 @@ * process. Since locks still depend on the process id, locks are inherited * after an exec() but not after a fork(). This agrees with POSIX, and both * BSD and SVR4 practice. - * Andy Walker (andy@keo.kvaerner.no), February 14, 1994 + * Andy Walker (andy@keo.kvaerner.no), February 14, 1995 + * + * Scrapped free list which is redundant now that we allocate locks + * dynamically with kmalloc()/kfree(). + * Andy Walker (andy@keo.kvaerner.no), February 21, 1995 * */ @@ -45,16 +49,11 @@ static int lock_it(struct file *filp, struct file_lock *caller); static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl); static void free_lock(struct file_lock **fl); -static void free_list_garbage_collect(void); #ifdef DEADLOCK_DETECTION int locks_deadlocked(int my_pid,int blocked_pid); #endif -#define FREE_LIST_GARBAGE_COLLECT 20 - static struct file_lock *file_lock_table = NULL; -static struct file_lock *file_lock_free_list = NULL; -static int free_list_cnt = 0; int fcntl_getlk(unsigned int fd, struct flock *l) { @@ -155,7 +154,8 @@ if (current->signal & ~current->blocked) return -ERESTARTSYS; #ifdef DEADLOCK_DETECTION - if (locks_deadlocked(file_lock.fl_owner->pid,fl->fl_owner->pid)) return -EDEADLOCK; + if (locks_deadlocked(file_lock.fl_owner->pid,fl->fl_owner->pid)) + return -EDEADLOCK; #endif interruptible_sleep_on(&fl->fl_wait); if (current->signal & ~current->blocked) @@ -192,9 +192,11 @@ dlock_wait = fl->fl_wait; do { if (dlock_wait->task != NULL) { - if (dlock_wait->task->pid == blocked_pid) return -EDEADLOCK; + if (dlock_wait->task->pid == blocked_pid) + return -EDEADLOCK; ret_val = locks_deadlocked(dlock_wait->task->pid,blocked_pid); - if (ret_val) return -EDEADLOCK; + if (ret_val) + return -EDEADLOCK; } dlock_wait = dlock_wait->next; } while (dlock_wait != fl->fl_wait); @@ -445,40 +447,26 @@ /* * File_lock() inserts a lock at the position pos of the linked list. - * - * Modified to create a new node if no free entries available - Chad Page - * */ static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl) { struct file_lock *tmp; - tmp = file_lock_free_list; - - if (tmp == NULL) - { - /* Okay, let's make a new file_lock structure... */ - tmp = (struct file_lock *)kmalloc(sizeof(struct file_lock), GFP_KERNEL); - tmp -> fl_owner = NULL; - tmp -> fl_next = file_lock_free_list; - tmp -> fl_nextlink = file_lock_table; - file_lock_table = tmp; - } - else - { - /* remove from free list */ - file_lock_free_list = tmp->fl_next; - free_list_cnt--; - } - - if (tmp->fl_owner != NULL) - panic("alloc_lock: broken free list\n"); + /* Okay, let's make a new file_lock structure... */ + tmp = (struct file_lock *)kmalloc(sizeof(struct file_lock), GFP_KERNEL); + if (!tmp) + return tmp; + tmp->fl_nextlink = file_lock_table; + tmp->fl_prevlink = NULL; + if (file_lock_table != NULL) + file_lock_table->fl_prevlink = tmp; + file_lock_table = tmp; tmp->fl_next = *pos; /* insert into file's list */ *pos = tmp; - tmp->fl_owner = current; /* FIXME: needed? */ + tmp->fl_owner = current; tmp->fl_wait = NULL; tmp->fl_type = fl->fl_type; @@ -490,7 +478,7 @@ } /* - * Add a lock to the free list ... + * Free up a lock... */ static void free_lock(struct file_lock **fl_p) @@ -498,24 +486,19 @@ struct file_lock *fl; fl = *fl_p; - if (fl->fl_owner == NULL) /* sanity check */ - panic("free_lock: broken lock list\n"); - *fl_p = (*fl_p)->fl_next; - fl->fl_next = file_lock_free_list; /* add to free list */ - file_lock_free_list = fl; - fl->fl_owner = NULL; /* for sanity checks */ - - free_list_cnt++; - if (free_list_cnt == FREE_LIST_GARBAGE_COLLECT) - free_list_garbage_collect(); + if (fl->fl_nextlink != NULL) + fl->fl_nextlink->fl_prevlink = fl->fl_prevlink; + + if (fl->fl_prevlink != NULL) + fl->fl_prevlink->fl_nextlink = fl->fl_nextlink; + else + file_lock_table = fl->fl_nextlink; wake_up(&fl->fl_wait); -} -static void free_list_garbage_collect(void) -{ - /* Do nothing for now */ + kfree(fl); + return; } diff -u --recursive --new-file v1.1.93/linux/fs/proc/mem.c linux/fs/proc/mem.c --- v1.1.93/linux/fs/proc/mem.c Wed Feb 1 09:23:06 1995 +++ linux/fs/proc/mem.c Mon Feb 20 21:29:53 1995 @@ -1,3 +1,4 @@ +#define THREE_LEVEL /* * linux/fs/proc/mem.c * @@ -25,7 +26,8 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int count) { - pgd_t *pgdir; + pgd_t *page_dir; + pmd_t *page_middle; pte_t pte; char * page; struct task_struct * tsk; @@ -50,15 +52,23 @@ while (count > 0) { if (current->signal & ~current->blocked) break; - pgdir = PAGE_DIR_OFFSET(tsk,addr); - if (pgd_none(*pgdir)) + page_dir = pgd_offset(tsk,addr); + if (pgd_none(*page_dir)) break; - if (pgd_bad(*pgdir)) { - printk("Bad page dir entry %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); + if (pgd_bad(*page_dir)) { + printk("Bad page dir entry %08lx\n", pgd_val(*page_dir)); + pgd_clear(page_dir); break; } - pte = *(pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + page_middle = pmd_offset(page_dir,addr); + if (pmd_none(*page_middle)) + break; + if (pmd_bad(*page_middle)) { + printk("Bad page middle entry %08lx\n", pmd_val(*page_middle)); + pmd_clear(page_middle); + break; + } + pte = *pte_offset(page_middle,addr); if (!pte_present(pte)) break; page = (char *) pte_page(pte) + (addr & ~PAGE_MASK); @@ -78,8 +88,9 @@ static int mem_write(struct inode * inode, struct file * file,char * buf, int count) { - pgd_t * pgdir; - pte_t * pte; + pgd_t *page_dir; + pmd_t *page_middle; + pte_t pte; char * page; struct task_struct * tsk; unsigned long addr, pid; @@ -103,15 +114,23 @@ while (count > 0) { if (current->signal & ~current->blocked) break; - pgdir = PAGE_DIR_OFFSET(tsk,addr); - if (pgd_none(*pgdir)) + page_dir = pgd_offset(tsk,addr); + if (pgd_none(*page_dir)) break; - if (pgd_bad(*pgdir)) { - printk("Bad page dir entry %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); + if (pgd_bad(*page_dir)) { + printk("Bad page dir entry %08lx\n", pgd_val(*page_dir)); + pgd_clear(page_dir); break; } - pte = *(pte_t *) (PAGE_PTR(addr) + pgd_page(*pgdir)); + page_middle = pmd_offset(page_dir,addr); + if (pmd_none(*page_middle)) + break; + if (pmd_bad(*page_middle)) { + printk("Bad page middle entry %08lx\n", pmd_val(*page_middle)); + pmd_clear(page_middle); + break; + } + pte = *pte_offset(page_middle,addr); if (!pte_present(pte)) break; if (!pte_write(pte)) @@ -157,6 +176,7 @@ { struct task_struct *tsk; pgd_t *src_dir, *dest_dir; + pmd_t *src_middle, *dest_middle; pte_t *src_table, *dest_table; unsigned long stmp, dtmp; struct vm_area_struct *src_vma = NULL; @@ -168,7 +188,6 @@ for (i = 1 ; i < NR_TASKS ; i++) if (task[i] && task[i]->pid == (inode->i_ino >> 16)) { tsk = task[i]; - src_vma = task[i]->mm->mmap; break; } @@ -180,6 +199,7 @@ moment because working out the vm_area_struct & nattach stuff isn't worth it. */ + src_vma = tsk->mm->mmap; stmp = vma->vm_offset; while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) { while (src_vma && stmp > src_vma->vm_end) @@ -187,15 +207,21 @@ if (!src_vma || (src_vma->vm_flags & VM_SHM)) return -EINVAL; - src_dir = PAGE_DIR_OFFSET(tsk, stmp); + src_dir = pgd_offset(tsk, stmp); if (pgd_none(*src_dir)) return -EINVAL; if (pgd_bad(*src_dir)) { printk("Bad source page dir entry %08lx\n", pgd_val(*src_dir)); return -EINVAL; } - - src_table = (pte_t *)(pgd_page(*src_dir) + PAGE_PTR(stmp)); + src_middle = pmd_offset(src_dir, stmp); + if (pmd_none(*src_middle)) + return -EINVAL; + if (pmd_bad(*src_middle)) { + printk("Bad source page middle entry %08lx\n", pmd_val(*src_middle)); + return -EINVAL; + } + src_table = pte_offset(src_middle, stmp); if (pte_none(*src_table)) return -EINVAL; @@ -208,7 +234,7 @@ stmp += PAGE_SIZE; } - src_vma = task[i]->mm->mmap; + src_vma = tsk->mm->mmap; stmp = vma->vm_offset; dtmp = vma->vm_start; @@ -216,28 +242,17 @@ while (src_vma && stmp > src_vma->vm_end) src_vma = src_vma->vm_next; - src_dir = PAGE_DIR_OFFSET(tsk, stmp); - src_table = (pte_t *) (pgd_page(*src_dir) + PAGE_PTR(stmp)); - - dest_dir = PAGE_DIR_OFFSET(current, dtmp); - - if (pgd_none(*dest_dir)) { - unsigned long page = get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - if (pgd_none(*dest_dir)) { - pgd_set(dest_dir, (pte_t *) page); - } else { - free_page(page); - } - } - - if (pgd_bad(*dest_dir)) { - printk("Bad dest directory entry %08lx\n", pgd_val(*dest_dir)); - return -EINVAL; - } - - dest_table = (pte_t *) (pgd_page(*dest_dir) + PAGE_PTR(dtmp)); + src_dir = pgd_offset(tsk, stmp); + src_middle = pmd_offset(src_dir, stmp); + src_table = pte_offset(src_middle, stmp); + + dest_dir = pgd_offset(current, dtmp); + dest_middle = pmd_alloc(dest_dir, dtmp); + if (!dest_middle) + return -ENOMEM; + dest_table = pte_alloc(dest_middle, dtmp); + if (!dest_table) + return -ENOMEM; if (!pte_present(*src_table)) do_no_page(src_vma, stmp, 1); diff -u --recursive --new-file v1.1.93/linux/include/asm-alpha/byteorder.h linux/include/asm-alpha/byteorder.h --- v1.1.93/linux/include/asm-alpha/byteorder.h Wed Jan 11 21:14:29 1995 +++ linux/include/asm-alpha/byteorder.h Tue Feb 21 09:05:02 1995 @@ -32,14 +32,11 @@ ((x & 0xff000000U) >> 24)); } -extern __inline__ unsigned long int -__constant_ntohl(unsigned long int x) -{ - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); -} +#define __constant_ntohl(x) \ +((unsigned int)((((unsigned int)(x) & 0x000000ffU) << 24) | \ + (((unsigned int)(x) & 0x0000ff00U) << 8) | \ + (((unsigned int)(x) & 0x00ff0000U) >> 8) | \ + (((unsigned int)(x) & 0xff000000U) >> 24))) extern __inline__ unsigned short int __ntohs(unsigned short int x) @@ -48,12 +45,9 @@ ((x & 0xff00) >> 8)); } -extern __inline__ unsigned short int -__constant_ntohs(unsigned short int x) -{ - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); -} +#define __constant_ntohs(x) \ +((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ + (((unsigned short int)(x) & 0xff00) >> 8))) #define __htonl(x) __ntohl(x) #define __htons(x) __ntohs(x) diff -u --recursive --new-file v1.1.93/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v1.1.93/linux/include/asm-alpha/pgtable.h Wed Feb 15 10:36:39 1995 +++ linux/include/asm-alpha/pgtable.h Wed Feb 22 12:27:52 1995 @@ -160,18 +160,33 @@ extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)] > 1; } extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } +extern inline void pte_reuse(pte_t * ptep) +{ + if (!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED)) + mem_map[MAP_NR(ptep)]++; +} extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || pmd_page(pmd) > high_memory; } extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; } extern inline int pmd_inuse(pmd_t *pmdp) { return mem_map[MAP_NR(pmdp)] > 1; } extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } +extern inline void pmd_reuse(pmd_t * pmdp) +{ + if (!(mem_map[MAP_NR(pmdp)] & MAP_PAGE_RESERVED)) + mem_map[MAP_NR(pmdp)]++; +} extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; } extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; } extern inline int pgd_inuse(pgd_t *pgdp) { return mem_map[MAP_NR(pgdp)] > 1; } extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } +extern inline void pgd_reuse(pgd_t * pgdp) +{ + if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED)) + mem_map[MAP_NR(pgdp)]++; +} /* * The following only work if pte_present() is true. diff -u --recursive --new-file v1.1.93/linux/include/asm-i386/byteorder.h linux/include/asm-i386/byteorder.h --- v1.1.93/linux/include/asm-i386/byteorder.h Mon Jan 9 07:22:09 1995 +++ linux/include/asm-i386/byteorder.h Tue Feb 21 09:02:02 1995 @@ -27,14 +27,11 @@ return x; } -extern __inline__ unsigned long int -__constant_ntohl(unsigned long int x) -{ - return (((x & 0x000000ffU) << 24) | - ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | - ((x & 0xff000000U) >> 24)); -} +#define __constant_ntohl(x) \ + ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \ + (((unsigned long int)(x) & 0x0000ff00U) << 8) | \ + (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \ + (((unsigned long int)(x) & 0xff000000U) >> 24))) extern __inline__ unsigned short int __ntohs(unsigned short int x) @@ -45,12 +42,9 @@ return x; } -extern __inline__ unsigned short int -__constant_ntohs(unsigned short int x) -{ - return (((x & 0x00ff) << 8) | - ((x & 0xff00) >> 8)); -} +#define __constant_ntohs(x) \ + ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ + (((unsigned short int)(x) & 0xff00) >> 8))) \ #define __htonl(x) __ntohl(x) #define __htons(x) __ntohs(x) diff -u --recursive --new-file v1.1.93/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h --- v1.1.93/linux/include/asm-sparc/system.h Mon Feb 20 21:34:56 1995 +++ linux/include/asm-sparc/system.h Wed Feb 22 08:47:40 1995 @@ -1,6 +1,8 @@ #ifndef __SPARC_SYSTEM_H #define __SPARC_SYSTEM_H +#include + /* * System defines.. Note that this is included both from .c and .S * files, so it does only defines, not any C code. diff -u --recursive --new-file v1.1.93/linux/include/asm-sparc/vac-ops.h linux/include/asm-sparc/vac-ops.h --- v1.1.93/linux/include/asm-sparc/vac-ops.h Thu Jan 26 07:49:15 1995 +++ linux/include/asm-sparc/vac-ops.h Wed Feb 22 08:47:40 1995 @@ -7,8 +7,8 @@ Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu) */ -extern unsigned int trapbase[]; -extern unsigned int end[], etext[], msgbuf[]; +extern unsigned long *trapbase; +extern char end, etext, msgbuf; extern void flush_vac_context(void); extern void flush_vac_segment(unsigned int foo_segment); diff -u --recursive --new-file v1.1.93/linux/include/linux/fs.h linux/include/linux/fs.h --- v1.1.93/linux/include/linux/fs.h Fri Feb 17 11:20:16 1995 +++ linux/include/linux/fs.h Wed Feb 22 09:31:32 1995 @@ -266,8 +266,9 @@ }; struct file_lock { - struct file_lock *fl_next; /* singly linked list */ - struct file_lock *fl_nextlink; + struct file_lock *fl_next; /* singly linked list for this inode (or the free list) */ + struct file_lock *fl_nextlink; /* doubly linked list of all locks */ + struct file_lock *fl_prevlink; /* used to simplify garbage collecting */ struct task_struct *fl_owner; /* NULL if on free list, for sanity checks */ struct wait_queue *fl_wait; char fl_type; diff -u --recursive --new-file v1.1.93/linux/include/linux/iso_fs_sb.h linux/include/linux/iso_fs_sb.h --- v1.1.93/linux/include/linux/iso_fs_sb.h Mon Jan 9 07:22:10 1995 +++ linux/include/linux/iso_fs_sb.h Wed Feb 22 08:15:14 1995 @@ -18,6 +18,7 @@ unsigned char s_cruft; /* Broken disks with high byte of length containing junk */ + unsigned char s_unhide; unsigned char s_nosuid; unsigned char s_nodev; mode_t s_mode; diff -u --recursive --new-file v1.1.93/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.1.93/linux/include/linux/sched.h Wed Feb 15 10:36:40 1995 +++ linux/include/linux/sched.h Wed Feb 22 12:27:52 1995 @@ -268,11 +268,12 @@ unsigned long flags, const char *device); extern void free_irq(unsigned int irq); -extern unsigned long copy_thread(int, unsigned long, struct task_struct *, struct pt_regs *); +extern void copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); extern void flush_thread(void); extern void exit_thread(void); extern int do_execve(char *, char **, char **, struct pt_regs *); +extern int do_fork(unsigned long, unsigned long, struct pt_regs *); asmlinkage int do_signal(unsigned long, struct pt_regs *); /* diff -u --recursive --new-file v1.1.93/linux/include/linux/serial.h linux/include/linux/serial.h --- v1.1.93/linux/include/linux/serial.h Thu Feb 9 10:18:53 1995 +++ linux/include/linux/serial.h Mon Feb 20 21:29:53 1995 @@ -22,10 +22,19 @@ unsigned short close_delay; char reserved_char[2]; int hub6; - int reserved[5]; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; }; /* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ASYNC_CLOSING_WAIT_INF 0 +#define ASYNC_CLOSING_WAIT_NONE 65535 + +/* * These are the supported serial types. */ #define PORT_UNKNOWN 0 @@ -34,7 +43,8 @@ #define PORT_16550 3 #define PORT_16550A 4 #define PORT_CIRRUS 5 -#define PORT_MAX 5 +#define PORT_16650 6 +#define PORT_MAX 6 /* * Definitions for async_struct (and serial_struct) flags field @@ -70,6 +80,23 @@ #define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ #define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ +/* + * Multiport serial configuration structure --- external structure + */ +struct serial_multiport_struct { + int irq; + int port1; + unsigned char mask1, match1; + int port2; + unsigned char mask2, match2; + int port3; + unsigned char mask3, match3; + int port4; + unsigned char mask4, match4; + int port_monitor; + int reserved[32]; +}; + #ifdef __KERNEL__ /* * This is our internal structure for each serial port's state. @@ -96,6 +123,8 @@ int custom_divisor; int x_char; /* xon/xoff character */ int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ int MCR_noint; /* MCR with interrupts off */ @@ -132,6 +161,21 @@ */ #define RS_EVENT_WRITE_WAKEUP 0 #define RS_EVENT_HANGUP 1 + +/* + * Multiport serial configuration structure --- internal structure + */ +struct rs_multiport_struct { + int port1; + unsigned char mask1, match1; + int port2; + unsigned char mask2, match2; + int port3; + unsigned char mask3, match3; + int port4; + unsigned char mask4, match4; + int port_monitor; +}; /* Export to allow PCMCIA to use this - Dave Hinds */ extern int register_serial(struct serial_struct *req); diff -u --recursive --new-file v1.1.93/linux/include/linux/serial_reg.h linux/include/linux/serial_reg.h --- v1.1.93/linux/include/linux/serial_reg.h Thu Feb 9 10:18:53 1995 +++ linux/include/linux/serial_reg.h Mon Feb 20 21:29:53 1995 @@ -21,6 +21,8 @@ #define UART_IER 1 /* Out: Interrupt Enable Register */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_EFR 2 /* I/O: Extended Features Register */ + /* (DLAB=1, 16C660 only) */ #define UART_LCR 3 /* Out: Line Control Register */ #define UART_MCR 4 /* Out: Modem Control Register */ #define UART_LSR 5 /* In: Line Status Register */ @@ -29,6 +31,7 @@ /* * These are the definitions for the FIFO Control Register + * (16650 only) */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ @@ -39,6 +42,15 @@ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ +/* 16650 redefinitions */ +#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ +#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ +#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ +#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ /* * These are the definitions for the Line Control Register @@ -108,6 +120,18 @@ #define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +/* + * These are the definitions for the Extended Features Register + * (StarTech 16C660 only, when DLAB=1) + */ +#define UART_EFR_CTS 0x80 /* CTS flow control */ +#define UART_EFR_RTS 0x40 /* RTS flow control */ +#define UART_EFR_SCD 0x20 /* Special character detect */ +#define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ +/* + * the low four bits control software flow control + */ #endif /* _LINUX_SERIAL_REG_H */ diff -u --recursive --new-file v1.1.93/linux/include/linux/sys.h linux/include/linux/sys.h --- v1.1.93/linux/include/linux/sys.h Mon Apr 18 11:38:20 1994 +++ linux/include/linux/sys.h Wed Feb 22 12:27:52 1995 @@ -7,11 +7,6 @@ #define NR_syscalls 256 /* - * 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.. * (please be careful - ibcs2 may need some of these). diff -u --recursive --new-file v1.1.93/linux/include/linux/termios.h linux/include/linux/termios.h --- v1.1.93/linux/include/linux/termios.h Tue Nov 29 18:58:28 1994 +++ linux/include/linux/termios.h Mon Feb 20 21:29:53 1995 @@ -54,6 +54,8 @@ #define TIOCSLCKTRMIOS 0x5457 #define TIOCSERGSTRUCT 0x5458 /* For debugging only */ #define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ /* Used for packet mode */ #define TIOCPKT_DATA 0 @@ -193,6 +195,7 @@ #define CBAUDEX 0010000 #define B57600 0010001 #define B115200 0010002 +#define B230400 0010003 #define CIBAUD 002003600000 /* input baud rate (not used) */ #define CRTSCTS 020000000000 /* flow control */ diff -u --recursive --new-file v1.1.93/linux/include/linux/tty.h linux/include/linux/tty.h --- v1.1.93/linux/include/linux/tty.h Fri Feb 17 11:20:16 1995 +++ linux/include/linux/tty.h Mon Feb 20 21:29:52 1995 @@ -222,6 +222,7 @@ */ unsigned int column; unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; + unsigned char closing:1; unsigned short minimum_to_wake; unsigned overrun_time; int num_overrun; diff -u --recursive --new-file v1.1.93/linux/ipc/shm.c linux/ipc/shm.c --- v1.1.93/linux/ipc/shm.c Wed Feb 1 09:23:08 1995 +++ linux/ipc/shm.c Mon Feb 20 21:32:18 1995 @@ -1,3 +1,4 @@ +#define THREE_LEVEL /* * linux/ipc/shm.c * Copyright (C) 1992, 1993 Krishna Balasubramanian @@ -20,7 +21,7 @@ extern unsigned int get_swap_page (void); static int findkey (key_t key); static int newseg (key_t key, int shmflg, int size); -static int shm_map (struct vm_area_struct *shmd, int remap); +static int shm_map (struct vm_area_struct *shmd); static void killseg (int id); static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); @@ -411,34 +412,16 @@ } /* - * check range is unmapped, ensure page tables exist + * ensure page tables exist * mark page table entries with shm_sgn. - * if remap != 0 the range is remapped. */ -static int shm_map (struct vm_area_struct *shmd, int remap) +static int shm_map (struct vm_area_struct *shmd) { pgd_t *page_dir; + pmd_t *page_middle; pte_t *page_table; unsigned long tmp, shm_sgn; - - /* check that the range is unmapped */ - if (!remap) - for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE) { - page_dir = PAGE_DIR_OFFSET(shmd->vm_task,tmp); - if (pgd_none(*page_dir)) - continue; - if (pgd_bad(*page_dir)) { - printk("bad ipc page directory entry %08lx\n", pgd_val(*page_dir)); - pgd_clear(page_dir); - continue; - } - page_table = (pte_t *) pgd_page(*page_dir); - page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1)); - if (!pte_none(*page_table)) { - /* printk("shmat() -> EINVAL because address 0x%lx is already mapped.\n",tmp); */ - return -EINVAL; - } - } + int error; /* clear old mappings */ do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start); @@ -447,35 +430,17 @@ insert_vm_struct(current, shmd); merge_segments(current, shmd->vm_start, shmd->vm_end); - /* check that the range has page_tables */ - for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE) { - page_dir = PAGE_DIR_OFFSET(shmd->vm_task,tmp); - if (!pgd_none(*page_dir)) { - page_table = (pte_t *) pgd_page(*page_dir); - page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1)); - if (!pte_none(*page_table)) { - if (pte_present(*page_table)) { - --current->mm->rss; - free_page (pte_page(*page_table)); - } else - swap_free(pte_val(*page_table)); - pte_clear(page_table); - } - } else { - if (!(page_table = (pte_t *) get_free_page(GFP_KERNEL))) - return -ENOMEM; - pgd_set(page_dir, page_table); - tmp |= (PGDIR_SIZE - PAGE_SIZE); - } - } - /* map page range */ shm_sgn = shmd->vm_pte + ((shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT); for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE, shm_sgn += (1 << SHM_IDX_SHIFT)) { - page_dir = PAGE_DIR_OFFSET(shmd->vm_task,tmp); - page_table = (pte_t *) pgd_page(*page_dir); - page_table += (tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); + page_dir = pgd_offset(shmd->vm_task,tmp); + page_middle = pmd_alloc(page_dir,tmp); + if (!page_middle) + break; + page_table = pte_alloc(page_middle,tmp); + if (!page_table) + break; pte_val(*page_table) = shm_sgn; } invalidate(); @@ -553,7 +518,7 @@ shmd->vm_ops = &shm_vm_ops; shp->shm_nattch++; /* prevent destruction */ - if ((err = shm_map (shmd, shmflg & SHM_REMAP))) { + if ((err = shm_map (shmd))) { if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST) killseg(id); kfree(shmd); @@ -749,6 +714,7 @@ for (shmd = shp->attaches; ; ) { do { pgd_t *page_dir; + pmd_t *page_middle; pte_t *page_table, pte; unsigned long tmp; @@ -759,15 +725,21 @@ tmp = shmd->vm_start + (idx << PAGE_SHIFT) - shmd->vm_offset; if (!(tmp >= shmd->vm_start && tmp < shmd->vm_end)) continue; - page_dir = PAGE_DIR_OFFSET(shmd->vm_task,tmp); + page_dir = pgd_offset(shmd->vm_task,tmp); if (pgd_none(*page_dir) || pgd_bad(*page_dir)) { printk("shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld\n", id, shmd->vm_start, idx); pgd_clear(page_dir); continue; } - page_table = (pte_t *) pgd_page(*page_dir); - page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1)); + page_middle = pmd_offset(page_dir,tmp); + if (pmd_none(*page_middle) || pmd_bad(*page_middle)) { + printk("shm_swap: bad pgmid! id=%ld start=%lx idx=%ld\n", + id, shmd->vm_start, idx); + pmd_clear(page_middle); + continue; + } + page_table = pte_offset(page_middle,tmp); pte = *page_table; if (!pte_present(pte)) continue; @@ -779,7 +751,8 @@ printk("shm_swap_out: page and pte mismatch\n"); pte_val(*page_table) = shmd->vm_pte | idx << SHM_IDX_SHIFT; mem_map[MAP_NR(pte_page(pte))]--; - shmd->vm_task->mm->rss--; + if (shmd->vm_task->mm->rss > 0) + shmd->vm_task->mm->rss--; invalid++; /* continue looping through circular list */ } while (0); diff -u --recursive --new-file v1.1.93/linux/kernel/fork.c linux/kernel/fork.c --- v1.1.93/linux/kernel/fork.c Mon Jan 30 06:41:59 1995 +++ linux/kernel/fork.c Wed Feb 22 12:27:52 1995 @@ -163,12 +163,11 @@ * information (task[nr]) and sets up the necessary registers. It * also copies the data segment in its entirety. */ -asmlinkage int sys_fork(struct pt_regs regs) +int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) { int nr; - struct task_struct *p; unsigned long new_stack; - unsigned long clone_flags = COPYVM | SIGCHLD; + struct task_struct *p; if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL))) goto bad_fork; @@ -206,7 +205,7 @@ task[nr] = p; /* copy all the process information */ - clone_flags = copy_thread(nr, COPYVM | SIGCHLD, p, ®s); + copy_thread(nr, clone_flags, usp, p, regs); if (copy_mm(clone_flags, p)) goto bad_fork_cleanup; p->semundo = NULL; diff -u --recursive --new-file v1.1.93/linux/kernel/sys.c linux/kernel/sys.c --- v1.1.93/linux/kernel/sys.c Mon Jan 30 06:41:59 1995 +++ linux/kernel/sys.c Mon Feb 20 21:29:53 1995 @@ -517,6 +517,7 @@ current->leader = 1; current->session = current->pgrp = current->pid; current->tty = NULL; + current->tty_old_pgrp = 0; return current->pgrp; } diff -u --recursive --new-file v1.1.93/linux/mm/swap.c linux/mm/swap.c --- v1.1.93/linux/mm/swap.c Mon Feb 20 21:34:56 1995 +++ linux/mm/swap.c Mon Feb 20 16:10:32 1995 @@ -506,11 +506,10 @@ static int swap_out(unsigned int priority) { static int swap_task; - int loop; - int counter = NR_TASKS * 2 >> priority; + int loop, counter; struct task_struct *p; - counter = NR_TASKS * 2 >> priority; + counter = 2*NR_TASKS >> priority; for(; counter >= 0; counter--, swap_task++) { /* * Check that swap_task is suitable for swapping. If not, look for @@ -557,6 +556,15 @@ return 0; } +/* + * we keep on shrinking one resource until it's considered "too hard", + * and then switch to the next one (priority being an indication on how + * hard we should try with the resource). + * + * This should automatically find the resource that can most easily be + * free'd, so hopefully we'll get reasonable behaviour even under very + * different circumstances. + */ static int try_to_free_page(int priority) { static int state = 0; @@ -565,23 +573,19 @@ switch (state) { do { case 0: - if (priority != GFP_NOBUFFER && shrink_buffers(i)) { - state = 1; + if (priority != GFP_NOBUFFER && shrink_buffers(i)) return 1; - } + state = 1; case 1: - if (shm_swap(i)) { - state = 2; + if (shm_swap(i)) return 1; - } - case 2: - if (swap_out(i)) { - state = 0; + state = 2; + default: + if (swap_out(i)) return 1; - } + state = 0; } while(--i); } - state = 2; return 0; } diff -u --recursive --new-file v1.1.93/linux/net/inet/af_inet.c linux/net/inet/af_inet.c --- v1.1.93/linux/net/inet/af_inet.c Mon Feb 20 21:34:56 1995 +++ linux/net/inet/af_inet.c Tue Feb 21 16:12:05 1995 @@ -864,11 +864,13 @@ { /* should be below! */ if (sk2->num != snum) continue; +#if 0 if (sk2->dead) { destroy_sock(sk2); goto outside_loop; } +#endif if (!sk->reuse) { sti(); diff -u --recursive --new-file v1.1.93/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.1.93/linux/net/inet/tcp.c Thu Feb 9 10:18:54 1995 +++ linux/net/inet/tcp.c Tue Feb 21 17:00:05 1995 @@ -2769,9 +2769,9 @@ newsk->linger=0; newsk->destroy = 0; init_timer(&newsk->timer); - init_timer(&newsk->retransmit_timer); newsk->timer.data = (unsigned long)newsk; newsk->timer.function = &net_timer; + init_timer(&newsk->retransmit_timer); newsk->retransmit_timer.data = (unsigned long)newsk; newsk->retransmit_timer.function=&retransmit_timer; newsk->dummy_th.source = skb->h.th->dest; @@ -4393,7 +4393,9 @@ tcp_set_state(sk,TCP_SYN_SENT); sk->rto = TCP_TIMEOUT_INIT; - init_timer(&sk->retransmit_timer); +#if 0 /* we already did this */ + init_timer(&sk->retransmit_timer); +#endif sk->retransmit_timer.function=&retransmit_timer; sk->retransmit_timer.data = (unsigned long)sk; reset_xmit_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */