diff -u --recursive --new-file v1.1.54/linux/Makefile linux/Makefile --- v1.1.54/linux/Makefile Thu Oct 20 09:37:27 1994 +++ linux/Makefile Tue Oct 18 10:08:37 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 54 +SUBLEVEL = 55 ARCH = i386 diff -u --recursive --new-file v1.1.54/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v1.1.54/linux/drivers/block/floppy.c Thu Oct 20 09:37:28 1994 +++ linux/drivers/block/floppy.c Wed Oct 19 11:48:42 1994 @@ -25,9 +25,9 @@ /* Define the following if you don't like that your drives seek audibly - * after a disk change + * after a disk change (but it may not work correctly for everybody) */ -#define SILENT_DC_CLEAR +/* #define SILENT_DC_CLEAR */ /* End of configuration */ @@ -304,7 +304,7 @@ { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"CompaQ"}, /* 9 2.88MB 3.5" */ { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ - { 3360,21,2,80,0,0x1C,0x00,0xCF,0x6C,"H1680" }, /* 11 1.68MB 3.5" */ + { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */ { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */ { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */ @@ -317,8 +317,8 @@ { 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"h880" }, /* 20 880KB 5.25" */ { 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5" */ { 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5" */ - { 3200,20,2,80,0,0x1C,0x20,0xCF,0x6C,"h1600" }, /* 23 1.6MB 5.25" */ - { 3520,22,2,80,0,0x1C,0x08,0xCF,0x6C,"H1760" }, /* 24 1.76MB 3.5" */ + { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ + { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ { 3840,24,2,80,0,0x1C,0x20,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5" */ { 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5" */ { 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5" */ @@ -326,7 +326,7 @@ { 3680,23,2,80,0,0x1C,0x10,0xCF,0x6C,"H1840" }, /* 29 1.84MB 3.5" */ { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ - { 3200,20,2,80,0,0x1C,0x00,0xCF,0x6C,"H1600" }, /* 31 1.6MB 3.5" */ + { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ }; #define NUMBER(x) (sizeof(x) / sizeof(*(x))) @@ -1278,9 +1278,10 @@ debugt("recal interrupt need 1 recal:"); #endif /* after a second recalibrate, we still haven't - * reached track 0. Probably no drive */ - DRS->track = PROVEN_ABSENT; - cont->done(0); + * reached track 0. Probably no drive. Raise an + * error, as failing immediately might upset + * computers possessed by the Devil :-) */ + cont->error(); cont->redo(); return; case NEED_2_RECAL: @@ -1691,7 +1692,7 @@ int count,head_shift,track_shift; raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | - FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; + /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK; raw_cmd.rate = floppy->rate & 0x3; raw_cmd.cmd_count = NR_F; COMMAND = FM_MODE(floppy,FD_FORMAT); diff -u --recursive --new-file v1.1.54/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.1.54/linux/drivers/block/hd.c Thu Oct 20 09:37:28 1994 +++ linux/drivers/block/hd.c Tue Oct 18 10:08:06 1994 @@ -15,10 +15,8 @@ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug * in the early extended-partition checks and added DM partitions * - * IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord. - * - * Support for BIOS drive geometry translation added by Mark Lord. - * -- hd.c no longer chokes on drives with "more than 16 heads". + * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", + * and general streamlining by mlord@bnr.ca (Mark Lord). */ #define DEFAULT_MULT_COUNT 0 /* set to 0 to disable multiple mode at boot */ @@ -62,6 +60,9 @@ #define RECAL_FREQ 4 /* Recalibrate every 4th retry */ #define MAX_HD 2 +#define STAT_OK (READY_STAT|SEEK_STAT) +#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) + static void recal_intr(void); static void bad_rw_intr(void); @@ -135,12 +136,12 @@ static void dump_status (char *msg, unsigned int stat) { unsigned long flags; - char dev; + char devc; - dev = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?'; + devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?'; save_flags (flags); sti(); - printk("hd%c: %s: status=0x%02x { ", dev, msg, stat & 0xff); + printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); if (stat & BUSY_STAT) printk("Busy "); if (stat & READY_STAT) printk("DriveReady "); if (stat & WRERR_STAT) printk("WriteFault "); @@ -150,55 +151,48 @@ if (stat & INDEX_STAT) printk("Index "); if (stat & ERR_STAT) printk("Error "); printk("}\n"); - if (stat & ERR_STAT) { - unsigned int err = inb(HD_ERROR); - printk("hd%c: %s: error=0x%02x { ", dev, msg, err & 0xff); - if (err & BBD_ERR) printk("BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); + if ((stat & ERR_STAT) == 0) { + hd_error = 0; + } else { + hd_error = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); + if (hd_error & BBD_ERR) printk("BadSector "); + if (hd_error & ECC_ERR) printk("UncorrectableError "); + if (hd_error & ID_ERR) printk("SectorIdNotFound "); + if (hd_error & ABRT_ERR) printk("DriveStatusError "); + if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); + if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); printk("}"); - if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - if (CURRENT) - printk(", sector=%ld", CURRENT->sector); + if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); + if (CURRENT) + printk(", sector=%ld", CURRENT->sector); } printk("\n"); } restore_flags (flags); } -static int win_result(void) +void check_status(void) { - int i=inb_p(HD_STATUS); + int i = inb_p(HD_STATUS); - if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)) - == (READY_STAT | SEEK_STAT)) { - hd_error = 0; - return 0; /* ok */ + if (!OK_STATUS(i)) { + dump_status("check_status", i); + bad_rw_intr(); } - dump_status("win_result", i); - return 1; } -static int controller_busy(void); -static int status_ok(void); - -static int controller_ready(unsigned int drive, unsigned int head) +static int controller_busy(void) { - int retry = 100; + int retries = 100000; + unsigned char status; do { - if (controller_busy() & BUSY_STAT) - return 0; - outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); - if (status_ok()) - return 1; - } while (--retry); - return 0; + status = inb_p(HD_STATUS); + } while ((status & BUSY_STAT) && --retries); + return status; } static int status_ok(void) @@ -206,7 +200,7 @@ unsigned char status = inb_p(HD_STATUS); if (status & BUSY_STAT) - return 1; + return 1; /* Ancient, but does it make sense??? */ if (status & WRERR_STAT) return 0; if (!(status & READY_STAT)) @@ -216,15 +210,18 @@ return 1; } -static int controller_busy(void) +static int controller_ready(unsigned int drive, unsigned int head) { - int retries = 100000; - unsigned char status; + int retry = 100; do { - status = inb_p(HD_STATUS); - } while ((status & BUSY_STAT) && --retries); - return status; + if (controller_busy() & BUSY_STAT) + return 0; + outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); + if (status_ok()) + return 1; + } while (--retry); + return 0; } static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, @@ -233,13 +230,6 @@ { unsigned short port; -#ifdef DEBUG - if (drive>1 || head>15) { - printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n", - drive, cyl, head, sect); - panic("harddisk driver problem"); - } -#endif #if (HD_DELAY > 0) while (read_timer() - last_req < HD_DELAY) /* nothing */; @@ -346,7 +336,7 @@ /* * Early model Quantum drives go weird at this point, * but doing a recalibrate seems to "fix" them. - * (Doing a full reset confuses some newer model Quantums) + * (Doing a full reset confuses some other model Quantums) */ if (!strncmp(id->model, "QUANTUM", 7)) special_op[dev] = recalibrate[dev] = 1; @@ -366,7 +356,7 @@ sti(); if (stat & (BUSY_STAT|ERR_STAT)) { mult_req[dev] = mult_count[dev] = 0; - dump_status("set multiple mode failed", stat); + dump_status("set multmode failed", stat); } else { if ((mult_count[dev] = mult_req[dev])) printk (" hd%c: enabled %d-sector multiple mode\n", @@ -388,8 +378,7 @@ for (i = 0; i < 500000 ; i++) { c = inb_p(HD_STATUS); - c &= (BUSY_STAT | READY_STAT | SEEK_STAT); - if (c == (READY_STAT | SEEK_STAT)) + if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) return 0; } dump_status("reset timed out", c); @@ -405,9 +394,9 @@ outb_p(hd_info[0].ctl & 0x0f,HD_CMD); for(i = 0; i < 1000; i++) nop(); if (drive_busy()) - printk("HD-controller still busy\n"); - if ((hd_error = inb(HD_ERROR)) != 1) - printk("HD-controller reset failed: %02x\n",hd_error); + printk("hd: controller still busy\n"); + else if ((hd_error = inb(HD_ERROR)) != 1) + printk("hd: controller reset failed: %02x\n",hd_error); } static void reset_hd(void) @@ -419,12 +408,13 @@ reset = 0; i = -1; reset_controller(); - } else if (win_result()) { - bad_rw_intr(); + } else { + check_status(); if (reset) goto repeat; } if (++i < NR_HD) { + special_op[i] = recalibrate[i] = 1; if (unmask_intr[i]) { unmask_intr[i] = DEFAULT_UNMASK_INTR; printk("hd%c: reset irq-unmasking to %d\n",i+'a', @@ -444,7 +434,6 @@ hd_request(); } - /* * Ok, don't know what to do with the unexpected interrupts: on some machines * doing a reset and a retry seems to result in an eternal loop. Right now I @@ -478,11 +467,11 @@ dev = DEVICE_NR(CURRENT->dev); if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { end_request(0); - special_op[dev] += recalibrate[dev] = 1; + special_op[dev] = recalibrate[dev] = 1; } else if (CURRENT->errors % RESET_FREQ == 0) reset = 1; else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) - special_op[dev] += recalibrate[dev] = 1; + special_op[dev] = recalibrate[dev] = 1; /* Otherwise just retry */ } @@ -497,9 +486,6 @@ return -1; } -#define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT) -#define STAT_OK (READY_STAT | SEEK_STAT) - static void read_intr(void) { unsigned int dev = DEVICE_NR(CURRENT->dev); @@ -511,7 +497,7 @@ i = (unsigned) inb_p(HD_STATUS); if (i & BUSY_STAT) continue; - if ((i & STAT_MASK) != STAT_OK) + if (!OK_STATUS(i)) break; if (i & DRQ_STAT) goto ok_to_read; @@ -534,9 +520,9 @@ i = (CURRENT->nr_sectors -= nsect); #ifdef DEBUG - printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n", + printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=0x%08lx\n", dev+'a', CURRENT->sector, CURRENT->sector+nsect, - CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9)); + CURRENT->nr_sectors, (unsigned long) CURRENT->buffer+(nsect<<9)); #endif if ((CURRENT->current_nr_sectors -= nsect) <= 0) end_request(1); @@ -581,7 +567,7 @@ if (unmask_intr[dev]) sti(); - if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) { + if (OK_STATUS(i=inb_p(HD_STATUS))) { if (i & DRQ_STAT) { if (WCURRENT.nr_sectors) { multwrite(dev); @@ -619,7 +605,7 @@ i = (unsigned) inb_p(HD_STATUS); if (i & BUSY_STAT) continue; - if ((i & STAT_MASK) != STAT_OK) + if (!OK_STATUS(i)) break; if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) goto ok_to_write; @@ -650,8 +636,7 @@ static void recal_intr(void) { - if (win_result()) - bad_rw_intr(); + check_status(); #if (HD_DELAY > 0) last_req = read_timer(); #endif @@ -664,116 +649,118 @@ */ static void hd_times_out(void) { + unsigned int dev; + DEVICE_INTR = NULL; - sti(); if (!CURRENT) return; + disable_irq(HD_IRQ); + sti(); reset = 1; - printk(KERN_DEBUG "HD timeout\n"); + dev = DEVICE_NR(CURRENT->dev); + printk("hd%c: timeout\n", dev+'a'); if (++CURRENT->errors >= MAX_ERRORS) { #ifdef DEBUG - printk("hd : too many errors.\n"); + printk("hd%c: too many errors\n", dev+'a'); #endif end_request(0); } cli(); - hd_request(); + enable_irq(HD_IRQ); +} + +int do_special_op (unsigned int dev) +{ + if (recalibrate[dev]) { + recalibrate[dev] = 0; + hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); + return reset; + } + if (!identified[dev]) { + identified[dev] = 1; + unmask_intr[dev] = DEFAULT_UNMASK_INTR; + mult_req[dev] = DEFAULT_MULT_COUNT; + hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr); + return reset; + } + if (mult_req[dev] != mult_count[dev]) { + hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr); + return reset; + } + if (hd_info[dev].head > 16) { + printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); + end_request(0); + } + special_op[dev] = 0; + return 1; } /* - * The driver has been modified to enable interrupts a bit more: in order to - * do this we first (a) disable the timeout-interrupt and (b) clear the - * device-interrupt. This way the interrupts won't mess with out code (the - * worst that can happen is that an unexpected HD-interrupt comes in and - * sets the "reset" variable and starts the timer) + * The driver enables interrupts as much as possible. In order to do this, + * (a) the device-interrupt is disabled before entering hd_request(), + * and (b) the timeout-interrupt is disabled before the sti(). + * + * Interrupts are still masked (by default) whenever we are exchanging + * data/cmds with a drive, because some drives seem to have very poor + * tolerance for latency during I/O. For devices which don't suffer from + * that problem (most don't), the unmask_intr[] flag can be set to unmask + * other interrupts during data/cmd transfers (by defining DEFAULT_UNMASK_INTR + * to 1, or by using "hdparm -u1 /dev/hd?" from the shell). */ static void hd_request(void) { - unsigned int block,dev; - unsigned int sec,head,cyl,track; - unsigned int nsect; + unsigned int dev, block, nsect, sec, track, head, cyl; if (CURRENT && CURRENT->dev < 0) return; - if (DEVICE_INTR) return; repeat: timer_active &= ~(1<dev); block = CURRENT->sector; nsect = CURRENT->nr_sectors; - if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) { + if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { #ifdef DEBUG - printk("hd : attempted read for sector %d past end of device at sector %d.\n", - block, hd[dev].nr_sects); + if (dev >= (NR_HD<<6)) + printk("hd: bad minor number: device=0x%04x\n", CURRENT->dev); + else + printk("hd%c: bad access: block=%d, count=%d\n", + (CURRENT->dev>>6)+'a', block, nsect); #endif end_request(0); goto repeat; } block += hd[dev].start_sect; dev >>= 6; - sec = block % hd_info[dev].sect + 1; + if (special_op[dev]) { + if (do_special_op(dev)) + goto repeat; + return; + } + sec = block % hd_info[dev].sect + 1; track = block / hd_info[dev].sect; - head = track % hd_info[dev].head; - cyl = track / hd_info[dev].head; + head = track % hd_info[dev].head; + cyl = track / hd_info[dev].head; #ifdef DEBUG - printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n", - dev+'a', cyl, head, sec, CURRENT->buffer); + printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", + dev+'a', (CURRENT->cmd == READ)?"read":"writ", + cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); #endif if (!unmask_intr[dev]) cli(); - if (reset) { - int i; - - for (i=0; i < NR_HD; i++) - special_op[i] = recalibrate[i] = 1; - cli(); /* better play it safe, as resets are the last resort */ - reset_hd(); - return; - } - if (special_op[dev]) { /* we use "special_op" to reduce overhead on r/w */ - if (recalibrate[dev]) { - recalibrate[dev] = 0; - hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); - if (reset) - goto repeat; - return; - } - if (!identified[dev]) { - identified[dev] = 1; - unmask_intr[dev] = DEFAULT_UNMASK_INTR; - mult_req[dev] = DEFAULT_MULT_COUNT; - hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr); - if (reset) - goto repeat; - return; - } - if (mult_req[dev] != mult_count[dev]) { - hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr); - if (reset) - goto repeat; - return; - } - if (hd_info[dev].head > 16) { - printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); - end_request(0); - goto repeat; - } - --special_op[dev]; - } /* special_op[dev] */ if (CURRENT->cmd == READ) { unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ; hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr); if (reset) goto repeat; -#ifdef DEBUG - printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n", - dev+'a', nsect, CURRENT->sector, - CURRENT->sector+nsect-1, (long) CURRENT->buffer); -#endif return; } if (CURRENT->cmd == WRITE) { @@ -783,11 +770,6 @@ hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); if (reset) goto repeat; -#ifdef DEBUG - printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n", - dev+'a', nsect, CURRENT->sector, - CURRENT->sector+nsect-1, (long) CURRENT->buffer); -#endif if (wait_DRQ()) { bad_rw_intr(); goto repeat; @@ -795,9 +777,8 @@ if (mult_count[dev]) { WCURRENT = *CURRENT; multwrite(dev); - } else { + } else outsw(HD_DATA,CURRENT->buffer,256); - } return; } panic("unknown hd-command"); @@ -905,11 +886,11 @@ if (arg > max_mult[dev]) err = -EINVAL; /* out of range for device */ else if (mult_req[dev] != mult_count[dev]) { - ++special_op[dev]; + special_op[dev] = 1; err = -EBUSY; /* busy, try again */ } else { mult_req[dev] = arg; - ++special_op[dev]; + special_op[dev] = 1; err = 0; } restore_flags(flags); @@ -1045,22 +1026,14 @@ } i = NR_HD; while (i-- > 0) { - hd[i<<6].nr_sects = 0; - if (bios_info[i].head > 16) { - /* - * The newer E-IDE BIOSs handle drives larger than 1024 - * cylinders by increasing the number of logical heads - * to keep the number of logical cylinders below the - * sacred INT13 limit of 1024 (10 bits). If that is - * what's happening here, we'll find out and correct - * it later when "identifying" the drive. - */ - printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n"); - printk(" (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a', - bios_info[i].cyl, - bios_info[i].sect, - bios_info[i].head); - } + /* + * The newer E-IDE BIOSs handle drives larger than 1024 + * cylinders by increasing the number of logical heads + * to keep the number of logical cylinders below the + * sacred INT13 limit of 1024 (10 bits). If that is + * what's happening here, we'll find out and correct + * it later when "identifying" the drive. + */ hd[i<<6].nr_sects = bios_info[i].head * bios_info[i].sect * bios_info[i].cyl; hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL); @@ -1068,7 +1041,7 @@ } if (NR_HD) { if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) { - printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ); + printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ); NR_HD = 0; } } @@ -1094,7 +1067,7 @@ unsigned long hd_init(unsigned long mem_start, unsigned long mem_end) { if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("Unable to get major %d for harddisk\n",MAJOR_NR); + printk("hd: unable to get major %d for harddisk\n",MAJOR_NR); return mem_start; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; diff -u --recursive --new-file v1.1.54/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v1.1.54/linux/drivers/char/lp.c Sun Oct 9 12:00:24 1994 +++ linux/drivers/char/lp.c Tue Oct 18 10:07:53 1994 @@ -514,4 +514,12 @@ return 0; } +void cleanup_module(void) +{ + if(MOD_IN_USE) + printk("lp: busy - remove delayed\n"); + else + unregister_chrdev(LP_MAJOR,"lp"); +} + #endif diff -u --recursive --new-file v1.1.54/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v1.1.54/linux/drivers/sound/Makefile Thu Jul 21 08:18:12 1994 +++ linux/drivers/sound/Makefile Tue Oct 18 10:07:28 1994 @@ -54,7 +54,11 @@ @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h - @echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h + @if [ -x /bin/dnsdomainname ]; then \ + echo \#define SOUND_CONFIG_DOMAIN \"`dnsdomainname`\"; \ + else \ + echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\"; \ + fi >> local.h clrconf: rm -f local.h .depend diff -u --recursive --new-file v1.1.54/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v1.1.54/linux/fs/binfmt_elf.c Thu Oct 20 09:37:35 1994 +++ linux/fs/binfmt_elf.c Tue Oct 18 10:07:47 1994 @@ -612,8 +612,8 @@ current->mm->start_code = start_code; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; - current->suid = current->euid = bprm->e_uid; - current->sgid = current->egid = bprm->e_gid; + current->suid = current->euid = current->fsuid = bprm->e_uid; + current->sgid = current->egid = current->fsgid = bprm->e_gid; /* Calling sys_brk effectively mmaps the pages that we need for the bss and break sections */ diff -u --recursive --new-file v1.1.54/linux/fs/ext/dir.c linux/fs/ext/dir.c --- v1.1.54/linux/fs/ext/dir.c Sun Oct 9 12:00:25 1994 +++ linux/fs/ext/dir.c Wed Oct 19 10:23:03 1994 @@ -20,6 +20,9 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int ext_dir_read(struct inode * inode, struct file * filp, char * buf, int count) { return -EISDIR; @@ -65,6 +68,7 @@ struct dirent * dirent, int count) { unsigned int i; + unsigned int ret; off_t offset; char c; struct buffer_head * bh; @@ -74,15 +78,23 @@ return -EBADF; if ((filp->f_pos & 7) != 0) return -EBADF; - while (filp->f_pos < inode->i_size) { + ret = 0; + while (!ret && filp->f_pos < inode->i_size) { offset = filp->f_pos & 1023; bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0); if (!bh) { filp->f_pos += 1024-offset; continue; } + for (i = 0; i < 1024 && i < offset; ) { + de = (struct ext_dir_entry *) (bh->b_data + i); + if (!de->rec_len) + break; + i += de->rec_len; + } + offset = i; de = (struct ext_dir_entry *) (offset + bh->b_data); - while (offset < 1024 && filp->f_pos < inode->i_size) { + while (!ret && offset < 1024 && filp->f_pos < inode->i_size) { if (de->rec_len < 8 || de->rec_len % 8 != 0 || de->rec_len < de->name_len + 8 || (de->rec_len + (off_t) filp->f_pos - 1) / 1024 > ((off_t) filp->f_pos / 1024)) { @@ -106,8 +118,8 @@ put_fs_long(de->inode,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); - brelse(bh); - return i; + ret = ROUND_UP(NAME_OFFSET(dirent)+i+1); + break; } } de = (struct ext_dir_entry *) ((char *) de @@ -115,5 +127,5 @@ } brelse(bh); } - return 0; + return ret; } diff -u --recursive --new-file v1.1.54/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v1.1.54/linux/fs/ext2/dir.c Sun Aug 21 17:48:35 1994 +++ linux/fs/ext2/dir.c Wed Oct 19 10:23:17 1994 @@ -22,6 +22,9 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int ext2_dir_read (struct inode * inode, struct file * filp, char * buf, int count) { @@ -98,17 +101,21 @@ struct dirent * dirent, int count) { unsigned long offset, blk; - int i, num; + int i, num, stored, dlen; struct buffer_head * bh, * tmp, * bha[16]; struct ext2_dir_entry * de; struct super_block * sb; - int err; - + int err, version; + if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; sb = inode->i_sb; - while (filp->f_pos < inode->i_size) { - offset = filp->f_pos & (sb->s_blocksize - 1); + + stored = 0; + bh = NULL; + offset = filp->f_pos & (sb->s_blocksize - 1); + + while (count > 0 && !stored && filp->f_pos < inode->i_size) { blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb); bh = ext2_bread (inode, blk, 0, &err); if (!bh) { @@ -135,39 +142,78 @@ } } - de = (struct ext2_dir_entry *) (offset + bh->b_data); - while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) { +revalidate: + /* If the dir block has changed since the last call to + readdir(2), then we might be pointing to an invalid dirent + right now. Scan from the start of the block to make + sure. */ + for (i = 0; i < sb->s_blocksize && i < offset; ) { + de = (struct ext2_dir_entry *) (bh->b_data + i); + /* It's too expensive to do a full dirent test + * each time round this loop, but we do have + * to test at least that it is non-zero. A + * failure will be detected in the dirent test + * below. */ + if (de->rec_len < EXT2_DIR_REC_LEN(1)) + break; + i += de->rec_len; + } + offset = i; + filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset; + + while (count > 0 && filp->f_pos < inode->i_size + && offset < sb->s_blocksize) { + de = (struct ext2_dir_entry *) (bh->b_data + offset); if (!ext2_check_dir_entry ("ext2_readdir", inode, de, bh, offset)) { + /* On error, skip the f_pos to the next block. */ + filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + + sb->s_blocksize; brelse (bh); - return 0; + return stored; } - offset += de->rec_len; - filp->f_pos += de->rec_len; if (de->inode) { - memcpy_tofs (dirent->d_name, de->name, - de->name_len); + dlen = ROUND_UP(NAME_OFFSET(dirent) + + de->name_len + 1); + /* Old libc libraries always use a count of 1. */ + if (count == 1 && !stored) + count = dlen; + if (count < dlen) { + count = 0; + break; + } + + /* We might block in the next section + * if the data destination is + * currently swapped out. So, use a + * version stamp to detect whether or + * not the directory has been modified + * during the copy operation. */ + version = inode->i_version; + i = de->name_len; + memcpy_tofs (dirent->d_name, de->name, i); put_fs_long (de->inode, &dirent->d_ino); - put_fs_byte (0, de->name_len + dirent->d_name); - put_fs_word (de->name_len, &dirent->d_reclen); + put_fs_byte (0, dirent->d_name + i); + put_fs_word (i, &dirent->d_reclen); + put_fs_long (dlen, &dirent->d_off); + if (version != inode->i_version) + goto revalidate; dcache_add(inode, de->name, de->name_len, de->inode); - i = de->name_len; - brelse (bh); - if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - return i; + + stored += dlen; + count -= dlen; + ((char *) dirent) += dlen; } - de = (struct ext2_dir_entry *) ((char *) de + - de->rec_len); + offset += de->rec_len; + filp->f_pos += de->rec_len; } + offset = 0; brelse (bh); } if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } - return 0; + return stored; } diff -u --recursive --new-file v1.1.54/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v1.1.54/linux/fs/ext2/namei.c Sun Aug 21 17:48:36 1994 +++ linux/fs/ext2/namei.c Wed Oct 19 10:23:17 1994 @@ -318,6 +318,7 @@ */ dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_dirt = 1; + dir->i_version = ++event; mark_buffer_dirty(bh, 1); *res_dir = de; *err = 0; @@ -923,8 +924,10 @@ goto start_up; try_again: - if (new_bh && new_de) + if (new_bh && new_de) { ext2_delete_entry(new_de, new_bh); + new_dir->i_version = ++event; + } brelse (old_bh); brelse (new_bh); brelse (dir_bh); @@ -1002,6 +1005,7 @@ &retval); if (!new_bh) goto end_rename; + new_dir->i_version = ++event; /* * sanity checking before doing the rename - avoid races */ @@ -1015,7 +1019,6 @@ * ok, that's it */ new_de->inode = old_inode->i_ino; - new_dir->i_version = ++event; dcache_add(new_dir, new_de->name, new_de->name_len, new_de->inode); retval = ext2_delete_entry (old_de, old_bh); if (retval == -ENOENT) diff -u --recursive --new-file v1.1.54/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- v1.1.54/linux/fs/hpfs/hpfs_fs.c Sun Aug 21 17:48:36 1994 +++ linux/fs/hpfs/hpfs_fs.c Wed Oct 19 10:23:18 1994 @@ -117,6 +117,9 @@ /* notation */ +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + #define little_ushort(x) (*(unsigned short *) &(x)) typedef void nonconst; @@ -1345,13 +1348,13 @@ case 0: write_one_dirent(dirent, ".", 1, inode->i_ino, lc); filp->f_pos = -1; - return 1; + return ROUND_UP(NAME_OFFSET(dirent) + 2); case -1: write_one_dirent(dirent, "..", 2, inode->i_hpfs_parent_dir, lc); filp->f_pos = 1; - return 2; + return ROUND_UP(NAME_OFFSET(dirent) + 3); case -2: return 0; @@ -1371,7 +1374,7 @@ write_one_dirent(dirent, de->name, namelen, ino, lc); brelse4(&qbh); - return namelen; + return ROUND_UP(NAME_OFFSET(dirent) + namelen + 1); } } diff -u --recursive --new-file v1.1.54/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v1.1.54/linux/fs/isofs/dir.c Sun Aug 7 03:30:41 1994 +++ linux/fs/isofs/dir.c Wed Oct 19 10:23:18 1994 @@ -22,6 +22,9 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int isofs_readdir(struct inode *, struct file *, struct dirent *, int); static struct file_operations isofs_dir_operations = { @@ -228,7 +231,7 @@ put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); - return i; + return ROUND_UP(NAME_OFFSET(dirent) + i + 1); } } /* We go here for any condition we cannot handle. We also drop through diff -u --recursive --new-file v1.1.54/linux/fs/minix/dir.c linux/fs/minix/dir.c --- v1.1.54/linux/fs/minix/dir.c Wed Dec 1 14:44:15 1993 +++ linux/fs/minix/dir.c Wed Oct 19 10:23:18 1994 @@ -13,6 +13,9 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int minix_dir_read(struct inode * inode, struct file * filp, char * buf, int count) { return -EISDIR; @@ -57,7 +60,8 @@ static int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { - unsigned int offset,i; + unsigned int offset,i,ret; + int version; char c; struct buffer_head * bh; struct minix_dir_entry * de; @@ -68,17 +72,19 @@ info = &inode->i_sb->u.minix_sb; if (filp->f_pos & (info->s_dirsize - 1)) return -EBADF; - while (filp->f_pos < inode->i_size) { + ret = 0; + while (!ret && filp->f_pos < inode->i_size) { offset = filp->f_pos & 1023; bh = minix_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0); if (!bh) { filp->f_pos += 1024-offset; continue; } - while (offset < 1024 && filp->f_pos < inode->i_size) { + while (!ret && offset < 1024 && filp->f_pos < inode->i_size) { de = (struct minix_dir_entry *) (offset + bh->b_data); offset += info->s_dirsize; filp->f_pos += info->s_dirsize; +retry: if (de->inode) { for (i = 0; i < info->s_namelen; i++) if ((c = de->name[i]) != 0) @@ -86,15 +92,17 @@ else break; if (i) { + version = inode->i_version; put_fs_long(de->inode,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); - brelse(bh); - return i; + if (version != inode->i_version) + goto retry; + ret = ROUND_UP(NAME_OFFSET(dirent)+i+1); } } } brelse(bh); } - return 0; + return ret; } diff -u --recursive --new-file v1.1.54/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v1.1.54/linux/fs/minix/namei.c Mon Aug 15 11:47:10 1994 +++ linux/fs/minix/namei.c Wed Oct 19 10:23:18 1994 @@ -195,6 +195,7 @@ dir->i_mtime = dir->i_ctime = CURRENT_TIME; for (i = 0; i < info->s_namelen ; i++) de->name[i] = (i < namelen) ? name[i] : 0; + dir->i_version = ++event; mark_buffer_dirty(bh, 1); *res_dir = de; break; @@ -470,11 +471,12 @@ if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink); de->inode = 0; + dir->i_version = ++event; mark_buffer_dirty(bh, 1); inode->i_nlink=0; inode->i_dirt=1; - dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->i_nlink--; dir->i_dirt=1; retval = 0; end_rmdir: @@ -523,6 +525,7 @@ inode->i_nlink=1; } de->inode = 0; + dir->i_version = ++event; mark_buffer_dirty(bh, 1); dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt = 1; @@ -768,8 +771,10 @@ new_de->inode = old_inode->i_ino; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; old_dir->i_dirt = 1; + old_dir->i_version = ++event; new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; new_dir->i_dirt = 1; + new_dir->i_version = ++event; if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; diff -u --recursive --new-file v1.1.54/linux/fs/msdos/dir.c linux/fs/msdos/dir.c --- v1.1.54/linux/fs/msdos/dir.c Wed Aug 31 10:14:11 1994 +++ linux/fs/msdos/dir.c Wed Oct 19 10:23:18 1994 @@ -14,7 +14,10 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count) { return -EISDIR; @@ -73,7 +76,7 @@ put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino); put_fs_byte(0,dirent->d_name+i); put_fs_word(i,&dirent->d_reclen); - return i; + return ROUND_UP(NAME_OFFSET(dirent) + i + 1); } } if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT; @@ -110,7 +113,7 @@ memcpy_tofs(dirent->d_name,bufname,i+1); put_fs_word(i,&dirent->d_reclen); brelse(bh); - return i; + return ROUND_UP(NAME_OFFSET(dirent) + i + 1); } } } diff -u --recursive --new-file v1.1.54/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v1.1.54/linux/fs/nfs/dir.c Wed Dec 1 14:44:15 1993 +++ linux/fs/nfs/dir.c Wed Oct 19 10:23:18 1994 @@ -18,6 +18,9 @@ #include /* for fs functions */ +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int nfs_dir_read(struct inode *, struct file *filp, char *buf, int count); static int nfs_readdir(struct inode *, struct file *, struct dirent *, int); @@ -153,7 +156,7 @@ put_fs_long(entry->fileid, &dirent->d_ino); put_fs_word(i, &dirent->d_reclen); filp->f_pos = entry->cookie; - return i; + return ROUND_UP(NAME_OFFSET(dirent)+i+1); } return 0; } diff -u --recursive --new-file v1.1.54/linux/fs/proc/link.c linux/fs/proc/link.c --- v1.1.54/linux/fs/proc/link.c Thu Oct 20 09:37:35 1994 +++ linux/fs/proc/link.c Thu Oct 20 09:54:33 1994 @@ -92,7 +92,8 @@ new_f->f_count++; current->files->fd[fd] = new_f; - f->f_count--; + if (!--f->f_count) + iput(f->f_inode); return 0; } diff -u --recursive --new-file v1.1.54/linux/fs/read_write.c linux/fs/read_write.c --- v1.1.54/linux/fs/read_write.c Sun Aug 21 17:48:37 1994 +++ linux/fs/read_write.c Wed Oct 19 10:23:18 1994 @@ -13,8 +13,14 @@ #include /* - * Count is not yet used: but we'll probably support reading several entries - * at once in the future. Use count=1 in the library for future expansions. + * Count is now a supported feature, but currently only the ext2fs + * uses it. A count value of 1 is supported for compatibility with + * earlier libraries, but larger values are supported: count should + * indicate the total buffer space available for filling with dirents. + * The d_off entry in the dirents will then indicate the offset from + * each dirent to the next, and the return value will indicate the + * number of bytes written. All dirents will be written at + * word-aligned addresses. [sct Oct 1994] */ asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count) { @@ -62,8 +68,10 @@ } if (tmp < 0) return -EINVAL; - file->f_pos = tmp; - file->f_reada = 0; + if (tmp != file->f_pos) { + file->f_pos = tmp; + file->f_reada = 0; + } return file->f_pos; } diff -u --recursive --new-file v1.1.54/linux/fs/sysv/dir.c linux/fs/sysv/dir.c --- v1.1.54/linux/fs/sysv/dir.c Sun Aug 21 17:48:37 1994 +++ linux/fs/sysv/dir.c Wed Oct 19 10:23:18 1994 @@ -20,6 +20,9 @@ #include #include +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count) { return -EISDIR; @@ -100,7 +103,7 @@ put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); - return i; + return ROUND_UP(NAME_OFFSET(dirent)+i+1); } } } diff -u --recursive --new-file v1.1.54/linux/fs/xiafs/dir.c linux/fs/xiafs/dir.c --- v1.1.54/linux/fs/xiafs/dir.c Wed Dec 1 14:44:15 1993 +++ linux/fs/xiafs/dir.c Wed Oct 19 10:23:19 1994 @@ -19,6 +19,9 @@ #include "xiafs_mac.h" +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+3) & ~3) + static int xiafs_dir_read(struct inode *, struct file *, char *, int); static int xiafs_readdir(struct inode *, struct file *, struct dirent *, int); @@ -65,7 +68,7 @@ static int xiafs_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { - u_int offset, i; + u_int offset, i,ret; struct buffer_head * bh; struct xiafs_direct * de; @@ -73,15 +76,24 @@ return -EBADF; if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) ) return -EBADF; - while (filp->f_pos < inode->i_size) { + ret = 0; + while (!ret && filp->f_pos < inode->i_size) { offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1); bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0); if (!bh) { filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset; continue; } + for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) { + de = (struct xiafs_direct *) (bh->b_data + i); + if (!de->d_rec_len) + break; + i += de->d_rec_len; + } + offset = i; de = (struct xiafs_direct *) (offset + bh->b_data); - while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) { + + while (!ret && offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) { if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || de->d_rec_len < 12 || (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data || @@ -100,12 +112,12 @@ put_fs_byte(0,i+dirent->d_name); put_fs_long(de->d_ino,&dirent->d_ino); put_fs_word(i,&dirent->d_reclen); - brelse(bh); if (!IS_RDONLY (inode)) { inode->i_atime=CURRENT_TIME; inode->i_dirt=1; } - return i; + ret = ROUND_UP(NAME_OFFSET(dirent)+i+1); + break; } de = (struct xiafs_direct *) (offset + bh->b_data); } diff -u --recursive --new-file v1.1.54/linux/include/linux/hdreg.h linux/include/linux/hdreg.h --- v1.1.54/linux/include/linux/hdreg.h Sun Oct 9 12:00:27 1994 +++ linux/include/linux/hdreg.h Tue Oct 18 10:08:05 1994 @@ -71,7 +71,6 @@ #define HDIO_SETUNMASKINTR 0x303 #define HDIO_GETMULTCOUNT 0x304 #define HDIO_SETMULTCOUNT 0x305 -#define HDIO_SETFEATURE 0x306 #define HDIO_GETIDENTITY 0x307 #endif diff -u --recursive --new-file v1.1.54/linux/include/linux/tty.h linux/include/linux/tty.h --- v1.1.54/linux/include/linux/tty.h Thu Oct 20 09:37:36 1994 +++ linux/include/linux/tty.h Tue Oct 18 10:07:59 1994 @@ -289,6 +289,7 @@ extern void start_tty(struct tty_struct * tty); extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_register_driver(struct tty_driver *driver); +extern int tty_unregister_driver(struct tty_driver *driver); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); diff -u --recursive --new-file v1.1.54/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.1.54/linux/kernel/ksyms.c Wed Aug 31 10:14:11 1994 +++ linux/kernel/ksyms.c Tue Oct 18 10:08:05 1994 @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef CONFIG_INET #include @@ -91,6 +92,9 @@ X(unregister_chrdev), X(register_blkdev), X(unregister_blkdev), + X(tty_register_driver), + X(tty_unregister_driver), + X(tty_std_termios), /* block device driver support */ X(block_read), diff -u --recursive --new-file v1.1.54/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.1.54/linux/net/inet/tcp.c Wed Oct 5 15:17:23 1994 +++ linux/net/inet/tcp.c Wed Oct 19 10:44:34 1994 @@ -83,6 +83,7 @@ * Matt Dillon : Yet more small nasties remove from the TCP code * (Be very nice to this man if tcp finally works 100%) 8) * Alan Cox : BSD accept semantics. + * Peter De Schrijver : ENOTCONN check missing in tcp_sendto(). * * * To Fix: @@ -1221,15 +1222,17 @@ { if (flags & ~(MSG_OOB|MSG_DONTROUTE)) return -EINVAL; - if (addr_len < sizeof(*addr)) - return(-EINVAL); + if (!tcp_connected(sk->state)) + return -ENOTCONN; + if (addr_len < sizeof(*addr)) + return -EINVAL; if (addr->sin_family && addr->sin_family != AF_INET) - return(-EINVAL); + return -EINVAL; if (addr->sin_port != sk->dummy_th.dest) - return(-EISCONN); + return -EISCONN; if (addr->sin_addr.s_addr != sk->daddr) - return(-EISCONN); - return(tcp_write(sk, from, len, nonblock, flags)); + return -EISCONN; + return tcp_write(sk, from, len, nonblock, flags); } @@ -2238,7 +2241,7 @@ /* The +1 is not needed because the FIN takes up seq is not read!!! */ if(skb->len > 0 && after(skb->h.th->seq + skb->len , sk->copied_seq)) - need_reset = 1; + need_reset = 0; kfree_skb(skb, FREE_READ); } if(sk->debug)