fd_device[drive] = type;
- if (old_dev && old_dev != type)
- invalidate_buffers(mk_kdev(MAJOR_NR, drive + (old_dev<<2)));
-
if (filp->f_flags & O_NDELAY)
return 0;
break;
case FDFMTEND:
floppy_off(drive);
- invalidate_device(inode->i_rdev, 0);
+ invalidate_bdev(inode->i_bdev, 0);
break;
case FDGETPRM:
memset((void *)&getprm, 0, sizeof (getprm));
#endif
local_irq_restore(flags);
- if (old_dev != system)
- invalidate_buffers(mk_kdev(FLOPPY_MAJOR, drive + (system << 2)));
-
unit[drive].dtype=&data_types[system];
unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
data_types[system].sects*unit[drive].type->sect_mult;
static __inline__ int get_head_settle_flag( void );
static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);
static void fd_error( void );
-static int do_format(kdev_t drive, struct atari_format_descr *desc);
+static int do_format(int drive, int type, struct atari_format_descr *desc);
static void do_fd_action( int drive );
static void fd_calibrate( void );
static void fd_calibrate_done( int status );
p += n; \
} while(0)
-static int do_format(kdev_t device, struct atari_format_descr *desc)
+static int do_format(int drive, int type, struct atari_format_descr *desc)
{
unsigned char *p;
int sect, nsect;
unsigned long flags;
- int type, drive = minor(device) & 3;
DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
drive, desc->track, desc->head, desc->sect_offset ));
atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
local_irq_restore(flags);
- type = minor(device) >> 2;
if (type) {
if (--type >= NUM_DISK_MINORS ||
minor2disktype[type].drive_types > DriveType) {
return -EBUSY;
if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
return -EFAULT;
- return do_format(device, &fmt_desc);
+ return do_format(drive, type, &fmt_desc);
case FDCLRPRM:
UDT = NULL;
/* MSch: invalidate default_params */
fd_device[drive] = type;
- if (old_dev && old_dev != type)
- invalidate_buffers(mk_kdev(FLOPPY_MAJOR, drive + (type<<2)));
-
if (filp->f_flags & O_NDELAY)
return 0;
static unsigned long fake_change;
static int initialising=1;
-static inline int TYPE(kdev_t x) {
- return (minor(x)>>2) & 0x1f;
-}
-static inline int DRIVE(kdev_t x) {
- return (minor(x)&0x03) | ((minor(x)&0x80) >> 5);
-}
#define ITYPE(x) (((x)>>2) & 0x1f)
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */
static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk *disks[N_DRIVE];
+static struct block_device *opened_bdev[N_DRIVE];
+static DECLARE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/*
if (type){
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ down(&open_lock);
LOCK_FDC(drive,1);
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- set_bit(drive, &fake_change);
- }
floppy_type[type] = *g;
floppy_type[type].name="user format";
for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
floppy_type[type].size+1;
process_fd_request();
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- __check_disk_change(
- MKDEV(FLOPPY_MAJOR,
- drive_state[cnt].fd_device));
+ for (cnt = 0; cnt < N_DRIVE; cnt++) {
+ struct block_device *bdev = opened_bdev[cnt];
+ if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
+ continue;
+ __invalidate_device(bdev, 0);
}
+ up(&open_lock);
} else {
LOCK_FDC(drive,1);
if (cmd != FDDEFPRM)
#define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
- int i,drive,type;
- kdev_t device;
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int i, type = ITYPE(UDRS->fd_device);
int ret;
int size;
union inparam {
} inparam; /* parameters coming from user space */
const char *outparam; /* parameters passed back to user space */
- device = inode->i_rdev;
- type = TYPE(device);
- drive = DRIVE(device);
/* convert compatibility eject ioctls into floppy eject ioctl.
* We do this in order to provide a means to eject floppy disks before
static int floppy_release(struct inode * inode, struct file * filp)
{
- int drive = DRIVE(inode->i_rdev);
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
+ down(&open_lock);
if (UDRS->fd_ref < 0)
UDRS->fd_ref=0;
else if (!UDRS->fd_ref--) {
DPRINT("floppy_release with fd_ref == 0");
UDRS->fd_ref = 0;
}
+ if (!UDRS->fd_ref)
+ opened_bdev[drive] = NULL;
floppy_release_irq_and_dma();
+ up(&open_lock);
return 0;
}
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
-
static int floppy_open(struct inode * inode, struct file * filp)
{
- int drive;
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
int old_dev;
int try;
+ int res = -EBUSY;
char *tmp;
filp->private_data = (void*) 0;
-
- drive = DRIVE(inode->i_rdev);
- if (drive >= N_DRIVE ||
- !(allowed_drive_mask & (1 << drive)) ||
- fdc_state[FDC(drive)].version == FDC_NONE)
- return -ENXIO;
-
- if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
- return -ENXIO;
+ down(&open_lock);
old_dev = UDRS->fd_device;
- if (UDRS->fd_ref && old_dev != minor(inode->i_rdev))
- return -EBUSY;
+ if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
+ goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
USETF(FD_DISK_CHANGED);
if (UDRS->fd_ref == -1 ||
(UDRS->fd_ref && (filp->f_flags & O_EXCL)))
- return -EBUSY;
+ goto out2;
if (floppy_grab_irq_and_dma())
- return -EBUSY;
+ goto out2;
if (filp->f_flags & O_EXCL)
UDRS->fd_ref = -1;
else
UDRS->fd_ref++;
+ opened_bdev[drive] = inode->i_bdev;
+
+ res = -ENXIO;
+
if (!floppy_track_buffer){
/* if opening an ED drive, reserve a big buffer,
* else reserve a small one */
}
if (!tmp && !floppy_track_buffer) {
DPRINT("Unable to allocate DMA memory\n");
- RETERR(ENXIO);
+ goto out;
}
if (floppy_track_buffer) {
if (tmp)
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive)
buffer_track = -1;
- /* umm, invalidate_buffers() in ->open?? --hch */
- invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev));
}
/* Allow ioctls if we have write-permissions even if read-only open.
if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2;
- if (filp->f_flags & O_NDELAY)
- return 0;
- if (filp->f_mode & 3) {
- UDRS->last_checked = 0;
- check_disk_change(inode->i_bdev);
- if (UTESTF(FD_DISK_CHANGED))
- RETERR(ENXIO);
- }
- if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
- RETERR(EROFS);
+ if (!filp->f_flags & O_NDELAY) {
+ if (filp->f_mode & 3) {
+ UDRS->last_checked = 0;
+ check_disk_change(inode->i_bdev);
+ if (UTESTF(FD_DISK_CHANGED))
+ goto out;
+ }
+ res = -EROFS;
+ if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+ goto out;
+ }
+ up(&open_lock);
return 0;
-#undef RETERR
+out:
+ if (UDRS->fd_ref < 0)
+ UDRS->fd_ref=0;
+ else
+ UDRS->fd_ref--;
+ if (!UDRS->fd_ref)
+ opened_bdev[drive] = NULL;
+ floppy_release_irq_and_dma();
+out2:
+ up(&open_lock);
+ return res;
}
/*
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
+ if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+ return NULL;
*part = 0;
return get_disk(disks[drive]);
}
static unsigned long fake_change;
static int initialising=1;
-static inline int TYPE(kdev_t x) {
- return (minor(x)>>2) & 0x1f;
-}
-static inline int DRIVE(kdev_t x) {
- return (minor(x)&0x03) | ((minor(x)&0x80) >> 5);
-}
#define ITYPE(x) (((x)>>2) & 0x1f)
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */
static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk *disks[N_DRIVE];
+static struct block_device *opened_bdev[N_DRIVE];
+static DECLARE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/*
if (type){
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ down(&open_lock);
LOCK_FDC(drive,1);
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- set_bit(drive, &fake_change);
- }
floppy_type[type] = *g;
floppy_type[type].name="user format";
for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
floppy_type[type].size+1;
process_fd_request();
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- __check_disk_change(
- MKDEV(FLOPPY_MAJOR,
- drive_state[cnt].fd_device));
+ for (cnt = 0; cnt < N_DRIVE; cnt++) {
+ struct block_device *bdev = opened_bdev[cnt];
+ if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
+ continue;
+ __invalidate_device(bdev, 0);
}
+ up(&open_lock);
} else {
LOCK_FDC(drive,1);
if (cmd != FDDEFPRM)
#define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
- int i,drive,type;
- kdev_t device;
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int i, type = ITYPE(UDRS->fd_device);
int ret;
int size;
union inparam {
} inparam; /* parameters coming from user space */
const char *outparam; /* parameters passed back to user space */
- device = inode->i_rdev;
- type = TYPE(device);
- drive = DRIVE(device);
-
/* convert compatibility eject ioctls into floppy eject ioctl.
* We do this in order to provide a means to eject floppy disks before
* installing the new fdutils package */
static int floppy_release(struct inode * inode, struct file * filp)
{
- int drive = DRIVE(inode->i_rdev);
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
+ down(&open_lock);
if (UDRS->fd_ref < 0)
UDRS->fd_ref=0;
else if (!UDRS->fd_ref--) {
DPRINT("floppy_release with fd_ref == 0");
UDRS->fd_ref = 0;
}
+ if (!UDRS->fd_ref)
+ opened_bdev[drive] = NULL;
floppy_release_irq_and_dma();
+ up(&open_lock);
return 0;
}
static int floppy_open(struct inode * inode, struct file * filp)
{
- int drive;
+ int drive = (long)inode->i_bdev->bd_disk->private_data;
int old_dev;
int try;
+ int res = -EBUSY;
char *tmp;
#ifdef PC9800_DEBUG_FLOPPY
#endif
filp->private_data = (void*) 0;
- drive = DRIVE(inode->i_rdev);
#ifdef PC9800_DEBUG_FLOPPY
printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n"
"floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n",
}
#endif /* PC9800_DEBUG_FLOPPY */
- if (drive >= N_DRIVE ||
- !(allowed_drive_mask & (1 << drive)) ||
- fdc_state[FDC(drive)].version == FDC_NONE)
- return -ENXIO;
-
- if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
- return -ENXIO;
+ down(&open_lock);
old_dev = UDRS->fd_device;
- if (UDRS->fd_ref && old_dev != minor(inode->i_rdev))
- return -EBUSY;
+ if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
+ goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
USETF(FD_DISK_CHANGED);
if (UDRS->fd_ref == -1 ||
(UDRS->fd_ref && (filp->f_flags & O_EXCL)))
- return -EBUSY;
+ goto out2;
if (floppy_grab_irq_and_dma())
- return -EBUSY;
+ goto out2;
if (filp->f_flags & O_EXCL)
UDRS->fd_ref = -1;
else
UDRS->fd_ref++;
+ opened_bdev[drive] = inode->i_bdev;
+
+ res = -ENXIO;
+
if (!floppy_track_buffer){
/* if opening an ED drive, reserve a big buffer,
* else reserve a small one */
}
if (!tmp && !floppy_track_buffer) {
DPRINT("Unable to allocate DMA memory\n");
- RETERR(ENXIO);
+ goto out;
}
if (floppy_track_buffer) {
if (tmp)
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive)
buffer_track = -1;
- /* umm, invalidate_buffers() in ->open?? --hch */
- invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev));
}
#ifdef PC9800_DEBUG_FLOPPY
printk("floppy open: floppy.c:%d passed\n", __LINE__);
#endif
- if (filp->f_flags & O_NDELAY)
- return 0;
- if (filp->f_mode & 3) {
- UDRS->last_checked = 0;
- check_disk_change(inode->i_bdev);
- if (UTESTF(FD_DISK_CHANGED))
- RETERR(ENXIO);
- }
- if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
- RETERR(EROFS);
+ if (!(filp->f_flags & O_NDELAY)) {
+ if (filp->f_mode & 3) {
+ UDRS->last_checked = 0;
+ check_disk_change(inode->i_bdev);
+ if (UTESTF(FD_DISK_CHANGED))
+ goto out;
+ }
+ res = -EROFS;
+ if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+ goto out;
#ifdef PC9800_DEBUG_FLOPPY
- printk("floppy open: end normally\n");
+ printk("floppy open: end normally\n");
#endif
-
+ }
+ up(&open_lock);
return 0;
-#undef RETERR
+out:
+ if (UDRS->fd_ref < 0)
+ UDRS->fd_ref=0;
+ else
+ UDRS->fd_ref--;
+ if (!UDRS->fd_ref)
+ opened_bdev[drive] = NULL;
+ floppy_release_irq_and_dma();
+out2:
+ up(&open_lock);
+ return res;
}
/*
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
+ if (((*part>>2) & 0x1f) >= NUMBER(floppy_type))
+ return NULL;
return get_disk(disks[drive]);
}
int unit;
struct mtop mtop;
- if (!inode || kdev_none(inode->i_rdev))
- return -EINVAL;
unit = DEVICE_NR(inode->i_rdev);
if (unit >= PT_UNITS)
return -EINVAL;
{
struct gendisk *disk = bdev->bd_disk;
struct block_device_operations * bdops = disk->fops;
- kdev_t dev = to_kdev_t(bdev->bd_dev);
if (!bdops->media_changed)
return 0;
if (!bdops->media_changed(bdev->bd_disk))
return 0;
- if (invalidate_device(dev, 0))
+ if (__invalidate_device(bdev, 0))
printk("VFS: busy inodes on changed media.\n");
if (bdops->revalidate_disk)
return 1;
}
-int full_check_disk_change(struct block_device *bdev)
-{
- int res = 0;
- if (bdev->bd_contains != bdev)
- BUG();
- down(&bdev->bd_sem);
- if (check_disk_change(bdev) && bdev->bd_invalidated) {
- rescan_partitions(bdev->bd_disk, bdev);
- res = 1;
- }
- up(&bdev->bd_sem);
- return res;
-}
-
-/*
- * Will die as soon as two remaining callers get converted.
- */
-int __check_disk_change(dev_t dev)
-{
- struct block_device *bdev = bdget(dev);
- int res;
- if (!bdev)
- return 0;
- if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
- return 0;
- res = full_check_disk_change(bdev);
- blkdev_put(bdev, BDEV_RAW);
- return res;
-}
-
static void bd_set_size(struct block_device *bdev, loff_t size)
{
unsigned bsize = bdev_hardsect_size(bdev);
invalidate_inode_pages(bdev->bd_inode->i_mapping);
}
-void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
-{
- struct block_device *bdev = bdget(kdev_t_to_nr(dev));
- if (bdev) {
- invalidate_bdev(bdev, destroy_dirty_buffers);
- bdput(bdev);
- }
-}
-
/*
* Kick pdflush then try to free up some ZONE_NORMAL memory.
*/
return busy;
}
-int invalidate_device(kdev_t dev, int do_sync)
+int __invalidate_device(struct block_device *bdev, int do_sync)
{
struct super_block *sb;
- struct block_device *bdev = bdget(kdev_t_to_nr(dev));
int res;
- if (!bdev)
- return 0;
-
if (do_sync)
fsync_bdev(bdev);
drop_super(sb);
}
invalidate_bdev(bdev, 0);
+ return res;
+}
+
+int invalidate_device(kdev_t dev, int do_sync)
+{
+ int res = 0;
+ struct block_device *bdev = bdget(kdev_t_to_nr(dev));
+ if (bdev)
+ res = __invalidate_device(bdev, do_sync);
bdput(bdev);
return res;
}
})
#define page_has_buffers(page) PagePrivate(page)
-#define invalidate_buffers(dev) __invalidate_buffers((dev), 0)
-
-
/*
* Declarations
*/
void mark_buffer_async_read(struct buffer_head *bh);
void mark_buffer_async_write(struct buffer_head *bh);
void invalidate_bdev(struct block_device *, int);
-void __invalidate_buffers(kdev_t dev, int);
int sync_blockdev(struct block_device *bdev);
void __wait_on_buffer(struct buffer_head *);
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
#define bio_data_dir(bio) ((bio)->bi_rw & 1)
extern int check_disk_change(struct block_device *);
-extern int full_check_disk_change(struct block_device *);
-extern int __check_disk_change(dev_t);
extern int invalidate_inodes(struct super_block *);
+extern int __invalidate_device(struct block_device *, int);
extern int invalidate_device(kdev_t, int);
unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end);
EXPORT_SYMBOL(put_filp);
EXPORT_SYMBOL(files_lock);
EXPORT_SYMBOL(check_disk_change);
-EXPORT_SYMBOL(__check_disk_change);
-EXPORT_SYMBOL(__invalidate_buffers);
EXPORT_SYMBOL(invalidate_bdev);
EXPORT_SYMBOL(invalidate_inodes);
EXPORT_SYMBOL(invalidate_device);
+EXPORT_SYMBOL(__invalidate_device);
EXPORT_SYMBOL(invalidate_inode_pages);
EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
EXPORT_SYMBOL(truncate_inode_pages);