diff -u --recursive --new-file v1.1.18/linux/Makefile linux/Makefile --- v1.1.18/linux/Makefile Thu Jun 9 18:56:02 1994 +++ linux/Makefile Mon Jun 6 16:03:19 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 18 +SUBLEVEL = 19 all: Version zImage diff -u --recursive --new-file v1.1.18/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.1.18/linux/drivers/char/keyboard.c Tue May 24 00:34:47 1994 +++ linux/drivers/char/keyboard.c Thu Jun 9 17:20:34 1994 @@ -468,7 +468,7 @@ static void send_intr(void) { - if (tty->termios && I_IGNBRK(tty)) + if (!tty || (tty->termios && I_IGNBRK(tty))) return; tty_insert_flip_char(tty, 0, TTY_BREAK); } diff -u --recursive --new-file v1.1.18/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v1.1.18/linux/drivers/char/pty.c Tue May 24 00:34:47 1994 +++ linux/drivers/char/pty.c Thu Jun 9 17:26:13 1994 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -32,9 +33,19 @@ #define PTY_MAGIC 0x5001 -#define PTY_BUF_SIZE 1024 +#define PTY_BUF_SIZE PAGE_SIZE/2 -static unsigned char tmp_buf[PTY_BUF_SIZE]; +/* + * tmp_buf is used as a temporary buffer by pty_write. We need to + * lock it in case the memcpy_fromfs blocks while swapping in a page, + * and some other program tries to do a pty write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the PTY's, since it significantly saves memory if + * large numbers of PTY's are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; struct tty_driver pty_driver, pty_slave_driver; static int pty_refcount; @@ -78,24 +89,34 @@ unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c, n; + int c=0, n, r; + char *temp_buffer; if (!to || tty->stopped) return 0; - count = MIN(count, to->ldisc.receive_room(to)); - if (from_user) { - for (c = count; c > 0; c -= n) { - n = MIN(c, PTY_BUF_SIZE); - memcpy_fromfs(tmp_buf, buf, n); - to->ldisc.receive_buf(to, tmp_buf, 0, n); - buf += n; + down(&tmp_buf_sem); + temp_buffer = tmp_buf + + ((tty->driver.subtype-1) * PTY_BUF_SIZE); + while (count > 0) { + n = MIN(count, PTY_BUF_SIZE); + memcpy_fromfs(temp_buffer, buf, n); + r = to->ldisc.receive_room(to); + if (r <= 0) + break; + n = MIN(n, r); + to->ldisc.receive_buf(to, temp_buffer, 0, n); + buf += n; c+= n; + count -= n; } - } else - to->ldisc.receive_buf(to, buf, 0, count); + up(&tmp_buf_sem); + } else { + c = MIN(count, to->ldisc.receive_room(to)); + to->ldisc.receive_buf(to, buf, 0, c); + } - return count; + return c; } static int pty_write_room(struct tty_struct *tty) @@ -146,7 +167,13 @@ return -ENODEV; pty = pty_state + line; tty->driver_data = pty; - + + if (!tmp_buf) { + tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + } + if (tty->driver.subtype == PTY_TYPE_SLAVE) clear_bit(TTY_SLAVE_CLOSED, &tty->link->flags); wake_up_interruptible(&pty->open_wait); @@ -199,12 +226,12 @@ pty_slave_driver.termios_locked = ttyp_termios_locked; pty_slave_driver.other = &pty_driver; + tmp_buf = 0; + if (tty_register_driver(&pty_driver)) - panic("Couldn't register pty driver\n"); + panic("Couldn't register pty driver"); if (tty_register_driver(&pty_slave_driver)) - panic("Couldn't register pty slave driver\n"); + panic("Couldn't register pty slave driver"); return kmem_start; } - - diff -u --recursive --new-file v1.1.18/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v1.1.18/linux/drivers/char/serial.c Tue May 31 12:48:16 1994 +++ linux/drivers/char/serial.c Thu Jun 9 17:20:34 1994 @@ -499,6 +499,10 @@ int pass_counter = 0; struct async_struct *end_mark = 0; +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info) return; @@ -512,6 +516,8 @@ } end_mark = 0; + info->last_active = jiffies; + status = serial_inp(info, UART_LSR); if (status & UART_LSR_DR) receive_chars(info, &status); @@ -543,6 +549,10 @@ int pass_counter = 0; struct async_struct * info; +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info || !info->tty) return; @@ -561,6 +571,7 @@ break; } } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); + info->last_active = jiffies; } #else /* CONFIG_SERIAL_NEW_ISR */ @@ -574,6 +585,11 @@ struct async_struct * info; int done = 1, pass_counter = 0; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info) return; @@ -625,6 +641,11 @@ int status; struct async_struct * info; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + info = IRQ_ports[irq]; if (!info || !info->tty) return; @@ -697,13 +718,39 @@ */ static void rs_timer(void) { + static unsigned long last_strobe = 0; + struct async_struct *info; + unsigned int i; + + if ((jiffies - last_strobe) >= 60*HZ) { + for (i=1; i < 16; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + cli(); + if (info->next_port) { + do { + serial_out(info, UART_IER, 0); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + info = info->next_port; + } while (info); + rs_interrupt(i); + } else + rs_interrupt_single(i); + sti(); + } + } + last_strobe = jiffies; + timer_table[RS_TIMER].expires = jiffies + 60 * HZ; + timer_active |= 1 << RS_TIMER; + if (IRQ_ports[0]) { cli(); rs_interrupt(0); sti(); timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; - timer_active |= 1 << RS_TIMER; } } @@ -757,7 +804,7 @@ /* * This routine figures out the correct timeout for a particular IRQ. * It uses the smallest timeout of all of the serial ports in a - * particular interrupt chain. + * particular interrupt chain. Now only used for IRQ 0.... */ static void figure_IRQ_timeout(int irq) { @@ -908,10 +955,8 @@ /* * Set up serial timers... */ - if (info->irq == 0) { - timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0]; - timer_active |= 1 << RS_TIMER; - } + timer_table[RS_TIMER].expires = jiffies + 2; + timer_active |= 1 << RS_TIMER; /* * and set the speed of the serial port @@ -1633,6 +1678,15 @@ rs_wild_int_mask = check_wild_interrupts(0); return 0; + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct async_struct)); + if (error) + return error; + memcpy_tofs((struct async_struct *) arg, + info, sizeof(struct async_struct)); + return 0; + default: return -ENOIOCTLCMD; } diff -u --recursive --new-file v1.1.18/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v1.1.18/linux/drivers/net/ppp.c Thu Jun 9 18:56:11 1994 +++ linux/drivers/net/ppp.c Thu Jun 9 17:20:34 1994 @@ -146,6 +146,7 @@ static void ppp_close(struct tty_struct *); #ifdef NEW_TTY_DRIVERS +static int ppp_receive_room(struct tty_struct *tty); static void ppp_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count); static void ppp_write_wakeup(struct tty_struct *tty); @@ -239,6 +240,7 @@ #ifdef NEW_TTY_DRIVERS ppp_ldisc.magic = TTY_LDISC_MAGIC; + ppp_ldisc.receive_room = ppp_receive_room; ppp_ldisc.receive_buf = ppp_receive_buf; ppp_ldisc.write_wakeup = ppp_write_wakeup; #else @@ -891,6 +893,12 @@ } #else +static int ppp_receive_room(struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} + + static void ppp_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count) { diff -u --recursive --new-file v1.1.18/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v1.1.18/linux/drivers/net/slip.c Tue May 24 00:34:53 1994 +++ linux/drivers/net/slip.c Thu Jun 9 17:20:33 1994 @@ -656,6 +656,10 @@ return(0); } +static int slip_receive_room(struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} /* * Handle the 'receiver data ready' interrupt. @@ -680,7 +684,7 @@ /* Read the characters out of the buffer */ while (count--) { - if (*fp++) { + if (fp && *fp++) { sl->flags |= SLF_ERROR; cp++; continue; @@ -1048,6 +1052,7 @@ unsigned int, unsigned long)) slip_ioctl; sl_ldisc.select = NULL; sl_ldisc.receive_buf = slip_receive_buf; + sl_ldisc.receive_room = slip_receive_room; sl_ldisc.write_wakeup = slip_write_wakeup; if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) printk("ERROR: %d\n", i); diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/ChangeLog linux/drivers/scsi/ChangeLog --- v1.1.18/linux/drivers/scsi/ChangeLog Fri May 27 10:49:06 1994 +++ linux/drivers/scsi/ChangeLog Mon Jun 6 15:54:09 1994 @@ -1,4 +1,40 @@ +Wed Jun 1 21:12:13 1994 Eric Youngdale (eric@esp22) + + * scsi.h: Add new return code for reset() function: + SCSI_RESET_PUNT. + + * scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for + now. + + * aha1542.c: If the command responsible for the reset is not + pending, return SCSI_RESET_PUNT. + + * aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return + SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE. + +Tue May 31 19:36:01 1994 Eric Youngdale (eric@esp22) + + * buslogic.c: Do not print out message about "must be Adaptec" + if we have detected a buslogic card. Print out a warning message + if we are configuring for >16Mb, since the 445S at board level + D or earlier does not work right. The "D" level board can be made + to work by flipping an undocumented switch, but this is too subtle. + + Changes based upon patches in Yggdrasil distribution. + + * sg.c, sg.h: Return sense data to user. + + * aha1542.c, aha1740.c, buslogic.c: Do not panic if + sense buffer is wrong size. + + * hosts.c: Test for ultrastor card before any of the others. + + * scsi.c: Allow boot-time option for max_scsi_luns=? so that + buggy firmware has an easy work-around. + Sun May 15 20:24:34 1994 Eric Youngdale (eric@esp22) + + * Linux 1.1.15 released. Post-codefreeze thaw... diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.1.18/linux/drivers/scsi/aha1542.c Fri May 27 10:49:07 1994 +++ linux/drivers/scsi/aha1542.c Mon Jun 6 15:54:09 1994 @@ -460,7 +460,6 @@ #ifndef DEBUG if (bufflen != sizeof(SCpnt->sense_buffer)) { printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - panic("aha1542.c"); }; #endif SCpnt->result = 0; @@ -1058,7 +1057,10 @@ } #endif - return SCSI_RESET_PENDING; + /* No active command at this time, so this means that each time we got + some kind of response the last time through. Tell the mid-level code + to request sense information in order to decide what to do next. */ + return SCSI_RESET_PUNT; } #ifdef CONFIG_BLK_DEV_SD diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v1.1.18/linux/drivers/scsi/aha1740.c Fri May 27 10:49:07 1994 +++ linux/drivers/scsi/aha1740.c Mon Jun 6 15:54:09 1994 @@ -251,7 +251,6 @@ if (bufflen != sizeof(SCpnt->sense_buffer)) { printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - panic("aha1740.c"); } SCpnt->result = 0; done(SCpnt); @@ -487,7 +486,7 @@ int aha1740_reset(Scsi_Cmnd * SCpnt) { DEB(printk("aha1740_reset called\n")); - return SCSI_RESET_SNOOZE; + return SCSI_RESET_PUNT; } int aha1740_biosparam(int size, int dev, int* ip) diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c --- v1.1.18/linux/drivers/scsi/buslogic.c Thu Jun 9 18:56:12 1994 +++ linux/drivers/scsi/buslogic.c Mon Jun 6 15:56:01 1994 @@ -1178,7 +1178,7 @@ #if BUSLOGIC_DEBUG buslogic_printk("buslogic_reset\n"); #endif - return SCSI_RESET_SNOOZE; + return SCSI_RESET_PUNT; } int buslogic_biosparam(int size, int dev, int *ip) diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v1.1.18/linux/drivers/scsi/hosts.c Fri May 27 10:49:09 1994 +++ linux/drivers/scsi/hosts.c Mon Jun 6 15:54:09 1994 @@ -110,6 +110,9 @@ Scsi_Host_Template scsi_hosts[] = { +#ifdef CONFIG_SCSI_ULTRASTOR + ULTRASTOR_14F, +#endif #ifdef CONFIG_SCSI_AHA152X AHA152X, #endif @@ -140,9 +143,6 @@ #endif #ifdef CONFIG_SCSI_T128 TRANTOR_T128, -#endif -#ifdef CONFIG_SCSI_ULTRASTOR - ULTRASTOR_14F, #endif #ifdef CONFIG_SCSI_7000FASST WD7000, diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.1.18/linux/drivers/scsi/scsi.c Fri May 27 10:49:10 1994 +++ linux/drivers/scsi/scsi.c Mon Jun 6 15:54:18 1994 @@ -192,6 +192,20 @@ #endif SCpnt->request.dev = 0xfffe; } + +#ifdef NO_MULTI_LUN +static int max_scsi_luns = 1; +#else +static int max_scsi_luns = 8; +#endif + +void scsi_luns_setup(char *str, int *ints) { + if (ints[0] != 1) + printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n"); + else + max_scsi_luns = ints[1]; +} + /* * Detecting SCSI devices : * We scan all present host adapter's busses, from ID 0 to ID 6. @@ -223,11 +237,7 @@ * We need the for so our continue, etc. work fine. */ -#ifdef NO_MULTI_LUN - for (lun = 0; lun < 1; ++lun) -#else - for (lun = 0; lun < 8; ++lun) -#endif + for (lun = 0; lun < max_scsi_luns; ++lun) { scsi_devices[NR_SCSI_DEVICES].host = shpnt; scsi_devices[NR_SCSI_DEVICES].id = dev; @@ -1491,6 +1501,7 @@ return 0; case SCSI_RESET_PENDING: return 0; + case SCSI_RESET_PUNT: case SCSI_RESET_WAKEUP: SCpnt->internal_timeout &= ~IN_RESET; scsi_request_sense (SCpnt); diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v1.1.18/linux/drivers/scsi/scsi.h Fri May 27 10:49:10 1994 +++ linux/drivers/scsi/scsi.h Mon Jun 6 15:54:18 1994 @@ -351,27 +351,34 @@ /* We do not know how to reset the bus, or we do not want to. Bummer. Anyway, just wait a little more for the command in question, and hope that - it eventually finishes */ + it eventually finishes. If it never finishes, the SCSI device could + hang, so use this with caution. */ #define SCSI_RESET_SNOOZE 0 +/* We do not know how to reset the bus, or we do not want to. Bummer. + We have given up on this ever completing. The mid-level code will + request sense information to decide how to proceed from here. */ +#define SCSI_RESET_PUNT 1 + /* This means that we were able to reset the bus. We have restarted all of the commands that should be restarted, and we should be able to continue on normally from here. We do not expect any interrupts that will return - DID_RESET to any of the other commands in the host_queue. */ -#define SCSI_RESET_SUCCESS 1 + DID_RESET to any of the other commands in the host_queue, and the mid-level + code does not need to do anything special to keep the commands alive. */ +#define SCSI_RESET_SUCCESS 2 /* We called for an reset of this bus, and we should get an interrupt when this succeeds. Each command should get it's own status passed up to scsi_done, but this has not happened yet. */ -#define SCSI_RESET_PENDING 2 +#define SCSI_RESET_PENDING 3 /* We did a reset, but do not expect an interrupt to signal DID_RESET. This tells the upper level code to request the sense info, and this should keep the command alive. */ -#define SCSI_RESET_WAKEUP 3 +#define SCSI_RESET_WAKEUP 4 /* Something went wrong, and we do not know how to fix it. */ -#define SCSI_RESET_ERROR 4 +#define SCSI_RESET_ERROR 5 void * scsi_malloc(unsigned int); int scsi_free(void *, unsigned int); diff -u --recursive --new-file v1.1.18/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v1.1.18/linux/drivers/scsi/sg.c Sat Mar 19 19:29:14 1994 +++ linux/drivers/scsi/sg.c Mon Jun 6 15:54:09 1994 @@ -173,7 +173,9 @@ buf+=sizeof(struct sg_header); if (count>device->header.pack_len) count=device->header.pack_len; - memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header)); + if (count > sizeof(struct sg_header)) { + memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header)); + } } else count=0; @@ -193,6 +195,7 @@ SCpnt->request.dev=-1; return; } + memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); if (SCpnt->sense_buffer[0]) { device->header.result=EIO; @@ -211,6 +214,7 @@ int bsize,size,amt,i; unsigned char cmnd[MAX_COMMAND_SIZE]; struct scsi_generic *device=&scsi_generics[dev]; + if ((i=verify_area(VERIFY_READ,buf,count))) return i; if (countsockaddr_len = sockaddr_len; /* now its legal */ return(0);