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
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
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).
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));
*/
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;
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) {
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))))
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];
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[] = {
{
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;
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;
*/
up_flag = (scancode & 0200);
scancode &= 0x7f;
-
+
if (prev_scancode) {
/*
* usually it will be 0xe0, but a Pause key generates
#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
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;
* 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)))))
{
static void compose(void)
{
- dead_key_next = 1;
+ dead_key_next = 1;
}
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);
}
#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. */
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;
}
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)
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)
}
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]--;
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;
val = KVAL(sym);
k_down[val]++;
shift_state |= (1<<val);
- }
+ }
}
}
}
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)
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <asm/io.h>
#include <asm/system.h>
#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>
#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"
#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
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 */
static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table);
#endif
+static int depca_na;
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)
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 */
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 */
/*
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) {
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;
** 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;
}
*/
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;
/*
** 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...
** 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;
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 */
/* Transmitter timeout, serious problems. */
if (dev->tbusy) {
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5) {
+ if (tickssofar < 10) {
status = -1;
} else {
STOP_DEPCA;
} else {
lp = (struct depca_private *)dev->priv;
ioaddr = dev->base_addr;
+ depca_na = lp->depca_na;
}
if (dev->interrupt)
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);
/* 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;
/* 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++;
/* 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;
+ }
}
/*
/*
** 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)
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
*/
*/
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 */
#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"
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. */
{
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");
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;
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 */
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;
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;
{
req->dev = -1;
*reqp = req->next;
+ wake_up(&wait_for_request);
};
} else {
SCpnt->request.dev = 0xffff; /* Busy */
{
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;
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 :
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;
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);
/* 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.
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 */
#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; \
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;
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;
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);
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;
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) {
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;
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++;
};
}
} while(nbytes);
+
+ SCpnt->result = 0;
+ (done)(SCpnt);
+ return;
+
if (SCpnt->use_sg && !scsi_debug_errsts)
if(bh) scsi_dump(SCpnt, 0);
break;
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");
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 */
#if 0
printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
+#endif
#endif
return 0;
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;
timer_active |= 1 << SCSI_DEBUG_TIMER;
};
sti();
+#endif
return;
};
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;
}
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;
return 0;
}
-char *scsi_debug_info(void)
+const char *scsi_debug_info(void)
{
static char buffer[] = " "; /* looks nicer without anything here */
return buffer;
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
};
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;
}
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
#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
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 */
#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;
};
if (!SCpnt) return; /* Could not find anything to do */
-
- wake_up(&wait_for_request);
-
+
/* Queue command */
requeue_sd_request(SCpnt);
}; /* While */
{
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:
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;
} 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
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;
} 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 */
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);
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){
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",
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){
their size, and reads partition table entries for them.
*/
+
unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
{
int i;
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 */
};
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)");
};
DEVICE_BUSY = 0;
return 0;
}
+
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;
};
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)");
};
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>
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;
p += chars;
buf += chars;
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
return written;
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];
/*
* 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;
}
/*
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--) {
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) {
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;
}
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;
}
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;
}
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);
}
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);
}
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);
}
(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);
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;
}
goto repeat;
}
*p = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
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;
}
#if 0
dir->i_ctime = CURRENT_TIME;
#endif
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
}
brelse (bh);
bh = NULL;
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;
}
return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
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)
return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
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--;
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;
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;
return -ENOSPC;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
return -ENOSPC;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
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;
continue;
}
*ind = 0;
- ind_bh->b_dirt = 1;
+ dirtify_buffer(ind_bh, 1);
brelse(bh);
ext_free_block(inode->i_sb,tmp);
}
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++)
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++)
}
}
- 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);
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);
}
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;
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;
}
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);
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);
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);
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);
}
"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);
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;
}
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);
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);
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;
}
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");
*/
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;
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);
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) {
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);
}
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);
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)
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);
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);
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);
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;
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);
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);
}
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) {
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);
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);
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);
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;
}
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, "
#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
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;
}
*/
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) {
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) {
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++)
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>
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);
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",
+ 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;
}
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
*
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;
if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0;
bhreq[bhrequest++] = *bhb;
- nextblock = (*bhb)->b_blocknr + 1;
};
if (++bhb == &buflist[NBUF])
/* 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
*/
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;
}
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
*/
}
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;
}
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)
}
clear_block(bh->b_data);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return j;
}
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)
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);
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;
}
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;
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;
}
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++)
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);
}
/* 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))
}
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))
goto repeat;
}
*p = tmp;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
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;
}
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;
}
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
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)
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
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--;
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--;
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;
return i;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
return error;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
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);
}
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++)
*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 >>
inode->i_size = filp->f_pos;
inode->i_dirt = 1;
}
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 0);
brelse(bh);
}
if (start == buf)
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);
}
else memset(data,0,SECTOR_SIZE);
}
if (bh) {
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
}
}
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);
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);
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);
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);
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);
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;
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 */
}
*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;
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 */
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 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)
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;
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 */
}
}
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;
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);
}
/* 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;
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;
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 */
}
}
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;
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;
}
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;
}
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
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)
return error;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
iput(dir);
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--;
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--;
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;
return i;
}
de->inode = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
return error;
}
de->inode = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
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) {
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++)
continue;
}
*ind = 0;
- indbh->b_dirt = 1;
+ dirtify_buffer(indbh, 1);
brelse(bh);
sysv_free_block(sb,block);
}
start_bit=j + (i << 5) + 1;
goto repeat;
}
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return j + (i << 5);
}
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);
}
}
clear_buf(bh);
bh->b_uptodate = 1;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return tmp;
}
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);
}
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;
}
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;
}
*lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
return result;
}
| (inode->u.xiafs_i.i_dind_zone & 0xffffff);
}
inode->i_dirt=0;
- bh->b_dirt=1;
+ dirtify_buffer(bh, 1);
return bh;
}
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;
return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
*result = inode;
return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
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)
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);
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--;
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--;
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;
return -ENOSPC;
}
de->d_ino = inode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
iput(inode);
return -ENOSPC;
}
de->d_ino = oldinode->i_ino;
- bh->b_dirt = 1;
+ dirtify_buffer(bh, 1);
brelse(bh);
iput(dir);
oldinode->i_nlink++;
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;
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);
}
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++);
#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 */
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;
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);
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;
} 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);
/* 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;
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
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"