@@ -351,6+351,13 @@ S: 249 Nichols Avenue S: Syracuse, New York 13206
S: USA
+N: Dirk Melchers
+E: dirk@merlin.nbg.sub.org
+D: 8 bit XT hard disk driver for OMTI5520
+S: Branderweg 4
+S: D-91058 Erlangen
+S: Germany
+
N: Craig Metz
E: cmetz@tjhsst.edu
D: Some of PAS 16 mixer & PCM support
VERSION = 1
PATCHLEVEL = 1
-SUBLEVEL = 1
+SUBLEVEL = 2
all: Version zImage
@@ -9,7+9,7 @@ all: Version zImage CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi)
-ROOT := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
+TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
#
# Make "config" the default target if there is no configuration file or
LD =ld
LDFLAGS =#-qmagic
HOSTCC =gcc
-CC =gcc -D__KERNEL__ -I$(ROOT)/include
+CC =gcc -D__KERNEL__ -I$(TOPDIR)/include
MAKE =make
CPP =$(CC) -E
AR =ar
@@ -81,9+81,6 @@ CONFIGURING the kernel: should probably answer 'n' to the questions for a "production"
kernel.
- - edit drivers/net/CONFIG to configure the networking parts of the
- kernel. The comments should hopefully clarify it all.
-
- Check the top Makefile for further site-dependent configuration
(default SVGA mode etc).
@@ -542,6+542,12 @@ static int hd_ioctl(struct inode * inode, struct file * file, put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
(long *) &loc->start);
return 0;
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(!inode->i_rdev) return -EINVAL;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
@@ -126,7+126,7 @@ void rd_load(void) */
for (tries = 0; tries < 1000; tries += 512) {
block = tries;
- bh = breada(ROOT_DEV,block+1,block,block+2,-1);
+ bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0, PAGE_SIZE);
if (!bh) {
printk("RAMDISK: I/O error while looking for super block!\n");
return;
@@ -154,7+154,7 @@ void rd_load(void) cp = rd_start;
while (nblocks) {
if (nblocks > 2)
- bh = breada(ROOT_DEV, block, block+1, block+2, -1);
+ bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0, PAGE_SIZE);
else
bh = bread(ROOT_DEV, block, BLOCK_SIZE);
if (!bh) {
@@ -252,6+252,12 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) return (0);
}
break;
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(!inode->i_rdev) return -EINVAL;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
case BLKGETSIZE:
if (arg) {
if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
@@ -85,7+85,7 @@ static int want_console = -1; static int last_console = 0; /* last used VC */
static int dead_key_next = 0;
static int shift_state = 0;
-static int npadch = -1; /* -1 or number assembled on pad */
+static int npadch = -1; /* -1 or number assembled on pad */
static unsigned char diacr = 0;
static char rep = 0; /* flag telling character repeat */
struct kbd_struct kbd_table[NR_CONSOLES];
@@ -100,7+100,7 @@ typedef void (*k_hand)(unsigned char value, char up_flag); typedef void (k_handfn)(unsigned char value, char up_flag);
static k_handfn
- do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
+ do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
do_meta, do_ascii, do_lock, do_lowercase;
static k_hand key_handler[] = {
@@ -196,7+196,7 @@ static void keyboard_interrupt(int int_pt_regs) {
unsigned char scancode;
static unsigned int prev_scancode = 0; /* remember E0, E1 */
- char up_flag; /* 0 or 0200 */
+ char up_flag; /* 0 or 0200 */
char raw_mode;
pt_regs = (struct pt_regs *) int_pt_regs;
@@ -214,15+214,15 @@ static void keyboard_interrupt(int int_pt_regs) goto end_kbd_intr;
} else if (scancode == 0) {
#ifdef KBD_REPORT_ERR
- printk("keyboard buffer overflow\n");
+ printk("keyboard buffer overflow\n");
#endif
goto end_kbd_intr;
} else if (scancode == 0xff) {
#ifdef KBD_REPORT_ERR
- printk("keyboard error\n");
+ printk("keyboard error\n");
#endif
- prev_scancode = 0;
- goto end_kbd_intr;
+ prev_scancode = 0;
+ goto end_kbd_intr;
}
tty = TTY_TABLE(0);
kbd = kbd_table + fg_console;
@@ -242,7+242,7 @@ static void keyboard_interrupt(int int_pt_regs) */
up_flag = (scancode & 0200);
scancode &= 0x7f;
-
+
if (prev_scancode) {
/*
* usually it will be 0xe0, but a Pause key generates
@@ -294,7+294,7 @@ static void keyboard_interrupt(int int_pt_regs) #endif
goto end_kbd_intr;
}
-
+
/*
* At this point the variable `scancode' contains the keysym.
* We keep track of the up/down status of the key, and
@@ -308,15+308,15 @@ static void keyboard_interrupt(int int_pt_regs) rep = 0;
} else
rep = set_bit(scancode, key_down);
-
+
if (raw_mode)
- goto end_kbd_intr;
+ goto end_kbd_intr;
if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
put_queue(scancode + up_flag);
goto end_kbd_intr;
}
-
+
/*
* Small change in philosophy: earlier we defined repetition by
* rep = scancode == prev_keysym;
@@ -330,7+330,7 @@ static void keyboard_interrupt(int int_pt_regs) * characters get echoed locally. This makes key repeat usable
* with slow applications and under heavy loads.
*/
- if (!rep ||
+ if (!rep ||
(vc_kbd_mode(kbd,VC_REPEAT) && tty &&
(L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q)))))
{
@@ -499,7+499,7 @@ static void boot_it(void)
static void compose(void)
{
- dead_key_next = 1;
+ dead_key_next = 1;
}
static void do_spec(unsigned char value, char up_flag)
@@ -523,22+523,22 @@ static void do_spec(unsigned char value, char up_flag)
static void do_lowercase(unsigned char value, char up_flag)
{
- printk("keyboard.c: do_lowercase was called - impossible\n");
+ printk("keyboard.c: do_lowercase was called - impossible\n");
}
-
+
static void do_self(unsigned char value, char up_flag)
{
if (up_flag)
return; /* no action, if this is a key release */
- if (diacr)
- value = handle_diacr(value);
+ if (diacr)
+ value = handle_diacr(value);
- if (dead_key_next) {
- dead_key_next = 0;
- diacr = value;
- return;
- }
+ if (dead_key_next) {
+ dead_key_next = 0;
+ diacr = value;
+ return;
+ }
put_queue(value);
}
@@ -549,7+549,7 @@ static void do_self(unsigned char value, char up_flag) #define A_TILDE '~'
#define A_DIAER '"'
static unsigned char ret_diacr[] =
- {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
+ {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
/* If a dead key pressed twice, output a character corresponding to it, */
/* otherwise just remember the dead key. */
@@ -559,12+559,12 @@ static void do_dead(unsigned char value, char up_flag) if (up_flag)
return;
- value = ret_diacr[value];
- if (diacr == value) { /* pressed twice */
- diacr = 0;
- put_queue(value);
- return;
- }
+ value = ret_diacr[value];
+ if (diacr == value) { /* pressed twice */
+ diacr = 0;
+ put_queue(value);
+ return;
+ }
diacr = value;
}
@@ -574,19+574,20 @@ static void do_dead(unsigned char value, char up_flag)
unsigned char handle_diacr(unsigned char ch)
{
- int d = diacr;
- int i;
+ int d = diacr;
+ int i;
- diacr = 0;
- if (ch == ' ')
- return d;
+ diacr = 0;
+ if (ch == ' ')
+ return d;
- for (i = 0; i < accent_table_size; i++)
- if(accent_table[i].diacr == d && accent_table[i].base == ch)
- return accent_table[i].result;
+ for (i = 0; i < accent_table_size; i++) {
+ if (accent_table[i].diacr == d && accent_table[i].base == ch)
+ return accent_table[i].result;
+ }
- put_queue(d);
- return ch;
+ put_queue(d);
+ return ch;
}
static void do_cons(unsigned char value, char up_flag)
@@ -601,9+602,9 @@ static void do_fn(unsigned char value, char up_flag) if (up_flag)
return;
if (value < SIZE(func_table))
- puts_queue(func_table[value]);
+ puts_queue(func_table[value]);
else
- printk("do_fn called with value=%d\n", value);
+ printk("do_fn called with value=%d\n", value);
}
static void do_pad(unsigned char value, char up_flag)
@@ -686,7+687,7 @@ static void do_shift(unsigned char value, char up_flag) }
if (up_flag) {
- /* handle the case that two shift or control
+ /* handle the case that two shift or control
keys are depressed simultaneously */
if (k_down[value])
k_down[value]--;
@@ -709,9+710,9 @@ static void do_shift(unsigned char value, char up_flag) recompute k_down[] and shift_state from key_down[] */
void compute_shiftstate(void)
{
- int i, j, k, sym, val;
+ int i, j, k, sym, val;
- shift_state = 0;
+ shift_state = 0;
for(i=0; i < SIZE(k_down); i++)
k_down[i] = 0;
@@ -725,7+726,7 @@ void compute_shiftstate(void) val = KVAL(sym);
k_down[val]++;
shift_state |= (1<<val);
- }
+ }
}
}
}
@@ -748,9+749,9 @@ static void do_ascii(unsigned char value, char up_flag) return;
if (npadch == -1)
- npadch = value;
+ npadch = value;
else
- npadch = (npadch * 10 + value) % 1000;
+ npadch = (npadch * 10 + value) % 1000;
}
static void do_lock(unsigned char value, char up_flag)
@@ -22,6+22,7 @@ static char *version = #include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -44,12+44,12 @@ static char *version = #include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
+#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <errno.h>
-#include <memory.h>
+#include <linux/errno.h>
#include "dev.h"
#include "eth.h"
-/* depca.c: A DIGITAL DEPCA ethernet driver for linux.
+/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
Written 1994 by David C. Davies.
- Copyright 1994 David C. Davies and United States Government as
- represented by the Director, National Security Agency. This software
- may be used and distributed according to the terms of the GNU Public
- License, incorporated herein by reference.
+
+ Copyright 1994 David C. Davies
+ and
+ United States Government
+ (as represented by the Director, National Security Agency).
+
+
+ This software may be used and distributed according to the terms of
+ the GNU Public License, incorporated herein by reference.
This driver is written for the Digital Equipment Corporation series
- of DEPCA ethernet cards:
+ of DEPCA and EtherWORKS ethernet cards:
- DE100 DEPCA
- DE200 DEPCA Turbo
- DE202 DEPCA Turbo (TP BNC)
- DE210 DEPCA
+ DEPCA (the original)
+ DE100
+ DE200 Turbo
+ DE201 Turbo
+ DE202 Turbo (TP BNC)
+ DE210
- The driver has been tested on DE100 and DE20x cards in a relatively busy
- network.
+ The driver has been tested on DE100, DE200 and DE202 cards in a
+ relatively busy network.
- The author may be reached as davies@wanton.enet.dec.com or
+ This driver will not work for the DE203, DE204 and DE205 series of
+ cards, since they have a new custom ASIC in place of the AMD LANCE chip.
+
+ The author may be reached as davies@wanton.lkg.dec.com or
Digital Equipment Corporation, 146 Main Street, Maynard MA 01754.
=========================================================================
the filter bit positions correctly. Hash filtering is not yet
implemented in the current driver set.
- The DE200 series boards have on-board 64kB RAM for use as a shared
- memory network buffer. Only the DE100 cards make use of a 2kB buffer
- mode which has not been implemented in this driver (only the 32kB and
- 64kB modes are supported).
+ The original DEPCA card requires that the ethernet ROM address counter
+ be enabled to count and has an 8 bit NICSR. The ROM counter enabling is
+ only done when a 0x08 is read as the first address octet (to minimise
+ the chances of writing over some other hardware's I/O register). The
+ size of the NICSR is tested by a word read: if both bytes are the same,
+ the register is 8 bits wide. Also, there is a maximum of only 48kB
+ network RAM for this card. My thanks to Torbjorn Lindh for help
+ debugging all this (and holding my feet to the fire until I got it
+ right).
+
+ The DE200 series boards have on-board 64kB RAM for use as a shared
+ memory network buffer. Only the DE100 cards make use of a 2kB buffer
+ mode which has not been implemented in this driver (only the 32kB and
+ 64kB modes are supported [16kB/48kB for the original DEPCA]).
At the most only 2 DEPCA cards can be supported because there is only
provision for two I/O base addresses on the cards (0x300 and 0x200). The
this unambiguously at the moment, since there is nothing on the cards to
tie I/O and memory information together.
- I am unable to test 2 DEPCAs together for now, so this code is
+ I am unable to test 2 cards together for now, so this code is
unchecked. All reports, good or bad, are welcome.
************************************************************************
- The board IRQ setting must be at an unused IRQ which is auto-probed
- using Donald Becker's autoprobe routines. DE100 board IRQs are
- {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is
+ The board IRQ setting must be at an unused IRQ which is auto-probed
+ using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
+ {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is
really IRQ9 in machines with 16 IRQ lines.
No 16MB memory limitation should exist with this driver as DMA is not
used and the common memory area is in low memory on the network card (my
current system has 20MB and I've not had problems yet).
- The DE203, DE204 and DE205 cards may also work with this driver (I
- haven't tested them so I don't know). If you have one of these cards,
- place the name in the DEPCA_SIGNATURE string around line 160, recompile
- the kernel and reboot. Check if the card is recognised and works - mail
- me if so, so that I can add it into the list of supported cards!
-
TO DO:
------
Version Date Description
- 0.1 25-jan-94 Initial writing
- 0.2 27-jan-94 Added LANCE TX buffer chaining
- 0.3 1-feb-94 Added multiple DEPCA support
- 0.31 4-feb-94 Added DE202 recognition
+ 0.1 25-jan-94 Initial writing.
+ 0.2 27-jan-94 Added LANCE TX buffer chaining.
+ 0.3 1-feb-94 Added multiple DEPCA support.
+ 0.31 4-feb-94 Added DE202 recognition.
0.32 19-feb-94 Tidy up. Improve multi-DEPCA support.
+ 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable.
+ Add jabber packet fix from murf@perftech.com
+ and becker@super.org
+ 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access.
+ 0.35 8-mar-94 Added DE201 recognition.
=========================================================================
*/
-static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n";
+static char *version = "depca.c:v0.35 3/8/94 davies@wanton.lkg.dec.com\n";
#include <stdarg.h>
#include <linux/config.h>
@@ -129,7+148,7 @@ static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n"; #include <asm/dma.h>
#include "dev.h"
-#include "iow.h"
+#include "iow.h" /* left in for pl13/14 compatibility... */
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -155,7+174,7 @@ int depca_debug = 1; #endif
#ifndef DEPCA_SIGNATURE
-#define DEPCA_SIGNATURE {"DEPCA","DE100","DE200","DE202","DE210",""}
+#define DEPCA_SIGNATURE {"DEPCA","DE100","DE200","DE201","DE202","DE210",""}
#define DEPCA_NAME_LENGTH 8
#endif
@@ -241,7+260,7 @@ struct depca_private { int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
int dma;
struct enet_statistics stats;
- char old_depca;
+ char depca_na; /* NICSR access width: 0=>byte, 1=>word */
short ringSize; /* ring size based on available memory */
short rmask; /* modulus mask based on ring size */
long rlen; /* log2(ringSize) for the descriptors */
@@ -275,6+294,7 @@ static int DevicePresent(short ioaddr); static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table);
#endif
+static int depca_na;
static int num_depcas = 0, num_eth = 0;;
/*
@@ -284,6+304,21 @@ static int num_depcas = 0, num_eth = 0;; outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA)
+#define GET_NICSR(a,b) \
+ if (depca_na) { \
+ (a) = inw((b)); \
+ } else { \
+ (a) = inb((b)); \
+ }
+
+#define PUT_NICSR(a,b) \
+ if (depca_na) { \
+ outw((a), (b)); \
+ } else { \
+ outb((a), (b)); \
+ }
+
+
\f
int depca_probe(struct device *dev)
@@ -294,7+329,10 @@ int depca_probe(struct device *dev) struct device *eth0 = (struct device *) NULL;
if (base_addr > 0x1ff) { /* Check a single specified location. */
- status = depca_probe1(dev, base_addr);
+ status = -ENODEV;
+ if (DevicePresent(base_addr) == 0) { /* Is DEPCA really here? */
+ status = depca_probe1(dev, base_addr);
+ }
} else if (base_addr > 0) { /* Don't probe at all. */
status = -ENXIO;
} else { /* First probe for the DEPCA test */
@@ -308,7+346,7 @@ int depca_probe(struct device *dev) if (check_region(ioaddr, DEPCA_TOTAL_SIZE))
continue;
#endif
- if (DevicePresent(DEPCA_PROM) == 0) {
+ if (DevicePresent(ioaddr) == 0) {
if (num_depcas > 0) { /* only gets here in autoprobe */
/*
@@ -370,17+408,18 @@ depca_probe1(struct device *dev, short ioaddr) int i,j, status=0;
unsigned long mem_start, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
char *name=(char *)NULL;
- int nicsr, offset;
+ unsigned int nicsr, offset, netRAM;
/*
- ** Stop the DEPCA. Enable the DBR ROM. Disable interrupts and remote boot
+ ** Stop the DEPCA. Enable the DBR ROM and the ethernet ROM address counter
+ ** (for the really old DEPCAs). Disable interrupts and remote boot.
*/
STOP_DEPCA;
- nicsr = inw(DEPCA_NICSR);
- nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
- outw(nicsr, DEPCA_NICSR);
+ GET_NICSR(nicsr, DEPCA_NICSR);
+ nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | AAC | IM);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
if (inw(DEPCA_DATA) == STOP) {
@@ -438,18+477,27 @@ depca_probe1(struct device *dev, short ioaddr) snarf_region(ioaddr, DEPCA_TOTAL_SIZE);
#endif
+ /*
+ ** Set up the maximum amount of network RAM(kB)
+ */
+ if (strstr(name,"DEPCA")==(char *)NULL) {
+ netRAM=64;
+ } else {
+ netRAM=48;
+ }
+
/*
** Determine the base address for the DEPCA RAM from the NI-CSR
** and make up a DEPCA-specific-data structure.
*/
if (nicsr & BUF) {
- offset = 0x8000; /* 32kbyte RAM */
+ offset = 0x8000; /* 32kbyte RAM offset*/
nicsr &= ~BS; /* DEPCA RAM in top 32k */
- printk(",\n with 32kB RAM");
+ printk(",\n with %dkB RAM", netRAM-(offset >> 10));
} else {
- offset = 0x0000; /* 64kbyte RAM */
- printk(",\n with 64kB RAM");
+ offset = 0x0000; /* 64k/48k bytes RAM */
+ printk(",\n with %dkB RAM", netRAM);
}
mem_start += offset;
@@ -459,17+507,19 @@ depca_probe1(struct device *dev, short ioaddr) ** Enable the shadow RAM.
*/
nicsr |= SHE;
- outw(nicsr, DEPCA_NICSR);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
/*
** Calculate the ring size based on the available RAM
** found above. Allocate an equal number of buffers, each
- ** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx. Make sure
+ ** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx, allowing one
+ ** descriptor entry (8 bytes) for each buffer. Make sure
** that this ring size is <= RING_SIZE. The ring size must be
** a power of 2.
*/
- j = ((0x10000 - offset) / PKT_BUF_SZ) >> 1;
+ j = (((netRAM << 10) - offset - sizeof(struct depca_private)) /
+ (PKT_BUF_SZ + 8)) >> 1;
for (i=0;j>1;i++) {
j >>= 1;
}
@@ -549,10+599,15 @@ depca_probe1(struct device *dev, short ioaddr) LoadCSRs(dev);
/*
+ ** Store the NICSR width for this DEPCA
+ */
+ lp->depca_na = depca_na;
+
+ /*
** Enable DEPCA board interrupts for autoprobing
*/
nicsr = ((nicsr & ~IM)|IEN);
- outw(nicsr, DEPCA_NICSR);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
/* The DMA channel may be passed in on this parameter. */
dev->dma = 0;
@@ -646,8+701,9 @@ depca_open(struct device *dev) /*
** Stop the DEPCA & get the board status information.
*/
+ depca_na=lp->depca_na;
STOP_DEPCA;
- nicsr = inw(DEPCA_NICSR);
+ GET_NICSR(nicsr, DEPCA_NICSR);
/*
** Re-initialize the DEPCA...
@@ -698,7+754,7 @@ depca_open(struct device *dev) ** Enable DEPCA board interrupts
*/
nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN);
- outw(nicsr, DEPCA_NICSR);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
outw(CSR0,DEPCA_ADDR);
dev->tbusy = 0;
@@ -709,7+765,8 @@ depca_open(struct device *dev)
if (depca_debug > 1){
printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA));
- printk("nicsr: 0x%4.4x\n",inw(DEPCA_NICSR));
+ GET_NICSR(nicsr, DEPCA_NICSR);
+ printk("nicsr: 0x%4.4x\n",nicsr);
}
return 0; /* Always succeed */
@@ -760,7+817,7 @@ depca_start_xmit(struct sk_buff *skb, struct device *dev) /* Transmitter timeout, serious problems. */
if (dev->tbusy) {
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5) {
+ if (tickssofar < 10) {
status = -1;
} else {
STOP_DEPCA;
@@ -921,6+978,7 @@ depca_interrupt(int reg_ptr) } else {
lp = (struct depca_private *)dev->priv;
ioaddr = dev->base_addr;
+ depca_na = lp->depca_na;
}
if (dev->interrupt)
@@ -929,9+987,9 @@ depca_interrupt(int reg_ptr) dev->interrupt = MASK_INTERRUPTS;
/* mask the DEPCA board interrupts and turn on the LED */
- nicsr = inw(DEPCA_NICSR);
+ GET_NICSR(nicsr, DEPCA_NICSR);
nicsr |= (IM|LED);
- outw(nicsr, DEPCA_NICSR);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
outw(CSR0, DEPCA_ADDR);
csr0 = inw(DEPCA_DATA);
@@ -961,7+1019,7 @@ depca_interrupt(int reg_ptr)
/* Unmask the DEPCA board interrupts and turn off the LED */
nicsr = (nicsr & ~IM & ~LED);
- outw(nicsr, DEPCA_NICSR);
+ PUT_NICSR(nicsr, DEPCA_NICSR);
dev->interrupt = UNMASK_INTERRUPTS;
return;
@@ -976,9+1034,32 @@ depca_rx(struct device *dev) /* If we own the next entry, it's a new packet. Send it up. */
for (; lp->rx_ring[entry].base >= 0; entry = (++lp->cur_rx) & lp->rmask) {
int status = lp->rx_ring[entry].base >> 16 ;
+ int chained;
- if (status & R_ERR) { /* There was an error. */
- lp->stats.rx_errors++; /* Update the error stats. */
+ /*
+ ** There is a tricky error noted by John Murphy, <murf@perftech.com>
+ ** to Russ Nelson: even with full-sized buffers, it's possible for a
+ ** jabber packet to use two buffers, with only the last one correctly
+ ** noting the error.
+ */
+
+ /* Check for a chaining buffer */
+ chained = 0;
+ if (status == R_STP) {
+ chained = 1;
+
+ /*
+ ** Wait for next buffer to complete to check for errors. This
+ ** is slow but infrequent and allows for correct hardware buffer
+ ** chaining (whilst defeating the chaining's purpose).
+ */
+ while ((status=(lp->rx_ring[(entry+1)&lp->rmask].base >> 16)) < 0);
+
+ /* NB: 'status' now comes from the buffer following 'entry'. */
+ }
+
+ if (status & R_ERR) { /* There was an error. */
+ lp->stats.rx_errors++; /* Update the error stats. */
if (status & R_FRAM) lp->stats.rx_frame_errors++;
if (status & R_OFLO) lp->stats.rx_over_errors++;
if (status & R_CRC) lp->stats.rx_crc_errors++;
@@ -1020,6+1101,10 @@ depca_rx(struct device *dev)
/* turn over ownership of the current entry back to the LANCE */
lp->rx_ring[entry].base |= R_OWN;
+ if (chained && (status & R_ERR)) { /* next entry also bad */
+ entry = (++lp->cur_rx) & lp->rmask;
+ lp->rx_ring[entry].base |= R_OWN;
+ }
}
/*
@@ -1277,7+1362,15 @@ static char *DepcaSignature(unsigned long mem_addr)
/*
** Look for a special sequence in the Ethernet station address PROM that
-** is common across all DEPCA products.
+** is common across all DEPCA products. Note that the original DEPCA needs
+** its ROM address counter to be initialized and enabled. Only enable
+** if the first address octet is a 0x08 - this minimises the chances of
+** messing around with some other hardware, but it assumes that this DEPCA
+** card initialized itself correctly. It also assumes that all past and
+** future DEPCA/EtherWORKS cards will have ethernet addresses beginning with
+** a 0x08. The choice of byte or word addressing is made here based on whether
+** word read of the NICSR returns two identical lower and upper bytes: if so
+** the register is 8 bits wide.
*/
static int DevicePresent(short ioaddr)
@@ -1285,9+1378,40 @@ static int DevicePresent(short ioaddr) static short fp=1,sigLength=0;
static char devSig[] = PROBE_SEQUENCE;
char data;
- int i, j, status = 0;
+ unsigned char LSB,MSB;
+ int i, j, nicsr, status = 0;
static char asc2hex(char value);
+/*
+** Initialize the counter on a DEPCA card. Two reads to ensure DEPCA ethernet
+** address counter is a) cleared and b) the correct data read.
+*/
+ data = inb(DEPCA_PROM); /* clear counter */
+ data = inb(DEPCA_PROM); /* read data */
+
+/*
+** Determine whether a byte or word access should be made on the NICSR.
+** Since the I/O 'functions' are actually in-line code, the choice not to use
+** pointers to functions vs. just set a conditional, is made for us. This code
+** assumes that the NICSR has an asymmetric bit pattern already in it.
+*/
+ nicsr = inw(DEPCA_NICSR);
+ LSB = nicsr & 0xff;
+ MSB = (((unsigned) nicsr) >> 8) & 0xff;
+ if (MSB == LSB) {
+ depca_na = 0; /* byte accesses */
+ } else {
+ depca_na = 1; /* word accesses */
+ }
+
+/*
+** Enable counter
+*/
+ if (data == 0x08) {
+ nicsr |= AAC;
+ PUT_NICSR(nicsr, DEPCA_NICSR);
+ }
+
/*
** Convert the ascii signature to a hex equivalent & pack in place
*/
@@ -1318,7+1442,7 @@ static int DevicePresent(short ioaddr) */
if (!status) {
for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
- data = inb(ioaddr);
+ data = inb(DEPCA_PROM);
if (devSig[j] == data) { /* track signature */
j++;
} else { /* lost signature; begin search again */
#define BS 0x0040 /* Bank Select */
#define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */
#define RBE 0x0010 /* Remote Boot Enable (1->net boot) */
-#define AAC 0x0008 /* for DEPCA family compatability */
+#define AAC 0x0008 /* Address ROM Address Counter (1->enable) */
#define IM 0x0004 /* Interrupt Mask (1->mask) */
#define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */
#define LED 0x0001 /* LED control */
@@ -42,12+42,12 @@ static char *version = #include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
+#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <errno.h>
-#include <memory.h>
+#include <linux/errno.h>
#include "dev.h"
#include "eth.h"
#include <linux/fs.h>
#include <linux/malloc.h>
#include <linux/if_ether.h>
-#include <memory.h>
+#include <linux/string.h>
#include "dev.h"
#include "eth.h"
@@ -127,6+127,7 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0}; static struct blist blacklist[] =
{
{"CHINON","CD-ROM CDS-431","H42"}, /* Locks up if polled for lun != 0 */
+ {"CHINON","CD-ROM CDS-535","Q14"}, /* Lockup if polled for lun != 0 */
{"DENON","DRD-25X","V"}, /* A cdrom that locks up when probed at lun != 0 */
{"IMS", "CDD521/10","2.06"}, /* Locks-up when LUN>0 polled. */
{"MAXTOR","XT-3280","PR02"}, /* Locks-up when LUN>0 polled. */
@@ -533,7+534,7 @@ Scsi_Cmnd * request_queueable (struct request * req, int index) {
Scsi_Cmnd * SCpnt = NULL;
int tablesize;
- struct buffer_head * bh;
+ struct buffer_head * bh, *bhp;
if ((index < 0) || (index > NR_SCSI_DEVICES))
panic ("Index number in allocate_device() is out of range.\n");
@@ -557,16+558,17 @@ Scsi_Cmnd * request_queueable (struct request * req, int index) if (req) {
memcpy(&SCpnt->request, req, sizeof(struct request));
tablesize = scsi_devices[index].host->sg_tablesize;
- bh = req->bh;
+ bhp = bh = req->bh;
if(!tablesize) bh = NULL;
/* Take a quick look through the table to see how big it is. We already
have our copy of req, so we can mess with that if we want to. */
while(req->nr_sectors && bh){
- tablesize--;
+ bhp = bhp->b_reqnext;
+ if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--;
req->nr_sectors -= bh->b_size >> 9;
req->sector += bh->b_size >> 9;
if(!tablesize) break;
- bh = bh->b_reqnext;
+ bh = bhp;
};
if(req->nr_sectors && bh && bh->b_reqnext){ /* Any leftovers? */
SCpnt->request.bhtail = bh;
@@ -579,9+581,10 @@ Scsi_Cmnd * request_queueable (struct request * req, int index) req->current_nr_sectors = bh->b_size >> 9;
req->buffer = bh->b_data;
SCpnt->request.waiting = NULL; /* Wait until whole thing done */
- } else
+ } else {
req->dev = -1;
-
+ wake_up(&wait_for_request);
+ };
} else {
SCpnt->request.dev = 0xffff; /* Busy, but no request */
SCpnt->request.waiting = NULL; /* And no one is waiting for the device either */
@@ -608,7+611,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, int index, int wait) int dev = -1;
struct request * req = NULL;
int tablesize;
- struct buffer_head * bh;
+ struct buffer_head * bh, *bhp;
struct Scsi_Host * host;
Scsi_Cmnd * SCpnt = NULL;
Scsi_Cmnd * SCwait = NULL;
@@ -654,16+657,17 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, int index, int wait) if (req) {
memcpy(&SCpnt->request, req, sizeof(struct request));
tablesize = scsi_devices[index].host->sg_tablesize;
- bh = req->bh;
+ bhp = bh = req->bh;
if(!tablesize) bh = NULL;
/* Take a quick look through the table to see how big it is. We already
have our copy of req, so we can mess with that if we want to. */
while(req->nr_sectors && bh){
- tablesize--;
+ bhp = bhp->b_reqnext;
+ if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--;
req->nr_sectors -= bh->b_size >> 9;
req->sector += bh->b_size >> 9;
if(!tablesize) break;
- bh = bh->b_reqnext;
+ bh = bhp;
};
if(req->nr_sectors && bh && bh->b_reqnext){ /* Any leftovers? */
SCpnt->request.bhtail = bh;
@@ -680,6+684,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, int index, int wait) {
req->dev = -1;
*reqp = req->next;
+ wake_up(&wait_for_request);
};
} else {
SCpnt->request.dev = 0xffff; /* Busy */
@@ -1503,8+1508,8 @@ void *scsi_malloc(unsigned int len) {
unsigned int nbits, mask;
int i, j;
- if((len & 0x1ff) || len > 4096)
- panic("Inappropriate buffer size requested");
+ if((len & 0x1ff) || len > 8192)
+ return NULL;
cli();
nbits = len >> 9;
@@ -1593,6+1598,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
for (i=0; i< NR_SCSI_DEVICES; i++) {
int j;
+ scsi_devices[i].scsi_request_fn = NULL;
switch (scsi_devices[i].type)
{
case TYPE_TAPE :
@@ -262,6+262,7 @@ typedef struct scsi_device { int access_count; /* Count of open channels/mounts */
struct wait_queue * device_wait; /* Used to wait if device is busy */
struct Scsi_Host * host;
+ void (*scsi_request_fn)(void); /* Used to jumpstart things after an ioctl */
char type;
char scsi_level;
unsigned writeable:1;
@@ -307,10+308,12 @@ struct scatterlist { char * address; /* Location data is to be transferred to */
char * alt_address; /* Location of actual if address is a
dma indirect buffer. NULL otherwise */
- unsigned short length;
+ unsigned int length;
};
#define ISA_DMA_THRESHOLD (0x00ffffff)
+#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data)
+
void * scsi_malloc(unsigned int);
int scsi_free(void *, unsigned int);
@@ -389,7+392,6 @@ typedef struct scsi_cmnd { /* Low-level done function - can be used by low-level driver to point
to completion function. Not used by mid/upper level code. */
void (*scsi_done)(struct scsi_cmnd *);
-
void (*done)(struct scsi_cmnd *); /* Mid-level done function */
/* The following fields can be written to by the host specific code.
@@ -426,7+428,6 @@ extern void scsi_do_cmd (Scsi_Cmnd *, const void *cmnd , extern Scsi_Cmnd * allocate_device(struct request **, int, int);
extern Scsi_Cmnd * request_queueable(struct request *, int);
-
extern int scsi_reset (Scsi_Cmnd *);
extern int max_scsi_hosts;
#include <asm/system.h>
#include <asm/io.h>
-
#include "../block/blk.h"
#include "scsi.h"
#include "hosts.h"
+/* A few options that we want selected */
+
+/* Do not attempt to use a timer to simulate a real disk with latency */
+/* Only use this in the actual kernel, not in the simulator. */
+#define IMMEDIATE
+
+/* Skip some consistency checking. Good for benchmarking */
+#define SPEEDY
+
/* Number of real scsi disks that will be detected ahead of time */
static int NR_REAL=-1;
-#define MAJOR_NR SCSI_DISK_MAJOR
+#define NR_BLK_DEV 12
+#ifndef MAJOR_NR
+#define MAJOR_NR 8
+#endif
#define START_PARTITION 4
#define SCSI_DEBUG_TIMER 20
/* Number of jiffies to wait before completing a command */
@@ -43,6+54,11 @@ static int npart = 0; #define DEB(x)
#endif
+#ifdef SPEEDY
+#define VERIFY1_DEBUG(RW) 1
+#define VERIFY_DEBUG(RW) 1
+#else
+
#define VERIFY1_DEBUG(RW) \
if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
start = 0; \
@@ -79,6+95,7 @@ static int npart = 0; panic ("Wrong bh block#");}; \
if (SCpnt->request.bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
};
+#endif
static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
static int scsi_debug_host = 0;
@@ -154,7+171,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
buff = (unsigned char *) SCpnt->request_buffer;
- if(target>=2 || SCpnt->lun != 0) {
+ if(target>=1 || SCpnt->lun != 0) {
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
@@ -187,6+204,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) buff[0] = TYPE_DISK;
buff[1] = 0x80; /* Removable disk */
buff[2] = 1;
+ buff[4] = 33 - 5;
memcpy(&buff[8],"Foo Inc",7);
memcpy(&buff[16],"XYZZY",5);
memcpy(&buff[32],"1",1);
@@ -219,7+237,21 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) else
block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
VERIFY_DEBUG(READ);
+#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
+ {
+ int delay = SCSI_SETUP_LATENCY;
+ double usec;
+
+ usec = 0.0;
+ usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
+ delay += usec;
+ if(delay) usleep(delay);
+ };
+#endif
+
+#ifdef DEBUG
printk("(r%d)",SCpnt->request.nr_sectors);
+#endif
nbytes = bufflen;
if(SCpnt->use_sg){
sgcount = 0;
@@ -231,7+263,10 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) scsi_debug_errsts = 0;
do{
VERIFY1_DEBUG(READ);
+/* For the speedy test, we do not even want to fill the buffer with anything */
+#ifndef SPEEDY
memset(buff, 0, bufflen);
+#endif
/* If this is block 0, then we want to read the partition table for this
device. Let's make one up */
if(block == 0 && target == 0) {
@@ -252,6+287,8 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
SCpnt->request.current_nr_sectors);
#endif
+
+#if 0
/* Simulate a disk change */
if(block == 0xfff0) {
sense_buffer[0] = 0x70;
@@ -270,14+307,19 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
break;
} /* End phony disk change code */
- memset(buff, 0, bufflen);
+#endif
+
+#ifndef SPEEDY
memcpy(buff, &target, sizeof(target));
memcpy(buff+sizeof(target), cmd, 24);
memcpy(buff+60, &block, sizeof(block));
memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
+#endif
nbytes -= bufflen;
if(SCpnt->use_sg){
+#ifndef SPEEDY
memcpy(buff+128, bh, sizeof(struct buffer_head));
+#endif
block += bufflen >> 9;
bh = bh->b_reqnext;
sgcount++;
@@ -288,6+330,11 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) };
}
} while(nbytes);
+
+ SCpnt->result = 0;
+ (done)(SCpnt);
+ return;
+
if (SCpnt->use_sg && !scsi_debug_errsts)
if(bh) scsi_dump(SCpnt, 0);
break;
@@ -301,7+348,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) else
block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
VERIFY_DEBUG(WRITE);
- printk("(w%d)",SCpnt->request.nr_sectors);
+/* printk("(w%d)",SCpnt->request.nr_sectors); */
if (SCpnt->use_sg){
if ((bufflen >> 9) != SCpnt->request.nr_sectors)
panic ("Trying to write wrong number of blocks\n");
@@ -344,6+391,10 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) else
printk("scsi_debug_queuecommand: done cant be NULL\n");
+#ifdef IMMEDIATE
+ SCpnt->result = scsi_debug_errsts;
+ scsi_debug_intr_handle(); /* No timer - do this one right away */
+#else
timeout[i] = jiffies+DISK_SPEED;
/* If no timers active, then set this one */
@@ -358,6+409,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) #if 0
printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
#endif
+#endif
return 0;
}
@@ -390,18+442,25 @@ static void scsi_debug_intr_handle(void) void (*my_done)(Scsi_Cmnd *);
int to;
+#ifndef IMMEDIATE
timer_table[SCSI_DEBUG_TIMER].expires = 0;
timer_active &= ~(1 << SCSI_DEBUG_TIMER);
+#endif
repeat:
cli();
for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
if (SCint[i] == 0) continue;
+#ifndef IMMEDIATE
if (timeout[i] == 0) continue;
if (timeout[i] <= jiffies) break;
+#else
+ break;
+#endif
};
if(i == SCSI_DEBUG_MAILBOXES){
+#ifndef IMMEDIATE
pending = INT_MAX;
for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
if (SCint[i] == 0) continue;
@@ -418,6+477,7 @@ static void scsi_debug_intr_handle(void) timer_active |= 1 << SCSI_DEBUG_TIMER;
};
sti();
+#endif
return;
};
@@ -454,8+514,10 @@ static void scsi_debug_intr_handle(void) int scsi_debug_detect(int hostnum)
{
scsi_debug_host = hostnum;
+#ifndef IMMEDIATE
timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
timer_table[SCSI_DEBUG_TIMER].expires = 0;
+#endif
return 1;
}
@@ -479,7+541,7 @@ int scsi_debug_abort(Scsi_Cmnd * SCpnt,int i) return 0;
}
-int scsi_debug_biosparam(int size, int* info){
+int scsi_debug_biosparam(int size, int dev, int* info){
info[0] = 32;
info[1] = 64;
info[2] = (size + 2047) >> 11;
@@ -506,7+568,7 @@ int scsi_debug_reset(Scsi_Cmnd * SCpnt) return 0;
}
-char *scsi_debug_info(void)
+const char *scsi_debug_info(void)
{
static char buffer[] = " "; /* looks nicer without anything here */
return buffer;
@@ -6,8+6,8 @@ int scsi_debug_detect(int); int scsi_debug_command(Scsi_Cmnd *);
int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int scsi_debug_abort(Scsi_Cmnd *, int);
-int scsi_debug_biosparam(int, int*);
-char *scsi_debug_info(void);
+int scsi_debug_biosparam(int, int, int[]);
+const char *scsi_debug_info(void);
int scsi_debug_reset(Scsi_Cmnd *);
#ifndef NULL
@@ -134,7+134,7 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd) };
result = SCpnt->result;
- SCpnt->request.dev = -1; /* Mark as not busy */
+ SCpnt->request.dev = -1;
wake_up(&scsi_devices[SCpnt->index].device_wait);
return result;
}
@@ -203,6+203,10 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) result = SCpnt->result;
SCpnt->request.dev = -1; /* Mark as not busy */
if (buf) scsi_free(buf, needed);
+
+ if(scsi_devices[SCpnt->index].scsi_request_fn)
+ (*scsi_devices[SCpnt->index].scsi_request_fn)();
+
wake_up(&scsi_devices[SCpnt->index].device_wait);
return result;
#else
@@ -223,8+227,6 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) #endif
}
-
-
/*
the scsi_ioctl() function differs from most ioctls in that it does
not take a major/minor number as the dev filed. Rather, it takes
@@ -302,4+304,3 @@ int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { set_fs(oldfs);
return tmp;
}
-
#define SCSI_IOCTL_PROBE_HOST 0
#define SCSI_IOCTL_SEND_COMMAND 1
#define SCSI_IOCTL_TEST_UNIT_READY 2
+#define SCSI_IOCTL_BENCHMARK_COMMAND 3
/* The door lock/unlock constants are compatible with Sun constants for
the cdrom */
#define SCSI_IOCTL_DOORLOCK 0x5380 /* lock the eject mechanism */
@@ -34,10+34,14 @@ static const char RCSid[] = "$Header:"; #define MAX_RETRIES 5
/*
- * Time out in seconds
+ * Time out in seconds for disks and Magneto-opticals (which are slower).
*/
#define SD_TIMEOUT 300
+#define SD_MOD_TIMEOUT 750
+
+#define CLUSTERABLE_DEVICE(SC) (SC->host->sg_tablesize < 64 && \
+ scsi_devices[SC->index].type != TYPE_MOD)
struct hd_struct * sd;
@@ -369,9+373,7 @@ static void do_sd_request (void) };
if (!SCpnt) return; /* Could not find anything to do */
-
- wake_up(&wait_for_request);
-
+
/* Queue command */
requeue_sd_request(SCpnt);
}; /* While */
@@ -381,7+383,10 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt) {
int dev, block, this_count;
unsigned char cmd[10];
- char * buff;
+ int bounce_size, contiguous;
+ int max_sg;
+ struct buffer_head * bh, *bhp;
+ char * buff, *bounce_buffer;
repeat:
@@ -440,8+445,35 @@ repeat:
SCpnt->this_count = 0;
- if (!SCpnt->request.bh ||
- (SCpnt->request.nr_sectors == SCpnt->request.current_nr_sectors)) {
+ /* If the host adapter can deal with very large scatter-gather
+ requests, it is a waste of time to cluster */
+ contiguous = (!CLUSTERABLE_DEVICE(SCpnt) ? 0 :1);
+ bounce_buffer = NULL;
+ bounce_size = (SCpnt->request.nr_sectors << 9);
+
+ /* First see if we need a bounce buffer for this request. If we do, make sure
+ that we can allocate a buffer. Do not waste space by allocating a bounce
+ buffer if we are straddling the 16Mb line */
+
+
+ if (contiguous && SCpnt->request.bh &&
+ ((int) SCpnt->request.bh->b_data) + (SCpnt->request.nr_sectors << 9) - 1 >
+ ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) {
+ if(((int) SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD)
+ bounce_buffer = scsi_malloc(bounce_size);
+ if(!bounce_buffer) contiguous = 0;
+ };
+
+ if(contiguous && SCpnt->request.bh && SCpnt->request.bh->b_reqnext)
+ for(bh = SCpnt->request.bh, bhp = bh->b_reqnext; bhp; bh = bhp,
+ bhp = bhp->b_reqnext) {
+ if(!CONTIGUOUS_BUFFERS(bh,bhp)) {
+ if(bounce_buffer) scsi_free(bounce_buffer, bounce_size);
+ contiguous = 0;
+ break;
+ }
+ };
+ if (!SCpnt->request.bh || contiguous) {
/* case of page request (i.e. raw device), or unlinked buffer */
this_count = SCpnt->request.nr_sectors;
@@ -450,7+482,7 @@ repeat:
} else if (SCpnt->host->sg_tablesize == 0 ||
(need_isa_buffer &&
- dma_free_sectors < 10)) {
+ dma_free_sectors <= 10)) {
/* Case of host adapter that cannot scatter-gather. We also
come here if we are running low on DMA buffer memory. We set
@@ -461,7+493,7 @@ repeat:
if (SCpnt->host->sg_tablesize != 0 &&
need_isa_buffer &&
- dma_free_sectors < 10)
+ dma_free_sectors <= 10)
printk("Warning: SCSI DMA buffer space running low. Using non scatter-gather I/O.\n");
this_count = SCpnt->request.current_nr_sectors;
@@ -471,25+503,41 @@ repeat: } else {
/* Scatter-gather capable host adapter */
- struct buffer_head * bh;
struct scatterlist * sgpnt;
int count, this_count_max;
+ int counted;
+
bh = SCpnt->request.bh;
this_count = 0;
this_count_max = (rscsi_disks[dev].ten ? 0xffff : 0xff);
count = 0;
- while(bh && count < SCpnt->host->sg_tablesize) {
+ bhp = NULL;
+ while(bh) {
if ((this_count + (bh->b_size >> 9)) > this_count_max) break;
+ if(!bhp || !CONTIGUOUS_BUFFERS(bhp,bh) ||
+ !CLUSTERABLE_DEVICE(SCpnt) ||
+ (SCpnt->host->unchecked_isa_dma &&
+ ((unsigned int) bh->b_data-1) == ISA_DMA_THRESHOLD)) {
+ if (count < SCpnt->host->sg_tablesize) count++;
+ else break;
+ };
this_count += (bh->b_size >> 9);
- count++;
+ bhp = bh;
bh = bh->b_reqnext;
};
+#if 0
+ if(SCpnt->host->unchecked_isa_dma &&
+ ((unsigned int) SCpnt->request.bh->b_data-1) == ISA_DMA_THRESHOLD) count--;
+#endif
SCpnt->use_sg = count; /* Number of chains */
count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/
while( count < (SCpnt->use_sg * sizeof(struct scatterlist)))
count = count << 1;
SCpnt->sglist_len = count;
+ max_sg = count / sizeof(struct scatterlist);
+ if(SCpnt->host->sg_tablesize < max_sg) max_sg = SCpnt->host->sg_tablesize;
sgpnt = (struct scatterlist * ) scsi_malloc(count);
+ memset(sgpnt, 0, count); /* Zero so it is easy to fill */
if (!sgpnt) {
printk("Warning - running *really* short on DMA buffers\n");
SCpnt->use_sg = 0; /* No memory left - bail out */
@@ -497,20+545,25 @@ repeat: buff = SCpnt->request.buffer;
} else {
buff = (char *) sgpnt;
- count = 0;
- bh = SCpnt->request.bh;
- for(count = 0, bh = SCpnt->request.bh; count < SCpnt->use_sg;
- count++, bh = bh->b_reqnext) {
- sgpnt[count].address = bh->b_data;
- sgpnt[count].alt_address = NULL;
- sgpnt[count].length = bh->b_size;
- if (((int) sgpnt[count].address) + sgpnt[count].length >
- ISA_DMA_THRESHOLD & (SCpnt->host->unchecked_isa_dma)) {
+ counted = 0;
+ for(count = 0, bh = SCpnt->request.bh, bhp = bh->b_reqnext;
+ count < SCpnt->use_sg && bh;
+ count++, bh = bhp) {
+
+ bhp = bh->b_reqnext;
+
+ if(!sgpnt[count].address) sgpnt[count].address = bh->b_data;
+ sgpnt[count].length += bh->b_size;
+ counted += bh->b_size >> 9;
+
+ if (((int) sgpnt[count].address) + sgpnt[count].length - 1 >
+ ISA_DMA_THRESHOLD && (SCpnt->host->unchecked_isa_dma) &&
+ !sgpnt[count].alt_address) {
sgpnt[count].alt_address = sgpnt[count].address;
/* We try and avoid exhausting the DMA pool, since it is easier
to control usage here. In other places we might have a more
pressing need, and we would be screwed if we ran out */
- if(dma_free_sectors < (bh->b_size >> 9) + 5) {
+ if(dma_free_sectors < (sgpnt[count].length >> 9) + 10) {
sgpnt[count].address = NULL;
} else {
sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length);
@@ -520,6+573,7 @@ repeat: 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 */
+#if 0
printk("Warning: Running low on SCSI DMA buffers");
/* Try switching back to a non scatter-gather operation. */
while(--count >= 0){
@@ -529,30+583,93 @@ repeat: this_count = SCpnt->request.current_nr_sectors;
buff = SCpnt->request.buffer;
SCpnt->use_sg = 0;
- scsi_free(buff, SCpnt->sglist_len);
+ scsi_free(sgpnt, SCpnt->sglist_len);
+#endif
+ SCpnt->use_sg = count;
+ this_count = counted -= bh->b_size >> 9;
break;
};
- if (SCpnt->request.cmd == WRITE)
- memcpy(sgpnt[count].address, sgpnt[count].alt_address,
- sgpnt[count].length);
};
+
+ /* Only cluster buffers if we know that we can supply DMA buffers
+ large enough to satisfy the request. Do not cluster a new
+ request if this would mean that we suddenly need to start
+ using DMA bounce buffers */
+ if(bhp && CONTIGUOUS_BUFFERS(bh,bhp) && CLUSTERABLE_DEVICE(SCpnt)) {
+ char * tmp;
+
+ if (((int) sgpnt[count].address) + sgpnt[count].length +
+ bhp->b_size - 1 > ISA_DMA_THRESHOLD &&
+ (SCpnt->host->unchecked_isa_dma) &&
+ !sgpnt[count].alt_address) continue;
+
+ if(!sgpnt[count].alt_address) {count--; continue; }
+ if(dma_free_sectors > 10)
+ tmp = scsi_malloc(sgpnt[count].length + bhp->b_size);
+ else {
+ tmp = NULL;
+ max_sg = SCpnt->use_sg;
+ };
+ if(tmp){
+ scsi_free(sgpnt[count].address, sgpnt[count].length);
+ sgpnt[count].address = tmp;
+ count--;
+ continue;
+ };
+
+ /* If we are allowed another sg chain, then increment counter so we
+ can insert it. Otherwise we will end up truncating */
+
+ if (SCpnt->use_sg < max_sg) SCpnt->use_sg++;
+ }; /* contiguous buffers */
}; /* for loop */
+
+ this_count = counted; /* This is actually how many we are going to transfer */
+
+ if(count < SCpnt->use_sg || SCpnt->use_sg > SCpnt->host->sg_tablesize){
+ bh = SCpnt->request.bh;
+ printk("Use sg, count %d %x %d\n", SCpnt->use_sg, count, dma_free_sectors);
+ printk("maxsg = %x, counted = %d this_count = %d\n", max_sg, counted, this_count);
+ while(bh){
+ printk("[%8.8x %x] ", bh->b_data, bh->b_size);
+ bh = bh->b_reqnext;
+ };
+ if(SCpnt->use_sg < 16)
+ for(count=0; count<SCpnt->use_sg; count++)
+ printk("{%d:%8.8x %8.8x %d} ", count,
+ sgpnt[count].address,
+ sgpnt[count].alt_address,
+ sgpnt[count].length);
+ panic("Ooops");
+ };
+
+ if (SCpnt->request.cmd == WRITE)
+ for(count=0; count<SCpnt->use_sg; count++)
+ if(sgpnt[count].alt_address)
+ memcpy(sgpnt[count].address, sgpnt[count].alt_address,
+ sgpnt[count].length);
}; /* Able to malloc sgpnt */
}; /* Host adapter capable of scatter-gather */
/* Now handle the possibility of DMA to addresses > 16Mb */
if(SCpnt->use_sg == 0){
- if (((int) buff) + (this_count << 9) > ISA_DMA_THRESHOLD &&
+ if (((int) buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD &&
(SCpnt->host->unchecked_isa_dma)) {
- buff = (char *) scsi_malloc(this_count << 9);
- if(buff == NULL) panic("Ran out of DMA buffers.");
+ if(bounce_buffer)
+ buff = bounce_buffer;
+ else
+ buff = (char *) scsi_malloc(this_count << 9);
+ if(buff == NULL) { /* Try backing off a bit if we are low on mem*/
+ this_count = SCpnt->request.current_nr_sectors;
+ buff = (char *) scsi_malloc(this_count << 9);
+ if(!buff) panic("Ran out of DMA buffers.");
+ };
if (SCpnt->request.cmd == WRITE)
memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9);
};
};
-
#ifdef DEBUG
printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(SCpnt->request.dev),
(SCpnt->request.cmd == WRITE) ? "writing" : "reading",
@@ -607,10+724,12 @@ repeat:
SCpnt->transfersize = rscsi_disks[dev].sector_size;
SCpnt->underflow = this_count << 9;
-
scsi_do_cmd (SCpnt, (void *) cmd, buff,
this_count * rscsi_disks[dev].sector_size,
- rw_intr, SD_TIMEOUT, MAX_RETRIES);
+ rw_intr,
+ (scsi_devices[SCpnt->index].type == TYPE_DISK ?
+ SD_TIMEOUT : SD_MOD_TIMEOUT),
+ MAX_RETRIES);
}
int check_scsidisk_media_change(int full_dev, int flag){
@@ -857,6+976,7 @@ static int sd_init_onedisk(int i) their size, and reads partition table entries for them.
*/
+
unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
@@ -893,7+1013,7 @@ unsigned long sd_init(unsigned long memory_start, unsigned long memory_end) the read-ahead to 16 blocks (32 sectors). If not, we use
a two block (4 sector) read ahead. */
if(rscsi_disks[0].device->host->sg_tablesize)
- read_ahead[MAJOR_NR] = 32;
+ read_ahead[MAJOR_NR] = 120;
/* 64 sector read-ahead */
else
read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
@@ -910,6+1030,7 @@ unsigned long sd_init1(unsigned long mem_start, unsigned long mem_end){ };
void sd_attach(Scsi_Device * SDp){
+ SDp->scsi_request_fn = do_sd_request;
rscsi_disks[NR_SD++].device = SDp;
if(NR_SD > MAX_SD) panic ("scsi_devices corrupt (sd)");
};
@@ -968,3+1089,4 @@ int revalidate_scsidisk(int dev, int maxusage){ DEVICE_BUSY = 0;
return 0;
}
+
@@ -53,6+53,12 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne put_fs_long(sd[MINOR(inode->i_rdev)].nr_sects,
(long *) arg);
return 0;
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(!inode->i_rdev) return -EINVAL;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
case BLKFLSBUF:
if(!suser()) return -EACCES;
if(!inode->i_rdev) return -EINVAL;
@@ -624,6+624,7 @@ unsigned long sr_init1(unsigned long mem_start, unsigned long mem_end){ };
void sr_attach(Scsi_Device * SDp){
+ SDp->scsi_request_fn = do_sr_request;
scsi_CDs[NR_SR++].device = SDp;
if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");
};
@@ -385,6+385,12 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne case CDROMREADMODE1:
return -EINVAL;
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(!inode->i_rdev) return -EINVAL;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
RO_IOCTLS(dev,arg);
default:
return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/ctype.h>
+#include <linux/string.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -54,7+54,8 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) if (chars == blocksize)
bh = getblk(dev, block, blocksize);
else
- bh = breada(dev,block,block+1,block+2,-1);
+ bh = breada(dev, block, blocksize, offset,
+ size << blocksize_bits);
block++;
if (!bh)
return written?written:-EIO;
@@ -67,7+68,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) p += chars;
buf += chars;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
return written;
@@ -46,6+46,10 @@ extern int check_cdu31a_media_change(int, int); extern int check_mcd_media_change(int, int);
#endif
+static char buffersize_index[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3};
+
+#define BUFSIZE_INDEX(X) (buffersize_index[(X)>>9])
+
static int grow_buffers(int pri, int size);
static struct buffer_head * hash_table[NR_HASH];
@@ -556,42+560,62 @@ struct buffer_head * bread(dev_t dev, int block, int size)
/*
* Ok, breada can be used as bread, but additionally to mark other
- * blocks for reading as well. End the argument list with a negative
- * number.
+ * blocks for reading as well.
*/
-struct buffer_head * breada(dev_t dev,int first, ...)
-{
- va_list args;
- unsigned int blocksize;
- struct buffer_head * bh, *tmp;
- va_start(args,first);
+#define NBUF 16
- blocksize = BLOCK_SIZE;
- if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
- blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
+struct buffer_head * breada(dev_t dev, int block, int bufsize,
+ unsigned int pos, unsigned int filesize)
+{
+ struct buffer_head * bhlist[NBUF];
+ unsigned int blocks;
+ struct buffer_head * bh;
+ int index;
+ int i, j;
- if (!(bh = getblk(dev, first, blocksize))) {
- printk("VFS: breada: READ error on device %d/%d\n",
- MAJOR(dev), MINOR(dev));
+ if (pos >= filesize)
return NULL;
- }
- if (!bh->b_uptodate)
- ll_rw_block(READ, 1, &bh);
- while ((first=va_arg(args,int))>=0) {
- tmp = getblk(dev, first, blocksize);
- if (tmp) {
- if (!tmp->b_uptodate)
- ll_rw_block(READA, 1, &tmp);
- tmp->b_count--;
+
+ if (block < 0 || !(bh = getblk(dev,block,bufsize)))
+ return NULL;
+
+ index = BUFSIZE_INDEX(bh->b_size);
+
+ if (bh->b_uptodate)
+ return bh;
+
+ blocks = ((filesize & (bufsize - 1)) - (pos & (bufsize - 1))) >> (9+index);
+
+ if (blocks > (read_ahead[MAJOR(dev)] >> index))
+ blocks = read_ahead[MAJOR(dev)] >> index;
+ if (blocks > NBUF)
+ blocks = NBUF;
+
+ bhlist[0] = bh;
+ j = 1;
+ for(i=1; i<blocks; i++) {
+ bh = getblk(dev,block+i,bufsize);
+ if (bh->b_uptodate) {
+ brelse(bh);
+ break;
}
+ bhlist[j++] = bh;
}
- va_end(args);
+
+ /* Request the read for these buffers, and then release them */
+ ll_rw_block(READ, j, bhlist);
+
+ for(i=1; i<j; i++)
+ brelse(bhlist[i]);
+
+ /* Wait for this buffer, and then continue on */
+ bh = bhlist[0];
wait_on_buffer(bh);
if (bh->b_uptodate)
return bh;
brelse(bh);
- return (NULL);
+ return NULL;
}
/*
@@ -616,7+640,7 @@ static void get_more_buffer_heads(void) if (unused_list)
return;
- if(! (bh = (struct buffer_head*) get_free_page(GFP_BUFFER)))
+ if (!(bh = (struct buffer_head*) get_free_page(GFP_BUFFER)))
return;
for (nr_buffer_heads+=i=PAGE_SIZE/sizeof*bh ; i>0; i--) {
@@ -870,7+894,7 @@ static int grow_buffers(int pri, int size) printk("VFS: grow_buffers: size = %d\n",size);
return 0;
}
- if(!(page = __get_free_page(pri)))
+ if (!(page = __get_free_page(pri)))
return 0;
bh = create_buffers(page, size);
if (!bh) {
@@ -104,7+104,8 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
bhb = bhe = buflist;
if (filp->f_reada) {
- blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
+ blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
if (block + blocks > size)
blocks = size - block;
}
@@ -247,7+248,7 @@ static int ext_file_write(struct inode * inode, struct file * filp, char * buf, memcpy_fromfs(p,buf,c);
buf += c;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -83,7+83,7 @@ printk("ext_free_block: block full, skipping to %d\n", block); }
sb->u.ext_sb.s_freeblockscount ++;
sb->s_dirt = 1;
- sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
+ dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
unlock_super (sb);
return;
}
@@ -104,7+104,7 @@ int ext_new_block(struct super_block * sb) efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
if (efb->count) {
j = efb->free[--efb->count];
- sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
+ dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
} else {
#ifdef EXTFS_DEBUG
printk("ext_new_block: block empty, skipping to %d\n", efb->next);
@@ -135,7+135,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next); }
clear_block(bh->b_data);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
#ifdef EXTFS_DEBUG
printk("ext_new_block: allocating block %d\n", j);
@@ -239,7+239,7 @@ printk("ext_free_inode: inode full, skipping to %d\n", ino); }
sb->u.ext_sb.s_freeinodescount ++;
sb->s_dirt = 1;
- sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
+ dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
unlock_super (sb);
}
@@ -263,7+263,7 @@ struct inode * ext_new_inode(const struct inode * dir) (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
if (efi->count) {
j = efi->free[--efi->count];
- sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
+ dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
} else {
#ifdef EXTFS_DEBUG
printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
@@ -139,7+139,7 @@ void ext_write_super (struct super_block *sb) es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse (bh);
sb->s_dirt = 0;
}
@@ -296,7+296,7 @@ repeat: goto repeat;
}
*p = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
@@ -407,7+407,7 @@ static struct buffer_head * ext_update_inode(struct inode * inode) raw_inode->i_zone[0] = inode->i_rdev;
else for (block = 0; block < 12; block++)
raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
inode->i_dirt=0;
return bh;
}
@@ -249,7+249,7 @@ printk ("ext_add_entry: skipping to next block\n"); #if 0
dir->i_ctime = CURRENT_TIME;
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
}
brelse (bh);
bh = NULL;
@@ -296,7+296,7 @@ printk ("ext_add_entry : creating next block\n"); de->name_len = namelen;
for (i=0; i < namelen ; i++)
de->name[i] = name[i];
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
*res_dir = de;
return bh;
}
@@ -334,7+334,7 @@ int ext_create(struct inode * dir,const char * name, int len, int mode, return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
@@ -393,7+393,7 @@ int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -445,7+445,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode) de->name_len=2;
strcpy(de->name,"..");
inode->i_nlink = 2;
- dir_block->b_dirt = 1;
+ dirtify_buffer(dir_block, 1);
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
if (dir->i_mode & S_ISGID)
@@ -459,7+459,7 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode) return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
@@ -567,7+567,7 @@ int ext_rmdir(struct inode * dir, const char * name, int len) de->inode = 0;
de->name_len = 0;
ext_merge_entries (de, pde, nde);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
dir->i_nlink--;
@@ -610,7+610,7 @@ int ext_unlink(struct inode * dir, const char * name, int len) de->inode = 0;
de->name_len = 0;
ext_merge_entries (de, pde, nde);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_nlink--;
inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
@@ -650,7+650,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym while (i < 1023 && (c = *(symname++)))
name_block->b_data[i++] = c;
name_block->b_data[i] = 0;
- name_block->b_dirt = 1;
+ dirtify_buffer(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
@@ -672,7+672,7 @@ int ext_symlink(struct inode * dir, const char * name, int len, const char * sym return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -708,7+708,7 @@ int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int return -ENOSPC;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
@@ -851,11+851,11 @@ start_up: new_inode->i_nlink--;
new_inode->i_dirt = 1;
}
- old_bh->b_dirt = 1;
- new_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
+ dirtify_buffer(new_bh, 1);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
+ dirtify_buffer(dir_bh, 1);
old_dir->i_nlink--;
new_dir->i_nlink++;
old_dir->i_dirt = 1;
@@ -102,7+102,7 @@ repeat: continue;
}
*ind = 0;
- ind_bh->b_dirt = 1;
+ dirtify_buffer(ind_bh, 1);
brelse(bh);
ext_free_block(inode->i_sb,tmp);
}
@@ -154,7+154,7 @@ repeat: if (!tmp)
continue;
retry |= trunc_indirect(inode,offset+(i<<8),dind);
- dind_bh->b_dirt = 1;
+ dirtify_buffer(dind_bh, 1);
}
dind = (unsigned long *) dind_bh->b_data;
for (i = 0; i < 256; i++)
@@ -201,7+201,7 @@ repeat: goto repeat;
tind = i+(unsigned long *) tind_bh->b_data;
retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
- tind_bh->b_dirt = 1;
+ dirtify_buffer(tind_bh, 1);
}
tind = (unsigned long *) tind_bh->b_data;
for (i = 0; i < 256; i++)
@@ -310,10+310,10 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block, }
}
- bh2->b_dirt = 1;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (sb->s_flags & MS_SYNC) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -524,7+524,7 @@ got_block:
j = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (sb->s_flags & MS_SYNC) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -544,16+544,16 @@ got_block: }
clear_block (bh->b_data, sb->s_blocksize);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse (bh);
ext2_debug ("allocating block %d. "
"Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
gdp->bg_free_blocks_count--;
- bh2->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
es->s_free_blocks_count--;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
unlock_super (sb);
return j;
@@ -112,8+112,8 @@ static int ext2_file_read (struct inode * inode, struct file * filp, blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb);
bhb = bhe = buflist;
if (filp->f_reada) {
- blocks += read_ahead[MAJOR(inode->i_dev)] >>
- (EXT2_BLOCK_SIZE_BITS(sb) - 9);
+ if (blocks < read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9))
+ blocks = read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9);
if (block + blocks > size)
blocks = size - block;
}
@@ -277,7+277,7 @@ static int ext2_file_write (struct inode * inode, struct file * filp, memcpy_fromfs (p, buf, c);
buf += c;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse (bh);
}
up(&inode->i_sem);
@@ -202,7+202,7 @@ static void set_inode_dtime (struct inode * inode, EXT2_INODES_PER_BLOCK(inode->i_sb));
raw_inode->i_links_count = 0;
raw_inode->i_dtime = CURRENT_TIME;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(inode)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -266,12+266,12 @@ void ext2_free_inode (struct inode * inode) gdp->bg_free_inodes_count++;
if (S_ISDIR(inode->i_mode))
gdp->bg_used_dirs_count--;
- bh2->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
es->s_free_inodes_count++;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
set_inode_dtime (inode, gdp);
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (sb->s_flags & MS_SYNC) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -313,7+313,7 @@ static void inc_inode_version (struct inode * inode, EXT2_INODES_PER_BLOCK(inode->i_sb));
raw_inode->i_version++;
inode->u.ext2_i.i_version = raw_inode->i_version;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse (bh);
}
@@ -438,7+438,7 @@ repeat: "bit already set for inode %d", j);
goto repeat;
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (sb->s_flags & MS_SYNC) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -466,9+466,9 @@ repeat: gdp->bg_free_inodes_count--;
if (S_ISDIR(mode))
gdp->bg_used_dirs_count++;
- bh2->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
es->s_free_inodes_count--;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
inode->i_mode = mode;
inode->i_sb = sb;
@@ -109,7+109,7 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal) }
clear_block (bh->b_data, inode->i_sb->s_blocksize);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse (bh);
} else {
ext2_discard_prealloc (inode);
@@ -314,7+314,7 @@ repeat: goto repeat;
}
*p = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(inode)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -549,7+549,7 @@ static struct buffer_head * ext2_update_inode (struct inode * inode) raw_inode->i_block[0] = inode->i_rdev;
else for (block = 0; block < EXT2_N_BLOCKS; block++)
raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_dirt = 0;
return bh;
}
@@ -275,9+275,6 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, de->rec_len = sb->s_blocksize;
dir->i_size = offset + sb->s_blocksize;
dir->i_dirt = 1;
-#if 0 /* XXX don't update any times until successful completion of syscall */
- dir->i_ctime = CURRENT_TIME;
-#endif
} else {
ext2_debug ("skipping to next block\n");
@@ -323,7+320,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, */
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_dirt = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
*res_dir = de;
*err = 0;
return bh;
@@ -397,7+394,7 @@ int ext2_create (struct inode * dir,const char * name, int len, int mode, ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
de->inode);
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -449,14+446,6 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode, init_fifo(inode);
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = rdev;
-#if 0
- /*
- * XXX we may as well use the times set by ext2_new_inode(). The
- * following usually does nothing, but sometimes it invalidates
- * inode->i_ctime.
- */
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
inode->i_dirt = 1;
bh = ext2_add_entry (dir, name, len, &de, &err);
if (!bh) {
@@ -471,7+460,7 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode, ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
de->inode);
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -508,9+497,6 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode) }
inode->i_op = &ext2_dir_inode_operations;
inode->i_size = inode->i_sb->s_blocksize;
-#if 0 /* XXX as above */
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
dir_block = ext2_bread (inode, 0, 1, &err);
if (!dir_block) {
iput (dir);
@@ -531,7+517,7 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode) de->name_len = 2;
strcpy (de->name, "..");
inode->i_nlink = 2;
- dir_block->b_dirt = 1;
+ dirtify_buffer(dir_block, 1);
brelse (dir_block);
inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
if (dir->i_mode & S_ISGID)
@@ -550,7+536,7 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode) ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
de->inode);
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -674,7+660,7 @@ repeat: up(&inode->i_sem);
if (retval)
goto end_rmdir;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -742,7+728,7 @@ repeat: retval = ext2_delete_entry (de, bh);
if (retval)
goto end_unlink;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -807,7+793,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len, link[i++] = c;
link[i] = 0;
if (name_block) {
- name_block->b_dirt = 1;
+ dirtify_buffer(name_block, 1);
brelse (name_block);
}
inode->i_size = i;
@@ -834,7+820,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len, ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
de->inode);
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -880,7+866,7 @@ int ext2_link (struct inode * oldinode, struct inode * dir, ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
de->inode);
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -1056,19+1042,19 @@ start_up: }
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
old_dir->i_dirt = 1;
- old_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
if (IS_SYNC(old_dir)) {
ll_rw_block (WRITE, 1, &old_bh);
wait_on_buffer (old_bh);
}
- new_bh->b_dirt = 1;
+ dirtify_buffer(new_bh, 1);
if (IS_SYNC(new_dir)) {
ll_rw_block (WRITE, 1, &new_bh);
wait_on_buffer (new_bh);
}
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
+ dirtify_buffer(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
if (new_inode) {
@@ -36,7+36,7 @@ void ext2_error (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
}
va_start (args, fmt);
@@ -66,7+66,7 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
}
va_start (args, fmt);
@@ -96,7+96,7 @@ void ext2_put_super (struct super_block * sb) lock_super (sb);
if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
}
#ifndef DONT_USE_DCACHE
ext2_dcache_invalidate (sb->s_dev);
@@ -159,10+159,10 @@ static int convert_pre_02b_fs (struct super_block * sb, gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
}
- bh2->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
brelse (bh2);
es->s_magic = EXT2_SUPER_MAGIC;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
sb->s_magic = EXT2_SUPER_MAGIC;
return 1;
}
@@ -287,7+287,7 @@ static void ext2_setup_super (struct super_block * sb, es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
es->s_mnt_count++;
es->s_mtime = CURRENT_TIME;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
if (test_opt (sb, DEBUG))
printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
@@ -570,7+570,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, #ifdef EXT2FS_PRE_02B_COMPAT
if (fs_converted) {
for (i = 0; i < bh_count; i++)
- sb->u.ext2_sb.s_group_desc[i]->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_group_desc[i], 1);
sb->s_dirt = 1;
}
#endif
@@ -582,7+582,7 @@ static void ext2_commit_super (struct super_block * sb, struct ext2_super_block * es)
{
es->s_wtime = CURRENT_TIME;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 0;
}
@@ -639,7+639,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data) */
es->s_state = sb->u.ext2_sb.s_mount_state;
es->s_mtime = CURRENT_TIME;
- sb->u.ext2_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
ext2_commit_super (sb, es);
}
if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
clear_block (bh->b_data, inode->i_sb->s_blocksize,
RANDOM_INT);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
}
brelse (bh);
if (free_count == 0) {
@@ -162,11+162,11 @@ repeat: continue;
}
*ind = 0;
- ind_bh->b_dirt = 1;
+ dirtify_buffer(ind_bh, 1);
if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
clear_block (bh->b_data, inode->i_sb->s_blocksize,
RANDOM_INT);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
}
brelse (bh);
if (free_count == 0) {
@@ -243,7+243,7 @@ repeat: continue;
retry |= trunc_indirect (inode, offset + (i * addr_per_block),
dind);
- dind_bh->b_dirt = 1;
+ dirtify_buffer(dind_bh, 1);
}
dind = (unsigned long *) dind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
@@ -302,7+302,7 @@ repeat: retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
addr_per_block + (i + 1) * addr_per_block * addr_per_block,
tind);
- tind_bh->b_dirt = 1;
+ dirtify_buffer(tind_bh, 1);
}
tind = (unsigned long *) tind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
#include <linux/hpfs_fs.h>
#include <linux/errno.h>
#include <linux/malloc.h>
+#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/locks.h>
#include <linux/stat.h>
@@ -1676,8+1677,7 @@ static void *map_4sectors(dev_t dev, unsigned secno, if (!data)
goto bail;
- qbh->bh[0] = bh = breada(dev,
- secno, secno + 1, secno + 2, secno + 3, -1);
+ qbh->bh[0] = bh = breada(dev, secno, 512, 0, UINT_MAX);
if (!bh)
goto bail0;
memcpy(data, bh->b_data, 512);
/*
* linux/fs/isofs/dir.c
*
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/locks.h>
static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
@@ -81,9+83,12 @@ static int isofs_readdir(struct inode * inode, struct file * filp,
offset = filp->f_pos & (bufsize - 1);
block = isofs_bmap(inode,filp->f_pos>>bufbits);
- if (!block || !(bh = bread(inode->i_dev,block,bufsize)))
- return 0;
-
+
+ if(!block) return 0;
+
+ if(!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
+ return 0;
+
while (filp->f_pos < inode->i_size) {
#ifdef DEBUG
printk("Block, offset: %x %x %x\n",
@@ -103,7+108,8 @@ static int isofs_readdir(struct inode * inode, struct file * filp, + ISOFS_BLOCK_SIZE);
block = isofs_bmap(inode,(filp->f_pos)>>bufbits);
if (!block
- || !(bh = bread(inode->i_dev,block,bufsize)))
+ || !(bh = breada(inode->i_dev, block, bufsize, filp->f_pos,
+ inode->i_size)))
return 0;
continue;
}
@@ -126,7+132,8 @@ static int isofs_readdir(struct inode * inode, struct file * filp, offset = filp->f_pos & (bufsize - 1);
block = isofs_bmap(inode,(filp->f_pos)>> bufbits);
if (!block
- || !(bh = bread(inode->i_dev,block,bufsize))) {
+ || !(bh = breada(inode->i_dev, block, bufsize,
+ filp->f_pos, inode->i_size))) {
kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
return 0;
};
/*
* linux/fs/isofs/file.c
*
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*
@@ -146,6+146,8 @@ static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, bhb = bhe = buflist;
ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ if(ra_blocks > blocks) blocks = ra_blocks;
+
max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
nextblock = -1;
@@ -169,7+171,6 @@ static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
- nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
@@ -177,37+178,12 @@ static int isofs_file_read(struct inode * inode, struct file * filp, char * buf,
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
- if(bhrequest == 0 && uptodate) break;
+ if(uptodate) break;
if (bhb == bhe)
break;
}
- if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) {
- /* If we are going to read something anyways, add in the
- read-ahead blocks */
- while(ra_blocks){
- if (block >= max_block) break;
- if(bhrequest == NBUF) break; /* Block full */
- --ra_blocks;
- *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
-
- if (*bhb && !(*bhb)->b_uptodate) {
- if((*bhb)->b_blocknr != nextblock) {
- brelse(*bhb);
- break;
- };
- nextblock = (*bhb)->b_blocknr + 1;
- bhreq[bhrequest++] = *bhb;
- };
-
- if (++bhb == &buflist[NBUF])
- bhb = buflist;
-
- if (bhb == bhe)
- break;
- };
- };
/* Now request them all */
if (bhrequest)
ll_rw_block(READ, bhrequest, bhreq);
/*
* linux/fs/isofs/inode.c
*
- * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
+ * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*/
@@ -354,7+354,7 @@ void isofs_read_inode(struct inode * inode) if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
if (cpnt == NULL) {
- printk(KERN_INFO "NoMem ISO inode %d\n",inode->i_ino);
+ printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
brelse(bh);
goto fail;
}
@@ -600,7+600,8 @@ int isofs_lookup_grandparent(struct inode * parent, int extent) brelse(bh);
offset = 0;
block++;
- if(block & 1) return -1;
+ if((block & 1) && (ISOFS_BLOCK_BITS - bufbits))
+ return -1;
if (!block
|| !(bh = bread(parent->i_dev,block, bufsize)))
return -1;
/*
* linux/fs/isofs/rock.c
*
- * (C) 1992 Eric Youngdale
+ * (C) 1992, 1993 Eric Youngdale
*
* Rock Ridge Extensions to iso9660
*/
@@ -93,7+93,7 @@ void minix_free_block(struct super_block * sb, int block) }
if (!clear_bit(bit,bh->b_data))
printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
return;
}
@@ -118,7+118,7 @@ repeat: printk("new_block: bit already set");
goto repeat;
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
if (j < sb->u.minix_sb.s_firstdatazone ||
j >= sb->u.minix_sb.s_nzones)
@@ -129,7+129,7 @@ repeat: }
clear_block(bh->b_data);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return j;
}
@@ -175,7+175,7 @@ void minix_free_inode(struct inode * inode) clear_inode(inode);
if (!clear_bit(ino & 8191, bh->b_data))
printk("free_inode: bit %lu already cleared.\n",ino);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
}
struct inode * minix_new_inode(const struct inode * dir)
@@ -204,7+204,7 @@ struct inode * minix_new_inode(const struct inode * dir) iput(inode);
return NULL;
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
j += i*8192;
if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) {
iput(inode);
@@ -98,7+98,8 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf, blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
bhb = bhe = buflist;
if (filp->f_reada) {
- blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
+ blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
if (block + blocks > size)
blocks = size - block;
}
@@ -239,7+240,7 @@ static int minix_file_write(struct inode * inode, struct file * filp, char * buf memcpy_fromfs(p,buf,c);
buf += c;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -28,7+28,7 @@ void minix_put_inode(struct inode *inode) static void minix_commit_super (struct super_block * sb,
struct minix_super_block * ms)
{
- sb->u.minix_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
sb->s_dirt = 0;
}
@@ -54,7+54,7 @@ void minix_put_super(struct super_block *sb) lock_super(sb);
if (!(sb->s_flags & MS_RDONLY)) {
sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
- sb->u.minix_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
}
sb->s_dev = 0;
for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
@@ -90,7+90,7 @@ int minix_remount (struct super_block * sb, int * flags, char * data) return 0;
/* Mounting a rw partition read-only. */
ms->s_state = sb->u.minix_sb.s_mount_state;
- sb->u.minix_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
sb->s_dirt = 1;
minix_commit_super (sb, ms);
}
@@ -98,7+98,7 @@ int minix_remount (struct super_block * sb, int * flags, char * data) /* Mount a partition which is read-only, read-write. */
sb->u.minix_sb.s_mount_state = ms->s_state;
ms->s_state &= ~MINIX_VALID_FS;
- sb->u.minix_sb.s_sbh->b_dirt = 1;
+ dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
sb->s_dirt = 1;
if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -197,7+197,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data, }
if (!(s->s_flags & MS_RDONLY)) {
ms->s_state &= ~MINIX_VALID_FS;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
s->s_dirt = 1;
}
if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -349,7+349,7 @@ repeat: goto repeat;
}
*p = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
@@ -477,7+477,7 @@ static struct buffer_head * minix_update_inode(struct inode * inode) else for (block = 0; block < 9; block++)
raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
inode->i_dirt=0;
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return bh;
}
@@ -195,7+195,7 @@ static int minix_add_entry(struct inode * dir, dir->i_mtime = dir->i_ctime = CURRENT_TIME;
for (i = 0; i < info->s_namelen ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
*res_dir = de;
break;
}
@@ -238,7+238,7 @@ int minix_create(struct inode * dir,const char * name, int len, int mode, return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
@@ -295,7+295,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -347,7+347,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode) de->inode = dir->i_ino;
strcpy(de->name,"..");
inode->i_nlink = 2;
- dir_block->b_dirt = 1;
+ dirtify_buffer(dir_block, 1);
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
if (dir->i_mode & S_ISGID)
@@ -361,7+361,7 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode) return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
@@ -469,7+469,7 @@ int minix_rmdir(struct inode * dir, const char * name, int len) if (inode->i_nlink != 2)
printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
de->inode = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
dir->i_nlink--;
@@ -522,7+522,7 @@ repeat: inode->i_nlink=1;
}
de->inode = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
inode->i_nlink--;
@@ -562,7+562,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s while (i < 1023 && (c=*(symname++)))
name_block->b_data[i++] = c;
name_block->b_data[i] = 0;
- name_block->b_dirt = 1;
+ dirtify_buffer(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
@@ -584,7+584,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s return i;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -621,7+621,7 @@ int minix_link(struct inode * oldinode, struct inode * dir, const char * name, i return error;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
@@ -774,11+774,11 @@ start_up: new_inode->i_ctime = CURRENT_TIME;
new_inode->i_dirt = 1;
}
- old_bh->b_dirt = 1;
- new_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
+ dirtify_buffer(new_bh, 1);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
+ dirtify_buffer(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
if (new_inode) {
continue;
}
*ind = 0;
- ind_bh->b_dirt = 1;
+ dirtify_buffer(ind_bh, 1);
brelse(bh);
minix_free_block(inode->i_sb,tmp);
}
@@ -144,7+144,7 @@ repeat: goto repeat;
dind = i+(unsigned short *) dind_bh->b_data;
retry |= trunc_indirect(inode,7+512+(i<<9),dind);
- dind_bh->b_dirt = 1;
+ dirtify_buffer(dind_bh, 1);
}
dind = (unsigned short *) dind_bh->b_data;
for (i = 0; i < 512; i++)
@@ -72,15+72,15 @@ int fat_access(struct super_block *sb,int nr,int new_value) *p_first = new_value & 0xff;
*p_last = (*p_last & 0xf0) | (new_value >> 8);
}
- bh2->b_dirt = 1;
+ dirtify_buffer(bh2, 1);
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
fat_length*copy,&c_data))) break;
memcpy(c_data,data,SECTOR_SIZE);
- c_bh->b_dirt = 1;
+ dirtify_buffer(c_bh, 1);
if (data != data2 || bh != bh2) {
if (!(c_bh2 = msdos_sread(sb->s_dev,
MSDOS_SB(sb)->fat_start+(first >>
@@ -200,7+200,7 @@ static int msdos_file_write(struct inode *inode,struct file *filp,char *buf, inode->i_size = filp->f_pos;
inode->i_dirt = 1;
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
if (start == buf)
@@ -415,7+415,7 @@ void msdos_write_inode(struct inode *inode) date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
raw_entry->time = CT_LE_W(raw_entry->time);
raw_entry->date = CT_LE_W(raw_entry->date);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
}
@@ -185,7+185,7 @@ printk("zeroing sector %d\n",sector); else memset(data,0,SECTOR_SIZE);
}
if (bh) {
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
}
}
@@ -181,7+181,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir, de->start = 0;
date_unix2dos(dir->i_mtime,&de->time,&de->date);
de->size = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
if ((*result = iget(dir->i_sb,ino)) != NULL)
msdos_read_inode(*result);
brelse(bh);
@@ -350,7+350,7 @@ int msdos_rmdir(struct inode *dir,const char *name,int len) dir->i_nlink--;
inode->i_dirt = dir->i_dirt = 1;
de->name[0] = DELETED_FLAG;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
res = 0;
rmdir_done:
brelse(bh);
@@ -384,7+384,7 @@ int msdos_unlink(struct inode *dir,const char *name,int len) MSDOS_I(inode)->i_busy = 1;
inode->i_dirt = dir->i_dirt = 1;
de->name[0] = DELETED_FLAG;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
unlink_done:
brelse(bh);
iput(inode);
@@ -429,12+429,12 @@ static int rename_same_dir(struct inode *old_dir,char *old_name, MSDOS_I(new_inode)->i_busy = 1;
new_inode->i_dirt = 1;
new_de->name[0] = DELETED_FLAG;
- new_bh->b_dirt = 1;
+ dirtify_buffer(new_bh, 1);
iput(new_inode);
brelse(new_bh);
}
memcpy(old_de->name,new_name,MSDOS_NAME);
- old_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
msdos_read_inode(old_inode);
@@ -503,7+503,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name, MSDOS_I(new_inode)->i_busy = 1;
new_inode->i_dirt = 1;
new_de->name[0] = DELETED_FLAG;
- new_bh->b_dirt = 1;
+ dirtify_buffer(new_bh, 1);
}
memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
memcpy(free_de->name,new_name,MSDOS_NAME);
@@ -526,8+526,8 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name, cache_inval_inode(old_inode);
old_inode->i_dirt = 1;
old_de->name[0] = DELETED_FLAG;
- old_bh->b_dirt = 1;
- free_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
+ dirtify_buffer(free_bh, 1);
if (!exists) iput(free_inode);
else {
MSDOS_I(new_inode)->i_depend = free_inode;
@@ -547,7+547,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name, dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
MSDOS_I(new_dir)->i_start;
dotdot_inode->i_dirt = 1;
- dotdot_bh->b_dirt = 1;
+ dirtify_buffer(dotdot_bh, 1);
old_dir->i_nlink--;
new_dir->i_nlink++;
/* no need to mark them dirty */
@@ -96,7+96,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) }
*flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */
memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
bh->b_uptodate = 1;
brelse(bh);
*sb->sv_sb_flc_count = 0;
@@ -117,7+117,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
memzero(bh_data, sb->sv_block_size);
/* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
bh->b_uptodate = 1;
brelse(bh);
/* still *sb->sv_sb_flc_count = 0 */
@@ -138,7+138,7 @@ void sysv_free_block(struct super_block * sb, unsigned int block) to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
else
*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
unlock_super(sb);
}
@@ -229,7+229,7 @@ int sysv_new_block(struct super_block * sb) return 0;
}
memzero(bh_data,sb->sv_block_size);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
bh->b_uptodate = 1;
brelse(bh);
if (sb->sv_convert)
@@ -237,7+237,7 @@ int sysv_new_block(struct super_block * sb) to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
else
*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
unlock_super(sb);
return block;
@@ -331,7+331,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
}
}
@@ -301,7+301,7 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, memcpy_fromfs(p,buf,c);
buf += c;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -74,10+74,10 @@ void sysv_free_inode(struct inode * inode) if (*sb->sv_sb_fic_count < sb->sv_fic_size)
sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)++] = ino;
(*sb->sv_sb_total_free_inodes)++;
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
memset(raw_inode, 0, sizeof(struct sysv_inode));
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
unlock_super(sb);
brelse(bh);
clear_inode(inode);
@@ -130,7+130,7 @@ struct inode * sysv_new_inode(const struct inode * dir) }
/* Now *sb->sv_sb_fic_count > 0. */
ino = sb->sv_sb_fic_inodes[--(*sb->sv_sb_fic_count)];
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
inode->i_count = 1;
inode->i_nlink = 1;
@@ -152,7+152,7 @@ struct inode * sysv_new_inode(const struct inode * dir) inode->i_dirt = 1; /* cleared by sysv_write_inode() */
/* That's it. */
(*sb->sv_sb_total_free_inodes)--;
- sb->sv_bh->b_dirt = 1; /* super-block has been modified again */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified again */
sb->s_dirt = 1; /* and needs time stamp again */
unlock_super(sb);
return inode;
@@ -191,7+191,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_sb_total_free_inodes = count;
- sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+ dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */
}
}
@@ -557,7+557,7 @@ repeat: goto repeat;
}
*p = (sb->sv_convert ? to_coh_ulong(block) : block);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
*start = result->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
return result;
@@ -773,7+773,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) for (block = 0; block < 10+1+1+1; block++)
write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
inode->i_dirt=0;
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return bh;
}
@@ -193,7+193,7 @@ static int sysv_add_entry(struct inode * dir, dir->i_mtime = dir->i_ctime = CURRENT_TIME;
for (i = 0; i < SYSV_NAMELEN ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
*res_dir = de;
break;
}
@@ -238,7+238,7 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode, return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
@@ -298,7+298,7 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -349,7+349,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) de->inode = dir->i_ino;
strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
inode->i_nlink = 2;
- dir_block->b_dirt = 1;
+ dirtify_buffer(dir_block, 1);
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
if (dir->i_mode & S_ISGID)
@@ -363,7+363,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
@@ -473,7+473,7 @@ int sysv_rmdir(struct inode * dir, const char * name, int len) if (inode->i_nlink != 2)
printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
de->inode = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
dir->i_nlink--;
@@ -526,7+526,7 @@ repeat: inode->i_nlink=1;
}
de->inode = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
inode->i_nlink--;
@@ -570,7+570,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy while (i < sb->sv_block_size_1 && (c = *(symname++)))
name_block_data[i++] = c;
name_block_data[i] = 0;
- name_block->b_dirt = 1;
+ dirtify_buffer(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
@@ -592,7+592,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy return i;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -629,7+629,7 @@ int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, in return error;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
@@ -782,11+782,11 @@ start_up: new_inode->i_ctime = CURRENT_TIME;
new_inode->i_dirt = 1;
}
- old_bh->b_dirt = 1;
- new_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
+ dirtify_buffer(new_bh, 1);
if (dir_bh) {
PARENT_INO(dir_bh_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
+ dirtify_buffer(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
if (new_inode) {
@@ -84,7+84,7 @@ static int coh_trunc_indirect (struct inode * inode, unsigned long blocks, unsig if (!indblock)
continue;
*ind = 0;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
sysv_free_block(sb,indblock);
}
for (i = 0; i < sb->sv_ind_per_block; i++)
@@ -338,7+338,7 @@ repeat: continue;
}
*ind = 0;
- indbh->b_dirt = 1;
+ dirtify_buffer(indbh, 1);
brelse(bh);
sysv_free_block(sb,block);
}
@@ -65,7+65,7 @@ zone_found: start_bit=j + (i << 5) + 1;
goto repeat;
}
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return j + (i << 5);
}
@@ -245,7+245,7 @@ void xiafs_free_zone(struct super_block * sb, int d_addr) printk("XIA-FS: dev %04x"
" block bit %u (0x%x) already cleared (%s %d)\n",
sb->s_dev, bit, bit, WHERE_ERR);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
}
@@ -277,7+277,7 @@ int xiafs_new_zone(struct super_block * sb, u_long prev_addr) }
clear_buf(bh);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return tmp;
}
@@ -305,7+305,7 @@ void xiafs_free_inode(struct inode * inode) printk("XIA-FS: dev %04x"
"inode bit %ld (0x%lx) already cleared (%s %d)\n",
inode->i_dev, ino, ino, WHERE_ERR);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
}
@@ -97,7+97,8 @@ xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count) zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
bhb = bhe = buflist;
if (filp->f_reada) {
- zones += read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
+ if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
+ zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
if (zone_nr + zones > f_zones)
zones = f_zones - zone_nr;
}
@@ -240,7+241,7 @@ xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count memcpy_fromfs(cp,buf,c);
buf += c;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -306,7+306,7 @@ repeat: }
*lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
@@ -466,7+466,7 @@ static struct buffer_head * xiafs_update_inode(struct inode * inode) | (inode->u.xiafs_i.i_dind_zone & 0xffffff);
}
inode->i_dirt=0;
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return bh;
}
@@ -221,7+221,7 @@ static struct buffer_head * xiafs_add_entry(struct inode * dir, memcpy(de->d_name, name, namelen);
de->d_name[namelen]=0;
de->d_name_len=namelen;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
*res_dir = de;
if (res_pre)
*res_pre = de_pre;
@@ -268,7+268,7 @@ int xiafs_create(struct inode * dir, const char * name, int len, int mode, return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
@@ -325,7+325,7 @@ int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -375,7+375,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode) de->d_name_len=2;
de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
inode->i_nlink = 2;
- dir_block->b_dirt = 1;
+ dirtify_buffer(dir_block, 1);
brelse(dir_block);
inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
if (dir->i_mode & S_ISGID)
@@ -389,7+389,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode) return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
@@ -518,7+518,7 @@ int xiafs_rmdir(struct inode * dir, const char * name, int len) if (inode->i_nlink != 2)
printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
xiafs_rm_entry(de, de_pre);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
dir->i_nlink--;
@@ -566,7+566,7 @@ repeat: inode->i_nlink=1;
}
xiafs_rm_entry(de, de_pre);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
inode->i_nlink--;
@@ -611,7+611,7 @@ int xiafs_symlink(struct inode * dir, const char * name, for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
name_block->b_data[i] = c;
name_block->b_data[i] = 0;
- name_block->b_dirt = 1;
+ dirtify_buffer(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
@@ -624,7+624,7 @@ int xiafs_symlink(struct inode * dir, const char * name, return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
@@ -661,7+661,7 @@ int xiafs_link(struct inode * oldinode, struct inode * dir, return -ENOSPC;
}
de->d_ino = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
@@ -798,11+798,11 @@ try_again: new_inode->i_nlink--;
new_inode->i_dirt = 1;
}
- old_bh->b_dirt = 1;
- new_bh->b_dirt = 1;
+ dirtify_buffer(old_bh, 1);
+ dirtify_buffer(new_bh, 1);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- dir_bh->b_dirt = 1;
+ dirtify_buffer(dir_bh, 1);
old_dir->i_nlink--;
new_dir->i_nlink++;
old_dir->i_dirt = 1;
@@ -104,7+104,7 @@ repeat: retry = 1;
else {
*indp = 0;
- ind_bh->b_dirt = 1;
+ dirtify_buffer(ind_bh, 1);
inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp);
}
@@ -157,7+157,7 @@ repeat: retry |= trunc_indirect(inode,
8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)),
dindp);
- dind_bh->b_dirt = 1;
+ dirtify_buffer(dind_bh, 1);
}
dindp = (u_long *) dind_bh->b_data;
for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
@@ -103,6+103,7 @@ extern unsigned long file_table_init(unsigned long start, unsigned long end); #define BLKRRPART 4703 /* re-read partition table */
#define BLKGETSIZE 4704 /* return device size */
#define BLKFLSBUF 4705 /* flush buffer cache */
+#define BLKRASET 4706 /* Set read ahead for block device */
/* These are a few other constants only used by scsi devices */
@@ -210,7+211,7 @@ struct file { off_t f_pos;
unsigned short f_flags;
unsigned short f_count;
- unsigned short f_reada;
+ off_t f_reada;
struct file *f_next, *f_prev;
struct inode * f_inode;
struct file_operations * f_op;
@@ -359,6+360,12 @@ extern int nr_buffers; extern int buffermem;
extern int nr_buffer_heads;
+/* Once the full cluster diffs are in place, this will be filled out a bit. */
+extern inline void dirtify_buffer(struct buffer_head * bh, int flag)
+{
+ bh->b_dirt = 1;
+}
+
extern void check_disk_change(dev_t dev);
extern void invalidate_inodes(dev_t dev);
extern void invalidate_buffers(dev_t dev);
@@ -392,7+399,8 @@ extern void brelse(struct buffer_head * buf); extern void set_blocksize(dev_t dev, int size);
extern struct buffer_head * bread(dev_t dev, int block, int size);
extern unsigned long bread_page(unsigned long addr,dev_t dev,int b[],int size,int prot);
-extern struct buffer_head * breada(dev_t dev,int block,...);
+extern struct buffer_head * breada(dev_t dev,int block, int size,
+ unsigned int pos, unsigned int filesize);
extern void put_super(dev_t dev);
extern dev_t ROOT_DEV;
#define X(name) { (void *) &name, "_" #name }
+#ifdef CONFIG_FTAPE
+extern char * ftape_big_buffer;
+extern void (*do_floppy)(void);
+#endif
+
struct {
void *addr;
const char *name;
@@ -902,7+902,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) } else
user_esp = regs->esp;
}
- if (error_code & 1)
+ if (error_code & PAGE_PRESENT)
do_wp_page(error_code, address, current, user_esp);
else
do_no_page(error_code, address, current, user_esp);
@@ -1084,10+1084,17 @@ void mem_init(unsigned long start_low_mem, /* mark usable pages in the mem_map[] */
start_low_mem = PAGE_ALIGN(start_low_mem);
start_mem = PAGE_ALIGN(start_mem);
- while (start_low_mem < 0xA0000) {
+
+ /*
+ * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
+ * They seem to have done something stupid with the floppy
+ * controller as well..
+ */
+ while (start_low_mem < 0x9f000) {
mem_map[MAP_NR(start_low_mem)] = 0;
start_low_mem += PAGE_SIZE;
}
+
while (start_mem < high_memory) {
mem_map[MAP_NR(start_mem)] = 0;
start_mem += PAGE_SIZE;
@@ -1133,21+1140,18 @@ void si_meminfo(struct sysinfo *val)
i = high_memory >> PAGE_SHIFT;
val->totalram = 0;
- val->freeram = 0;
val->sharedram = 0;
+ val->freeram = nr_free_pages << PAGE_SHIFT;
val->bufferram = buffermem;
while (i-- > 0) {
if (mem_map[i] & MAP_PAGE_RESERVED)
continue;
val->totalram++;
- if (!mem_map[i]) {
- val->freeram++;
+ if (!mem_map[i])
continue;
- }
val->sharedram += mem_map[i]-1;
}
val->totalram <<= PAGE_SHIFT;
- val->freeram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
return;
}
#include <linux/fcntl.h>
#include <linux/socket.h>
#include <linux/in.h>
+#include <linux/string.h>
#include "inet.h"
#include "dev.h"
#include "ip.h"
* Linus Torvalds/ : Memory leakage on fragmentation
* Alan Cox : handling.
* Gerhard Koerting: Forwarding uses IP priority hints
+ * Teemu Rantanen : Fragment problems.
*
* To Fix:
* IP option processing is mostly not needed. ip_forward needs to know about routing rules
@@ -774,6+775,7 @@ static struct sk_buff *ip_glue(struct ipq *qp) skb->len = (len - qp->maclen);
skb->h.raw = skb->data;
skb->free = 1;
+ skb->dev = qp->dev;
/* Copy the original MAC and IP headers into the new buffer. */
ptr = (unsigned char *) skb->h.raw;
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/in.h>
+#include <linux/string.h>
#include "inet.h"
#include "dev.h"
#include "ip.h"