*/
static DEFINE_SPINLOCK(floppy_lock);
-static struct completion device_release;
static unsigned short virtual_dma_port = 0x3f0;
irqreturn_t floppy_interrupt(int irq, void *dev_id);
* 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
* side 0 is on physical side 0 (but with the misnamed sector IDs).
* 'stretch' should probably be renamed to something more general, like
- * 'options'. Other parameters should be self-explanatory (see also
- * setfdprm(8)).
+ * 'options'.
+ *
+ * Bits 2 through 9 of 'stretch' tell the number of the first sector.
+ * The LSB (bit 2) is flipped. For most disks, the first sector
+ * is 1 (represented by 0x00<<2). For some CP/M and music sampler
+ * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2).
+ * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2).
+ *
+ * Other parameters should be self-explanatory (see also setfdprm(8)).
*/
/*
Size
static int set_dor(int fdc, char mask, char data)
{
- register unsigned char drive, unit, newdor, olddor;
+ unsigned char unit;
+ unsigned char drive;
+ unsigned char newdor;
+ unsigned char olddor;
if (FDCS->address == -1)
return -1;
static void floppy_off(unsigned int drive)
{
unsigned long volatile delta;
- register int fdc = FDC(drive);
+ int fdc = FDC(drive);
if (!(FDCS->dor & (0x10 << UNIT(drive))))
return;
}
/* Convert step rate from microseconds to milliseconds and 4 bits */
- srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR);
if (slow_floppy) {
srt = srt / 4;
}
SUPBOUND(srt, 0xf);
INFBOUND(srt, 0);
- hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR);
if (hlt < 0x01)
hlt = 0x01;
else if (hlt > 0x7f)
hlt = hlt_max_code;
- hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR);
if (hut < 0x1)
hut = 0x1;
else if (hut > 0xf)
}
}
}
- if (_floppy->stretch & FD_ZEROBASED) {
+ if (_floppy->stretch & FD_SECTBASEMASK) {
for (count = 0; count < F_SECT_PER_TRACK; count++)
- here[count].sect--;
+ here[count].sect += FD_SECTBASE(_floppy) - 1;
}
}
* =============================
*/
-static void floppy_end_request(struct request *req, int uptodate)
+static void floppy_end_request(struct request *req, int error)
{
unsigned int nr_sectors = current_count_sectors;
+ unsigned int drive = (unsigned long)req->rq_disk->private_data;
/* current_count_sectors can be zero if transfer failed */
- if (!uptodate)
+ if (error)
nr_sectors = req->current_nr_sectors;
- if (end_that_request_first(req, uptodate, nr_sectors))
+ if (__blk_end_request(req, error, nr_sectors << 9))
return;
- add_disk_randomness(req->rq_disk);
- floppy_off((long)req->rq_disk->private_data);
- blkdev_dequeue_request(req);
- end_that_request_last(req, uptodate);
/* We're done with the request */
+ floppy_off(drive);
current_req = NULL;
}
/* unlock chained buffers */
spin_lock_irqsave(q->queue_lock, flags);
- floppy_end_request(req, 1);
+ floppy_end_request(req, 0);
spin_unlock_irqrestore(q->queue_lock, flags);
} else {
if (rq_data_dir(req) == WRITE) {
DRWE->last_error_generation = DRS->generation;
}
spin_lock_irqsave(q->queue_lock, flags);
- floppy_end_request(req, 0);
+ floppy_end_request(req, -EIO);
spin_unlock_irqrestore(q->queue_lock, flags);
}
}
#ifdef FLOPPY_SANITY_CHECK
if (nr_sectors / ssize >
- (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
+ DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
DPRINT("long rw: %x instead of %lx\n",
nr_sectors, current_count_sectors);
printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
}
HEAD = fsector_t / _floppy->sect;
- if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
+ if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
max_sector = _floppy->sect;
CODE2SIZE;
SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
- ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
+ FD_SECTBASE(_floppy);
/* tracksize describes the size which can be filled up with sectors
* of size ssize.
g->head <= 0 ||
g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
/* check if reserved bits are set */
- (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
+ (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
return -EINVAL;
if (type) {
if (!capable(CAP_SYS_ADMIN))
if (DRS->maxblock > user_params[drive].sect ||
DRS->maxtrack ||
((user_params[drive].sect ^ oldStretch) &
- (FD_SWAPSIDES | FD_ZEROBASED)))
+ (FD_SWAPSIDES | FD_SECTBASEMASK)))
invalidate_drive(bdev);
else
process_fd_request();
return 0;
}
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
unsigned long param)
{
-#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
+#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
#define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
- int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(UDRS->fd_device);
int i;
int ret;
current_type[drive] = NULL;
floppy_sizes[drive] = MAX_DISK_SIZE << 1;
UDRS->keep_data = 0;
- return invalidate_drive(inode->i_bdev);
+ return invalidate_drive(bdev);
case FDSETPRM:
case FDDEFPRM:
return set_geometry(cmd, &inparam.g,
- drive, type, inode->i_bdev);
+ drive, type, bdev);
case FDGETPRM:
ECALL(get_floppy_geometry(drive, type,
(struct floppy_struct **)
case FDFMTEND:
case FDFLUSH:
LOCK_FDC(drive, 1);
- return invalidate_drive(inode->i_bdev);
+ return invalidate_drive(bdev);
case FDSETEMSGTRESH:
UDP->max_errors.reporting =
printk("\n");
}
-static int floppy_release(struct inode *inode, struct file *filp)
+static int floppy_release(struct gendisk *disk, fmode_t mode)
{
- int drive = (long)inode->i_bdev->bd_disk->private_data;
+ int drive = (long)disk->private_data;
mutex_lock(&open_lock);
if (UDRS->fd_ref < 0)
* /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers.
*/
-static int floppy_open(struct inode *inode, struct file *filp)
+static int floppy_open(struct block_device *bdev, fmode_t mode)
{
- int drive = (long)inode->i_bdev->bd_disk->private_data;
- int old_dev;
+ int drive = (long)bdev->bd_disk->private_data;
+ int old_dev, new_dev;
int try;
int res = -EBUSY;
char *tmp;
- filp->private_data = (void *)0;
mutex_lock(&open_lock);
old_dev = UDRS->fd_device;
- if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
+ if (opened_bdev[drive] && opened_bdev[drive] != bdev)
goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
USETF(FD_VERIFY);
}
- if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
+ if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL)))
goto out2;
- if (filp->f_flags & O_EXCL)
+ if (mode & FMODE_EXCL)
UDRS->fd_ref = -1;
else
UDRS->fd_ref++;
- opened_bdev[drive] = inode->i_bdev;
+ opened_bdev[drive] = bdev;
res = -ENXIO;
}
}
- UDRS->fd_device = iminor(inode);
- set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
- if (old_dev != -1 && old_dev != iminor(inode)) {
+ new_dev = MINOR(bdev->bd_dev);
+ UDRS->fd_device = new_dev;
+ set_capacity(disks[drive], floppy_sizes[new_dev]);
+ if (old_dev != -1 && old_dev != new_dev) {
if (buffer_drive == drive)
buffer_track = -1;
}
- /* Allow ioctls if we have write-permissions even if read-only open.
- * Needed so that programs such as fdrawcmd still can work on write
- * protected disks */
- if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
- filp->private_data = (void *)8;
-
if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2;
- if (!(filp->f_flags & O_NDELAY)) {
- if (filp->f_mode & 3) {
+ if (!(mode & FMODE_NDELAY)) {
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
UDRS->last_checked = 0;
- check_disk_change(inode->i_bdev);
+ check_disk_change(bdev);
if (UTESTF(FD_DISK_CHANGED))
goto out;
}
res = -EROFS;
- if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+ if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
goto out;
}
mutex_unlock(&open_lock);
.owner = THIS_MODULE,
.open = floppy_open,
.release = floppy_release,
- .ioctl = fd_ioctl,
+ .locked_ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
printk("\n");
} else
DPRINT("botched floppy option\n");
- DPRINT("Read Documentation/floppy.txt\n");
+ DPRINT("Read Documentation/blockdev/floppy.txt\n");
return 0;
}
static void floppy_device_release(struct device *dev)
{
- complete(&device_release);
}
static struct platform_device floppy_device[N_DRIVE];
int i, unit, drive;
int err, dr;
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
if (check_legacy_ioport(FDC1))
return -ENODEV;
#endif
}
}
-int __init init_module(void)
+static int __init floppy_module_init(void)
{
if (floppy)
parse_floppy_cfg_string(floppy);
return floppy_init();
}
+module_init(floppy_module_init);
-void cleanup_module(void)
+static void __exit floppy_module_exit(void)
{
int drive;
- init_completion(&device_release);
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR, "fd");
/* eject disk, if any */
fd_eject(0);
-
- wait_for_completion(&device_release);
}
+module_exit(floppy_module_exit);
module_param(floppy, charp, 0);
module_param(FLOPPY_IRQ, int, 0);