*
* Architecture specifics
*/
+#include <linux/config.h>
#include <linux/tty.h>
#include <linux/init.h>
.long SYMBOL_NAME(sys_setfsuid) /* 215 */
.long SYMBOL_NAME(sys_setfsgid)
.long SYMBOL_NAME(sys_pivot_root)
+ .long SYMBOL_NAME(sys_mincore)
/*
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-217
+ .rept NR_syscalls-218
.long SYMBOL_NAME(sys_ni_syscall)
.endr
/* These are the functions used to load ELF style executables and shared
* libraries. There is no binary dependent code anywhere else.
*/
-static inline int do_load_irix_binary(struct linux_binprm * bprm,
- struct pt_regs * regs)
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct elfhdr elf_ex, interp_elf_ex;
struct dentry *interpreter_dentry;
sys_close(elf_exec_fileno);
current->personality = PER_IRIX32;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
if (current->binfmt && current->binfmt->module)
__MOD_DEC_USE_COUNT(current->binfmt->module);
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &irix_format;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
if (current->binfmt && current->binfmt->module)
__MOD_INC_USE_COUNT(current->binfmt->module);
goto out;
}
-static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_irix_binary(bprm, regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/* This is really simpleminded and specialized - we are loading an
* a.out library that is given an ELF header.
*/
int retval = -EACCES;
struct file *file;
- MOD_INC_USE_COUNT;
file = fget(fd);
if (file) {
retval = do_load_irix_library(file);
fput(file);
}
- MOD_DEC_USE_COUNT;
return retval;
}
elf_fpregset_t fpu; /* NT_PRFPREG */
struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
-#ifndef CONFIG_BINFMT_IRIX
- MOD_INC_USE_COUNT;
-#endif
-
/* Count what's needed to dump, up to the limit of coredump size. */
segs = 0;
size = 0;
end_coredump:
set_fs(fs);
-#ifndef CONFIG_BINFMT_IRIX
- MOD_DEC_USE_COUNT;
-#endif
return has_dumped;
}
#include <linux/smp.h>
#include <linux/smp_lock.h>
+/* CHECKME: this stuff looks rather bogus */
asmlinkage int
do_solaris_syscall (struct pt_regs *regs)
{
int ret;
lock_kernel();
+ put_exec_domain(current->exec_domain);
current->personality = PER_SVR4;
current->exec_domain = lookup_exec_domain(PER_SVR4);
* dumping of the process results in another error..
*/
-static inline int
-do_aout32_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
{
mm_segment_t fs;
int has_dumped = 0;
return has_dumped;
}
-static int
-aout32_core_dump(long signr, struct pt_regs * regs, struct file * file)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_aout32_core_dump(signr, regs, file);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/*
* create_aout32_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* libraries. There is no binary dependent code anywhere else.
*/
-static inline int do_load_aout32_binary(struct linux_binprm * bprm,
- struct pt_regs * regs)
+static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct exec ex;
struct file * file;
}
}
beyond_if:
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
if (current->binfmt && current->binfmt->module)
__MOD_DEC_USE_COUNT(current->binfmt->module);
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout32_format;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
if (current->binfmt && current->binfmt->module)
__MOD_INC_USE_COUNT(current->binfmt->module);
return 0;
}
-
-static int
-load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_aout32_binary(bprm, regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
-static inline int
-do_load_aout32_library(int fd)
+static int load_aout32_library(int fd)
{
struct file * file;
struct inode * inode;
return retval;
}
-static int
-load_aout32_library(int fd)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_aout32_library(fd);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
static int __init init_aout32_binfmt(void)
{
return register_binfmt(&aout32_format);
{
lock_kernel();
current->personality = PER_SVR4;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
current->exec_domain = lookup_exec_domain(current->personality);
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
unlock_kernel();
}
"status %4.4x.\n", dev->name, (long)skb->len,
inw(ioaddr + EL3_STATUS));
- netif_stop_queue (dev);
-
outw(skb->len, ioaddr + TX_FIFO);
outw(0, ioaddr + TX_FIFO);
outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
dev->trans_start = jiffies;
/* TxFree appears only in Window 1, not offset 0x1c. */
- if (inw(ioaddr + TxFree) > 1536) {
- netif_start_queue (dev);
- } else
+ if (inw(ioaddr + TxFree) <= 1536) {
+ netif_stop_queue (dev);
/* Interrupt us when the FIFO has room for max-sized packet.
The threshold is in units of dwords. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-
+ }
+
dev_kfree_skb (skb);
pop_tx_status(dev);
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
netif_wake_queue (dev);
- } else {
- netif_stop_queue (dev);
}
if (status & TxComplete)
break;
ap->chan.private = ap;
ap->chan.ops = &sync_ops;
- err = ppp_register_channel(&ap->chan, val);
+ err = ppp_register_channel(&ap->chan);
if (err != 0)
break;
ap->connected = 1;
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/delay.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#define VERSION "0.13"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <asm/dma.h>
#include <linux/ioport.h>
#include <linux/init.h>
-#include <linux/netdevice.h>
#include "comx.h"
#include "z85230.h"
#define VERSION "0.64"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#define VERSION "0.72"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#define VERSION "0.80"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#define VERSION "0.23"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
* tx_carrier_errors modem line status changes
* tx_fifo_errors tx underrun (locomx)
*/
+#include <linux/config.h>
struct comx_protocol {
char *name;
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-if [ "$CONFIG_CHR_DEV_ST" != "n" ]; then
- int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
-fi
-
dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Sat Aug 7 13:52:16 1999 by makisara@kai.makisara.local
+Last modified: Sat Mar 11 10:34:44 2000 by makisara@kai.makisara.local
BASICS
maximum number of these buffers is defined by ST_MAX_BUFFERS. The
maximum can be changed with kernel or module startup options. One
buffer is allocated for each drive detected when the driver is
-initialized up to the maximum. The minimum number of allocated buffers
-is ST_EXTRA_DEVS (in hosts.h) (unless this number exceeds the defined
-maximum). This ensures some functionality also for the drives found
-after tape driver initialization (a SCSI adapter driver is loaded as a
-module). The default for ST_EXTRA_DEVS is two.
+initialized up to the maximum.
The driver tries to allocate new buffers at run-time if
necessary. These buffers are freed after use. If the maximum number of
Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
Contribution and ideas from several people including (in alphabetical
order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
- Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
+ Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and
+ Eric Youngdale.
Copyright 1992 - 2000 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Tue Feb 29 20:47:03 2000 by makisara@kai.makisara.local
+ Last modified: Mon Mar 13 21:15:29 2000 by makisara@kai.makisara.local
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
24 bits) */
#define SET_DENS_AND_BLK 0x10001
+#define ST_DEV_ARR_LUMP 6
+static rwlock_t st_dev_arr_lock = RW_LOCK_UNLOCKED;
+
static int st_nbr_buffers;
-static ST_buffer **st_buffers;
+static ST_buffer **st_buffers = NULL;
static int st_buffer_size = ST_BUFFER_SIZE;
static int st_write_threshold = ST_WRITE_THRESHOLD;
static int st_max_buffers = ST_MAX_BUFFERS;
static int st_max_sg_segs = ST_MAX_SG;
-static Scsi_Tape *scsi_tapes = NULL;
+static Scsi_Tape **scsi_tapes = NULL;
static int modes_defined = FALSE;
static int st_compression(Scsi_Tape *, int);
-static int find_partition(struct inode *);
-static int update_partition(struct inode *);
+static int find_partition(Scsi_Tape *);
+static int update_partition(Scsi_Tape *);
-static int st_int_ioctl(struct inode *inode, unsigned int cmd_in,
- unsigned long arg);
+static int st_int_ioctl(Scsi_Tape *, unsigned int, unsigned long);
\f
-
/* Convert the result to success code */
-static int st_chk_result(Scsi_Request * SRpnt)
+static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt)
{
int dev;
int result = SRpnt->sr_result;
if (driver_byte(result) & DRIVER_SENSE)
scode = sense[2] & 0x0f;
- else
+ else {
+ sense[0] = 0;
scode = 0;
+ }
dev = TAPE_NR(SRpnt->sr_request.rq_dev);
DEB(
&& SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
#endif
) {
- scsi_tapes[dev].recover_count++;
- scsi_tapes[dev].mt_status->mt_erreg += (1 << MT_ST_SOFTERR_SHIFT);
+ STp->recover_count++;
+ STp->recover_reg++;
DEB(
if (debugging) {
else
stp = "ioctl";
printk(ST_DEB_MSG "st%d: Recovered %s error (%d).\n", dev, stp,
- scsi_tapes[dev].recover_count);
+ STp->recover_count);
} ) /* end DEB */
if ((sense[2] & 0xe0) == 0)
Scsi_Tape *STp;
if ((st_nbr = TAPE_NR(SCpnt->request.rq_dev)) < st_template.nr_dev) {
- STp = &(scsi_tapes[st_nbr]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[st_nbr];
+ read_unlock(&st_dev_arr_lock);
if ((STp->buffer)->writing &&
(SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
(SCpnt->sense_buffer[2] & 0x40)) {
if (do_wait) {
down(SRpnt->sr_request.sem);
SRpnt->sr_request.sem = NULL;
- (STp->buffer)->syscall_result = st_chk_result(SRpnt);
+ (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
}
return SRpnt;
}
down(&(STp->sem));
(STp->buffer)->last_SRpnt->sr_request.sem = NULL;
- (STp->buffer)->syscall_result = st_chk_result((STp->buffer)->last_SRpnt);
+ (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
scsi_release_request((STp->buffer)->last_SRpnt);
if (STbuffer->writing < STbuffer->buffer_bytes)
/* Flush the tape buffer. The tape will be positioned correctly unless
seek_next is true. */
-static int flush_buffer(struct inode *inode, struct file *filp, int seek_next)
+static int flush_buffer(Scsi_Tape *STp, int seek_next)
{
int backspace, result;
- Scsi_Tape *STp;
ST_buffer *STbuffer;
ST_partstat *STps;
- int dev = TAPE_NR(inode->i_rdev);
- STp = &(scsi_tapes[dev]);
STbuffer = STp->buffer;
/*
}
}
if (!result && backspace > 0)
- result = st_int_ioctl(inode, MTBSR, backspace);
+ result = st_int_ioctl(STp, MTBSR, backspace);
} else if (STps->eof == ST_FM_HIT) {
if (STps->drv_file >= 0)
STps->drv_file++;
}
\f
/* Set the mode parameters */
-static int set_mode_densblk(struct inode *inode, Scsi_Tape * STp, ST_mode * STm)
+static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm)
{
int set_it = FALSE;
unsigned long arg;
- int dev = TAPE_NR(inode->i_rdev);
+ int dev = TAPE_NR(STp->devt);
if (!STp->density_changed &&
STm->default_density >= 0 &&
} else
arg |= STp->block_size;
if (set_it &&
- st_int_ioctl(inode, SET_DENS_AND_BLK, arg)) {
+ st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
printk(KERN_WARNING
"st%d: Can't set default block size to %d bytes and density %x.\n",
dev, STm->default_blksize, STm->default_density);
int dev = TAPE_NR(inode->i_rdev);
int mode = TAPE_MODE(inode->i_rdev);
- if (dev >= st_template.dev_max || !scsi_tapes[dev].device)
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ if (dev >= st_template.dev_max || STp == NULL) {
+ read_unlock(&st_dev_arr_lock);
return (-ENXIO);
+ }
+ read_unlock(&st_dev_arr_lock);
- if (!scsi_block_when_processing_errors(scsi_tapes[dev].device)) {
+ if (!scsi_block_when_processing_errors(STp->device)) {
return -ENXIO;
}
- STp = &(scsi_tapes[dev]);
if (STp->in_use) {
DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
return (-EBUSY);
}
STp->in_use = 1;
- STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+ STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
- if (scsi_tapes[dev].device->host->hostt->module)
- __MOD_INC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+ if (STp->device->host->hostt->module)
+ __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
if (st_template.module)
__MOD_INC_USE_COUNT(st_template.module);
/* Allocate a buffer for this user */
need_dma_buffer = STp->restr_dma;
+ read_lock(&st_dev_arr_lock);
for (i = 0; i < st_nbr_buffers; i++)
if (!st_buffers[i]->in_use &&
- (!need_dma_buffer || st_buffers[i]->dma))
+ (!need_dma_buffer || st_buffers[i]->dma)) {
+ STp->buffer = st_buffers[i];
break;
+ }
+ read_unlock(&st_dev_arr_lock);
if (i >= st_nbr_buffers) {
STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
if (STp->buffer == NULL) {
retval = (-EBUSY);
goto err_out;
}
- } else
- STp->buffer = st_buffers[i];
+ }
+
(STp->buffer)->in_use = 1;
(STp->buffer)->writing = 0;
(STp->buffer)->syscall_result = 0;
partition support has been enabled. */
DEBC(printk(ST_DEB_MSG
"st%d: Updating partition number in status.\n", dev));
- if ((STp->partition = find_partition(inode)) < 0) {
+ if ((STp->partition = find_partition(STp)) < 0) {
retval = STp->partition;
goto err_out;
}
STp->density_changed = STp->blksize_changed = FALSE;
STp->compression_changed = FALSE;
if (!(STm->defaults_for_writes) &&
- (retval = set_mode_densblk(inode, STp, STm)) < 0)
+ (retval = set_mode_densblk(STp, STm)) < 0)
goto err_out;
if (STp->default_drvbuffer != 0xff) {
- if (st_int_ioctl(inode, MTSETDRVBUFFER, STp->default_drvbuffer))
+ if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
printk(KERN_WARNING
"st%d: Can't set default drive buffering to %d.\n",
dev, STp->default_drvbuffer);
STp->buffer = NULL;
}
STp->in_use = 0;
- if (scsi_tapes[dev].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+ if (STp->device->host->hostt->module)
+ __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
if (st_template.module)
__MOD_DEC_USE_COUNT(st_template.module);
return retval;
return 0;
dev = TAPE_NR(devt);
- STp = &(scsi_tapes[dev]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
STm = &(STp->modes[STp->current_mode]);
STps = &(STp->ps[STp->partition]);
}
if (STp->can_partitions &&
- (result2 = update_partition(inode)) < 0) {
+ (result2 = update_partition(STp)) < 0) {
DEBC(printk(ST_DEB_MSG
"st%d: update_partition at close failed.\n", dev));
if (result == 0)
STps = &(STp->ps[STp->partition]);
if (!STm->sysv || STps->rw != ST_READING) {
if (STp->can_bsr)
- result = flush_buffer(inode, filp, 0);
+ result = flush_buffer(STp, 0);
else if (STps->eof == ST_FM_HIT) {
result = cross_eof(STp, FALSE);
if (result) {
out:
if (STp->rew_at_close) {
- result2 = st_int_ioctl(inode, MTREW, 1);
+ result2 = st_int_ioctl(STp, MTREW, 1);
if (result == 0)
result = result2;
}
int dev;
dev = TAPE_NR(devt);
- STp = &(scsi_tapes[dev]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
if (STp->door_locked == ST_LOCKED_AUTO)
- st_int_ioctl(inode, MTUNLOCK, 0);
+ st_int_ioctl(STp, MTUNLOCK, 0);
if (STp->buffer != NULL) {
normalize_buffer(STp->buffer);
}
STp->in_use = 0;
- if (scsi_tapes[dev].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
+ if (STp->device->host->hostt->module)
+ __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
if (st_template.module)
__MOD_DEC_USE_COUNT(st_template.module);
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
- STp = &(scsi_tapes[dev]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
/*
* If we are in the middle of error recovery, don't let anyone
}
if (STp->can_partitions &&
- (retval = update_partition(inode)) < 0)
+ (retval = update_partition(STp)) < 0)
return retval;
STps = &(STp->ps[STp->partition]);
return (-EOVERFLOW);
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
- !st_int_ioctl(inode, MTLOCK, 0))
+ !st_int_ioctl(STp, MTLOCK, 0))
STp->door_locked = ST_LOCKED_AUTO;
if (STps->rw == ST_READING) {
- retval = flush_buffer(inode, filp, 0);
+ retval = flush_buffer(STp, 0);
if (retval)
return retval;
STps->rw = ST_WRITING;
} else if (STps->rw != ST_WRITING &&
STps->drv_file == 0 && STps->drv_block == 0) {
- if ((retval = set_mode_densblk(inode, STp, STm)) < 0)
+ if ((retval = set_mode_densblk(STp, STm)) < 0)
return retval;
if (STm->default_compression != ST_DONT_TOUCH &&
!(STp->compression_changed)) {
/* Read data from the tape. Returns zero in the normal case, one if the
eof status has changed, and the negative error code in case of a
fatal error. Otherwise updates the buffer and the eof state. */
-static long read_tape(struct inode *inode, long count, Scsi_Request ** aSRpnt)
+static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt)
{
int transfer, blks, bytes;
static unsigned char cmd[MAX_COMMAND_SIZE];
Scsi_Request *SRpnt;
- Scsi_Tape *STp;
ST_mode *STm;
ST_partstat *STps;
- int dev = TAPE_NR(inode->i_rdev);
+ int dev = TAPE_NR(STp->devt);
int retval = 0;
if (count == 0)
return 0;
- STp = &(scsi_tapes[dev]);
STm = &(STp->modes[STp->current_mode]);
STps = &(STp->ps[STp->partition]);
if (STps->eof == ST_FM_HIT)
printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
if (STps->drv_block >= 0)
STps->drv_block += blks - transfer + 1;
- st_int_ioctl(inode, MTBSR, 1);
+ st_int_ioctl(STp, MTBSR, 1);
return (-EIO);
}
/* We have some data, deliver it */
dev, count, (STp->buffer)->buffer_bytes));
if (STps->drv_block >= 0)
STps->drv_block += 1;
- if (st_int_ioctl(inode, MTBSR, 1))
+ if (st_int_ioctl(STp, MTBSR, 1))
return (-EIO);
}
} else if (SRpnt->sr_sense_buffer[2] & 0x80) { /* FM overrides EOM */
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
- STp = &(scsi_tapes[dev]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
/*
* If we are in the middle of error recovery, don't let anyone
} ) /* end DEB */
if (STp->can_partitions &&
- (total = update_partition(inode)) < 0)
+ (total = update_partition(STp)) < 0)
return total;
if (STp->block_size == 0 &&
return (-EIO); /* Read must be integral number of blocks */
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
- !st_int_ioctl(inode, MTLOCK, 0))
+ !st_int_ioctl(STp, MTLOCK, 0))
STp->door_locked = ST_LOCKED_AUTO;
STps = &(STp->ps[STp->partition]);
if (STps->rw == ST_WRITING) {
- transfer = flush_buffer(inode, filp, 0);
+ transfer = flush_buffer(STp, 0);
if (transfer)
return transfer;
STps->rw = ST_READING;
/* Get new data if the buffer is empty */
if ((STp->buffer)->buffer_bytes == 0) {
- special = read_tape(inode, count - total, &SRpnt);
+ special = read_tape(STp, count - total, &SRpnt);
if (special < 0) { /* No need to continue read */
if (SRpnt != NULL) {
scsi_release_request(SRpnt);
}
-static int st_set_options(struct inode *inode, long options)
+static int st_set_options(Scsi_Tape *STp, long options)
{
int value;
long code;
- Scsi_Tape *STp;
ST_mode *STm;
- int dev = TAPE_NR(inode->i_rdev);
+ int dev = TAPE_NR(STp->devt);
- STp = &(scsi_tapes[dev]);
STm = &(STp->modes[STp->current_mode]);
if (!STm->defined) {
memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
return 0;
}
\f
+#define MODE_HEADER_LENGTH 4
-#define COMPRESSION_PAGE 0x0f
-#define COMPRESSION_PAGE_LENGTH 16
+/* Mode header and page byte offsets */
+#define MH_OFF_DATA_LENGTH 0
+#define MH_OFF_MEDIUM_TYPE 1
+#define MH_OFF_DEV_SPECIFIC 2
+#define MH_OFF_BDESCS_LENGTH 3
+#define MP_OFF_PAGE_NBR 0
+#define MP_OFF_PAGE_LENGTH 1
-#define MODE_HEADER_LENGTH 4
+/* Mode header and page bit masks */
+#define MH_BIT_WP 0x80
+#define MP_MSK_PAGE_NBR 0x3f
-#define DCE_MASK 0x80
-#define DCC_MASK 0x40
-#define RED_MASK 0x60
+/* Don't return block descriptors */
+#define MODE_SENSE_OMIT_BDESCS 0x08
+#define MODE_SELECT_PAGE_FORMAT 0x10
-/* Control the compression with mode page 15. Algorithm not changed if zero. */
-static int st_compression(Scsi_Tape * STp, int state)
+/* Read a mode page into the tape buffer. The block descriptors are included
+ if incl_block_descs is true. */
+static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs)
{
- int dev;
unsigned char cmd[MAX_COMMAND_SIZE];
Scsi_Request *SRpnt = NULL;
- if (STp->ready != ST_READY)
- return (-EIO);
-
- /* Read the current page contents */
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SENSE;
- cmd[1] = 8;
- cmd[2] = COMPRESSION_PAGE;
- cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
+ if (omit_block_descs)
+ cmd[1] = MODE_SENSE_OMIT_BDESCS;
+ cmd[2] = page;
+ cmd[4] = 255;
SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ,
STp->timeout, 0, TRUE);
if (SRpnt == NULL)
return (STp->buffer)->syscall_result;
- dev = TAPE_NR(SRpnt->sr_request.rq_dev);
+ scsi_release_request(SRpnt);
- if ((STp->buffer)->syscall_result != 0) {
+ return (STp->buffer)->syscall_result;
+}
+
+
+/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
+ in the buffer is correctly formatted. */
+static int write_mode_page(Scsi_Tape *STp, int page)
+{
+ int pgo;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ Scsi_Request *SRpnt = NULL;
+
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = MODE_SELECT;
+ cmd[1] = MODE_SELECT_PAGE_FORMAT;
+ pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
+ cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
+
+ /* Clear reserved fields */
+ (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
+ (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
+ (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
+ (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
+
+ SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
+ STp->timeout, 0, TRUE);
+ if (SRpnt == NULL)
+ return (STp->buffer)->syscall_result;
+
+ scsi_release_request(SRpnt);
+
+ return (STp->buffer)->syscall_result;
+}
+
+
+#define COMPRESSION_PAGE 0x0f
+#define COMPRESSION_PAGE_LENGTH 16
+
+#define CP_OFF_DCE_DCC 2
+
+#define DCE_MASK 0x80
+#define DCC_MASK 0x40
+#define RED_MASK 0x60
+
+
+/* Control the compression with mode page 15. Algorithm not changed if zero.
+
+ The block descriptors are read and written because Sony SDT-7000 does not
+ work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
+ Including block descriptors should not cause any harm to other drives. */
+
+static int st_compression(Scsi_Tape * STp, int state)
+{
+ int retval;
+ int mpoffs; /* Offset to mode page start */
+ unsigned char *b_data = (STp->buffer)->b_data;
+ DEB( int dev = TAPE_NR(STp->devt); )
+
+ if (STp->ready != ST_READY)
+ return (-EIO);
+
+ /* Read the current page contents */
+ retval = read_mode_page(STp, COMPRESSION_PAGE, FALSE);
+ if (retval) {
DEBC(printk(ST_DEB_MSG "st%d: Compression mode page not supported.\n",
dev));
- scsi_release_request(SRpnt);
- SRpnt = NULL;
return (-EIO);
}
+
+ mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
DEBC(printk(ST_DEB_MSG "st%d: Compression state is %d.\n", dev,
- ((STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] & DCE_MASK ? 1 : 0)));
+ (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
/* Check if compression can be changed */
- if (((STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] & DCC_MASK) == 0) {
+ if ((b_data[mpoffs + 2] & DCC_MASK) == 0) {
DEBC(printk(ST_DEB_MSG "st%d: Compression not supported.\n", dev));
- scsi_release_request(SRpnt);
- SRpnt = NULL;
return (-EIO);
}
/* Do the change */
if (state)
- (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] |= DCE_MASK;
+ b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
else
- (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] &= ~DCE_MASK;
+ b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
- memset(cmd, 0, MAX_COMMAND_SIZE);
- cmd[0] = MODE_SELECT;
- cmd[1] = 0x10;
- cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
-
- (STp->buffer)->b_data[0] = 0; /* Reserved data length */
- (STp->buffer)->b_data[1] = 0; /* Reserved media type byte */
- (STp->buffer)->b_data[MODE_HEADER_LENGTH] &= 0x3f;
- SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
- STp->timeout, 0, TRUE);
-
- if ((STp->buffer)->syscall_result != 0) {
+ retval = write_mode_page(STp, COMPRESSION_PAGE);
+ if (retval) {
DEBC(printk(ST_DEB_MSG "st%d: Compression change failed.\n", dev));
- scsi_release_request(SRpnt);
- SRpnt = NULL;
return (-EIO);
}
DEBC(printk(ST_DEB_MSG "st%d: Compression state changed to %d.\n",
dev, state));
- scsi_release_request(SRpnt);
- SRpnt = NULL;
STp->compression_changed = TRUE;
return 0;
}
\f
/* Internal ioctl function */
-static int st_int_ioctl(struct inode *inode,
- unsigned int cmd_in, unsigned long arg)
+static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg)
{
int timeout;
long ltmp;
int chg_eof = TRUE;
unsigned char cmd[MAX_COMMAND_SIZE];
Scsi_Request *SRpnt;
- Scsi_Tape *STp;
ST_partstat *STps;
int fileno, blkno, at_sm, undone;
int datalen = 0, direction = SCSI_DATA_NONE;
- int dev = TAPE_NR(inode->i_rdev);
+ int dev = TAPE_NR(STp->devt);
- STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY && cmd_in != MTLOAD) {
if (STp->ready == ST_NO_TAPE)
return (-ENOMEDIUM);
case MTEOM:
if (!STp->fast_mteom) {
/* space to the end of tape */
- ioctl_result = st_int_ioctl(inode, MTFSF, 0x3fff);
+ ioctl_result = st_int_ioctl(STp, MTFSF, 0x3fff);
fileno = STps->drv_file;
if (STps->eof >= ST_EOD_1)
return 0;
STp->door_locked = ST_UNLOCKED;
if (cmd_in == MTBSFM)
- ioctl_result = st_int_ioctl(inode, MTFSF, 1);
+ ioctl_result = st_int_ioctl(STp, MTFSF, 1);
else if (cmd_in == MTFSFM)
- ioctl_result = st_int_ioctl(inode, MTBSF, 1);
+ ioctl_result = st_int_ioctl(STp, MTBSF, 1);
if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
STp->block_size = arg & MT_ST_BLKSIZE_MASK;
if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
STp->rew_at_close = 0;
else if (cmd_in == MTLOAD) {
- STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+ STp->rew_at_close = STp->autorew_dev;
for (i = 0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
STp->ps[i].last_block_valid = FALSE;
/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
structure. */
-static int get_location(struct inode *inode, unsigned int *block, int *partition,
+static int get_location(Scsi_Tape *STp, unsigned int *block, int *partition,
int logical)
{
- Scsi_Tape *STp;
- int dev = TAPE_NR(inode->i_rdev);
int result;
unsigned char scmd[MAX_COMMAND_SIZE];
Scsi_Request *SRpnt;
+ DEB( int dev = TAPE_NR(STp->devt); )
- STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
/* Set the tape block and partition. Negative partition means that only the
block should be set in vendor specific way. */
-static int set_location(struct inode *inode, unsigned int block, int partition,
+static int set_location(Scsi_Tape *STp, unsigned int block, int partition,
int logical)
{
- Scsi_Tape *STp;
ST_partstat *STps;
- int dev = TAPE_NR(inode->i_rdev);
int result, p;
unsigned int blk;
int timeout;
unsigned char scmd[MAX_COMMAND_SIZE];
Scsi_Request *SRpnt;
+ DEB( int dev = TAPE_NR(STp->devt); )
- STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
timeout = STp->long_timeout;
partition >= ST_NBR_PARTITIONS)
return (-EINVAL);
if (partition != STp->partition) {
- if (get_location(inode, &blk, &p, 1))
+ if (get_location(STp, &blk, &p, 1))
STps->last_block_valid = FALSE;
else {
STps->last_block_valid = TRUE;
result = (-EIO);
if (STp->can_partitions &&
(STp->device)->scsi_level >= SCSI_2 &&
- (p = find_partition(inode)) >= 0)
+ (p = find_partition(STp)) >= 0)
STp->partition = p;
} else {
if (STp->can_partitions) {
/* Find the current partition number for the drive status. Called from open and
returns either partition number of negative error code. */
-static int find_partition(struct inode *inode)
+static int find_partition(Scsi_Tape *STp)
{
int i, partition;
unsigned int block;
- if ((i = get_location(inode, &block, &partition, 1)) < 0)
+ if ((i = get_location(STp, &block, &partition, 1)) < 0)
return i;
if (partition >= ST_NBR_PARTITIONS)
return (-EIO);
/* Change the partition if necessary */
-static int update_partition(struct inode *inode)
+static int update_partition(Scsi_Tape *STp)
{
- int dev = TAPE_NR(inode->i_rdev);
- Scsi_Tape *STp;
ST_partstat *STps;
- STp = &(scsi_tapes[dev]);
if (STp->partition == STp->new_partition)
return 0;
STps = &(STp->ps[STp->new_partition]);
if (!STps->last_block_valid)
STps->last_block_visited = 0;
- return set_location(inode, STps->last_block_visited, STp->new_partition, 1);
+ return set_location(STp, STps->last_block_visited, STp->new_partition, 1);
}
\f
/* Functions for reading and writing the medium partition mode page. These
seem to work with Wangtek 6200HS and HP C1533A. */
#define PART_PAGE 0x11
-#define PART_PAGE_LENGTH 10
+#define PART_PAGE_FIXED_LENGTH 8
+
+#define PP_OFF_MAX_ADD_PARTS 2
+#define PP_OFF_NBR_ADD_PARTS 3
+#define PP_OFF_FLAGS 4
+#define PP_OFF_PART_UNITS 6
+#define PP_OFF_RESERVED 7
+
+#define PP_BIT_IDP 0x20
+#define PP_MSK_PSUM_MB 0x10
/* Get the number of partitions on the tape. As a side effect reads the
mode page into the tape buffer. */
-static int nbr_partitions(struct inode *inode)
+static int nbr_partitions(Scsi_Tape *STp)
{
- int dev = TAPE_NR(inode->i_rdev), result;
- Scsi_Tape *STp;
- Scsi_Request *SRpnt = NULL;
- unsigned char cmd[MAX_COMMAND_SIZE];
+ int result;
+ DEB( int dev = TAPE_NR(STp->devt) );
- STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
- memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
- cmd[0] = MODE_SENSE;
- cmd[1] = 8; /* Page format */
- cmd[2] = PART_PAGE;
- cmd[4] = 200;
-
- SRpnt = st_do_scsi(SRpnt, STp, cmd, 200, SCSI_DATA_READ, STp->timeout,
- MAX_READY_RETRIES, TRUE);
- if (SRpnt == NULL)
- return (STp->buffer)->syscall_result;
+ result = read_mode_page(STp, PART_PAGE, TRUE);
- scsi_release_request(SRpnt);
- SRpnt = NULL;
-
- if ((STp->buffer)->syscall_result != 0) {
+ if (result) {
DEBC(printk(ST_DEB_MSG "st%d: Can't read medium partition page.\n",
dev));
result = (-EIO);
} else {
- result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] + 1;
+ result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
+ PP_OFF_NBR_ADD_PARTS] + 1;
DEBC(printk(ST_DEB_MSG "st%d: Number of partitions %d.\n", dev, result));
}
/* Partition the tape into two partitions if size > 0 or one partition if
- size == 0 */
-static int partition_tape(struct inode *inode, int size)
+ size == 0.
+
+ The block descriptors are read and written because Sony SDT-7000 does not
+ work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
+
+ My HP C1533A drive returns only one partition size field. This is used to
+ set the size of partition 1. There is no size field for the default partition.
+ Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
+ used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
+ The following algorithm is used to accomodate both drives: if the number of
+ partition size fields is greater than the maximum number of additional partitions
+ in the mode page, the second field is used. Otherwise the first field is used.
+ */
+static int partition_tape(Scsi_Tape *STp, int size)
{
- int dev = TAPE_NR(inode->i_rdev), result;
- int length;
- Scsi_Tape *STp;
- Scsi_Request *SRpnt = NULL;
- unsigned char cmd[MAX_COMMAND_SIZE], *bp;
+ int dev = TAPE_NR(STp->devt), result;
+ int pgo, psd_cnt, psdo;
+ unsigned char *bp;
- if ((result = nbr_partitions(inode)) < 0)
+ result = read_mode_page(STp, PART_PAGE, FALSE);
+ if (result) {
+ DEBC(printk(ST_DEB_MSG "st%d: Can't read partition mode page.\n", dev));
return result;
- STp = &(scsi_tapes[dev]);
-
+ }
/* The mode page is in the buffer. Let's modify it and write it. */
- bp = &((STp->buffer)->b_data[0]);
+ bp = (STp->buffer)->b_data;
+ pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
+ DEBC(printk(ST_DEB_MSG "st%d: Partition page length is %d bytes.\n",
+ dev, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
+
+ psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
+ psdo = pgo + PART_PAGE_FIXED_LENGTH;
+ if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
+ bp[psdo] = bp[psdo + 1] = 0xff; /* Rest of the tape */
+ psdo += 2;
+ }
+ memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
+
+ DEBC(printk("st%d: psd_cnt %d, max.parts %d, nbr_parts %d\n", dev,
+ psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
+ bp[pgo + PP_OFF_NBR_ADD_PARTS]));
+
if (size <= 0) {
- length = 8;
- bp[MODE_HEADER_LENGTH + 3] = 0;
+ bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
DEBC(printk(ST_DEB_MSG "st%d: Formatting tape with one partition.\n",
dev));
} else {
- length = 10;
- bp[MODE_HEADER_LENGTH + 3] = 1;
- bp[MODE_HEADER_LENGTH + 8] = (size >> 8) & 0xff;
- bp[MODE_HEADER_LENGTH + 9] = size & 0xff;
+ bp[psdo] = (size >> 8) & 0xff;
+ bp[psdo + 1] = size & 0xff;
+ bp[pgo + 3] = 1;
DEBC(printk(ST_DEB_MSG
- "st%d: Formatting tape with two partition (1 = %d MB).\n",
+ "st%d: Formatting tape with two partitions (1 = %d MB).\n",
dev, size));
}
- bp[MODE_HEADER_LENGTH + 6] = 0;
- bp[MODE_HEADER_LENGTH + 7] = 0;
- bp[MODE_HEADER_LENGTH + 4] = 0x30; /* IDP | PSUM = MB */
-
- bp[0] = 0;
- bp[1] = 0;
- bp[MODE_HEADER_LENGTH] &= 0x3f;
- bp[MODE_HEADER_LENGTH + 1] = length - 2;
+ bp[pgo + PP_OFF_PART_UNITS] = 0;
+ bp[pgo + PP_OFF_RESERVED] = 0;
+ bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
- memset(cmd, 0, MAX_COMMAND_SIZE);
- cmd[0] = MODE_SELECT;
- cmd[1] = 0x10;
- cmd[4] = length + MODE_HEADER_LENGTH;
-
- SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
- STp->long_timeout, MAX_READY_RETRIES, TRUE);
- if (SRpnt == NULL)
- return (STp->buffer)->syscall_result;
-
- scsi_release_request(SRpnt);
- SRpnt = NULL;
-
- if ((STp->buffer)->syscall_result != 0) {
+ result = write_mode_page(STp, PART_PAGE);
+ if (result) {
printk(KERN_INFO "st%d: Partitioning of tape failed.\n", dev);
result = (-EIO);
- } else
- result = 0;
+ }
return result;
}
{
int i, cmd_nr, cmd_type, bt;
unsigned int blk;
- struct mtop mtc;
- struct mtpos mt_pos;
Scsi_Tape *STp;
ST_mode *STm;
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
- STp = &(scsi_tapes[dev]);
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
+
DEB(
if (debugging && !STp->in_use) {
printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
cmd_nr = _IOC_NR(cmd_in);
if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
+ struct mtop mtc;
+
if (_IOC_SIZE(cmd_in) != sizeof(mtc))
return (-EINVAL);
mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
mtc.mt_op == MTCOMPRESSION;
}
- i = flush_buffer(inode, file, i);
+ i = flush_buffer(STp, i);
if (i < 0)
return i;
} else {
STp->device->was_reset = 0;
if (STp->door_locked != ST_UNLOCKED &&
STp->door_locked != ST_LOCK_FAILS) {
- if (st_int_ioctl(inode, MTLOCK, 0)) {
+ if (st_int_ioctl(STp, MTLOCK, 0)) {
printk(KERN_NOTICE
"st%d: Could not relock door after bus reset.\n",
dev);
STps->rw = ST_IDLE; /* Prevent automatic WEOF and fsf */
if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
- st_int_ioctl(inode, MTUNLOCK, 0); /* Ignore result! */
+ st_int_ioctl(STp, MTUNLOCK, 0); /* Ignore result! */
if (mtc.mt_op == MTSETDRVBUFFER &&
(mtc.mt_count & MT_ST_OPTIONS) != 0)
- return st_set_options(inode, mtc.mt_count);
+ return st_set_options(STp, mtc.mt_count);
if (mtc.mt_op == MTSETPART) {
if (!STp->can_partitions ||
mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
return (-EINVAL);
if (mtc.mt_count >= STp->nbr_partitions &&
- (STp->nbr_partitions = nbr_partitions(inode)) < 0)
+ (STp->nbr_partitions = nbr_partitions(STp)) < 0)
return (-EIO);
if (mtc.mt_count >= STp->nbr_partitions)
return (-EINVAL);
if (mtc.mt_op == MTMKPART) {
if (!STp->can_partitions)
return (-EINVAL);
- if ((i = st_int_ioctl(inode, MTREW, 0)) < 0 ||
- (i = partition_tape(inode, mtc.mt_count)) < 0)
+ if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
+ (i = partition_tape(STp, mtc.mt_count)) < 0)
return i;
for (i = 0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
}
if (mtc.mt_op == MTSEEK) {
- i = set_location(inode, mtc.mt_count, STp->new_partition, 0);
+ i = set_location(STp, mtc.mt_count, STp->new_partition, 0);
if (!STp->can_partitions)
STp->ps[0].rw = ST_IDLE;
return i;
}
if (STp->can_partitions && STp->ready == ST_READY &&
- (i = update_partition(inode)) < 0)
+ (i = update_partition(STp)) < 0)
return i;
if (mtc.mt_op == MTCOMPRESSION)
return st_compression(STp, (mtc.mt_count & 1));
else
- return st_int_ioctl(inode, mtc.mt_op, mtc.mt_count);
+ return st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
}
if (!STm->defined)
return (-ENXIO);
- if ((i = flush_buffer(inode, file, FALSE)) < 0)
+ if ((i = flush_buffer(STp, FALSE)) < 0)
return i;
if (STp->can_partitions &&
- (i = update_partition(inode)) < 0)
+ (i = update_partition(STp)) < 0)
return i;
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
+ struct mtget mt_status;
if (_IOC_SIZE(cmd_in) != sizeof(struct mtget))
return (-EINVAL);
- (STp->mt_status)->mt_dsreg =
+ mt_status.mt_type = STp->tape_type;
+ mt_status.mt_dsreg =
((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
- (STp->mt_status)->mt_blkno = STps->drv_block;
- (STp->mt_status)->mt_fileno = STps->drv_file;
+ mt_status.mt_blkno = STps->drv_block;
+ mt_status.mt_fileno = STps->drv_file;
if (STp->block_size != 0) {
if (STps->rw == ST_WRITING)
- (STp->mt_status)->mt_blkno +=
+ mt_status.mt_blkno +=
(STp->buffer)->buffer_bytes / STp->block_size;
else if (STps->rw == ST_READING)
- (STp->mt_status)->mt_blkno -=
+ mt_status.mt_blkno -=
((STp->buffer)->buffer_bytes +
STp->block_size - 1) / STp->block_size;
}
- (STp->mt_status)->mt_gstat = 0;
+ mt_status.mt_gstat = 0;
if (STp->drv_write_prot)
- (STp->mt_status)->mt_gstat |= GMT_WR_PROT(0xffffffff);
- if ((STp->mt_status)->mt_blkno == 0) {
- if ((STp->mt_status)->mt_fileno == 0)
- (STp->mt_status)->mt_gstat |= GMT_BOT(0xffffffff);
+ mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
+ if (mt_status.mt_blkno == 0) {
+ if (mt_status.mt_fileno == 0)
+ mt_status.mt_gstat |= GMT_BOT(0xffffffff);
else
- (STp->mt_status)->mt_gstat |= GMT_EOF(0xffffffff);
+ mt_status.mt_gstat |= GMT_EOF(0xffffffff);
}
- (STp->mt_status)->mt_resid = STp->partition;
+ mt_status.mt_erreg = (STp->recover_reg << MT_ST_SOFTERR_SHIFT);
+ mt_status.mt_resid = STp->partition;
if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
- (STp->mt_status)->mt_gstat |= GMT_EOT(0xffffffff);
+ mt_status.mt_gstat |= GMT_EOT(0xffffffff);
else if (STps->eof >= ST_EOM_OK)
- (STp->mt_status)->mt_gstat |= GMT_EOD(0xffffffff);
+ mt_status.mt_gstat |= GMT_EOD(0xffffffff);
if (STp->density == 1)
- (STp->mt_status)->mt_gstat |= GMT_D_800(0xffffffff);
+ mt_status.mt_gstat |= GMT_D_800(0xffffffff);
else if (STp->density == 2)
- (STp->mt_status)->mt_gstat |= GMT_D_1600(0xffffffff);
+ mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
else if (STp->density == 3)
- (STp->mt_status)->mt_gstat |= GMT_D_6250(0xffffffff);
+ mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
if (STp->ready == ST_READY)
- (STp->mt_status)->mt_gstat |= GMT_ONLINE(0xffffffff);
+ mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
if (STp->ready == ST_NO_TAPE)
- (STp->mt_status)->mt_gstat |= GMT_DR_OPEN(0xffffffff);
+ mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
if (STps->at_sm)
- (STp->mt_status)->mt_gstat |= GMT_SM(0xffffffff);
+ mt_status.mt_gstat |= GMT_SM(0xffffffff);
if (STm->do_async_writes ||
(STm->do_buffer_writes && STp->block_size != 0) ||
STp->drv_buffer != 0)
- (STp->mt_status)->mt_gstat |= GMT_IM_REP_EN(0xffffffff);
+ mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
- i = copy_to_user((char *) arg, (char *) (STp->mt_status),
+ i = copy_to_user((char *) arg, (char *) &(mt_status),
sizeof(struct mtget));
if (i)
return (-EFAULT);
- (STp->mt_status)->mt_erreg = 0; /* Clear after read */
+ STp->recover_reg = 0; /* Clear after read */
return 0;
} /* End of MTIOCGET */
if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
+ struct mtpos mt_pos;
if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
return (-EINVAL);
- if ((i = get_location(inode, &blk, &bt, 0)) < 0)
+ if ((i = get_location(STp, &blk, &bt, 0)) < 0)
return i;
mt_pos.mt_blkno = blk;
i = copy_to_user((char *) arg, (char *) (&mt_pos), sizeof(struct mtpos));
}
\f
-/* Try to allocate a new tape buffer */
+/* Try to allocate a new tape buffer. Calling function must not hold
+ dev_arr_lock. */
static ST_buffer *
new_tape_buffer(int from_initialization, int need_dma)
{
int i, priority, b_size, order, got = 0, segs = 0;
+ unsigned long flags;
ST_buffer *tb;
- if (st_nbr_buffers >= st_template.dev_max)
+ read_lock(&st_dev_arr_lock);
+ if (st_nbr_buffers >= st_template.dev_max) {
+ read_unlock(&st_dev_arr_lock);
return NULL; /* Should never happen */
+ }
+ read_unlock(&st_dev_arr_lock);
if (from_initialization)
priority = GFP_ATOMIC;
tb->dma = need_dma;
tb->buffer_size = got;
tb->writing = 0;
+
+ write_lock_irqsave(&st_dev_arr_lock, flags);
st_buffers[st_nbr_buffers++] = tb;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
return tb;
}
priority |= GFP_DMA;
for (b_size = PAGE_SIZE, order=0;
b_size * nbr < new_size - STbuffer->buffer_size;
- order++, b_size *= 2);
+ order++, b_size *= 2)
+ ; /* empty */
for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
segs < max_segs && got < new_size;) {
for (i = STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
order++, b_size *= 2)
- ;
+ ; /* empty */
free_pages((unsigned long)(STbuffer->sg[i].address), order);
STbuffer->buffer_size -= STbuffer->sg[i].length;
}
Scsi_Tape *tpnt;
ST_mode *STm;
ST_partstat *STps;
- int i, mode;
+ int i, mode, target_nbr;
+ unsigned long flags = 0;
if (SDp->type != TYPE_TAPE)
return 1;
+ write_lock_irqsave(&st_dev_arr_lock, flags);
if (st_template.nr_dev >= st_template.dev_max) {
- SDp->attached--;
- return 1;
+ Scsi_Tape **tmp_da;
+ ST_buffer **tmp_ba;
+ int tmp_dev_max;
+
+ tmp_dev_max = st_template.nr_dev + ST_DEV_ARR_LUMP;
+ if (tmp_dev_max > ST_MAX_TAPES)
+ tmp_dev_max = ST_MAX_TAPES;
+ if (tmp_dev_max <= st_template.nr_dev) {
+ SDp->attached--;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
+ ST_MAX_TAPES);
+ return 1;
+ }
+
+ tmp_da = (Scsi_Tape **) kmalloc(tmp_dev_max * sizeof(Scsi_Tape *),
+ GFP_ATOMIC);
+ tmp_ba = (ST_buffer **) kmalloc(tmp_dev_max * sizeof(ST_buffer *),
+ GFP_ATOMIC);
+ if (tmp_da == NULL || tmp_ba == NULL) {
+ if (tmp_da != NULL)
+ kfree(tmp_da);
+ SDp->attached--;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ printk(KERN_ERR "st: Can't extend device array.\n");
+ return 1;
+ }
+
+ memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *));
+ if (scsi_tapes != NULL) {
+ memcpy(tmp_da, scsi_tapes,
+ st_template.dev_max * sizeof(Scsi_Tape *));
+ kfree(scsi_tapes);
+ }
+ scsi_tapes = tmp_da;
+
+ memset(tmp_ba, 0, tmp_dev_max * sizeof(ST_buffer *));
+ if (st_buffers != NULL) {
+ memcpy(tmp_ba, st_buffers,
+ st_template.dev_max * sizeof(ST_buffer *));
+ kfree(st_buffers);
+ }
+ st_buffers = tmp_ba;
+
+ st_template.dev_max = tmp_dev_max;
}
- for (tpnt = scsi_tapes, i = 0; i < st_template.dev_max; i++, tpnt++)
- if (!tpnt->device)
+ for (i = 0; i < st_template.dev_max; i++)
+ if (scsi_tapes[i] == NULL)
break;
-
if (i >= st_template.dev_max)
panic("scsi_devices corrupt (st)");
+ tpnt = (Scsi_Tape *)kmalloc(sizeof(Scsi_Tape), GFP_ATOMIC);
+ if (tpnt == NULL) {
+ SDp->attached--;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ printk(KERN_ERR "st: Can't allocate device descriptor.\n");
+ return 1;
+ }
+ memset(tpnt, 0, sizeof(Scsi_Tape));
+ scsi_tapes[i] = tpnt;
+
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
char name[8];
static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"};
0, 0, &st_fops, NULL);
}
devfs_register_tape (tpnt->de_r[0]);
- scsi_tapes[i].device = SDp;
+ tpnt->device = SDp;
if (SDp->scsi_level <= 2)
- scsi_tapes[i].mt_status->mt_type = MT_ISSCSI1;
+ tpnt->tape_type = MT_ISSCSI1;
else
- scsi_tapes[i].mt_status->mt_type = MT_ISSCSI2;
+ tpnt->tape_type = MT_ISSCSI2;
tpnt->inited = 0;
tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i);
tpnt->blksize_changed = FALSE;
st_template.nr_dev++;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
+
+ /* See if we need to allocate more static buffers */
+ target_nbr = st_template.nr_dev;
+ if (target_nbr > st_max_buffers)
+ target_nbr = st_max_buffers;
+ for (i=st_nbr_buffers; i < target_nbr; i++)
+ if (!new_tape_buffer(TRUE, TRUE)) {
+ printk(KERN_INFO "st: Unable to allocate new static buffer.\n");
+ break;
+ }
+ /* If the previous allocation fails, we will try again when the buffer is
+ really needed. */
+
return 0;
};
/* Driver initialization (not __init because may be called later) */
static int st_init()
{
- int i, j;
- Scsi_Tape *STp;
- int target_nbr;
+ unsigned long flags;
- if (st_template.dev_noticed == 0)
+ if (st_template.dev_noticed == 0 || st_registered)
return 0;
printk(KERN_INFO "st: bufsize %d, wrt %d, max init. buffers %d, s/g segs %d.\n",
st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
+ write_lock_irqsave(&st_dev_arr_lock, flags);
if (!st_registered) {
if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops)) {
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
MAJOR_NR);
return 1;
}
st_registered++;
}
- if (scsi_tapes)
- return 0;
- st_template.dev_max = st_template.dev_noticed + ST_EXTRA_DEVS;
- if (st_template.dev_max < ST_MAX_TAPES)
- st_template.dev_max = ST_MAX_TAPES;
- if (st_template.dev_max > 128 / ST_NBR_MODES)
- printk(KERN_INFO "st: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
- scsi_tapes =
- (Scsi_Tape *) kmalloc(st_template.dev_max * sizeof(Scsi_Tape),
- GFP_ATOMIC);
- if (scsi_tapes == NULL) {
- printk(KERN_ERR "Unable to allocate descriptors for SCSI tapes.\n");
- devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- return 1;
- }
-
- DEB(printk(ST_DEB_MSG "st: Buffer size %d bytes, write threshold %d bytes.\n",
- st_buffer_size, st_write_threshold));
- memset(scsi_tapes, 0, st_template.dev_max * sizeof(Scsi_Tape));
- for (i = 0; i < st_template.dev_max; ++i) {
- STp = &(scsi_tapes[i]);
- STp->capacity = 0xfffff;
- STp->mt_status = (struct mtget *) kmalloc(sizeof(struct mtget),
- GFP_ATOMIC);
- if (STp->mt_status == NULL) {
- for (j=0; j < i; j++)
- kfree(scsi_tapes[j].mt_status);
- kfree(scsi_tapes);
- devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- return 1;
- }
- /* Initialize status */
- memset((void *) scsi_tapes[i].mt_status, 0, sizeof(struct mtget));
- }
-
- /* Allocate the buffers */
- st_buffers =
- (ST_buffer **) kmalloc(st_template.dev_max * sizeof(ST_buffer *),
- GFP_ATOMIC);
- if (st_buffers == NULL) {
- printk(KERN_ERR "Unable to allocate tape buffer pointers.\n");
- devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- for (i=0; i < st_template.dev_max; i++)
- kfree(scsi_tapes[i].mt_status);
- kfree(scsi_tapes);
- unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- return 1;
- }
- target_nbr = st_template.dev_noticed;
- if (target_nbr < ST_EXTRA_DEVS)
- target_nbr = ST_EXTRA_DEVS;
- if (target_nbr > st_max_buffers)
- target_nbr = st_max_buffers;
-
- for (i = st_nbr_buffers = 0; i < target_nbr; i++) {
- if (!new_tape_buffer(TRUE, TRUE)) {
- if (i == 0) {
- printk(KERN_INFO
- "No tape buffers allocated at initialization.\n");
- break;
- }
- printk(KERN_INFO "Number of tape buffers adjusted.\n");
- break;
- }
- }
+ st_template.dev_max = 0;
+ st_nbr_buffers = 0;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
return 0;
}
{
Scsi_Tape *tpnt;
int i, mode;
+ unsigned long flags;
- for (tpnt = scsi_tapes, i = 0; i < st_template.dev_max; i++, tpnt++)
- if (tpnt->device == SDp) {
+ write_lock_irqsave(&st_dev_arr_lock, flags);
+ for (i = 0; i < st_template.dev_max; i++) {
+ tpnt = scsi_tapes[i];
+ if (tpnt != NULL && tpnt->device == SDp) {
tpnt->device = NULL;
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_unregister (tpnt->de_r[mode]);
devfs_unregister (tpnt->de_n[mode]);
tpnt->de_n[mode] = NULL;
}
+ kfree(tpnt);
+ scsi_tapes[i] = 0;
SDp->attached--;
st_template.nr_dev--;
st_template.dev_noticed--;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
return;
}
+ }
+
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
return;
}
st_registered--;
if (scsi_tapes != NULL) {
for (i=0; i < st_template.dev_max; ++i)
- kfree(scsi_tapes[i].mt_status);
+ if (scsi_tapes[i])
+ kfree(scsi_tapes[i]);
kfree(scsi_tapes);
if (st_buffers != NULL) {
for (i = 0; i < st_nbr_buffers; i++) {
#define ST_NBR_MODES (1 << ST_NBR_MODE_BITS)
#define ST_MODE_SHIFT (7 - ST_NBR_MODE_BITS)
#define ST_MODE_MASK ((ST_NBR_MODES - 1) << ST_MODE_SHIFT)
+#define ST_MAX_TAPES (1 << ST_MODE_SHIFT)
/* The status related to each partition */
typedef struct {
/* The tape drive descriptor */
typedef struct {
kdev_t devt;
- unsigned capacity;
Scsi_Device *device;
struct semaphore sem;
ST_buffer *buffer;
unsigned char restr_dma;
unsigned char scsi2_logical;
unsigned char default_drvbuffer; /* 0xff = don't touch, value 3 bits */
+ int tape_type;
int write_threshold;
int timeout; /* timeout for normal commands */
int long_timeout; /* timeout for commands known to take long time */
unsigned char drv_buffer;
unsigned char density;
unsigned char door_locked;
- unsigned char rew_at_close;
+ unsigned char autorew_dev; /* auto-rewind device */
+ unsigned char rew_at_close; /* rewind necessary at close */
unsigned char inited;
int block_size;
int min_block;
int max_block;
- int recover_count;
- struct mtget *mt_status;
+ int recover_count; /* From tape opening */
+ int recover_reg; /* From last status call */
#if DEBUG
unsigned char write_pending;
#endif
} Scsi_Tape;
-extern Scsi_Tape *scsi_tapes;
/* Values of eof */
#define ST_NOEOF 0
Copyright 1995-2000 Kai Makisara.
- Last modified: Sat Jan 1 18:34:38 2000 by makisara@kai.makisara.local
+ Last modified: Sat Mar 11 10:32:00 2000 by makisara@kai.makisara.local
*/
#ifndef _ST_OPTIONS_H
#define _ST_OPTIONS_H
-/* The minimum limit for the number of SCSI tape devices is determined by
- ST_MAX_TAPES. If the number of tape devices and the "slack" defined by
- ST_EXTRA_DEVS exceeds ST_MAX_TAPES, the large number is used. */
-#define ST_MAX_TAPES 4
-
/* The driver does not wait for some operations to finish before returning
to the user program if ST_NOWAIT is non-zero. This helps if the SCSI
adapter does not support multiple outstanding commands. However, the user
driver initialisation. The number is also constrained by the number
of drives detected. If more buffers are needed, they are allocated
at run time and freed after use. */
-#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
+#define ST_MAX_BUFFERS 4
/* Maximum number of scatter/gather segments */
#define ST_MAX_SG 16
dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+ bool ' Verbose initialisation' CONFIG_SOUND_TRACEINIT
+ bool ' Persistent DMA buffers' CONFIG_SOUND_DMAP
+
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate ' AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND
fi
-
dep_tristate ' Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
dep_tristate ' Adlib Cards' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS
dep_tristate ' ACI mixer (miroPCM12)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
#include "sound_config.h"
int softoss_dev = 0;
-int sound_started = 0;
-int sndtable_get_cardcount(void);
int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
int driver_size, int flags, unsigned int format_mask,
* NOTE! NOTE! NOTE! NOTE!
*/
-extern int sound_started;
-
struct driver_info
{
char *driver_id;
#ifdef _DEV_TABLE_C_
-struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
-struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
-struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
-struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
-
+struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL};
+int num_audiodevs = 0;
+struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL};
+int num_mixers = 0;
+struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL};
+int num_synths = 0;
+struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL};
+int num_midis = 0;
#ifndef EXCLUDE_TIMERS
extern struct sound_timer_operations default_sound_timer;
struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {
#else
-extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs;
-extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
-extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths;
-extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
-extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; extern int num_sound_timers;
+extern struct audio_operations *audio_devs[MAX_AUDIO_DEV];
+extern int num_audiodevs;
+extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
+extern int num_mixers;
+extern struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV];
+extern int num_synths;
+extern struct midi_operations *midi_devs[MAX_MIDI_DEV];
+extern int num_midis;
+extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV];
+extern int num_sound_timers;
#endif /* _DEV_TABLE_C_ */
-void setup_cards(void);
-int sndtable_get_cardcount (void);
-void sound_chconf(int card_type, int ioaddr, int irq, int dma);
-int snd_find_driver(int type);
-void sound_unload_driver(int type);
-int sndtable_identify_card(char *name);
extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
int sndtable_probe (int unit, struct address_info *hw_config);
{
/* Can be loaded either for module use or to provide functions
to others */
- cfg.irq = irq;
- cfg.io_base = io;
-
- if (cfg.io_base != -1 && cfg.irq != -1) {
- printk(KERN_WARNING "mpu401: need io and irq !");
- return -ENODEV;
+ if (io != -1 && irq != -1) {
+ cfg.irq = irq;
+ cfg.io_base = io;
+ if (probe_mpu401(&cfg) == 0)
+ return -ENODEV;
+ attach_mpu401(&cfg);
}
- if (probe_mpu401(&cfg) == 0)
- return -ENODEV;
- attach_mpu401(&cfg);
-
SOUND_LOCK;
return 0;
}
void cleanup_mpu401(void)
{
- unload_mpu401(&cfg);
+ if (io != -1 && irq != -1) {
+ /* Check for use by, for example, sscape driver */
+ unload_mpu401(&cfg);
+ }
SOUND_LOCK_END;
}
/* @X@0001:mpu
*/
-#ifdef CONFIG_MIDI
if((mpu_dev = isapnp_find_dev(bus,
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL)))
{
}
else
printk(KERN_ERR "sb: DT0197H panic: mpu not found\n");
-#endif
/* @P@:Gameport
int sound_nblocks = 0;
/* Persistent DMA buffers */
-int sound_dmap_flag = 0;
+#ifdef CONFIG_SOUND_DMAP
+int sound_dmap_flag = 1;
+#else
+int sound_dmap_flag = 0;
+#endif
+
static int soundcard_configured = 0;
static char dma_alloc_map[MAX_DMA_CHANNELS] = {0};
static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
static int num_mixer_volumes = 0;
-int traceinit = 0;
-
int *load_mixer_volumes(char *name, int *levels, int present)
{
int i, n;
soundcard_configured = 1;
-#if defined(CONFIG_LOWLEVEL_SOUND) && !defined(MODULE)
- sound_preinit_lowlevel_drivers();
- sound_init_lowlevel_drivers();
-#endif
-
audio_init_devices();
soundcard_register_devfs(1); /* register after we know # of devices */
static int dmabuf = 0;
static int dmabug = 0;
-MODULE_PARM(traceinit, "i");
MODULE_PARM(dmabuf, "i");
MODULE_PARM(dmabug, "i");
int init_module(void)
{
int err;
-#if FIXED_FOR_2_4_0
- int ints[21];
- int i;
-#endif
-#ifdef HAS_BRIDGE_BUGGY_FUNC
if(dmabug)
isa_dma_bridge_buggy = dmabug;
-#else
- if(dmabug)
- printk(KERN_ERR "sound: rebuild with PCI_QUIRKS enabled to configure this.\n");
-#endif
-
-#if FIXED_FOR_2_4_0
- /*
- * "sound=" command line handling by Harald Milz.
- */
- i = 0;
- while (i < 20 && sound[i])
- ints[i + 1] = sound[i++];
- ints[0] = i;
-
- if (i)
- sound_setup("sound=", ints);
-#endif
err = create_special_devices();
if (err)
sound_stop_timer();
-#ifdef CONFIG_LOWLEVEL_SOUND
- {
- extern void sound_unload_lowlevel_drivers(void);
-
- sound_unload_lowlevel_drivers();
- }
-#endif
sequencer_unload();
for (i = 0; i < MAX_DMA_CHANNELS; i++)
void conf_printf(char *name, struct address_info *hw_config)
{
- if (!traceinit)
- return;
+#ifndef CONFIG_SOUND_TRACEINIT
+ return;
+#else
printk("<%s> at 0x%03x", name, hw_config->io_base);
if (hw_config->irq)
}
printk("\n");
}
+#endif
void conf_printf2(char *name, int base, int irq, int dma, int dma2)
{
- if (!traceinit)
- return;
-
+#ifndef CONFIG_SOUND_TRACEINIT
+ return;
+#else
printk("<%s> at 0x%03x", name, base);
if (irq)
}
printk("\n");
}
+#endif
/*
* Module and lock management
/* Handle mangled (versioned) external symbols */
-#include <linux/config.h> /* retrieve the CONFIG_* macros */
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/list.h>
*
* History:
*
+ * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
+ * minor fixes
* - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for
* HGA-only systems
* - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#define DPRINTK(args...)
#endif
-#if 1
+#if 0
#define CHKINFO(ret) if (info != &fb_info) { printk(KERN_DEBUG __FILE__": This should never happen, line:%d \n", __LINE__); return ret; }
#else
#define CHKINFO(ret)
#define HGA_GFX_MODE_EN 0x01
#define HGA_GFX_PAGE_EN 0x02
+/* Global locks */
+
+spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED;
+
/* Framebuffer driver structures */
static struct fb_var_screeninfo hga_default_var = {
static void write_hga_b(unsigned int val, unsigned char reg)
{
- unsigned long flags;
-
- save_flags(flags); cli();
-
outb_p(reg, HGA_INDEX_PORT);
outb_p(val, HGA_VALUE_PORT);
-
- restore_flags(flags);
}
static void write_hga_w(unsigned int val, unsigned char reg)
{
- unsigned long flags;
-
- save_flags(flags); cli();
-
outb_p(reg, HGA_INDEX_PORT); outb_p(val >> 8, HGA_VALUE_PORT);
outb_p(reg+1, HGA_INDEX_PORT); outb_p(val & 0xff, HGA_VALUE_PORT);
-
- restore_flags(flags);
}
static int test_hga_b(unsigned char val, unsigned char reg)
{
- unsigned long flags;
-
- save_flags(flags); cli();
-
outb_p(reg, HGA_INDEX_PORT);
outb (val, HGA_VALUE_PORT);
-
udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
-
- restore_flags(flags);
-
return val;
}
static void hga_clear_screen(void)
{
+ unsigned char fillchar = 0xbf; /* magic */
+ unsigned long flags;
+
+ spin_lock_irqsave(&hga_reg_lock, flags);
if (hga_mode == HGA_TXT)
- memset((char *)hga_vram_base, ' ', hga_vram_len);
+ fillchar = ' ';
else if (hga_mode == HGA_GFX)
- memset((char *)hga_vram_base, 0, hga_vram_len);
+ fillchar = 0x00;
+ spin_unlock_irqrestore(&hga_reg_lock, flags);
+ if (fillchar != 0xbf)
+ memset((char *)hga_vram_base, fillchar, hga_vram_len);
}
+#ifdef MODULE
static void hga_txt_mode(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hga_reg_lock, flags);
outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_BLINK_EN, HGA_MODE_PORT);
outb_p(0x00, HGA_GFX_PORT);
outb_p(0x00, HGA_STATUS_PORT);
write_hga_w(0x0000, 0x0e); /* cursor location */
hga_mode = HGA_TXT;
+ spin_unlock_irqrestore(&hga_reg_lock, flags);
}
+#endif /* MODULE */
static void hga_gfx_mode(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hga_reg_lock, flags);
outb_p(0x00, HGA_STATUS_PORT);
outb_p(HGA_GFX_MODE_EN, HGA_GFX_PORT);
outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
write_hga_w(0x0000, 0x0e); /* cursor location */
hga_mode = HGA_GFX;
+ spin_unlock_irqrestore(&hga_reg_lock, flags);
}
#ifdef MODULE
static void hga_pan(unsigned int xoffset, unsigned int yoffset)
{
unsigned int base;
+ unsigned long flags;
+
base = (yoffset / 8) * 90 + xoffset;
+ spin_lock_irqsave(&hga_reg_lock, flags);
write_hga_w(base, 0x0c); /* start address */
+ spin_unlock_irqrestore(&hga_reg_lock, flags);
DPRINTK("hga_pan: base:%d\n", base);
}
-static int hga_card_detect(void)
+static void hga_blank(int blank_mode)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hga_reg_lock, flags);
+ if (blank_mode) {
+ outb_p(0x00, HGA_MODE_PORT); /* disable video */
+ } else {
+ outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
+ }
+ spin_unlock_irqrestore(&hga_reg_lock, flags);
+}
+
+static int __init hga_card_detect(void)
{
int count=0;
u16 *p, p_save;
hga_vram_base = VGA_MAP_MEM(0xb0000);
hga_vram_len = 0x08000;
- if (!request_mem_region(hga_vram_base, hga_vram_len, "hgafb")) {
- printk(KERN_ERR "hgafb: cannot reserve video memory at 0x%lX\n",
- hga_vram_base);
- return 0;
- }
if (request_region(0x3b0, 12, "hgafb"))
release_io_ports = 1;
if (request_region(0x3bf, 1, "hgafb"))
CHKINFO( );
DPRINTK("hga_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info);
- if (blank_mode) {
- outb_p(0x00, HGA_MODE_PORT); /* disable video */
- } else {
- outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
- }
+ hga_blank(blank_mode);
}
disp.line_length = hga_fix.line_length;
disp.can_soft_blank = 1;
disp.inverse = 0;
+#ifdef FBCON_HAS_HGA
disp.dispsw = &fbcon_hga;
+#else
+#warning HGAFB will not work as a console!
+ disp.dispsw = &fbcon_dummy;
+#endif
disp.dispsw_data = NULL;
disp.scrollmode = SCROLL_YREDRAW;
unregister_framebuffer(info);
if (release_io_ports) release_region(0x3b0, 12);
if (release_io_port) release_region(0x3bf, 1);
- release_mem_region(hga_vram_base, hga_vram_len);
}
#endif /* MODULE */
*
* Common directory handling for ADFS
*/
+#include <linux/config.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/fs.h>
static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
-int __init init_affs_fs(void)
+static int __init init_affs_fs(void)
{
return register_filesystem(&affs_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int
-init_module(void)
-{
- return register_filesystem(&affs_fs_type);
-}
-
-void
-cleanup_module(void)
+static void __exit exit_affs_fs(void)
{
unregister_filesystem(&affs_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_affs_fs)
+module_exit(exit_affs_fs)
static DECLARE_FSTYPE_DEV( bfs_fs_type, "bfs", bfs_read_super);
-#ifdef MODULE
-#define init_bfs_fs init_module
-
-void cleanup_module(void)
+static int __init init_bfs_fs(void)
{
- unregister_filesystem(&bfs_fs_type);
+ return register_filesystem(&bfs_fs_type);
}
-#endif
-int __init init_bfs_fs(void)
+static void __exit exit_bfs_fs(void)
{
- return register_filesystem(&bfs_fs_type);
+ unregister_filesystem(&bfs_fs_type);
}
+
+module_init(init_bfs_fs)
+module_exit(exit_bfs_fs)
* dumping of the process results in another error..
*/
-static inline int
-do_aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
+static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
{
mm_segment_t fs;
int has_dumped = 0;
return has_dumped;
}
-static int
-aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_aout_core_dump(signr, regs, file);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/*
* create_aout_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* libraries. There is no binary dependent code anywhere else.
*/
-static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct exec ex;
struct file * file;
}
}
beyond_if:
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
if (current->binfmt && current->binfmt->module)
__MOD_DEC_USE_COUNT(current->binfmt->module);
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
if (current->binfmt && current->binfmt->module)
__MOD_INC_USE_COUNT(current->binfmt->module);
return 0;
}
-
-static int
-load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_aout_binary(bprm, regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
-static inline int
-do_load_aout_library(int fd)
+static int load_aout_library(int fd)
{
struct file * file;
struct inode * inode;
return retval;
}
-static int
-load_aout_library(int fd)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_aout_library(fd);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
-
static int __init init_aout_binfmt(void)
{
return register_binfmt(&aout_format);
module_init(init_aout_binfmt);
module_exit(exit_aout_binfmt);
-
#define INTERPRETER_ELF 2
-static inline int
-do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct file * file;
struct dentry *interpreter_dentry = NULL; /* to shut gcc up */
if (interpreter_type != INTERPRETER_AOUT)
sys_close(elf_exec_fileno);
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
if (current->binfmt && current->binfmt->module)
__MOD_DEC_USE_COUNT(current->binfmt->module);
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &elf_format;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
if (current->binfmt && current->binfmt->module)
__MOD_INC_USE_COUNT(current->binfmt->module);
goto out;
}
-static int
-load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_elf_binary(bprm, regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/* This is really simpleminded and specialized - we are loading an
a.out library that is given an ELF header. */
-static inline int
-do_load_elf_library(int fd)
+static int load_elf_library(int fd)
{
struct file * file;
struct dentry * dentry;
return error;
}
-static int load_elf_library(int fd)
-{
- int retval;
-
- MOD_INC_USE_COUNT;
- retval = do_load_elf_library(fd);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
/*
* Note that some platforms still use traditional core dumps and not
* the ELF core dump. Each platform can select it as appropriate.
elf_fpregset_t fpu; /* NT_PRFPREG */
struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
-#ifndef CONFIG_BINFMT_ELF
- MOD_INC_USE_COUNT;
-#endif
-
/* Count what's needed to dump, up to the limit of coredump size */
segs = 0;
size = 0;
end_coredump:
set_fs(fs);
-#ifndef CONFIG_BINFMT_ELF
- MOD_DEC_USE_COUNT;
-#endif
return has_dumped;
}
#endif /* USE_ELF_CORE_DUMP */
#define EM86_INTERP "/usr/bin/em86"
#define EM86_I_NAME "em86"
-static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *interp, *i_name, *i_arg;
struct dentry * dentry;
return search_binary_handler(bprm, regs);
}
-static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
-{
- int retval;
- MOD_INC_USE_COUNT;
- retval = do_load_em86(bprm,regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
struct linux_binfmt em86_format = {
NULL, THIS_MODULE, load_em86, NULL, NULL, 0
};
char *iname_addr = iname;
int retval;
- MOD_INC_USE_COUNT;
retval = -ENOEXEC;
if (!enabled)
goto _ret;
if (retval >= 0)
retval = search_binary_handler(bprm, regs);
_ret:
- MOD_DEC_USE_COUNT;
return retval;
}
#include <linux/init.h>
#include <linux/smp_lock.h>
-static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *cp, *i_name, *i_arg;
struct dentry * dentry;
return search_binary_handler(bprm,regs);
}
-static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
-{
- int retval;
- MOD_INC_USE_COUNT;
- retval = do_load_script(bprm,regs);
- MOD_DEC_USE_COUNT;
- return retval;
-}
-
struct linux_binfmt script_format = {
NULL, THIS_MODULE, load_script, NULL, NULL, 0
};
}
vcp->vc_inuse++;
- MOD_INC_USE_COUNT;
if ( file->f_flags == O_RDWR ) {
vcp->vc_pid = current->pid;
}
vcp->vc_inuse--;
- MOD_DEC_USE_COUNT;
CDEBUG(D_PSDEV, "inuse: %d, vc_pid %d, caller %d\n",
vcp->vc_inuse, vcp->vc_pid, current->pid);
static struct super_operations efs_superblock_operations = {
read_inode: efs_read_inode,
- put_super: efs_put_super,
statfs: efs_statfs,
};
-int __init init_efs_fs(void) {
- return register_filesystem(&efs_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void) {
+static int __init init_efs_fs(void) {
printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
- return init_efs_fs();
+ return register_filesystem(&efs_fs_type);
}
-void cleanup_module(void) {
+static void __exit exit_efs_fs(void) {
unregister_filesystem(&efs_fs_type);
}
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_efs_fs)
+module_exit(exit_efs_fs)
static efs_block_t efs_validate_vh(struct volume_header *vh) {
int i;
return(NULL);
}
-void efs_put_super(struct super_block *s) {
-}
-
int efs_statfs(struct super_block *s, struct statfs *buf) {
struct efs_sb_info *sb = SUPER_INFO(s);
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
+#include <linux/spinlock.h>
+#define __NO_VERSION__
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#endif
static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
+static spinlock_t binfmt_lock = SPIN_LOCK_UNLOCKED;
int register_binfmt(struct linux_binfmt * fmt)
{
return -EINVAL;
if (fmt->next)
return -EBUSY;
+ spin_lock(&binfmt_lock);
while (*tmp) {
- if (fmt == *tmp)
+ if (fmt == *tmp) {
+ spin_unlock(&binfmt_lock);
return -EBUSY;
+ }
tmp = &(*tmp)->next;
}
fmt->next = formats;
formats = fmt;
+ spin_unlock(&binfmt_lock);
return 0;
}
{
struct linux_binfmt ** tmp = &formats;
+ spin_lock(&binfmt_lock);
while (*tmp) {
if (fmt == *tmp) {
*tmp = fmt->next;
+ spin_unlock(&binfmt_lock);
return 0;
}
tmp = &(*tmp)->next;
}
+ spin_unlock(&binfmt_lock);
return -EINVAL;
}
+static inline void put_binfmt(struct linux_binfmt * fmt)
+{
+ if (fmt->module)
+ __MOD_DEC_USE_COUNT(fmt->module);
+}
+
/* N.B. Error returns must be < 0 */
int open_dentry(struct dentry * dentry, int mode)
{
file = fget(fd);
retval = -ENOEXEC;
if (file && file->f_dentry && file->f_op && file->f_op->read) {
+ spin_lock(&binfmt_lock);
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(int) = fmt->load_shlib;
if (!fn)
continue;
+ if (!try_inc_mod_count(fmt->module))
+ continue;
+ spin_unlock(&binfmt_lock);
/* N.B. Should use file instead of fd */
retval = fn(fd);
+ spin_lock(&binfmt_lock);
+ put_binfmt(fmt);
if (retval != -ENOEXEC)
break;
}
+ spin_unlock(&binfmt_lock);
}
fput(file);
sys_close(fd);
}
#endif
for (try=0; try<2; try++) {
+ spin_lock(&binfmt_lock);
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
if (!fn)
continue;
+ if (!try_inc_mod_count(fmt->module))
+ continue;
+ spin_unlock(&binfmt_lock);
retval = fn(bprm, regs);
if (retval >= 0) {
+ put_binfmt(fmt);
if (bprm->dentry) {
lock_kernel();
dput(bprm->dentry);
current->did_exec = 1;
return retval;
}
+ spin_lock(&binfmt_lock);
+ put_binfmt(fmt);
if (retval != -ENOEXEC)
break;
- if (!bprm->dentry) /* We don't have the dentry anymore */
+ if (!bprm->dentry) {
+ spin_unlock(&binfmt_lock);
return retval;
+ }
}
+ spin_unlock(&binfmt_lock);
if (retval != -ENOEXEC) {
break;
#ifdef CONFIG_KMOD
#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
#include <linux/version.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/mm.h>
#include <linux/msdos_fs.h>
EXPORT_SYMBOL(fat_dir_empty);
EXPORT_SYMBOL(fat_truncate);
-int init_fat_fs(void)
+static int __init init_fat_fs(void)
{
fat_hash_init();
return 0;
}
+
+module_init(init_fat_fs)
~MSDOS_SB(sb)->options.fs_umask;
return 0;
}
-
-
-#ifdef MODULE
-int init_module(void)
-{
- return init_fat_fs();
-}
-
-
-void cleanup_module(void)
-{
- /* Nothing to be done, really! */
- return;
-}
-#endif
-
#include <linux/config.h>
#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/umsdos_fs.h>
-#include <linux/proc_fs.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/nfs_fs.h>
-#include <linux/iso_fs.h>
-#include <linux/sysv_fs.h>
-#include <linux/hpfs_fs.h>
-#include <linux/smb_fs.h>
-#include <linux/ncp_fs.h>
-#include <linux/affs_fs.h>
-#include <linux/ufs_fs.h>
-#include <linux/efs_fs.h>
-#include <linux/romfs_fs.h>
#include <linux/auto_fs.h>
-#include <linux/qnx4_fs.h>
-#include <linux/udf_fs.h>
-#include <linux/ntfs_fs.h>
-#include <linux/hfs_fs.h>
#include <linux/devpts_fs.h>
-#include <linux/bfs_fs.h>
-#include <linux/openprom_fs.h>
#include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
extern int init_devpts_fs(void);
#endif
-#ifdef CONFIG_SUN_OPENPROMFS
-extern int init_openprom_fs(void);
-#endif
-
void __init filesystem_setup(void)
{
-#ifdef CONFIG_MINIX_FS
- init_minix_fs();
-#endif
-
-#ifdef CONFIG_ROMFS_FS
- init_romfs_fs();
-#endif
-
-#ifdef CONFIG_UMSDOS_FS
- init_umsdos_fs();
-#endif
-
-#ifdef CONFIG_FAT_FS
- init_fat_fs();
-#endif
-
-#ifdef CONFIG_MSDOS_FS
- init_msdos_fs();
-#endif
-
-#ifdef CONFIG_VFAT_FS
- init_vfat_fs();
-#endif
-
-#ifdef CONFIG_PROC_FS
- init_proc_fs();
-#endif
-
init_devfs_fs(); /* Header file may make this empty */
#ifdef CONFIG_NFS_FS
init_coda();
#endif
-#ifdef CONFIG_SMB_FS
- init_smb_fs();
-#endif
-
-#ifdef CONFIG_NCP_FS
- init_ncp_fs();
-#endif
-
-#ifdef CONFIG_ISO9660_FS
- init_iso9660_fs();
-#endif
-
-#ifdef CONFIG_SYSV_FS
- init_sysv_fs();
-#endif
-
-#ifdef CONFIG_HPFS_FS
- init_hpfs_fs();
-#endif
-
-#ifdef CONFIG_NTFS_FS
- init_ntfs_fs();
-#endif
-
-#ifdef CONFIG_HFS_FS
- init_hfs_fs();
-#endif
-
-#ifdef CONFIG_AFFS_FS
- init_affs_fs();
-#endif
-
-#ifdef CONFIG_UFS_FS
- init_ufs_fs();
-#endif
-
-#ifdef CONFIG_EFS_FS
- init_efs_fs();
-#endif
-
#ifdef CONFIG_DEVPTS_FS
init_devpts_fs();
#endif
-
-#ifdef CONFIG_QNX4FS_FS
- init_qnx4_fs();
-#endif
-
-#ifdef CONFIG_UDF_FS
- init_udf_fs();
-#endif
-
-#ifdef CONFIG_BFS_FS
- init_bfs_fs();
-#endif
-
-#ifdef CONFIG_SUN_OPENPROMFS
- init_openprom_fs();
-#endif
}
#ifndef CONFIG_NFSD
return NULL;
}
-int __init init_hfs_fs(void)
+static int __init init_hfs_fs(void)
{
hfs_cat_init();
return register_filesystem(&hfs_fs);
}
-#ifdef MODULE
-int init_module(void) {
- int error;
-
-#if defined(DEBUG_SIZES) || defined(DEBUG_ALL)
- hfs_warn("HFS inode: %d bytes available\n",
- sizeof(struct ext2_inode_info)-sizeof(struct hfs_inode_info));
- hfs_warn("HFS super_block: %d bytes available\n",
- sizeof(struct ext2_sb_info)-sizeof(struct hfs_sb_info));
- if ((sizeof(struct hfs_inode_info)>sizeof(struct ext2_inode_info)) ||
- (sizeof(struct hfs_sb_info)>sizeof(struct ext2_sb_info))) {
- return -ENOMEM; /* well sort of */
- }
-#endif
- error = init_hfs_fs();
- if (!error) {
- /* register_symtab(NULL); */
- }
- return error;
-}
-
-void cleanup_module(void) {
+static void __exit exit_hfs_fs(void) {
hfs_cat_free();
unregister_filesystem(&hfs_fs);
}
-#endif
+
+module_init(init_hfs_fs)
+module_exit(exit_hfs_fs)
#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
long int hfs_alloc = 0;
kdev_t dev = s->s_dev;
struct buffer_head *bh;
- if (!ahead || secno + ahead >= s->s_hpfs_fs_size)
+ /* vvvv - workaround for the breada bug */
+ if (!ahead || secno + ahead + (read_ahead[MAJOR(dev)] >> 9) >= s->s_hpfs_fs_size)
*bhp = bh = bread(dev, secno, 512);
else *bhp = bh = breada(dev, secno, 512, 0, (ahead + 1) << 9);
if (bh != NULL)
/*return hpfs_map_sector(s, secno, bhp, 0);*/
if ((*bhp = bh = getblk(s->s_dev, secno, 512)) != NULL) {
+ if (!buffer_uptodate(bh)) wait_on_buffer(bh);
mark_buffer_uptodate(bh, 1);
return bh->b_data;
} else {
goto bail;
}
- if (!ahead || secno + 4 + ahead > s->s_hpfs_fs_size)
- qbh->bh[0] = bh = breada(dev, secno, 512, 0, 2048);
+ /* vvvv - workaround for the breada bug */
+ if (!ahead || secno + 4 + ahead + (read_ahead[MAJOR(dev)] >> 9) > s->s_hpfs_fs_size)
+ qbh->bh[0] = bh = bread(dev, secno, 512);
else qbh->bh[0] = bh = breada(dev, secno, 512, 0, (ahead + 4) << 9);
if (!bh)
goto bail0;
void hpfs_put_super(struct super_block *);
unsigned hpfs_count_one_bitmap(struct super_block *, secno);
int hpfs_statfs(struct super_block *, struct statfs *);
-struct super_block *hpfs_read_super(struct super_block *, void *, int);
extern struct address_space_operations hpfs_aops;
void hpfs_delete_inode(struct inode *inode)
{
hpfs_remove_fnode(inode->i_sb, inode->i_ino);
+ clear_inode(inode);
}
#include <linux/string.h>
#include "hpfs_fn.h"
#include <linux/module.h>
+#include <linux/init.h>
/* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
-int init_hpfs_fs(void)
+static int __init init_hpfs_fs(void)
{
return register_filesystem(&hpfs_fs_type);
}
-#ifdef MODULE
-
-/*int register_symtab_from(struct symbol_table *, long *);*/
-
-int init_module(void)
-{
- /*int status;
- if (!(status = init_hpfs_fs())) register_symtab(NULL);
- return status;*/
- return init_hpfs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_hpfs_fs(void)
{
unregister_filesystem(&hpfs_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_hpfs_fs)
+module_exit(exit_hpfs_fs)
static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
-int __init init_iso9660_fs(void)
+static int __init init_iso9660_fs(void)
{
return register_filesystem(&iso9660_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static void __exit exit_iso9660_fs(void)
{
- return init_iso9660_fs();
+ unregister_filesystem(&iso9660_fs_type);
}
-void cleanup_module(void)
-{
- unregister_filesystem(&iso9660_fs_type);
-}
+EXPORT_NO_SYMBOLS;
-#endif
+module_init(init_iso9660_fs)
+module_exit(exit_iso9660_fs)
static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
-int __init init_minix_fs(void)
+static int __init init_minix_fs(void)
{
return register_filesystem(&minix_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static void __exit exit_minix_fs(void)
{
- return init_minix_fs();
+ unregister_filesystem(&minix_fs_type);
}
-void cleanup_module(void)
-{
- unregister_filesystem(&minix_fs_type);
-}
+EXPORT_NO_SYMBOLS;
-#endif
+module_init(init_minix_fs)
+module_exit(exit_minix_fs)
EXPORT_SYMBOL(msdos_read_super);
EXPORT_SYMBOL(msdos_put_super);
+static DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
-DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
-
-int __init init_msdos_fs(void)
+static int __init init_msdos_fs(void)
{
return register_filesystem(&msdos_fs_type);
}
+
+static void __exit exit_msdos_fs(void)
+{
+ unregister_filesystem(&msdos_fs_type);
+}
+
+module_init(init_msdos_fs)
+module_exit(exit_msdos_fs)
MSDOS_SB(sb)->options.isvfat = 0;
res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
- if (res == NULL)
- goto out_fail;
- sb->s_root->d_op = &msdos_dentry_operations;
+ if (res)
+ sb->s_root->d_op = &msdos_dentry_operations;
return res;
-
-out_fail:
- return NULL;
-}
-
-
-
-#ifdef MODULE
-int init_module(void)
-{
- return init_msdos_fs();
}
-
-
-void cleanup_module(void)
-{
- unregister_filesystem(&msdos_fs_type);
-}
-
-#endif
-
static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
-int __init init_ncp_fs(void)
-{
- return register_filesystem(&ncp_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
+static int __init init_ncp_fs(void)
{
DPRINTK("ncpfs: init_module called\n");
return init_ncp_fs();
}
-void cleanup_module(void)
+static void __exit exit_ncp_fs(void)
{
DPRINTK("ncpfs: cleanup_module called\n");
unregister_filesystem(&ncp_fs_type);
#endif
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ncp_fs)
+module_exit(exit_ncp_fs)
*/
static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
-/* When this code is not compiled as a module, this is the main entry point,
- * called by do_sys_setup() in fs/filesystems.c
- *
- * NOTE : __init is a macro used to remove this function from memory
- * once initialization is done
- */
-int __init init_ntfs_fs(void)
+static int __init init_ntfs_fs(void)
{
/* Comment this if you trust klogd. There are reasons not to trust it
*/
return register_filesystem(&ntfs_fs_type);
}
-#ifdef MODULE
-/* A module is a piece of code which can be inserted in and removed
- * from the running kernel whenever you want using lsmod, or on demand using
- * kmod
- */
+static __exit void exit_ntfs_fs(void)
+{
+ SYSCTL(0);
+ ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
+ unregister_filesystem(&ntfs_fs_type);
+}
-/* No function of this module is needed by another module */
EXPORT_NO_SYMBOLS;
-/* Only used for documentation purposes at the moment,
- * see include/linux/module.h
- */
MODULE_AUTHOR("Martin von Löwis");
MODULE_DESCRIPTION("NTFS driver");
-/* no MODULE_SUPPORTED_DEVICE() */
-/* Load-time parameter */
MODULE_PARM(ntdebug, "i");
MODULE_PARM_DESC(ntdebug, "Debug level");
-/* When this code is compiled as a module, if you use mount -t ntfs when no
- * ntfs filesystem is registered (see /proc/filesystems), get_fs_type() in
- * fs/super.c asks kmod to load the module named ntfs in memory.
- *
- * Therefore, this function is the main entry point in this case
- */
-int init_module(void)
-{
- return init_ntfs_fs();
-}
-
-/* Called by kmod just before the kernel removes the module from memory */
-void cleanup_module(void)
-{
- SYSCTL(0);
- ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
- unregister_filesystem(&ntfs_fs_type);
-}
-#endif
-
+module_init(init_ntfs_fs)
+module_exit(exit_ntfs_fs)
/*
* Local variables:
* c-file-style: "linux"
static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);
-int init_openprom_fs(void)
+static int __init init_openprom_fs(void)
{
nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
if (!nodes) {
return register_filesystem(&openprom_fs_type);
}
-#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-
-int init_module (void)
-{
- return init_openprom_fs();
-}
-
-#else
-
-void __init openpromfs_init (void)
-{
- init_openprom_fs();
-}
-#endif
-
-#ifdef MODULE
-void cleanup_module (void)
+static void __exit exit_openprom_fs(void)
{
int i;
unregister_filesystem(&openprom_fs_type);
kfree (alias_names [i]);
nodes = NULL;
}
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_openprom_fs)
+module_exit(exit_openprom_fs)
static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, 0);
-int __init init_proc_fs(void)
+static int __init init_proc_fs(void)
{
- return register_filesystem(&proc_fs_type) == 0;
+ return register_filesystem(&proc_fs_type);
}
+
+static void __exit exit_proc_fs(void)
+{
+ unregister_filesystem(&proc_fs_type);
+}
+
+module_init(init_proc_fs)
+module_exit(exit_proc_fs)
static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
-int __init init_qnx4_fs(void)
+static int __init init_qnx4_fs(void)
{
printk("QNX4 filesystem 0.2.2 registered.\n");
return register_filesystem(&qnx4_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_qnx4_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_qnx4_fs(void)
{
unregister_filesystem(&qnx4_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_qnx4_fs)
+module_exit(exit_qnx4_fs)
static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);
-int __init init_romfs_fs(void)
+static int __init init_romfs_fs(void)
{
return register_filesystem(&romfs_fs_type);
}
-#ifdef MODULE
+static void __exit exit_romfs_fs(void)
+{
+ unregister_filesystem(&romfs_fs_type);
+}
/* Yes, works even as a module... :) */
EXPORT_NO_SYMBOLS;
-int
-init_module(void)
-{
- return init_romfs_fs();
-}
-
-void
-cleanup_module(void)
-{
- unregister_filesystem(&romfs_fs_type);
-}
-#endif
+module_init(init_romfs_fs)
+module_exit(exit_romfs_fs)
static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
-int __init init_smb_fs(void)
-{
- return register_filesystem(&smb_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int
-init_module(void)
+static int __init init_smb_fs(void)
{
pr_debug("smbfs: init_module called\n");
return init_smb_fs();
}
-void
-cleanup_module(void)
+static void __exit exit_smb_fs(void)
{
pr_debug("smbfs: cleanup_module called\n");
unregister_filesystem(&smb_fs_type);
#endif
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_smb_fs)
+module_exit(exit_smb_fs)
static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
-int __init init_sysv_fs(void)
+static int __init init_sysv_fs(void)
{
return register_filesystem(&sysv_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_sysv_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_sysv_fs(void)
{
unregister_filesystem(&sysv_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_sysv_fs)
+module_exit(exit_sysv_fs)
uid_t uid;
};
-#if defined(MODULE)
-
-/*
- * cleanup_module
- *
- * PURPOSE
- * Unregister the UDF filesystem type.
- *
- * DESCRIPTION
- * Clean-up before the module is unloaded.
- * This routine only applies when compiled as a module.
- *
- * HISTORY
- * July 1, 1997 - Andrew E. Mileski
- * Written, tested, and released.
- */
-int
-cleanup_module(void)
-{
- printk(KERN_NOTICE "udf: unregistering filesystem\n");
- return unregister_filesystem(&udf_fstype);
-}
-/*
- * init_module / init_udf_fs
- *
- * PURPOSE
- * Register the UDF filesystem type.
- *
- * HISTORY
- * July 1, 1997 - Andrew E. Mileski
- * Written, tested, and released.
- */
-int init_module(void)
-#else /* if !defined(MODULE) */
-int __init init_udf_fs(void)
-#endif
+static int __init init_udf_fs(void)
{
printk(KERN_NOTICE "udf: registering filesystem\n");
- {
- struct super_block sb;
- int size;
-
- size = sizeof(struct super_block) +
- (long)&sb.u - (long)&sb;
- if ( size < sizeof(struct udf_sb_info) )
- {
- printk(KERN_ERR "udf: Danger! Kernel was compiled without enough room for udf_sb_info\n");
- printk(KERN_ERR "udf: Kernel has room for %u bytes, udf needs %lu\n",
- size, (unsigned long)sizeof(struct udf_sb_info));
- return 0;
- }
- }
return register_filesystem(&udf_fstype);
}
+static void __exit exit_udf_fs(void)
+{
+ printk(KERN_NOTICE "udf: unregistering filesystem\n");
+ unregister_filesystem(&udf_fstype);
+}
+
+module_init(init_udf_fs)
+module_exit(exit_udf_fs)
+
/*
* udf_parse_options
*
static DECLARE_FSTYPE_DEV(ufs_fs_type, "ufs", ufs_read_super);
-int __init init_ufs_fs(void)
+static int __init init_ufs_fs(void)
{
return register_filesystem(&ufs_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_ufs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_ufs_fs(void)
{
unregister_filesystem(&ufs_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ufs_fs)
+module_exit(exit_ufs_fs)
static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super);
-int __init init_umsdos_fs (void)
+static int __init init_umsdos_fs (void)
{
return register_filesystem (&umsdos_fs_type);
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module (void)
-{
- return init_umsdos_fs ();
-}
-
-void cleanup_module (void)
+static void __exit exit_umsdos_fs (void)
{
unregister_filesystem (&umsdos_fs_type);
}
-#endif
+EXPORT_NO_SYMBOLS;
+
+module_init(init_umsdos_fs)
+module_exit(exit_umsdos_fs)
return res;
}
-
-#ifdef MODULE
-int init_module(void)
-{
- return init_vfat_fs();
-}
-
-void cleanup_module(void)
-{
- unregister_filesystem(&vfat_fs_type);
-}
-
-#endif /* ifdef MODULE */
#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
#include <linux/version.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/mm.h>
#include <linux/msdos_fs.h>
EXPORT_SYMBOL(vfat_read_super);
EXPORT_SYMBOL(vfat_lookup);
-int init_vfat_fs(void)
+static int __init init_vfat_fs(void)
{
return register_filesystem(&vfat_fs_type);
}
+static void __exit exit_vfat_fs(void)
+{
+ unregister_filesystem(&vfat_fs_type);
+}
+
+module_init(init_vfat_fs)
+module_exit(exit_vfat_fs)
#define __NR_setfsuid32 215
#define __NR_setfsgid32 216
#define __NR_pivot_root 217
+#define __NR_mincore 218
/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
/* super.c */
extern int affs_fs(void);
-extern int init_affs_fs(void);
/* file.c */
#ifdef __KERNEL__
-/* inode.c */
-extern int init_bfs_fs(void);
-
/* file.c */
extern struct inode_operations bfs_file_inops;
extern struct file_operations bfs_file_operations;
extern struct file_operations efs_dir_operations;
extern struct address_space_operations efs_symlink_aops;
-extern int init_module(void);
-extern void cleanup_module(void);
extern struct super_block *efs_read_super(struct super_block *, void *, int);
-extern void efs_put_super(struct super_block *);
extern int efs_statfs(struct super_block *, struct statfs *);
extern void efs_read_inode(struct inode *);
extern struct dentry *efs_lookup(struct inode *, struct dentry *);
extern int efs_bmap(struct inode *, int);
-extern int init_efs_fs(void);
-
#endif /* __EFS_FS_H__ */
-
/* super.c */
extern struct super_block *hfs_read_super(struct super_block *,void *,int);
-extern int init_hfs_fs(void);
/* trans.c */
extern void hfs_colon2mac(struct hfs_name *, const char *, int);
#define HPFS_SUPER_MAGIC 0xf995e849
-/* The entry point for a VFS */
-
-extern struct super_block *hpfs_read_super (struct super_block *, void *, int);
-extern int init_hpfs_fs(void);
-
#endif
extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
extern int isofs_get_block(struct inode *, long, struct buffer_head *, int);
extern int isofs_bmap(struct inode *, int);
-extern int init_iso9660_fs(void);
extern int isofs_lookup_grandparent(struct inode *, int);
extern struct inode_operations isofs_dir_inode_operations;
extern struct buffer_head * minix_bread(struct inode *, int, int);
extern void minix_truncate(struct inode *);
-extern int init_minix_fs(void);
extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct file *, struct dentry *);
extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
extern void fat_truncate(struct inode *inode);
-/* vfat.c */
-extern int init_vfat_fs(void);
-
-
-/* msdosfs_syms.c */
-extern int init_msdos_fs(void);
-extern struct file_system_type msdos_fs_type;
-
/* msdos.c */
extern struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent);
struct inode *new_dir,struct dentry *new_dentry);
/* nls.c */
-extern int init_fat_nls(void);
extern struct fat_nls_table *fat_load_nls(int codepage);
/* tables.c */
struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
void ncp_update_inode(struct inode *, struct ncp_entry_info *);
void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
-extern int init_ncp_fs(void);
/* linux/fs/ncpfs/dir.c */
extern struct inode_operations ncp_dir_inode_operations;
#ifndef _LINUX_NTFS_FS_H
#define _LINUX_NTFS_FS_H
-
-int init_ntfs_fs(void);
-
#endif
-
extern struct exec_domain *lookup_exec_domain(unsigned long personality);
extern int register_exec_domain(struct exec_domain *it);
extern int unregister_exec_domain(struct exec_domain *it);
+#define put_exec_domain(it) \
+ if (it && it->module) __MOD_DEC_USE_COUNT(it->module);
asmlinkage long sys_personality(unsigned long personality);
#endif /* _PERSONALITY_H */
extern struct super_block *proc_super_blocks;
extern struct super_block *proc_read_super(struct super_block *,void *,int);
-extern int init_proc_fs(void);
extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
extern int proc_match(int, const char *,struct proc_dir_entry *);
extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
extern struct buffer_head *qnx4_bread(struct inode *, int, int);
-extern int init_qnx4_fs(void);
extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
#ifdef __KERNEL__
/* Not much now */
-extern int init_romfs_fs(void);
#endif /* __KERNEL__ */
#endif
int smb_notify_change(struct dentry *, struct iattr *);
unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *);
-extern int init_smb_fs(void);
/* linux/fs/smbfs/proc.c */
__u32 smb_len(unsigned char *);
extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
extern void sysv_truncate(struct inode *);
-extern int init_sysv_fs(void);
extern void sysv_write_inode(struct inode *);
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *);
/*
* Function prototypes (all other prototypes included in udfdecl.h)
*/
-extern int init_udf_fs(void);
#endif /* __KERNEL__ */
extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern int init_ufs_fs(void);
extern void ufs_write_super (struct super_block *);
/* symlink.c */
extern struct inode_operations umsdos_rdir_inode_operations;
extern struct file_operations umsdos_dir_operations;
extern struct file_operations umsdos_rdir_operations;
-extern int init_umsdos_fs (void);
#include <linux/umsdos_fs.p>
};
static struct exec_domain *exec_domains = &default_exec_domain;
-
+static spinlock_t exec_domains_lock = SPIN_LOCK_UNLOCKED;
static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
{
* personality set incorrectly. Check to see whether SVr4 is available,
* and use it, otherwise give the user a SEGV.
*/
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
-
+ put_exec_domain(current->exec_domain);
current->personality = PER_SVR4;
current->exec_domain = lookup_exec_domain(current->personality);
- if (current->exec_domain && current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
-
if (current->exec_domain && current->exec_domain->handler
&& current->exec_domain->handler != no_lcall7) {
current->exec_domain->handler(segment, regs);
unsigned long pers = personality & PER_MASK;
struct exec_domain *it;
+ spin_lock(&exec_domains_lock);
for (it=exec_domains; it; it=it->next)
- if (pers >= it->pers_low
- && pers <= it->pers_high)
+ if (pers >= it->pers_low && pers <= it->pers_high) {
+ if (!try_inc_mod_count(it->module))
+ continue;
+ spin_unlock(&exec_domains_lock);
return it;
+ }
+ spin_unlock(&exec_domains_lock);
/* Should never get this far. */
printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
return -EINVAL;
if (it->next)
return -EBUSY;
+ spin_lock(&exec_domains_lock);
for (tmp=exec_domains; tmp; tmp=tmp->next)
- if (tmp == it)
+ if (tmp == it) {
+ spin_unlock(&exec_domains_lock);
return -EBUSY;
+ }
it->next = exec_domains;
exec_domains = it;
+ spin_unlock(&exec_domains_lock);
return 0;
}
struct exec_domain ** tmp;
tmp = &exec_domains;
+ spin_lock(&exec_domains_lock);
while (*tmp) {
if (it == *tmp) {
*tmp = it->next;
it->next = NULL;
+ spin_unlock(&exec_domains_lock);
return 0;
}
tmp = &(*tmp)->next;
}
+ spin_unlock(&exec_domains_lock);
return -EINVAL;
}
goto out;
old_personality = current->personality;
- if (current->exec_domain && current->exec_domain->module)
- __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ put_exec_domain(current->exec_domain);
current->personality = personality;
current->exec_domain = it;
- if (current->exec_domain->module)
- __MOD_INC_USE_COUNT(current->exec_domain->module);
ret = old_personality;
out:
unlock_kernel();
int len = 0;
struct exec_domain * e;
+ spin_lock(&exec_domains_lock);
for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
e->pers_low, e->pers_high, e->name,
e->module ? e->module->name : "kernel");
+ spin_unlock(&exec_domains_lock);
return len;
}
tsk->exit_code = code;
exit_notify();
task_unlock(tsk);
- if (tsk->exec_domain && tsk->exec_domain->module)
- __MOD_DEC_USE_COUNT(tsk->exec_domain->module);
+ put_exec_domain(tsk->exec_domain);
if (tsk->binfmt && tsk->binfmt->module)
__MOD_DEC_USE_COUNT(tsk->binfmt->module);
schedule();
bad_fork_cleanup_files:
exit_files(p); /* blocking */
bad_fork_cleanup:
- if (p->exec_domain && p->exec_domain->module)
- __MOD_DEC_USE_COUNT(p->exec_domain->module);
+ put_exec_domain(p->exec_domain);
if (p->binfmt && p->binfmt->module)
__MOD_DEC_USE_COUNT(p->binfmt->module);
bad_fork_cleanup_count:
return error;
}
+/*
+ * Later we can get more picky about what "in core" means precisely.
+ * For now, simply check to see if the page is in the page cache,
+ * and is up to date; i.e. that no page-in operation would be required
+ * at this time if an application were to map and access this page.
+ */
+static unsigned char mincore_page(struct vm_area_struct * vma,
+ unsigned long pgoff)
+{
+ unsigned char present = 0;
+ struct address_space * as = &vma->vm_file->f_dentry->d_inode->i_data;
+ struct page * page, ** hash = page_hash(as, pgoff);
+
+ spin_lock(&pagecache_lock);
+ page = __find_page_nolock(as, pgoff, *hash);
+ if ((page) && (Page_Uptodate(page)))
+ present = 1;
+ spin_unlock(&pagecache_lock);
+
+ return present;
+}
+
+static long mincore_vma(struct vm_area_struct * vma,
+ unsigned long start, unsigned long end, unsigned char * vec)
+{
+ long error, i, remaining;
+ unsigned char * tmp;
+
+ error = -ENOMEM;
+ if (!vma->vm_file)
+ return error;
+
+ start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+ if (end > vma->vm_end)
+ end = vma->vm_end;
+ end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+ error = -EAGAIN;
+ tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
+ if (!tmp)
+ return error;
+
+ /* (end - start) is # of pages, and also # of bytes in "vec */
+ remaining = (end - start),
+
+ error = 0;
+ for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) {
+ int j = 0;
+ long thispiece = (remaining < PAGE_SIZE) ?
+ remaining : PAGE_SIZE;
+
+ while (j < thispiece)
+ tmp[j++] = mincore_page(vma, start++);
+
+ if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) {
+ error = -EFAULT;
+ break;
+ }
+ }
+
+ free_page((unsigned long) tmp);
+ return error;
+}
+
+/*
+ * The mincore(2) system call.
+ *
+ * mincore() returns the memory residency status of the pages in the
+ * current process's address space specified by [addr, addr + len).
+ * The status is returned in a vector of bytes. The least significant
+ * bit of each byte is 1 if the referenced page is in memory, otherwise
+ * it is zero.
+ *
+ * Because the status of a page can change after mincore() checks it
+ * but before it returns to the application, the returned vector may
+ * contain stale information. Only locked pages are guaranteed to
+ * remain in memory.
+ *
+ * return values:
+ * zero - success
+ * -EFAULT - vec points to an illegal address
+ * -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
+ * or len has a nonpositive value
+ * -ENOMEM - Addresses in the range [addr, addr + len] are
+ * invalid for the address space of this process, or
+ * specify one or more pages which are not currently
+ * mapped
+ * -EAGAIN - A kernel resource was temporarily unavailable.
+ */
+asmlinkage long sys_mincore(unsigned long start, size_t len,
+ unsigned char * vec)
+{
+ int index = 0;
+ unsigned long end;
+ struct vm_area_struct * vma;
+ int unmapped_error = 0;
+ long error = -EINVAL;
+
+ down(¤t->mm->mmap_sem);
+
+ if (start & ~PAGE_MASK)
+ goto out;
+ len = (len + ~PAGE_MASK) & PAGE_MASK;
+ end = start + len;
+ if (end < start)
+ goto out;
+
+ error = 0;
+ if (end == start)
+ goto out;
+
+ /*
+ * If the interval [start,end) covers some unmapped address
+ * ranges, just ignore them, but return -ENOMEM at the end.
+ */
+ vma = find_vma(current->mm, start);
+ for (;;) {
+ /* Still start < end. */
+ error = -ENOMEM;
+ if (!vma)
+ goto out;
+
+ /* Here start < vma->vm_end. */
+ if (start < vma->vm_start) {
+ unmapped_error = -ENOMEM;
+ start = vma->vm_start;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end. */
+ if (end <= vma->vm_end) {
+ if (start < end) {
+ error = mincore_vma(vma, start, end,
+ &vec[index]);
+ if (error)
+ goto out;
+ }
+ error = unmapped_error;
+ goto out;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end < end. */
+ error = mincore_vma(vma, start, vma->vm_end, &vec[index]);
+ if (error)
+ goto out;
+ index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
+ start = vma->vm_end;
+ vma = vma->vm_next;
+ }
+
+out:
+ up(¤t->mm->mmap_sem);
+ return error;
+}
+
struct page *read_cache_page(struct address_space *mapping,
unsigned long index,
int (*filler)(void *,struct page*),