diff -u --recursive --new-file v2.1.61/linux/CREDITS linux/CREDITS --- v2.1.61/linux/CREDITS Sat Nov 1 11:04:27 1997 +++ linux/CREDITS Sun Nov 2 13:13:44 1997 @@ -1094,10 +1094,10 @@ S: Germany N: David Mosberger-Tang -E: davidm@azstarnet.com +E: David.Mosberger@acm.org D: Linux/Alpha -S: 2552 E. Copper Street -S: Tucson, Arizona 85716-2406 +S: 35706 Runckel Lane +S: Fremont, CA 94536 S: USA N: Ian A. Murdock diff -u --recursive --new-file v2.1.61/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.61/linux/Documentation/Configure.help Sat Oct 25 02:44:14 1997 +++ linux/Documentation/Configure.help Sat Nov 1 12:23:52 1997 @@ -1667,10 +1667,10 @@ Enable vendor-specific extensions (for SCSI CDROM) CONFIG_BLK_DEV_SR_VENDOR This enables the usage of vendor specific SCSI commands. This is - required for some stuff which is newer than the SCSI-II standard: - MultiSession CD support and some ioctls for reading Mode 2 Form 2 - sectors. You'll probably want to say Y here, unless you have a - _really old_ CD-ROM drive. + required to support multisession CD's on with old NEC/TOSHIBA + cdrom drives (and HP Writers). If you have such a drive and get + the first session only, try to turn this on. Most drives should + work fine without this. SCSI generic support CONFIG_CHR_DEV_SG diff -u --recursive --new-file v2.1.61/linux/Makefile linux/Makefile --- v2.1.61/linux/Makefile Sat Nov 1 11:04:27 1997 +++ linux/Makefile Mon Nov 3 09:30:30 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 61 +SUBLEVEL = 62 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.61/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.1.61/linux/arch/alpha/kernel/time.c Wed Apr 16 14:14:59 1997 +++ linux/arch/alpha/kernel/time.c Sat Nov 1 09:53:00 1997 @@ -12,6 +12,10 @@ * precision CMOS clock update * 1997-01-09 Adrian Sun * use interval timer if CONFIG_RTC=y + * 1997-10-29 John Bowman (bowman@math.ualberta.ca) + * fixed tick loss calculation in timer_interrupt + * (round system clock to nearest tick instead of truncating) + * fixed algorithm in time_init for getting time from CMOS clock */ #include #include @@ -23,6 +27,7 @@ #include #include #include +#include #include #include @@ -45,10 +50,11 @@ */ #define FIX_SHIFT 48 +static unsigned long round_ticks; + /* lump static variables together for more efficient access: */ static struct { __u32 last_time; /* cycle counter last time it got invoked */ - __u32 max_cycles_per_tick; /* more makes us think we lost an interrupt */ unsigned long scaled_ticks_per_cycle; /* ticks/cycle * 2^48 */ long last_rtc_update; /* last time the cmos clock got updated */ } state; @@ -70,19 +76,15 @@ void timer_interrupt(int irq, void *dev, struct pt_regs * regs) { __u32 delta, now; + int i, nticks; now = rpcc(); delta = now - state.last_time; state.last_time = now; - if (delta > state.max_cycles_per_tick) { - int i, missed_ticks; - - missed_ticks = ((delta * state.scaled_ticks_per_cycle) >> FIX_SHIFT) - 1; - for (i = 0; i < missed_ticks; ++i) { - do_timer(regs); - } + nticks = ((delta * state.scaled_ticks_per_cycle+round_ticks) >> FIX_SHIFT); + for (i = 0; i < nticks; ++i) { + do_timer(regs); } - do_timer(regs); /* * If we have an externally synchronized Linux clock, then update @@ -136,7 +138,6 @@ #endif void (*irq_handler)(int, void *, struct pt_regs *); unsigned int year, mon, day, hour, min, sec; - int i; /* The Linux interpretation of the CMOS clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the @@ -144,20 +145,23 @@ * Let's hope other operating systems interpret the RTC the same way. */ /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); + /* Wait for rise.... (may take up to 1 second) */ + + while(!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); + + /* Wait for fall.... */ + + while(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + + __delay(1000000); + + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); @@ -186,7 +190,7 @@ } state.last_time = rpcc(); state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq; - state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ; + round_ticks=(unsigned long) 1 << (FIX_SHIFT-1); state.last_rtc_update = 0; #ifdef CONFIG_RTC diff -u --recursive --new-file v2.1.61/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.1.61/linux/drivers/block/ide-probe.c Mon Oct 20 10:36:52 1997 +++ linux/drivers/block/ide-probe.c Mon Nov 3 09:31:00 1997 @@ -123,11 +123,12 @@ #endif /* CONFIG_BLK_DEV_PROMISE */ switch (type) { case ide_floppy: - if (strstr (id->model, "oppy") || strstr (id->model, "poyp")) { + if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) + printk("cdrom or floppy?, assuming "); + if (drive->media != ide_cdrom) { printk ("FLOPPY"); break; } - printk ("cdrom or floppy?, assuming "); type = ide_cdrom; /* Early cdrom models used zero */ case ide_cdrom: printk ("CDROM"); diff -u --recursive --new-file v2.1.61/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.1.61/linux/drivers/char/lp.c Wed Sep 24 20:05:46 1997 +++ linux/drivers/char/lp.c Fri Oct 31 11:23:36 1997 @@ -272,9 +272,9 @@ return total_bytes_written; } -static long lp_write(struct inode * inode, struct file * file, - const char * buf, unsigned long count) +static ssize_t lp_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { + struct inode *inode = file->f_dentry->d_inode; unsigned int minor = MINOR(inode->i_rdev); int retv; @@ -315,9 +315,9 @@ } /* Status readback confirming to ieee1284 */ -static long lp_read(struct inode * inode, struct file * file, - char * buf, unsigned long count) +static ssize_t lp_read(struct file * file, char * buf, size_t count, loff_t *ppos) { + struct inode *inode = file->f_dentry->d_inode; unsigned char z=0, Byte=0, status; char *temp; int retval; diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- v2.1.61/linux/drivers/isdn/avmb1/capi.c Wed Sep 24 20:05:47 1997 +++ linux/drivers/isdn/avmb1/capi.c Mon Nov 3 10:14:54 1997 @@ -45,12 +45,11 @@ #include #include #include -#if (LINUX_VERSION_CODE >= 0x020117) -#include -#endif #include #include +#include + #include "compat.h" #include "capiutil.h" #include "capicmd.h" @@ -96,29 +95,16 @@ /* -------- file_operations ----------------------------------------- */ -#if LINUX_VERSION_CODE < 0x020100 -static int capi_lseek(struct inode *inode, struct file *file, - off_t offset, int origin) +static loff_t capi_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } -#else -static long long capi_llseek(struct inode *inode, struct file *file, - long long offset, int origin) -{ - return -ESPIPE; -} -#endif -#if LINUX_VERSION_CODE < 0x020100 -static int capi_read(struct inode *inode, struct file *file, - char *buf, int count) -#else -static long capi_read(struct inode *inode, struct file *file, - char *buf, unsigned long count) -#endif +static ssize_t capi_read(struct file *file, + char *buf, size_t count, + loff_t *off) { - unsigned int minor = MINOR(inode->i_rdev); + unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); struct capidev *cdev; struct sk_buff *skb; int retval; @@ -164,15 +150,11 @@ return copied; } -#if LINUX_VERSION_CODE < 0x020100 -static int capi_write(struct inode *inode, struct file *file, - const char *buf, int count) -#else -static long capi_write(struct inode *inode, struct file *file, - const char *buf, unsigned long count) -#endif +static ssize_t capi_write(struct file *file, + const char *buf, size_t count, + loff_t *off) { - unsigned int minor = MINOR(inode->i_rdev); + unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); struct capidev *cdev; struct sk_buff *skb; int retval; @@ -215,40 +197,6 @@ return count; } -#if (LINUX_VERSION_CODE < 0x020117) -static int capi_select(struct inode *inode, struct file *file, - int sel_type, select_table * wait) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct capidev *cdev; - - if (!minor || minor > CAPI_MAXMINOR || !capidevs[minor].is_registered) - return -ENODEV; - - cdev = &capidevs[minor]; - - switch (sel_type) { - case SEL_IN: - if (!skb_queue_empty(&cdev->recv_queue)) - return 1; - /* fall througth */ - case SEL_EX: - /* error conditions ? */ - - select_wait(&cdev->recv_wait, wait); - return 0; - case SEL_OUT: - /* - if (!queue_full()) - return 1; - select_wait(&cdev->send_wait, wait); - return 0; - */ - return 1; - } - return 1; -} -#else static unsigned int capi_poll(struct file *file, poll_table * wait) { @@ -266,7 +214,6 @@ mask |= POLLIN | POLLRDNORM; return mask; } -#endif static int capi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -480,19 +427,11 @@ static struct file_operations capi_fops = { -#if LINUX_VERSION_CODE < 0x020100 - capi_lseek, -#else capi_llseek, -#endif capi_read, capi_write, NULL, /* capi_readdir */ -#if (LINUX_VERSION_CODE < 0x020117) - capi_select, -#else capi_poll, -#endif capi_ioctl, NULL, /* capi_mmap */ capi_open, diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c --- v2.1.61/linux/drivers/isdn/hisax/avm_a1.c Thu May 29 21:53:05 1997 +++ linux/drivers/isdn/hisax/avm_a1.c Mon Nov 3 09:54:38 1997 @@ -558,7 +558,7 @@ u_char val, sval, stat = 0; char tmp[32]; - sp = (struct IsdnCardState *) irq2dev_map[intno]; + sp = (struct IsdnCardState *) dev_id; if (!sp) { printk(KERN_WARNING "AVM A1: Spurious interrupt!\n"); @@ -798,8 +798,7 @@ printk(KERN_WARNING "AVM A1: IRQ(%d) getting no interrupts during init\n", sp->irq); - irq2dev_map[sp->irq] = NULL; - free_irq(sp->irq, NULL); + free_irq(sp->irq, sp); return (0); } } diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c --- v2.1.61/linux/drivers/isdn/hisax/elsa.c Thu May 29 21:53:05 1997 +++ linux/drivers/isdn/hisax/elsa.c Mon Nov 3 09:54:38 1997 @@ -887,7 +887,7 @@ struct IsdnCardState *sp; u_char val; - sp = (struct IsdnCardState *) irq2dev_map[intno]; + sp = (struct IsdnCardState *) dev_id; if (!sp) { printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); @@ -1219,8 +1219,7 @@ "Elsa: IRQ(%d) getting no interrupts during init %d\n", sp->irq, 4 - cnt); if (cnt == 1) { - irq2dev_map[sp->irq] = NULL; - free_irq(sp->irq, NULL); + free_irq(sp->irq, sp); return (0); } else { reset_elsa(sp); diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c --- v2.1.61/linux/drivers/isdn/hisax/isdnl1.c Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/hisax/isdnl1.c Mon Nov 3 09:54:38 1997 @@ -766,13 +766,12 @@ save_flags(flags); cli(); if (request_irq(card->sp->irq, routine, - I4L_IRQ_FLAG, "HiSax", NULL)) { + I4L_IRQ_FLAG, "HiSax", card->sp)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", card->sp->irq); restore_flags(flags); return (0); } - irq2dev_map[card->sp->irq] = (void *) card->sp; restore_flags(flags); return (1); } @@ -782,8 +781,7 @@ { struct IsdnCard *card = cards + cardnr; - irq2dev_map[card->sp->irq] = NULL; - free_irq(card->sp->irq, NULL); + free_irq(card->sp->irq, card->sp); } void diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c --- v2.1.61/linux/drivers/isdn/hisax/ix1_micro.c Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/hisax/ix1_micro.c Mon Nov 3 09:54:38 1997 @@ -644,7 +644,7 @@ struct IsdnCardState *sp; u_char val, stat = 0; - sp = (struct IsdnCardState *) irq2dev_map[intno]; + sp = (struct IsdnCardState *) dev_id; if (!sp) { printk(KERN_WARNING "Teles: Spurious interrupt!\n"); @@ -867,8 +867,7 @@ printk(KERN_WARNING "ix1-Micro: IRQ(%d) getting no interrupts during init\n", sp->irq); - irq2dev_map[sp->irq] = NULL; - free_irq(sp->irq, NULL); + free_irq(sp->irq, sp); return (0); } } diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c --- v2.1.61/linux/drivers/isdn/hisax/teles0.c Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/hisax/teles0.c Mon Nov 3 09:54:38 1997 @@ -605,7 +605,7 @@ struct IsdnCardState *sp; u_char val, stat = 0; - sp = (struct IsdnCardState *) irq2dev_map[intno]; + sp = (struct IsdnCardState *) dev_id; if (!sp) { printk(KERN_WARNING "Teles0: Spurious interrupt!\n"); @@ -828,8 +828,7 @@ printk(KERN_WARNING "Teles0: IRQ(%d) getting no interrupts during init\n", sp->irq); - irq2dev_map[sp->irq] = NULL; - free_irq(sp->irq, NULL); + free_irq(sp->irq, sp); return (0); } } diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c --- v2.1.61/linux/drivers/isdn/hisax/teles3.c Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/hisax/teles3.c Mon Nov 3 09:54:38 1997 @@ -585,7 +585,7 @@ u_char val, stat = 0; int count = 0; - sp = (struct IsdnCardState *) irq2dev_map[intno]; + sp = (struct IsdnCardState *) dev_id; if (!sp) { printk(KERN_WARNING "Teles: Spurious interrupt!\n"); @@ -829,8 +829,7 @@ printk(KERN_WARNING "Teles3: IRQ(%d) getting no interrupts during init\n", sp->irq); - irq2dev_map[sp->irq] = NULL; - free_irq(sp->irq, NULL); + free_irq(sp->irq, sp); return (0); } } diff -u --recursive --new-file v2.1.61/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.1.61/linux/drivers/isdn/isdn_common.c Tue Sep 23 16:48:47 1997 +++ linux/drivers/isdn/isdn_common.c Mon Nov 3 09:58:23 1997 @@ -849,9 +849,9 @@ } static RWTYPE -isdn_read(struct inode *inode, struct file *file, char *buf, RWARG count) +isdn_read(struct file *file, char *buf, RWARG count, loff_t *off) { - uint minor = MINOR(inode->i_rdev); + uint minor = MINOR(file->f_dentry->d_inode->i_rdev); int len = 0; ulong flags; int drvidx; @@ -869,7 +869,7 @@ if ((len = strlen(p)) <= count) { if (copy_to_user(buf, p, len)) return -EFAULT; - file->f_pos += len; + *off += len; return len; } return 0; @@ -886,7 +886,7 @@ save_flags(flags); cli(); len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1); - file->f_pos += len; + *off += len; restore_flags(flags); return len; } @@ -912,7 +912,7 @@ else dev->drv[drvidx]->stavail = 0; restore_flags(flags); - file->f_pos += len; + *off += len; return len; } #ifdef CONFIG_ISDN_PPP @@ -928,9 +928,9 @@ } static RWTYPE -isdn_write(struct inode *inode, struct file *file, const char *buf, RWARG count) +isdn_write(struct file *file, const char *buf, RWARG count, loff_t * off) { - uint minor = MINOR(inode->i_rdev); + uint minor = MINOR(file->f_dentry->d_inode->i_rdev); int drvidx; int chidx; diff -u --recursive --new-file v2.1.61/linux/drivers/net/3c501.c linux/drivers/net/3c501.c --- v2.1.61/linux/drivers/net/3c501.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/3c501.c Mon Nov 3 09:29:30 1997 @@ -758,7 +758,7 @@ * Free and disable the IRQ. */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); outb(AX_RESET, AX_CMD); /* Reset the chip */ MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v2.1.61/linux/drivers/net/3c503.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/3c503.c Mon Nov 3 09:29:30 1997 @@ -369,7 +369,7 @@ static int el2_close(struct device *dev) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); dev->irq = ei_status.saved_irq; outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/3c505.c linux/drivers/net/3c505.c --- v2.1.61/linux/drivers/net/3c505.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/3c505.c Mon Nov 3 09:29:30 1997 @@ -1216,7 +1216,7 @@ /* * release the IRQ */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); free_dma(dev->dma); free_pages((unsigned long) adapter->dma_buffer, __get_order(DMA_BUFFER_SIZE)); diff -u --recursive --new-file v2.1.61/linux/drivers/net/3c507.c linux/drivers/net/3c507.c --- v2.1.61/linux/drivers/net/3c507.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/3c507.c Mon Nov 3 09:29:30 1997 @@ -890,7 +890,7 @@ dev_3c507.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_3c507.irq, NULL); + free_irq(dev_3c507.irq, &dev_3c507); release_region(dev_3c507.base_addr, EL16_IO_EXTENT); } #endif /* MODULE */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.1.61/linux/drivers/net/3c509.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/3c509.c Mon Nov 3 09:29:30 1997 @@ -866,7 +866,7 @@ if (dev->priv != NULL) { kfree_s(dev->priv,sizeof(struct el3_private)); dev->priv = NULL; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(dev->base_addr, EL3_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c --- v2.1.61/linux/drivers/net/ac3200.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/ac3200.c Mon Nov 3 09:29:30 1997 @@ -173,7 +173,7 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (" unable to allocate memory for dev->priv.\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENOMEM; } @@ -303,7 +303,7 @@ #ifdef notyet /* We should someday disable shared memory and interrupts. */ outb(0x00, ioaddr + 6); /* Disable interrupts. */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); #endif ei_close(dev); @@ -369,7 +369,7 @@ kfree(dev->priv); dev->priv = NULL; /* Someday free_irq may be in ac_close_card() */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(dev->base_addr, AC_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/apricot.c linux/drivers/net/apricot.c --- v2.1.61/linux/drivers/net/apricot.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/apricot.c Mon Nov 3 09:29:30 1997 @@ -547,7 +547,7 @@ if (i < 4) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -EAGAIN; } @@ -930,7 +930,7 @@ dev->name, lp->scb.status, lp->scb.command); break; } - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); remove_rx_bufs(dev); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/arc-rimi.c linux/drivers/net/arc-rimi.c --- v2.1.61/linux/drivers/net/arc-rimi.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/arc-rimi.c Mon Nov 3 09:29:30 1997 @@ -220,7 +220,7 @@ dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { - free_irq(airq,NULL); + free_irq(airq,dev); return -ENOMEM; } memset(dev->priv,0,sizeof(struct arcnet_local)); @@ -790,7 +790,7 @@ if (dev->irq) { - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); } unregister_netdev(dev); diff -u --recursive --new-file v2.1.61/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.1.61/linux/drivers/net/at1700.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/at1700.c Mon Nov 3 09:29:30 1997 @@ -654,7 +654,7 @@ dev_at1700.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_at1700.irq, NULL); + free_irq(dev_at1700.irq, &dev_at1700); release_region(dev_at1700.base_addr, AT1700_IO_EXTENT); } #endif /* MODULE */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v2.1.61/linux/drivers/net/atp.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/atp.c Mon Nov 3 09:29:30 1997 @@ -727,7 +727,7 @@ /* Free the IRQ line. */ outb(0x00, ioaddr + PAR_CONTROL); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); /* Leave the hardware in a reset state. */ write_reg_high(ioaddr, CMR1, CMR1h_RESET); diff -u --recursive --new-file v2.1.61/linux/drivers/net/auto_irq.c linux/drivers/net/auto_irq.c --- v2.1.61/linux/drivers/net/auto_irq.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/auto_irq.c Fri Oct 31 11:23:47 1997 @@ -46,8 +46,11 @@ irqs = probe_irq_on(); } +#define BUSY_LOOP_UNTIL(j) while ((long)(jiffies-(j)) < 0) ; int autoirq_report(int waittime) { + unsigned long delay = jiffies + waittime; + BUSY_LOOP_UNTIL(delay) return probe_irq_off(irqs); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/com20020.c linux/drivers/net/com20020.c --- v2.1.61/linux/drivers/net/com20020.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/com20020.c Mon Nov 3 09:29:30 1997 @@ -354,7 +354,7 @@ dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { - free_irq(airq,NULL); + free_irq(airq,dev); release_region(ioaddr,ARCNET_TOTAL_SIZE); return -ENOMEM; } @@ -1024,7 +1024,7 @@ if (dev->irq) { - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); } if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); diff -u --recursive --new-file v2.1.61/linux/drivers/net/com90io.c linux/drivers/net/com90io.c --- v2.1.61/linux/drivers/net/com90io.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/com90io.c Mon Nov 3 09:29:30 1997 @@ -314,7 +314,7 @@ dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { - free_irq(airq,NULL); + free_irq(airq,dev); release_region(ioaddr,ARCNET_TOTAL_SIZE); return -ENOMEM; } @@ -903,7 +903,7 @@ if (dev->irq) { - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); } if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); diff -u --recursive --new-file v2.1.61/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c --- v2.1.61/linux/drivers/net/com90xx.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/com90xx.c Mon Nov 3 09:29:30 1997 @@ -584,7 +584,7 @@ dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { - free_irq(airq,NULL); + free_irq(airq,dev); release_region(ioaddr,ARCNET_TOTAL_SIZE); return -ENOMEM; } @@ -1201,7 +1201,7 @@ if (dev->irq) { - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); } if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); diff -u --recursive --new-file v2.1.61/linux/drivers/net/cops.c linux/drivers/net/cops.c --- v2.1.61/linux/drivers/net/cops.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/cops.c Mon Nov 3 09:29:30 1997 @@ -1005,7 +1005,7 @@ { /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - free_irq(dev_cops.irq, NULL); + free_irq(dev_cops.irq, &dev_cops); release_region(dev_cops.base_addr, COPS_IO_EXTENT); unregister_netdev(&dev_cops); diff -u --recursive --new-file v2.1.61/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c --- v2.1.61/linux/drivers/net/cs89x0.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/cs89x0.c Mon Nov 3 09:29:30 1997 @@ -655,7 +655,7 @@ printk("%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON)); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -EAGAIN; } @@ -918,7 +918,7 @@ dev->start = 0; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); /* Update the statistics here. */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/de600.c linux/drivers/net/de600.c --- v2.1.61/linux/drivers/net/de600.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/de600.c Mon Nov 3 09:29:30 1997 @@ -366,7 +366,7 @@ select_prn(); if (dev->start) { - free_irq(DE600_IRQ, NULL); + free_irq(DE600_IRQ, dev); dev->start = 0; MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.1.61/linux/drivers/net/de620.c linux/drivers/net/de620.c --- v2.1.61/linux/drivers/net/de620.c Sat Oct 25 02:44:15 1997 +++ linux/drivers/net/de620.c Mon Nov 3 09:29:30 1997 @@ -463,7 +463,7 @@ /* disable recv */ de620_set_register(dev, W_TCR, RXOFF); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); dev->start = 0; MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v2.1.61/linux/drivers/net/depca.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/depca.c Mon Nov 3 09:29:30 1997 @@ -1057,7 +1057,7 @@ /* ** Free the associated irq */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/e2100.c linux/drivers/net/e2100.c --- v2.1.61/linux/drivers/net/e2100.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/e2100.c Mon Nov 3 09:29:30 1997 @@ -352,7 +352,7 @@ if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); dev->irq = ei_status.saved_irq; /* Shut off the interrupt line and secondary interface. */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v2.1.61/linux/drivers/net/eepro.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/eepro.c Mon Nov 3 09:29:30 1997 @@ -819,7 +819,7 @@ outb(RESET_CMD, ioaddr); /* release the interrupt */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); /* Update the statistics here. What statistics? */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v2.1.61/linux/drivers/net/eexpress.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/eexpress.c Mon Nov 3 09:29:30 1997 @@ -388,7 +388,7 @@ lp->started = 0; scb_command(dev, SCB_CUsuspend|SCB_RUsuspend); outb(0,ioaddr+SIGNAL_CA); - free_irq(irq,NULL); + free_irq(irq,dev); outb(i586_RST,ioaddr+EEPROM_Ctrl); release_region(ioaddr,16); diff -u --recursive --new-file v2.1.61/linux/drivers/net/es3210.c linux/drivers/net/es3210.c --- v2.1.61/linux/drivers/net/es3210.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/es3210.c Mon Nov 3 09:29:30 1997 @@ -225,7 +225,7 @@ if (mem_enabled != 0x80) { printk(" shared mem disabled - giving up\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENXIO; } dev->mem_start = 0xC0000 + mem_bits*0x4000; @@ -243,7 +243,7 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (" unable to allocate memory for dev->priv.\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENOMEM; } @@ -432,7 +432,7 @@ if (dev->priv != NULL) { kfree(dev->priv); dev->priv = NULL; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(dev->base_addr, ES_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c --- v2.1.61/linux/drivers/net/eth16i.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/eth16i.c Mon Nov 3 09:29:30 1997 @@ -1225,7 +1225,7 @@ void cleanup_module(void) { unregister_netdev( &dev_eth16i ); - free_irq( dev_eth16i.irq, NULL ); + free_irq( dev_eth16i.irq, &dev_eth16i ); release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT ); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v2.1.61/linux/drivers/net/ewrk3.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ewrk3.c Mon Nov 3 09:29:30 1997 @@ -1148,7 +1148,7 @@ while (inb(EWRK3_RQ)); if (!lp->hard_strapped) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); } MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c --- v2.1.61/linux/drivers/net/fmv18x.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/fmv18x.c Mon Nov 3 09:29:30 1997 @@ -641,7 +641,7 @@ dev_fmv18x.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_fmv18x.irq, NULL); + free_irq(dev_fmv18x.irq, &dev_fmv18x); release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT); } #endif /* MODULE */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v2.1.61/linux/drivers/net/hp-plus.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/hp-plus.c Mon Nov 3 09:29:30 1997 @@ -288,7 +288,7 @@ int ioaddr = dev->base_addr - NIC_OFFSET; int option_reg = inw(ioaddr + HPP_OPTION); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); ei_close(dev); outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset, ioaddr + HPP_OPTION); diff -u --recursive --new-file v2.1.61/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v2.1.61/linux/drivers/net/hp.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/hp.c Mon Nov 3 09:29:30 1997 @@ -180,7 +180,7 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENOMEM; } @@ -435,7 +435,7 @@ int ioaddr = dev->base_addr - NIC_OFFSET; kfree(dev->priv); dev->priv = NULL; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(ioaddr, HP_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c --- v2.1.61/linux/drivers/net/ibmtr.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ibmtr.c Mon Nov 3 09:29:30 1997 @@ -1577,7 +1577,7 @@ for (i = 0; i < IBMTR_MAX_ADAPTERS; i++) if (dev_ibmtr[i]) { unregister_trdev(dev_ibmtr[i]); - free_irq(dev_ibmtr[i]->irq, NULL); + free_irq(dev_ibmtr[i]->irq, dev_ibmtr[i]); release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT); kfree_s(dev_ibmtr[i]->priv, sizeof(struct tok_info)); kfree_s(dev_ibmtr[i], sizeof(struct device)); diff -u --recursive --new-file v2.1.61/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.1.61/linux/drivers/net/lance.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/lance.c Mon Nov 3 09:29:30 1997 @@ -1129,7 +1129,7 @@ if (dev->dma != 4) disable_dma(dev->dma); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return 0; } diff -u --recursive --new-file v2.1.61/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c --- v2.1.61/linux/drivers/net/ltpc.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ltpc.c Mon Nov 3 09:29:30 1997 @@ -1023,9 +1023,9 @@ cli(); - if (!probe3) free_irq(3,NULL); - if (!probe4) free_irq(4,NULL); - if (!probe9) free_irq(9,NULL); + if (!probe3) free_irq(3,dev); + if (!probe4) free_irq(4,dev); + if (!probe9) free_irq(9,dev); sti(); @@ -1248,7 +1248,7 @@ if(debug&DEBUG_VERBOSE) printk("freeing irq\n"); if(dev_ltpc.irq) { - free_irq(dev_ltpc.irq,NULL); + free_irq(dev_ltpc.irq,&dev_ltpc); dev_ltpc.irq = 0; } diff -u --recursive --new-file v2.1.61/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.1.61/linux/drivers/net/ne.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ne.c Mon Nov 3 09:29:30 1997 @@ -440,7 +440,7 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENOMEM; } @@ -785,7 +785,7 @@ if (dev->priv != NULL) { kfree(dev->priv); dev->priv = NULL; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(dev->base_addr, NE_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.1.61/linux/drivers/net/net_init.c Mon Jun 16 16:35:55 1997 +++ linux/drivers/net/net_init.c Mon Nov 3 10:20:52 1997 @@ -59,7 +59,7 @@ */ /* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */ -#define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */ +#define MAX_ETH_CARDS 16 static struct device *ethdev_index[MAX_ETH_CARDS]; @@ -439,7 +439,7 @@ #ifdef CONFIG_TR /* The list of used and available "tr" slots */ -#define MAX_TR_CARDS 16 /* same as the number of irq's in irq2dev[] */ +#define MAX_TR_CARDS 16 static struct device *trdev_index[MAX_TR_CARDS]; struct device *init_trdev(struct device *dev, int sizeof_priv) diff -u --recursive --new-file v2.1.61/linux/drivers/net/ni52.c linux/drivers/net/ni52.c --- v2.1.61/linux/drivers/net/ni52.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ni52.c Mon Nov 3 09:29:30 1997 @@ -240,7 +240,7 @@ */ static int ni52_close(struct device *dev) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); ni_reset586(); /* the hard way to stop the receiver */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/ni65.c linux/drivers/net/ni65.c --- v2.1.61/linux/drivers/net/ni65.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/ni65.c Mon Nov 3 09:29:30 1997 @@ -285,7 +285,7 @@ } else { - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); dev->start = 0; return -EAGAIN; } @@ -312,7 +312,7 @@ } } #endif - free_irq(dev->irq,NULL); + free_irq(dev->irq,dev); dev->tbusy = 1; dev->start = 0; MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/pi2.c linux/drivers/net/pi2.c --- v2.1.61/linux/drivers/net/pi2.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/pi2.c Mon Nov 3 09:29:30 1997 @@ -1439,7 +1439,7 @@ if (dev->base_addr & 2) { /* if A channel */ if (first_time) { if (request_dma(dev->dma,"pi2")) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -EAGAIN; } } @@ -1669,7 +1669,7 @@ void cleanup_module(void) { - free_irq(pi0a.irq, NULL); /* IRQs and IO Ports are shared */ + free_irq(pi0a.irq, &pi0a); /* IRQs and IO Ports are shared */ release_region(pi0a.base_addr & 0x3f0, PI_TOTAL_SIZE); kfree(pi0a.priv); diff -u --recursive --new-file v2.1.61/linux/drivers/net/pt.c linux/drivers/net/pt.c --- v2.1.61/linux/drivers/net/pt.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/pt.c Mon Nov 3 09:29:30 1997 @@ -896,7 +896,7 @@ { if (request_dma(dev->dma, "pt")) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -EAGAIN; } } @@ -1769,7 +1769,7 @@ void cleanup_module(void) { - free_irq(pt0a.irq, NULL); /* IRQs and IO Ports are shared */ + free_irq(pt0a.irq, &pt0a); /* IRQs and IO Ports are shared */ release_region(pt0a.base_addr & 0x3f0, PT_TOTAL_SIZE); kfree(pt0a.priv); diff -u --recursive --new-file v2.1.61/linux/drivers/net/sdla.c linux/drivers/net/sdla.c --- v2.1.61/linux/drivers/net/sdla.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/sdla.c Mon Nov 3 09:29:30 1997 @@ -1694,6 +1694,6 @@ if (sdla0.priv) kfree(sdla0.priv); if (sdla0.irq) - free_irq(sdla0.irq, NULL); + free_irq(sdla0.irq, &sdla0); } #endif /* MODULE */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c --- v2.1.61/linux/drivers/net/seeq8005.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/seeq8005.c Mon Nov 3 09:29:30 1997 @@ -573,7 +573,7 @@ /* Flush the Tx and disable Rx here. */ outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); /* Update the statistics here. */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.1.61/linux/drivers/net/sgiseeq.c Thu Jun 26 12:33:39 1997 +++ linux/drivers/net/sgiseeq.c Mon Nov 3 09:29:31 1997 @@ -468,7 +468,7 @@ /* Shutdown the Seeq. */ reset_hpc3_and_seeq(sp->hregs, sregs); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return 0; } diff -u --recursive --new-file v2.1.61/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v2.1.61/linux/drivers/net/sk_g16.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/sk_g16.c Mon Nov 3 09:29:31 1997 @@ -1630,7 +1630,7 @@ SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */ - free_irq(dev->irq, NULL); /* Free IRQ */ + free_irq(dev->irq, dev); /* Free IRQ */ return 0; /* always succeed */ diff -u --recursive --new-file v2.1.61/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- v2.1.61/linux/drivers/net/skeleton.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/skeleton.c Mon Nov 3 09:29:31 1997 @@ -322,7 +322,7 @@ * and clean up on failure. */ if (request_dma(dev->dma, cardname)) { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -EAGAIN; } @@ -497,7 +497,7 @@ /* If not IRQ or DMA jumpered, free up the line. */ outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); free_dma(dev->dma); /* Update the statistics here. */ @@ -604,7 +604,7 @@ * allocate them in net_probe1(). */ /* - free_irq(this_device.irq, NULL); + free_irq(this_device.irq, dev); free_dma(this_device.dma); */ release_region(this_device.base_addr, NETCARD_IO_EXTENT); diff -u --recursive --new-file v2.1.61/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.1.61/linux/drivers/net/smc-mca.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/smc-mca.c Mon Nov 3 09:29:31 1997 @@ -289,7 +289,7 @@ printk("%s: Shutting down ethercard.\n", dev->name); outb(0x00, ioaddr + 6); /* Disable interrupts. */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); NS8390_init(dev, 0); /* We should someday disable shared memory and change to 8-bit mode diff -u --recursive --new-file v2.1.61/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.1.61/linux/drivers/net/smc-ultra.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/smc-ultra.c Mon Nov 3 09:29:31 1997 @@ -405,7 +405,7 @@ printk("%s: Shutting down ethercard.\n", dev->name); outb(0x00, ioaddr + 6); /* Disable interrupts. */ - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); NS8390_init(dev, 0); diff -u --recursive --new-file v2.1.61/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.1.61/linux/drivers/net/smc9194.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/smc9194.c Mon Nov 3 09:29:31 1997 @@ -1763,7 +1763,7 @@ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ unregister_netdev(&devSMC9194); - free_irq(devSMC9194.irq, NULL ); + free_irq(devSMC9194.irq, &devSMC9194); release_region(devSMC9194.base_addr, SMC_IO_EXTENT); if (devSMC9194.priv) diff -u --recursive --new-file v2.1.61/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.1.61/linux/drivers/net/wavelan.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/wavelan.c Mon Nov 3 09:29:31 1997 @@ -3922,7 +3922,7 @@ } else { - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); #ifdef DEBUG_CONFIG_ERRORS printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n", dev->name); @@ -3970,7 +3970,7 @@ */ wv_82586_stop(dev); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.61/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v2.1.61/linux/drivers/net/wd.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/wd.c Mon Nov 3 09:29:31 1997 @@ -262,7 +262,7 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); return -ENOMEM; } @@ -499,7 +499,7 @@ int ioaddr = dev->base_addr - WD_NIC_OFFSET; kfree(dev->priv); dev->priv = NULL; - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); release_region(ioaddr, WD_IO_EXTENT); unregister_netdev(dev); } diff -u --recursive --new-file v2.1.61/linux/drivers/net/znet.c linux/drivers/net/znet.c --- v2.1.61/linux/drivers/net/znet.c Sat Oct 25 02:44:16 1997 +++ linux/drivers/net/znet.c Mon Nov 3 09:29:31 1997 @@ -601,7 +601,7 @@ disable_dma(zn.rx_dma); disable_dma(zn.tx_dma); - free_irq(dev->irq, NULL); + free_irq(dev->irq, dev); if (znet_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.61/linux/drivers/scsi/Makefile Mon Aug 18 18:19:46 1997 +++ linux/drivers/scsi/Makefile Sat Nov 1 12:23:52 1997 @@ -67,12 +67,8 @@ endif endif -ifeq ($(CONFIG_BLK_DEV_SR_VENDOR),y) -SR_VENDOR = sr_vendor.o -endif - ifeq ($(CONFIG_BLK_DEV_SR),y) -L_OBJS += sr.o sr_ioctl.o $(SR_VENDOR) +L_OBJS += sr.o sr_ioctl.o sr_vendor.o else ifeq ($(CONFIG_BLK_DEV_SR),m) M_OBJS += sr_mod.o @@ -461,8 +457,8 @@ scsicam.o scsi_proc.o $(LD) $(LD_RFLAG) -r -o $@ $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o -sr_mod.o: sr.o sr_ioctl.o $(SR_VENDOR) - $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o $(SR_VENDOR) +sr_mod.o: sr.o sr_ioctl.o sr_vendor.o + $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o sr_vendor.o sd_mod.o: sd.o sd_ioctl.o $(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c --- v2.1.61/linux/drivers/scsi/ppa.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/scsi/ppa.c Sat Nov 1 12:40:30 1997 @@ -225,7 +225,7 @@ return; } -static int ppa_release(struct Scsi_Host *host) +int ppa_release(struct Scsi_Host *host) { int host_no = host->unique_id; diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h --- v2.1.61/linux/drivers/scsi/ppa.h Mon Aug 4 16:25:38 1997 +++ linux/drivers/scsi/ppa.h Mon Nov 3 10:27:43 1997 @@ -52,7 +52,7 @@ int ppa_reset(Scsi_Cmnd *, unsigned int); int ppa_proc_info(char *, char **, off_t, int, int, int); int ppa_biosparam(Disk *, kdev_t, int*); -static int ppa_release(struct Scsi_Host *); +int ppa_release(struct Scsi_Host *); #ifndef MODULE #ifdef PPA_CODE diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.1.61/linux/drivers/scsi/scsi.c Thu Jul 17 10:06:05 1997 +++ linux/drivers/scsi/scsi.c Sat Nov 1 12:23:53 1997 @@ -3293,6 +3293,7 @@ * This does any final handling that is required. */ if(tpnt->finish && tpnt->nr_dev) (*tpnt->finish)(); + resize_dma_pool(); MOD_INC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.1.61/linux/drivers/scsi/sr.c Mon Aug 18 18:19:46 1997 +++ linux/drivers/scsi/sr.c Sat Nov 1 12:23:53 1997 @@ -45,6 +45,8 @@ #include /* For the door lock/unlock commands */ #include "constants.h" +MODULE_PARM(xa_test,"i"); /* see sr_ioctl.c */ + #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) @@ -67,12 +69,15 @@ static int sr_open(struct cdrom_device_info*, int); void get_sectorsize(int); +void get_capabilities(int); void requeue_sr_request (Scsi_Cmnd * SCpnt); static int sr_media_change(struct cdrom_device_info*, int); static void sr_release(struct cdrom_device_info *cdi) { + if (scsi_CDs[MINOR(cdi->dev)].sector_size > 2048) + sr_set_blocklength(MINOR(cdi->dev),2048); sync_dev(cdi->dev); scsi_CDs[MINOR(cdi->dev)].device->access_count--; if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module) @@ -89,14 +94,14 @@ sr_media_change, /* media changed */ sr_tray_move, /* tray move */ sr_lock_door, /* lock door */ - NULL, /* select speed */ + sr_select_speed, /* select speed */ NULL, /* select disc */ sr_get_last_session, /* get last session */ sr_get_mcn, /* get universal product code */ sr_reset, /* hard reset */ sr_audio_ioctl, /* audio ioctl */ sr_dev_ioctl, /* device-specific ioctl */ - CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | + CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO, 0 }; @@ -139,10 +144,9 @@ /* If the disk changed, the capacity will now be different, * so we force a re-read of this information */ if (retval) { -#ifdef CONFIG_BLK_DEV_SR_VENDOR + /* check multisession offset etc */ sr_cd_check(cdi); -#endif - + /* * If the disk changed, the capacity will now be different, * so we force a re-read of this information @@ -311,7 +315,8 @@ } if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) { - printk("CD-ROM error: "); + printk("sr%d: CD-ROM error: ", + DEVICE_NR(SCpnt->request.rq_dev)); print_sense("sr", SCpnt); printk("command was: "); print_command(SCpnt->cmnd); @@ -329,7 +334,8 @@ } if (SCpnt->sense_buffer[2] == NOT_READY) { - printk(KERN_INFO "CD-ROM not ready. Make sure you have a disc in the drive.\n"); + printk(KERN_INFO "sr%d: CD-ROM not ready. Make sure you have a disc in the drive.\n", + DEVICE_NR(SCpnt->request.rq_dev)); SCpnt = end_scsi_request(SCpnt, 0, this_count); requeue_sr_request(SCpnt); /* Do next request */ return; @@ -358,7 +364,7 @@ requeue_sr_request(SCpnt); return; } - } + } /* We only get this far if we have an error we have not recognized */ if(result) { @@ -443,6 +449,17 @@ SDev->was_reset = 0; } + /* we do lazy blocksize switching (when reading XA sectors, + * see CDROMREADMODE2 ioctl) */ + if (scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].sector_size > 2048) { + if (!in_interrupt()) + sr_set_blocklength(DEVICE_NR(CURRENT->rq_dev),2048); +#if 1 + else + printk("sr: can't switch blocksize: in interrupt\n"); +#endif + } + if (flag++ == 0) SCpnt = allocate_device(&CURRENT, scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device, 0); @@ -649,7 +666,7 @@ * ensure that all scsi operations are able to do at least a non-scatter/gather * operation */ if(sgpnt[count].address == NULL){ /* Out of dma memory */ - printk("Warning: Running low on SCSI DMA buffers"); + printk("Warning: Running low on SCSI DMA buffers\n"); /* Try switching back to a non scatter-gather operation. */ while(--count >= 0){ if(sgpnt[count].alt_address) @@ -805,17 +822,7 @@ SDp->scsi_request_fn = do_sr_request; scsi_CDs[i].device = SDp; - scsi_CDs[i].cdi.ops = &sr_dops; - scsi_CDs[i].cdi.handle = &scsi_CDs[i]; - scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR,i); - scsi_CDs[i].cdi.mask = 0; - scsi_CDs[i].cdi.speed = 1; - scsi_CDs[i].cdi.capacity = 1; - register_cdrom(&scsi_CDs[i].cdi, "sr"); - -#ifdef CONFIG_BLK_DEV_SR_VENDOR sr_vendor_init(i); -#endif sr_template.nr_dev++; if(sr_template.nr_dev > sr_template.dev_max) @@ -902,7 +909,7 @@ case 512: break; default: - printk ("scd%d : unsupported sector size %d.\n", + printk ("sr%d: unsupported sector size %d.\n", i, scsi_CDs[i].sector_size); scsi_CDs[i].capacity = 0; scsi_CDs[i].needs_sector_size = 1; @@ -919,6 +926,58 @@ scsi_free(buffer, 512); } +void get_capabilities(int i){ + unsigned char cmd[6]; + unsigned char *buffer; + int rc,n; + + static char *loadmech[] = { + "caddy", + "tray", + "pop-up", + "", + "changer", + "changer", + "", + "" + }; + + buffer = (unsigned char *) scsi_malloc(512); + cmd[0] = MODE_SENSE; + cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0; + cmd[2] = 0x2a; + cmd[4] = 128; + cmd[3] = cmd[5] = 0; + rc = sr_do_ioctl(i, cmd, buffer, 128, 1); + + if (-EINVAL == rc) { + /* failed, drive has'nt this mode page */ + scsi_CDs[i].cdi.speed = 1; + scsi_CDs[i].cdi.capacity = 1; + /* disable speed select, drive probably can't do this either */ + scsi_CDs[i].cdi.mask |= CDC_SELECT_SPEED; + } else { + n = buffer[3]+4; + scsi_CDs[i].cdi.speed = ((buffer[n+8] << 8) + buffer[n+9])/176; + scsi_CDs[i].cdi.capacity = 1; + scsi_CDs[i].readcd_known = 1; + scsi_CDs[i].readcd_cdda = buffer[n+5] & 0x01; + /* print some capability bits */ + printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s\n",i, + ((buffer[n+14] << 8) + buffer[n+15])/176, + scsi_CDs[i].cdi.speed, + buffer[n+3]&0x01 ? "writer " : "", /* CD Writer */ + buffer[n+2]&0x02 ? "cd/rw " : "", /* can read rewriteable */ + buffer[n+4]&0x20 ? "xa/form2 " : "", /* can read xa/from2 */ + buffer[n+5]&0x01 ? "cdda " : "", /* can read audio data */ + loadmech[buffer[n+6]>>5]); + if ((buffer[n+6] >> 5) == 0) + /* caddy drives can't close tray... */ + scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; + } + scsi_free(buffer, 512); +} + static int sr_registered = 0; static int sr_init() @@ -984,7 +1043,16 @@ scsi_CDs[i].use = 1; scsi_CDs[i].ten = 1; scsi_CDs[i].remap = 1; + scsi_CDs[i].readcd_known = 0; + scsi_CDs[i].readcd_cdda = 0; sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9); + + scsi_CDs[i].cdi.ops = &sr_dops; + scsi_CDs[i].cdi.handle = &scsi_CDs[i]; + scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR,i); + scsi_CDs[i].cdi.mask = 0; + get_capabilities(i); + register_cdrom(&scsi_CDs[i].cdi, "sr"); } diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/sr.h linux/drivers/scsi/sr.h --- v2.1.61/linux/drivers/scsi/sr.h Mon Apr 14 16:28:16 1997 +++ linux/drivers/scsi/sr.h Mon Nov 3 09:49:42 1997 @@ -17,8 +17,6 @@ #ifndef _SR_H #define _SR_H -#include - #include "scsi.h" typedef struct @@ -34,13 +32,15 @@ unsigned ten:1; /* support ten byte commands */ unsigned remap:1; /* support remapping */ unsigned use:1; /* is this device still supportable */ - unsigned xa_flag:1; /* CD has XA sectors */ + unsigned xa_flag:1; /* CD has XA sectors ? */ + unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ + unsigned readcd_cdda:1; /* reading audio data using READ_CD */ struct cdrom_device_info cdi; } Scsi_CD; extern Scsi_CD * scsi_CDs; -int sr_do_ioctl(int, unsigned char*, void*, unsigned); +int sr_do_ioctl(int, unsigned char*, void*, unsigned, int); int sr_lock_door(struct cdrom_device_info*, int); int sr_tray_move(struct cdrom_device_info*, int); @@ -49,15 +49,16 @@ int sr_get_last_session(struct cdrom_device_info*, struct cdrom_multisession*); int sr_get_mcn(struct cdrom_device_info*, struct cdrom_mcn*); int sr_reset(struct cdrom_device_info*); +int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_audio_ioctl(struct cdrom_device_info*, unsigned int, void*); int sr_dev_ioctl(struct cdrom_device_info*, unsigned int, unsigned long); -/* vendor-specific */ -#ifdef CONFIG_BLK_DEV_SR_VENDOR -void sr_vendor_init(int minor); -int sr_cd_check(struct cdrom_device_info*); int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest); +int sr_is_xa(int minor); -#endif +/* sr_vendor.c */ +void sr_vendor_init(int minor); +int sr_cd_check(struct cdrom_device_info*); +int sr_set_blocklength(int minor, int blocklength); #endif diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.1.61/linux/drivers/scsi/sr_ioctl.c Mon Jul 7 08:24:28 1997 +++ linux/drivers/scsi/sr_ioctl.c Mon Nov 3 09:49:55 1997 @@ -1,4 +1,3 @@ -#include #include #include #include @@ -16,6 +15,17 @@ #include #include "sr.h" +#if 0 +# define DEBUG +#endif + +/* for now we borrow the "operation not supported" from the network folks */ +#define EDRIVE_CANT_DO_THIS EOPNOTSUPP + +/* The sr_is_xa() seems to trigger firmware bugs with some drives :-( + * It is off by default and can be turned on with this module parameter */ +static int xa_test = 0; + extern void get_sectorsize(int); #define IOCTL_RETRIES 3 @@ -39,12 +49,14 @@ error code is. Normally the UNIT_ATTENTION code will automatically clear after one error */ -int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength) +int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength, int quiet) { Scsi_Cmnd * SCpnt; - int result; + int result, err = 0, retries = 0; SCpnt = allocate_device(NULL, scsi_CDs[target].device, 1); + +retry: { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; @@ -61,28 +73,79 @@ switch(SCpnt->sense_buffer[2] & 0xf) { case UNIT_ATTENTION: scsi_CDs[target].device->changed = 1; - printk("Disc change detected.\n"); + printk(KERN_INFO "sr%d: disc change detected.\n", target); + if (retries++ < 10) + goto retry; + err = -ENOMEDIUM; break; case NOT_READY: /* This happens if there is no disc in drive */ - printk(KERN_INFO "CDROM not ready. Make sure there is a disc in the drive.\n"); + if (SCpnt->sense_buffer[12] == 0x04 && + SCpnt->sense_buffer[13] == 0x01) { + /* sense: Logical unit is in process of becoming ready */ + if (!quiet) + printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target); + if (retries++ < 10) { + /* sleep 2 sec and try again */ + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 200; + schedule (); + goto retry; + } else { + /* 20 secs are enouth? */ + err = -ENOMEDIUM; + break; + } + } + printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n",target); +#ifdef DEBUG + print_sense("sr", SCpnt); +#endif + err = -ENOMEDIUM; break; case ILLEGAL_REQUEST: - printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); + if (!quiet) + printk("sr%d: CDROM (ioctl) reports ILLEGAL REQUEST.\n", + target); + if (SCpnt->sense_buffer[12] == 0x20 && + SCpnt->sense_buffer[13] == 0x00) { + /* sense: Invalid command operation code */ + err = -EDRIVE_CANT_DO_THIS; + } else { + err = -EINVAL; + } +#ifdef DEBUG + print_command(sr_cmd); + print_sense("sr", SCpnt); +#endif break; default: + printk("sr%d: CDROM (ioctl) error, command: ", target); + print_command(sr_cmd); print_sense("sr", SCpnt); + err = -EIO; }; result = SCpnt->result; SCpnt->request.rq_status = RQ_INACTIVE; /* Deallocate */ + /* Wake up a process waiting for device */ wake_up(&SCpnt->device->device_wait); - /* Wake up a process waiting for device*/ - return result; + + return err; } /* ---------------------------------------------------------------------- */ /* interface to cdrom.c */ +static int test_unit_ready(int minor) +{ + u_char sr_cmd[10]; + + sr_cmd[0] = TEST_UNIT_READY; + sr_cmd[1] = ((scsi_CDs[minor].device -> lun) << 5); + sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; + return sr_do_ioctl(minor, sr_cmd, NULL, 255, 1); +} + int sr_tray_move(struct cdrom_device_info *cdi, int pos) { u_char sr_cmd[10]; @@ -92,7 +155,7 @@ sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */; - return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 255); + return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 255, 0); } int sr_lock_door(struct cdrom_device_info *cdi, int lock) @@ -109,51 +172,39 @@ return -EINVAL; } - if (!scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device, - SCSI_IOCTL_TEST_UNIT_READY,0)) - return CDS_DISC_OK; - -#if 1 - /* Tell tray is open if the drive is not ready. Seems there is - * no way to check whenever the tray is really open, but this way - * we get auto-close-on-open work. And it seems to have no ill - * effects with caddy drives... */ + if (0 == test_unit_ready(MINOR(cdi->dev))) + return CDS_DISC_OK; + return CDS_TRAY_OPEN; -#else - return CDS_NO_DISC; -#endif } int sr_disk_status(struct cdrom_device_info *cdi) { struct cdrom_tochdr toc_h; struct cdrom_tocentry toc_e; - int i; + int i,rc,have_datatracks = 0; - if (scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,SCSI_IOCTL_TEST_UNIT_READY,0)) - return CDS_NO_DISC; - - /* if the xa-bit is on, we tell it is XA... */ - if (scsi_CDs[MINOR(cdi->dev)].xa_flag) - return CDS_XA_2_1; + /* look for data tracks */ + if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) + return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; - /* ...else we look for data tracks */ - if (sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h)) - return CDS_NO_INFO; for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { toc_e.cdte_track = i; toc_e.cdte_format = CDROM_LBA; if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) return CDS_NO_INFO; - if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) - return CDS_DATA_1; -#if 0 - if (i == toc_h.cdth_trk0 && toc_e.cdte_addr.lba > 100) - /* guess: looks like a "hidden track" CD */ - return CDS_DATA_1; -#endif + if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { + have_datatracks = 1; + break; + } } - return CDS_AUDIO; + if (!have_datatracks) + return CDS_AUDIO; + + if (scsi_CDs[MINOR(cdi->dev)].xa_flag) + return CDS_XA_2_1; + else + return CDS_DATA_1; } int sr_get_last_session(struct cdrom_device_info *cdi, @@ -161,7 +212,7 @@ { ms_info->addr.lba=scsi_CDs[MINOR(cdi->dev)].ms_offset; ms_info->xa_flag=scsi_CDs[MINOR(cdi->dev)].xa_flag || - scsi_CDs[MINOR(cdi->dev)].ms_offset > 0; + (scsi_CDs[MINOR(cdi->dev)].ms_offset > 0); return 0; } @@ -185,7 +236,7 @@ buffer = (unsigned char*) scsi_malloc(512); if(!buffer) return -ENOMEM; - result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24); + result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0); memcpy (mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; @@ -201,6 +252,26 @@ return 0; } +int sr_select_speed(struct cdrom_device_info *cdi, int speed) +{ + u_char sr_cmd[12]; + + if (speed == 0) + speed = 0xffff; /* set to max */ + else + speed *= 177; /* Nx to kbyte/s */ + + memset(sr_cmd,0,12); + sr_cmd[0] = 0xbb; /* SET CD SPEED */ + sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->lun) << 5; + sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */ + sr_cmd[3] = speed & 0xff; /* LSB */ + + if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0)) + return -EIO; + return 0; +} + /* ----------------------------------------------------------------------- */ /* this is called by the generic cdrom driver. arg is a _kernel_ pointer, */ /* becauce the generic cdrom driver does the user access stuff for us. */ @@ -224,7 +295,7 @@ sr_cmd[8] = 0; sr_cmd[9] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; case CDROMRESUME: @@ -236,7 +307,7 @@ sr_cmd[8] = 1; sr_cmd[9] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; case CDROMPLAYMSF: @@ -254,7 +325,7 @@ sr_cmd[8] = msf->cdmsf_frame1; sr_cmd[9] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; } @@ -273,7 +344,7 @@ sr_cmd[8] = blk->len; sr_cmd[9] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; } @@ -292,7 +363,7 @@ sr_cmd[8] = ti->cdti_ind1; sr_cmd[9] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; } @@ -312,7 +383,7 @@ buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; - result = sr_do_ioctl(target, sr_cmd, buffer, 12); + result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0); tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; @@ -338,7 +409,7 @@ buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; - result = sr_do_ioctl (target, sr_cmd, buffer, 12); + result = sr_do_ioctl (target, sr_cmd, buffer, 12, 0); tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; @@ -361,7 +432,7 @@ sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = 0; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; case CDROMSTART: @@ -370,7 +441,7 @@ sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = 1; - result = sr_do_ioctl(target, sr_cmd, NULL, 255); + result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); break; case CDROMVOLCTRL: @@ -390,7 +461,7 @@ buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; - if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28))) { + if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0))) { printk ("Hosed while obtaining audio mode page\n"); scsi_free(buffer, 512); break; @@ -410,7 +481,7 @@ break; }; - if ((result = sr_do_ioctl (target, sr_cmd, mask, 28))) { + if ((result = sr_do_ioctl (target, sr_cmd, mask, 28, 0))) { printk ("Hosed while obtaining mask for audio mode page\n"); scsi_free(buffer, 512); scsi_free(mask, 512); @@ -431,7 +502,7 @@ sr_cmd[4] = 28; sr_cmd[5] = 0; - result = sr_do_ioctl (target, sr_cmd, buffer, 28); + result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0); scsi_free(buffer, 512); scsi_free(mask, 512); break; @@ -454,7 +525,7 @@ buffer = (unsigned char *) scsi_malloc(512); if(!buffer) return -ENOMEM; - if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28))) { + if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0))) { printk ("(CDROMVOLREAD) Hosed while obtaining audio mode page\n"); scsi_free(buffer, 512); break; @@ -487,7 +558,7 @@ buffer = (unsigned char*) scsi_malloc(512); if(!buffer) return -ENOMEM; - result = sr_do_ioctl(target, sr_cmd, buffer, 16); + result = sr_do_ioctl(target, sr_cmd, buffer, 16, 0); subchnl->cdsc_audiostatus = buffer[1]; subchnl->cdsc_format = CDROM_MSF; @@ -516,7 +587,120 @@ return result; } - + +/* ----------------------------------------------------------------------- + * a function to read all sorts of funny cdrom sectors using the READ_CD + * scsi-3 mmc command + * + * lba: linear block address + * format: 0 = data (anything) + * 1 = audio + * 2 = data (mode 1) + * 3 = data (mode 2) + * 4 = data (mode 2 form1) + * 5 = data (mode 2 form2) + * blksize: 2048 | 2336 | 2340 | 2352 + */ + +int +sr_read_cd(int minor, unsigned char *dest, int lba, int format, int blksize) +{ + unsigned char cmd[12]; + +#ifdef DEBUG + printk("sr%d: sr_read_cd lba=%d format=%d blksize=%d\n", + minor,lba,format,blksize); +#endif + + memset(cmd,0,12); + cmd[0] = 0xbe /* READ_CD */; + cmd[1] = (scsi_CDs[minor].device->lun << 5) | ((format & 7) << 2); + cmd[2] = (unsigned char)(lba >> 24) & 0xff; + cmd[3] = (unsigned char)(lba >> 16) & 0xff; + cmd[4] = (unsigned char)(lba >> 8) & 0xff; + cmd[5] = (unsigned char) lba & 0xff; + cmd[8] = 1; + switch (blksize) { + case 2336: cmd[9] = 0x58; break; + case 2340: cmd[9] = 0x78; break; + case 2352: cmd[9] = 0xf8; break; + default: cmd[9] = 0x10; break; + } + return sr_do_ioctl(minor, cmd, dest, blksize, 0); +} + +/* + * read sectors with blocksizes other than 2048 + */ + +int +sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) +{ + unsigned char cmd[12]; /* the scsi-command */ + int rc; + + /* we try the READ CD command first... */ + if (scsi_CDs[minor].readcd_known) { + rc = sr_read_cd(minor, dest, lba, 0, blksize); + if (-EDRIVE_CANT_DO_THIS != rc) + return rc; + scsi_CDs[minor].readcd_known = 0; + printk("CDROM does'nt support READ CD (0xbe) command\n"); + /* fall & retry the other way */ + } + + /* ... if this fails, we switch the blocksize using MODE SELECT */ + if (blksize != scsi_CDs[minor].sector_size) + if (0 != (rc = sr_set_blocklength(minor, blksize))) + return rc; + +#ifdef DEBUG + printk("sr%d: sr_read_sector lba=%d blksize=%d\n",minor,lba,blksize); +#endif + + memset(cmd,0,12); + cmd[0] = READ_10; + cmd[1] = (scsi_CDs[minor].device->lun << 5); + cmd[2] = (unsigned char)(lba >> 24) & 0xff; + cmd[3] = (unsigned char)(lba >> 16) & 0xff; + cmd[4] = (unsigned char)(lba >> 8) & 0xff; + cmd[5] = (unsigned char) lba & 0xff; + cmd[8] = 1; + rc = sr_do_ioctl(minor, cmd, dest, blksize, 0); + + return rc; +} + +/* + * read a sector in raw mode to check the sector format + * ret: 1 == mode2 (XA), 0 == mode1, <0 == error + */ + +int +sr_is_xa(int minor) +{ + unsigned char *raw_sector; + int is_xa; + + if (!xa_test) + return 0; + + raw_sector = (unsigned char *) scsi_malloc(2048+512); + if (!raw_sector) return -ENOMEM; + if (0 == sr_read_sector(minor,scsi_CDs[minor].ms_offset+16, + CD_FRAMESIZE_RAW1,raw_sector)) { + is_xa = (raw_sector[3] == 0x02) ? 1 : 0; + } else { + /* read a raw sector failed for some reason. */ + is_xa = -1; + } + scsi_free(raw_sector, 2048+512); +#ifdef DEBUG + printk("sr%d: sr_is_xa: %d\n",minor,is_xa); +#endif + return is_xa; +} + int sr_dev_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { @@ -525,33 +709,31 @@ target = MINOR(cdi->dev); switch (cmd) { - /* these are compatible with the ide-cd driver */ - case CDROMREADRAW: case CDROMREADMODE1: case CDROMREADMODE2: - -#if CONFIG_BLK_DEV_SR_VENDOR + case CDROMREADRAW: { unsigned char *raw; struct cdrom_msf msf; - int blocksize, lba, rc; + int lba, rc; + int blocksize = 2048; - if (cmd == CDROMREADMODE1) - blocksize = CD_FRAMESIZE; /* 2048 */ - else if (cmd == CDROMREADMODE2) - blocksize = CD_FRAMESIZE_RAW0; /* 2336 */ - else - /* some SCSI drives do not allow this one */ - blocksize = CD_FRAMESIZE_RAW; /* 2352 */ + switch (cmd) { + case CDROMREADMODE2: blocksize = CD_FRAMESIZE_RAW0; break; /* 2336 */ + case CDROMREADRAW: blocksize = CD_FRAMESIZE_RAW; break; /* 2352 */ + } if (copy_from_user(&msf,(void*)arg,sizeof(msf))) return -EFAULT; if (!(raw = scsi_malloc(2048+512))) - return -ENOMEM; + return -ENOMEM; lba = (((msf.cdmsf_min0 * CD_SECS) + msf.cdmsf_sec0) * CD_FRAMES + msf.cdmsf_frame0) - CD_BLOCK_OFFSET; - rc = sr_read_sector(target, lba, blocksize, raw); + if (lba < 0 || lba >= scsi_CDs[target].capacity) + return -EINVAL; + + rc = sr_read_sector(target, lba, blocksize, raw); if (!rc) if (copy_to_user((void*)arg, raw, blocksize)) rc = -EFAULT; @@ -559,11 +741,44 @@ scsi_free(raw,2048+512); return rc; } -#else - return -EINVAL; -#endif + case CDROMREADAUDIO: + { + unsigned char *raw; + int lba, rc=0; + struct cdrom_read_audio ra; - + if (!scsi_CDs[target].readcd_known || !scsi_CDs[target].readcd_cdda) + return -EINVAL; /* -EDRIVE_DOES_NOT_SUPPORT_THIS ? */ + + if (copy_from_user(&ra,(void*)arg,sizeof(ra))) + return -EFAULT; + + if (ra.addr_format == CDROM_LBA) + lba = ra.addr.lba; + else + lba = (((ra.addr.msf.minute * CD_SECS) + ra.addr.msf.second) + * CD_FRAMES + ra.addr.msf.frame) - CD_BLOCK_OFFSET; + + if (lba < 0 || lba >= scsi_CDs[target].capacity) + return -EINVAL; + if (!(raw = scsi_malloc(2048+512))) + return -ENOMEM; + + while (ra.nframes > 0) { + rc = sr_read_cd(target, raw, lba, 1, CD_FRAMESIZE_RAW); + if (!rc) + if (copy_to_user(ra.buf, raw, CD_FRAMESIZE_RAW)) + rc = -EFAULT; + if (rc) + break; + + ra.buf += CD_FRAMESIZE_RAW; + ra.nframes -= 1; + lba++; + } + scsi_free(raw,2048+512); + return rc; + } case BLKRAGET: if (!arg) return -EINVAL; diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c --- v2.1.61/linux/drivers/scsi/sr_vendor.c Tue Sep 23 16:48:48 1997 +++ linux/drivers/scsi/sr_vendor.c Mon Nov 3 09:50:20 1997 @@ -6,6 +6,12 @@ * the like) are to new to be included into the SCSI-II standard (to * be exact: there is'nt anything in my draft copy). * + * Aug 1997: Ha! Got a SCSI-3 cdrom spec across my fingers. SCSI-3 does + * multisession using the READ TOC command (like SONY). + * + * Rearranged stuff here: SCSI-3 is included allways, support + * for NEC/TOSHIBA/HP commands is optional. + * * Gerd Knorr * * -------------------------------------------------------------------------- @@ -20,14 +26,15 @@ * - SONY: Detection and support of multisession CD's. * added by Thomas Quinot * - * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: - * Known to work with SONY code. + * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: known to + * work with SONY (SCSI3 now) code. * * - HP: Much like SONY, but a little different... (Thomas) * HP-Writers only ??? Maybe other CD-Writers work with this too ? * HP 6020 writers now supported. */ +#include #include #include @@ -40,27 +47,33 @@ #include #include "sr.h" +#if 0 +# define DEBUG +#endif + /* here are some constants to sort the vendors into groups */ -#define VENDOR_CAN_NOT_HANDLE 1 /* don't know how to handle */ +#define VENDOR_SCSI3 1 /* default: scsi-3 mmc */ + #define VENDOR_NEC 2 #define VENDOR_TOSHIBA 3 -#define VENDOR_SONY_LIKE 4 /* much drives are Sony compatible */ -#define VENDOR_HP_4020 5 /* HP 4xxx writers, others too ?? */ -#define VENDOR_HP_6020 6 /* HP 6020 writers */ +#define VENDOR_HP_4020 4 /* HP 4xxx writers, others too ?? */ +#define VENDOR_HP_6020 5 /* HP 6020 writers */ #define VENDOR_ID (scsi_CDs[minor].vendor) -#if 0 -#define DEBUG -#endif - void sr_vendor_init(int minor) { +#ifndef CONFIG_BLK_DEV_SR_VENDOR + VENDOR_ID = VENDOR_SCSI3; +#else char *vendor = scsi_CDs[minor].device->vendor; char *model = scsi_CDs[minor].device->model; - + + /* default */ + VENDOR_ID = VENDOR_SCSI3; + if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) && scsi_CDs[minor].device->type == TYPE_WORM) { if (!strncmp(model,"CD-Writer 6020",14)) @@ -80,29 +93,33 @@ } else if (!strncmp (vendor, "TOSHIBA", 7)) { VENDOR_ID = VENDOR_TOSHIBA; - } else { - /* most drives can handled like Sony ones, so we take - * it as default */ - VENDOR_ID = VENDOR_SONY_LIKE; -#ifdef DEBUG - printk(KERN_DEBUG - "sr: using \"Sony group\" multisession code\n"); -#endif } +#endif } /* small handy function for switching block length using MODE SELECT, * used by sr_read_sector() */ -static int -set_density_and_blocklength(int minor, unsigned char *buffer, - int density, int blocklength) +int +sr_set_blocklength(int minor, int blocklength) { + unsigned char *buffer; /* the buffer for the ioctl */ unsigned char cmd[12]; /* the scsi-command */ struct ccs_modesel_head *modesel; - int rc; + int rc,density = 0; + +#ifdef CONFIG_BLK_DEV_SR_VENDOR + if (VENDOR_ID == VENDOR_TOSHIBA) + density = (blocklength > 2048) ? 0x81 : 0x83; +#endif + + buffer = (unsigned char *) scsi_malloc(512); + if (!buffer) return -ENOMEM; +#ifdef DEBUG + printk("sr%d: MODE SELECT 0x%x/%d\n",minor,density,blocklength); +#endif memset(cmd,0,12); cmd[0] = MODE_SELECT; cmd[1] = (scsi_CDs[minor].device->lun << 5) | (1 << 4); @@ -113,53 +130,17 @@ modesel->density = density; modesel->block_length_med = (blocklength >> 8 ) & 0xff; modesel->block_length_lo = blocklength & 0xff; - rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel)); + if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0))) + scsi_CDs[minor].sector_size = blocklength; #ifdef DEBUG - if (rc) - printk("sr: switching blocklength to %d bytes failed\n", - blocklength); + else + printk("sr%d: switching blocklength to %d bytes failed\n", + minor,blocklength); #endif - return rc; -} - - -/* read a sector with other than 2048 bytes length - * dest is assumed to be allocated with scsi_malloc - * - * XXX maybe we have to do some locking here. - */ - -int -sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) -{ - unsigned char *buffer; /* the buffer for the ioctl */ - unsigned char cmd[12]; /* the scsi-command */ - int rc, density; - - density = (VENDOR_ID == VENDOR_TOSHIBA) ? 0x83 : 0; - - buffer = (unsigned char *) scsi_malloc(512); - if (!buffer) return -ENOMEM; - - rc = set_density_and_blocklength(minor, buffer, density, blksize); - if (!rc) { - memset(cmd,0,12); - cmd[0] = READ_10; - cmd[1] = (scsi_CDs[minor].device->lun << 5); - cmd[2] = (unsigned char)(lba >> 24) & 0xff; - cmd[3] = (unsigned char)(lba >> 16) & 0xff; - cmd[4] = (unsigned char)(lba >> 8) & 0xff; - cmd[5] = (unsigned char) lba & 0xff; - cmd[8] = 1; - rc = sr_do_ioctl(minor, cmd, dest, blksize); - set_density_and_blocklength(minor, buffer, density, 2048); - } - scsi_free(buffer, 512); return rc; } - /* This function gets called after a media change. Checks if the CD is multisession, asks for offset etc. */ @@ -169,7 +150,6 @@ { unsigned long sector,min,sec,frame; unsigned char *buffer; /* the buffer for the ioctl */ - unsigned char *raw_sector; unsigned char cmd[12]; /* the scsi-command */ int rc,is_xa,no_multi,minor; @@ -187,16 +167,41 @@ switch(VENDOR_ID) { + case VENDOR_SCSI3: + memset(cmd,0,12); + cmd[0] = READ_TOC; + cmd[1] = (scsi_CDs[minor].device->lun << 5); + cmd[8] = 12; + cmd[9] = 0x40; + rc = sr_do_ioctl(minor, cmd, buffer, 12, 0); + if (rc != 0) + break; + if ((buffer[0] << 8) + buffer[1] < 0x0a) { + printk(KERN_INFO "sr%d: Hmm, seems the drive " + "doesn't support multisession CD's\n",minor); + no_multi = 1; + break; + } + sector = buffer[11] + (buffer[10] << 8) + + (buffer[9] << 16) + (buffer[8] << 24); + if (buffer[6] <= 1) { + /* ignore sector offsets from first track */ + sector = 0; + } + break; + +#ifdef CONFIG_BLK_DEV_SR_VENDOR case VENDOR_NEC: memset(cmd,0,12); cmd[0] = 0xde; cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03; cmd[2] = 0xb0; - rc = sr_do_ioctl(minor, cmd, buffer, 0x16); + rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 0); if (rc != 0) break; if (buffer[14] != 0 && buffer[14] != 0xb0) { - printk(KERN_INFO "sr (nec): Hmm, seems the cdrom doesn't support multisession CD's\n"); + printk(KERN_INFO "sr%d: Hmm, seems the cdrom " + "doesn't support multisession CD's\n",minor); no_multi = 1; break; } @@ -205,20 +210,19 @@ frame = BCD_TO_BIN(buffer[17]); sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame; break; - + case VENDOR_TOSHIBA: /* we request some disc information (is it a XA-CD ?, * where starts the last session ?) */ memset(cmd,0,12); cmd[0] = 0xc7; cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3; - rc = sr_do_ioctl(minor, cmd, buffer, 4); - if (rc == 0x28000002 && - !scsi_ioctl(scsi_CDs[minor].device, - SCSI_IOCTL_TEST_UNIT_READY, NULL)) { - printk(KERN_INFO "sr (toshiba): Hmm, seems the drive doesn't support multisession CD's\n"); - no_multi = 1; - break; + rc = sr_do_ioctl(minor, cmd, buffer, 4, 0); + if (rc == -EINVAL) { + printk(KERN_INFO "sr%d: Hmm, seems the drive " + "doesn't support multisession CD's\n",minor); + no_multi = 1; + break; } if (rc != 0) break; @@ -239,102 +243,57 @@ 0x04 : 0x0c; cmd[9] = 0x40; rc = sr_do_ioctl(minor, cmd, buffer, - (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c); + (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c, 0); if (rc != 0) { break; } if ((rc = buffer[2]) == 0) { printk (KERN_WARNING - "sr (hp): No finished session\n"); + "sr%d: No finished session\n",minor); break; } - if (VENDOR_ID == VENDOR_HP_4020) { - cmd[0] = READ_TOC; /* Read TOC */ - cmd[1] = (scsi_CDs[minor].device->lun << 5); - cmd[6] = rc & 0x7f; /* number of last session */ - cmd[8] = 0x0c; - cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12); - if (rc != 0) { - break; - } + if (VENDOR_ID == VENDOR_HP_4020) { + cmd[0] = READ_TOC; /* Read TOC */ + cmd[1] = (scsi_CDs[minor].device->lun << 5); + cmd[6] = rc & 0x7f; /* number of last session */ + cmd[8] = 0x0c; + cmd[9] = 0x40; + rc = sr_do_ioctl(minor, cmd, buffer, 12, 0); + if (rc != 0) { + break; + } } sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16) + (buffer[8] << 24); break; - - case VENDOR_SONY_LIKE: - memset(cmd,0,12); - cmd[0] = READ_TOC; - cmd[1] = (scsi_CDs[minor].device->lun << 5); - cmd[8] = 12; - cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12); - if (rc != 0) { - break; - } - if ((buffer[0] << 8) + buffer[1] < 0x0a) { - printk(KERN_INFO "sr (sony): Hmm, seems the drive doesn't support multisession CD's\n"); - no_multi = 1; - break; - } - sector = buffer[11] + (buffer[10] << 8) + - (buffer[9] << 16) + (buffer[8] << 24); - if (buffer[6] <= 1) { - /* ignore sector offsets from first track */ - sector = 0; - } - break; - - case VENDOR_CAN_NOT_HANDLE: - sector = 0; - no_multi = 1; - break; +#endif /* CONFIG_BLK_DEV_SR_VENDOR */ default: /* should not happen */ printk(KERN_WARNING - "sr: unknown vendor code (%i), not initialized ?\n", - VENDOR_ID); + "sr%d: unknown vendor code (%i), not initialized ?\n", + minor,VENDOR_ID); sector = 0; no_multi = 1; break; } - - scsi_CDs[minor].xa_flag = 0; - if (CDS_AUDIO != sr_disk_status(cdi)) { - /* read a sector in raw mode to check the sector format */ - raw_sector = (unsigned char *) scsi_malloc(2048+512); - if (!buffer) return -ENOMEM; - if (0 == sr_read_sector(minor,sector+16,CD_FRAMESIZE_RAW1, - raw_sector)){ - is_xa = (raw_sector[3] == 0x02); - if (sector > 0 && !is_xa) - printk(KERN_INFO "sr: broken CD found: It is " - "multisession, but has'nt XA sectors\n"); - } else { - /* read a raw sector failed for some reason. */ - is_xa = (sector > 0); - } - scsi_free(raw_sector, 2048+512); - } -#ifdef DEBUG - else printk("sr: audio CD found\n"); -#endif - scsi_CDs[minor].ms_offset = sector; - scsi_CDs[minor].xa_flag = is_xa; + scsi_CDs[minor].xa_flag = 0; + if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(minor)) + scsi_CDs[minor].xa_flag = 1; + + if (2048 != scsi_CDs[minor].sector_size) + sr_set_blocklength(minor,2048); if (no_multi) cdi->mask |= CDC_MULTI_SESSION; #ifdef DEBUG - printk(KERN_DEBUG - "sr: multisession offset=%lu, XA=%s\n", - sector,is_xa ? "yes" : "no"); + if (sector) + printk(KERN_DEBUG "sr%d: multisession offset=%lu\n", + minor,sector); #endif - scsi_free(buffer, 512); return rc; } diff -u --recursive --new-file v2.1.61/linux/fs/dquot.c linux/fs/dquot.c --- v2.1.61/linux/fs/dquot.c Thu Sep 11 09:02:23 1997 +++ linux/fs/dquot.c Sat Nov 1 10:59:56 1997 @@ -223,25 +223,17 @@ short type = dquot->dq_type; struct file *filp = dquot->dq_mnt->mnt_quotas[type]; unsigned long fs; + loff_t offset; if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL)) return; lock_dquot(dquot); down(&dquot->dq_mnt->mnt_sem); - if (filp->f_op->llseek) { - if (filp->f_op->llseek(filp->f_dentry->d_inode, filp, - dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) { - up(&dquot->dq_mnt->mnt_sem); - unlock_dquot(dquot); - return; - } - } else - filp->f_pos = dqoff(dquot->dq_id); + offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); - if (filp->f_op->write(filp->f_dentry->d_inode, filp, - (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk)) + if (filp->f_op->write(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset) == sizeof(struct dqblk)) dquot->dq_flags &= ~DQ_MOD; up(&dquot->dq_mnt->mnt_sem); @@ -255,23 +247,16 @@ short type = dquot->dq_type; struct file *filp = dquot->dq_mnt->mnt_quotas[type]; unsigned long fs; + loff_t offset; if (filp == (struct file *)NULL) return; lock_dquot(dquot); down(&dquot->dq_mnt->mnt_sem); - if (filp->f_op->llseek) { - if (filp->f_op->llseek(filp->f_dentry->d_inode, filp, - dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) { - up(&dquot->dq_mnt->mnt_sem); - unlock_dquot(dquot); - return; - } - } else - filp->f_pos = dqoff(dquot->dq_id); + offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); - filp->f_op->read(filp->f_dentry->d_inode, filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk)); + filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset); up(&dquot->dq_mnt->mnt_sem); set_fs(fs); if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 && diff -u --recursive --new-file v2.1.61/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.61/linux/fs/nfs/dir.c Sat Nov 1 11:04:27 1997 +++ linux/fs/nfs/dir.c Sun Nov 2 11:00:08 1997 @@ -29,6 +29,8 @@ #include /* for fs functions */ +#define NFS_MAX_AGE 10*HZ /* max age for dentry validation */ + /* needed by smbfs as well ... move to dcache? */ extern void nfs_renew_times(struct dentry *); extern void nfs_invalidate_dircache_sb(struct super_block *); @@ -51,6 +53,8 @@ __u32 * entry; /* three __u32's per entry */ }; +static int nfs_safe_remove(struct dentry *); + static int nfs_dir_open(struct inode * inode, struct file * file); static ssize_t nfs_dir_read(struct file *, char *, size_t, loff_t *); static int nfs_readdir(struct file *, void *, filldir_t); @@ -62,7 +66,8 @@ static int nfs_symlink(struct inode *, struct dentry *, const char *); static int nfs_link(struct inode *, struct inode *, struct dentry *); static int nfs_mknod(struct inode *, struct dentry *, int, int); -static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +static int nfs_rename(struct inode *, struct dentry *, + struct inode *, struct dentry *); static struct file_operations nfs_dir_operations = { NULL, /* lseek - default */ @@ -387,7 +392,7 @@ goto bad; } if (S_ISDIR(dentry->d_inode->i_mode)) - max = 10*HZ; + max = NFS_MAX_AGE; } return (time < max) || IS_ROOT(dentry); @@ -395,13 +400,44 @@ return 0; } -static void nfs_silly_delete(struct dentry *); +/* + * This is called from dput() when d_count is going to 0. + * We use it to clean up silly-renamed files, and to check + * for dentries that have already expired. + */ +static void nfs_dentry_delete(struct dentry *dentry) +{ + if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { + int error; + + dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; +#ifdef NFS_DEBUG +printk("nfs_dentry_delete: unlinking %s/%s\n", +dentry->d_parent->d_name.name, dentry->d_name.name); +#endif + /* Unhash it first */ + d_drop(dentry); + error = nfs_safe_remove(dentry); + if (error) + printk("NFS: can't silly-delete %s/%s, error=%d\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, error); + } + /* + * Check whether to expire the dentry ... + */ + else { + unsigned long age = jiffies - dentry->d_time; + if (age > NFS_MAX_AGE) + d_drop(dentry); + } +} static struct dentry_operations nfs_dentry_operations = { nfs_lookup_revalidate, /* d_validate(struct dentry *) */ 0, /* d_hash */ 0, /* d_compare */ - nfs_silly_delete, /* d_delete(struct dentry *) */ + nfs_dentry_delete /* d_delete(struct dentry *) */ }; /* @@ -564,8 +600,12 @@ } /* - * Update inode->i_nlink immediately after a successful operation. - * (See comments for nfs_unlink.) + * To avoid retaining a stale inode reference, we check the dentry + * use count prior to the operation, and return EBUSY if it has + * multiple users. + * + * Update inode->i_nlink immediately after a successful operation. + * (See comments for nfs_unlink.) */ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) { @@ -579,17 +619,27 @@ return -ENOENT; } + error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) - return -ENAMETOOLONG; + goto out; + error = -EBUSY; + if (dentry->d_count > 1) { + /* Attempt to shrink child dentries ... */ + shrink_dcache_sb(dentry->d_sb); /* Arghhh */ + if (dentry->d_count > 1) + goto out; + } + /* Drop the dentry to force a new lookup */ + d_drop(dentry); error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name); if (!error) { if (dentry->d_inode->i_nlink) dentry->d_inode->i_nlink --; nfs_invalidate_dircache(dir); nfs_renew_times(dentry); - d_delete(dentry); } +out: return error; } @@ -606,24 +656,22 @@ * * Concerning my choice of the temp name: it is just nice to have * i_ino part of the temp name, as this offers another check whether - * somebody attempts to remove the "silly renamed" dentry - * itself. Which is something that I consider evil. Your opinion may - * vary. + * somebody attempts to remove the "silly renamed" dentry itself. + * Which is something that I consider evil. Your opinion may vary. * BUT: * Now that I compute the hash value right, it should be possible to simply * check for the DCACHE_NFSFS_RENAMED flag in dentry->d_flag instead of * doing the string compare. * WHICH MEANS: * This offers the opportunity to shorten the temp name. Currently, I use - * the hex representation of i_ino + the hex value of jiffies. This - * sums up to as much as 36 characters for a 64 bit machine, and needs - * 20 chars on a 32 bit machine. Have a look at jiffiesize etc. + * the hex representation of i_ino + an event counter. This sums up to + * as much as 36 characters for a 64 bit machine, and needs 20 chars on + * a 32 bit machine. * QUINTESSENCE * The use of i_ino is simply cosmetic. All we need is a unique temp - * file name for the .nfs files. The hex representation of "jiffies" - * seemed to be adequate. And as we retry in case such a file already - * exists we are guaranteed to succed (after some jiffies have passed - * by :) + * file name for the .nfs files. The event counter seemed to be adequate. + * And as we retry in case such a file already exists, we are guaranteed + * to succeed. */ static @@ -631,15 +679,11 @@ { struct qstr sqstr; struct dentry *sdentry; - unsigned long hash; - int i, error; + int error; sqstr.name = silly; sqstr.len = slen; - hash = init_name_hash(); - for (i= 0; i < slen; i++) - hash = partial_name_hash(silly[i], hash); - sqstr.hash = end_name_hash(hash); + sqstr.hash = full_name_hash(silly, slen); sdentry = d_lookup(parent, &sqstr); if (!sdentry) { sdentry = d_alloc(parent, &sqstr); @@ -661,11 +705,16 @@ const int countersize = sizeof(sillycounter)*2; const int slen = strlen(".nfs") + i_inosize + countersize; char silly[slen+1]; - int error; struct dentry *sdentry; + int error = -EIO; + /* + * Note that a silly-renamed file can be deleted once it's + * no longer in use -- it's just an ordinary file now. + */ if (dentry->d_count == 1) { - return -EIO; /* No need to silly rename. */ + dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; + goto out; /* No need to silly rename. */ } #ifdef NFS_PARANOIA @@ -673,12 +722,12 @@ printk("NFS: silly-renaming %s/%s, negative dentry??\n", dentry->d_parent->d_name.name, dentry->d_name.name); #endif - if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { - return -EBUSY; /* don't allow to unlink silly inode -- nope, - * think a bit: silly DENTRY, NOT inode -- - * itself - */ - } + /* + * We don't allow a dentry to be silly-renamed twice. + */ + error = -EBUSY; + if (dentry->d_flags & DCACHE_NFSFS_RENAMED) + goto out; sprintf(silly, ".nfs%*.*lx", i_inosize, i_inosize, dentry->d_inode->i_ino); @@ -695,9 +744,12 @@ dentry->d_name.name, silly); sdentry = nfs_silly_lookup(dentry->d_parent, silly, slen); - if (IS_ERR(sdentry)) { - return -EIO; /* FIXME ? */ - } + /* + * N.B. Better to return EBUSY here ... it could be + * dangerous to delete the file while it's in use. + */ + if (IS_ERR(sdentry)) + goto out; } while(sdentry->d_inode != NULL); /* need negative lookup */ error = nfs_proc_rename(NFS_SERVER(dir), @@ -711,58 +763,67 @@ /* If we return 0 we don't unlink */ } dput(sdentry); +out: return error; } -static void nfs_silly_delete(struct dentry *dentry) +/* + * Remove a file after making sure there are no pending writes, + * and after checking that the file has only one user. + * + * Updating inode->i_nlink here rather than waiting for the next + * nfs_refresh_inode() is not merely cosmetic; once an object has + * been deleted, we want to get rid of the inode locally. The NFS + * server may reuse the fileid for a new inode, and we don't want + * that to be confused with this inode. + */ +static int nfs_safe_remove(struct dentry *dentry) { - if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { - struct inode *dir = dentry->d_parent->d_inode; - int error; + struct inode *dir = dentry->d_parent->d_inode; + struct inode *inode = dentry->d_inode; + int error; - dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; - - /* Unhash it first */ - d_drop(dentry); - dfprintk(VFS, "trying to unlink %s\n", dentry->d_name.name); - error = nfs_proc_remove(NFS_SERVER(dir), - NFS_FH(dir), dentry->d_name.name); - if (error < 0) - printk("NFS: can't silly-delete %s/%s, error=%d\n", - dentry->d_parent->d_name.name, - dentry->d_name.name, error); - if (dentry->d_inode) { - if (dentry->d_inode->i_nlink) - dentry->d_inode->i_nlink --; - } else { + error = -EBUSY; + if (inode) { + if (NFS_WRITEBACK(inode)) { + nfs_flush_dirty_pages(inode, 0, 0, 0); + if (NFS_WRITEBACK(inode)) { #ifdef NFS_PARANOIA - printk("nfs_silly_delete: negative dentry %s/%s\n", - dentry->d_parent->d_name.name, - dentry->d_name.name); +printk("nfs_safe_remove: %s/%s writes pending, d_count=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); #endif + goto out; + } } - nfs_invalidate_dircache(dir); + } else { +#ifdef NFS_PARANOIA +printk("nfs_safe_remove: %s/%s already negative??\n", +dentry->d_parent->d_name.name, dentry->d_name.name); +#endif } - /* - * Check whether to expire the dentry ... - */ - else { - unsigned long age = jiffies - dentry->d_time; - if (age > 10*HZ) - d_drop(dentry); + + if (dentry->d_count > 1) { +#ifdef NFS_PARANOIA +printk("nfs_safe_remove: %s/%s busy, d_count=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); +#endif + goto out; } + error = nfs_proc_remove(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name); + if (!error) { + nfs_invalidate_dircache(dir); + if (inode && inode->i_nlink) + inode->i_nlink --; + } +out: + return error; } /* We do silly rename. In case sillyrename() returns -EBUSY, the inode * belongs to an active ".nfs..." file and we return -EBUSY. * * If sillyrename() returns 0, we do nothing, otherwise we unlink. - * - * Updating inode->i_nlink here rather than waiting for the next - * nfs_refresh_inode() is not merely cosmetic; once an object has - * been deleted, we want to get rid of the inode locally. The NFS - * server may reuse the fileid for a new inode, and we don't want - * that to be confused with this inode. */ static int nfs_unlink(struct inode *dir, struct dentry *dentry) { @@ -781,23 +842,9 @@ goto out; error = nfs_sillyrename(dir, dentry); - if (error && error != -EBUSY) { -#ifdef NFS_PARANOIA -if (dentry->d_count > 1) -printk("nfs_unlink: dentry %s/%s, d_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); -if (dentry->d_inode && dentry->d_inode->i_count > 1) -printk("nfs_unlink: dentry %s/%s, inode i_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_inode->i_count); -#endif - /* N.B. should check for d_count > 1 and fail */ - error = nfs_proc_remove(NFS_SERVER(dir), - NFS_FH(dir), dentry->d_name.name); + error = nfs_safe_remove(dentry); if (!error) { - if (dentry->d_inode->i_nlink) - dentry->d_inode->i_nlink --; - nfs_invalidate_dircache(dir); nfs_renew_times(dentry); d_delete(dentry); } @@ -868,31 +915,13 @@ if (dentry->d_name.len > NFS_MAXNAMLEN) goto out; - /* - * The NFS server may want to use a new fileid for the link, - * so we can't reuse the existing inode for the new dentry. - * To force a new lookup after the link operation, we can just - * drop the new dentry, as long as it's not busy. (See above.) - */ - error = -EBUSY; - if (dentry->d_count > 1) { -#ifdef NFS_PARANOIA -printk("nfs_link: dentry %s/%s busy, count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); -#endif - goto out; - } - d_drop(dentry); - error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode), NFS_FH(dir), dentry->d_name.name); if (!error) { nfs_invalidate_dircache(dir); -#if 0 inode->i_count ++; inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */ d_instantiate(dentry, inode); -#endif } out: return error; @@ -916,23 +945,16 @@ * using the inode layer * * Unfortunately, things are a little more complicated than indicated - * above. The NFS server may decide to use a new fileid for the renamed - * file, so we can't link the new name to the old inode. Otherwise, the - * server might reuse the fileid after the old file has been removed, - * which would leave the new dentry holding an invalid fileid (possibly - * leading to file corruption). To handle this consider these cases: - * (1) within-directory: - * -- no problem, just use nfs_proc_rename - * (2) cross-directory, only one user for old and new dentry: - * -- drop both dentries to force new lookups, then use rename - * (3) cross-directory, multiple users for old, one user for new: - * -- drop new dentry, silly-rename old dentry and make a link - * (4) cross-directory, multiple users for new dentry: - * -- sorry, we're busy. + * above. For a cross-directory move, we want to make sure we can get + * rid of the old inode after the operation. This means there must be + * no pending writes (if it's a file), and the use count must be 1. + * If these conditions are met, we can drop the dentries before doing + * the rename. */ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { + struct inode *inode = old_dentry->d_inode; int update = 1, error; #ifdef NFS_DEBUG_VERBOSE @@ -955,60 +977,71 @@ new_dentry->d_name.len > NFS_MAXNAMLEN) goto out; /* - * Examine the cases as noted above. + * Check for within-directory rename ... no complications. */ if (new_dir == old_dir) - goto simple_case; + goto do_rename; + /* + * Cross-directory move ... check whether it's a file. + */ error = -EBUSY; - if (new_dentry->d_count > 1) { + if (S_ISREG(inode->i_mode)) { + if (NFS_WRITEBACK(inode)) { #ifdef NFS_PARANOIA -printk("nfs_rename: new dentry %s/%s busy, count=%d\n", -new_dentry->d_parent->d_name.name, new_dentry->d_name.name, -new_dentry->d_count); +printk("nfs_rename: %s/%s has pending writes\n", +old_dentry->d_parent->d_name.name, old_dentry->d_name.name); #endif - goto out; + nfs_flush_dirty_pages(inode, 0, 0, 0); + if (NFS_WRITEBACK(inode)) { +#ifdef NFS_PARANOIA +printk("nfs_rename: %s/%s has pending writes after flush\n", +old_dentry->d_parent->d_name.name, old_dentry->d_name.name); +#endif + goto out; + } + } } - d_drop(new_dentry); - if (old_dentry->d_count > 1) - goto complex_case; - d_drop(old_dentry); - update = 0; - - /* no need for silly rename, proceed as usual */ -simple_case: - error = nfs_proc_rename(NFS_SERVER(old_dir), - NFS_FH(old_dir), old_dentry->d_name.name, - NFS_FH(new_dir), new_dentry->d_name.name); - if (error) - goto out; - nfs_invalidate_dircache(new_dir); - nfs_invalidate_dircache(old_dir); - - /* Update the dcache if needed */ - if (update) - d_move(old_dentry, new_dentry); - goto out; + /* + * Moving a directory ... prune child dentries if needed. + */ + else if (old_dentry->d_count > 1) + shrink_dcache_sb(old_dentry->d_sb); /* Arghhh */ /* - * We don't need to update the dcache in this case ... the - * new dentry has been dropped, and the old one silly-renamed. + * Now check the use counts ... we can't safely do the + * rename unless we can drop the dentries first. */ -complex_case: - error = nfs_sillyrename(old_dir, old_dentry); - if (error) + if (old_dentry->d_count > 1) { +#ifdef NFS_PARANOIA +printk("nfs_rename: old dentry %s/%s busy, d_count=%d\n", +old_dentry->d_parent->d_name.name,old_dentry->d_name.name,old_dentry->d_count); +#endif goto out; - nfs_invalidate_dircache(old_dir); + } - error = nfs_link(old_dentry->d_inode, new_dir, new_dentry); - if (error) - goto out; - nfs_invalidate_dircache(new_dir); + if (new_dentry->d_count > 1) { #ifdef NFS_PARANOIA -printk("nfs_rename: dentry %s/%s linked to %s/%s, old count=%d\n", -new_dentry->d_parent->d_name.name,new_dentry->d_name.name, -old_dentry->d_parent->d_name.name,old_dentry->d_name.name,old_dentry->d_count); +printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n", +new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count); #endif + goto out; + } + d_drop(old_dentry); + d_drop(new_dentry); + update = 0; + +do_rename: + error = nfs_proc_rename(NFS_SERVER(old_dir), + NFS_FH(old_dir), old_dentry->d_name.name, + NFS_FH(new_dir), new_dentry->d_name.name); + if (!error) { + nfs_invalidate_dircache(new_dir); + nfs_invalidate_dircache(old_dir); + /* Update the dcache if needed */ + if (update) + d_move(old_dentry, new_dentry); + } out: return error; } diff -u --recursive --new-file v2.1.61/linux/include/linux/isdnif.h linux/include/linux/isdnif.h --- v2.1.61/linux/include/linux/isdnif.h Thu May 29 21:53:11 1997 +++ linux/include/linux/isdnif.h Mon Nov 3 10:08:48 1997 @@ -390,9 +390,9 @@ #include #define GET_USER get_user #define PUT_USER put_user -#define RWTYPE long +#define RWTYPE ssize_t #define LSTYPE long long -#define RWARG unsigned long +#define RWARG size_t #define LSARG long long #endif diff -u --recursive --new-file v2.1.61/linux/include/linux/quota.h linux/include/linux/quota.h --- v2.1.61/linux/include/linux/quota.h Thu Jun 12 15:28:32 1997 +++ linux/include/linux/quota.h Sat Nov 1 11:01:24 1997 @@ -132,7 +132,7 @@ #define dq_btime dq_dqb.dqb_btime #define dq_itime dq_dqb.dqb_itime -#define dqoff(UID) ((off_t)((UID) * sizeof (struct dqblk))) +#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) struct dqstats { __u32 lookups; diff -u --recursive --new-file v2.1.61/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.61/linux/kernel/ksyms.c Sat Oct 25 02:44:18 1997 +++ linux/kernel/ksyms.c Mon Nov 3 09:27:45 1997 @@ -167,6 +167,7 @@ EXPORT_SYMBOL(invalidate_buffers); EXPORT_SYMBOL(invalidate_inodes); EXPORT_SYMBOL(invalidate_inode_pages); +EXPORT_SYMBOL(truncate_inode_pages); EXPORT_SYMBOL(fsync_dev); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(inode_setattr); @@ -197,6 +198,7 @@ EXPORT_SYMBOL(dput); EXPORT_SYMBOL(get_cached_page); EXPORT_SYMBOL(put_cached_page); +EXPORT_SYMBOL(shrink_dcache_sb); #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) EXPORT_SYMBOL(do_nfsservctl);