Commit a885c8c4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

[PATCH] Add block_device_operations.getgeo block device method

HDIO_GETGEO is implemented in most block drivers, and all of them have to
duplicate the code to copy the structure to userspace, as well as getting
the start sector.  This patch moves that to common code [1] and adds a
->getgeo method to fill out the raw kernel hd_geometry structure.  For many
drivers this means ->ioctl can go away now.

[1] the s390 block drivers are odd in this respect.  xpram sets ->start
    to 4 always which seems more than odd, and the dasd driver shifts
    the start offset around, probably because of it's non-standard
    sector size.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Jens Axboe <axboe@suse.de>
Cc: <mike.miller@hp.com>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Cc: Neil Brown <neilb@cse.unsw.edu.au>
Cc: Markus Lidel <Markus.Lidel@shadowconnect.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Signed-off-by: Adrian Bunk's avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5b0ed2c6
......@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_release(struct inode * inode, struct file * file);
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
#define MAX_DEV (8)
......@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
.open = ubd_open,
.release = ubd_release,
.ioctl = ubd_ioctl,
.getgeo = ubd_getgeo,
};
/* Protected by the queue_lock */
......@@ -1058,6 +1060,16 @@ static void do_ubd_request(request_queue_t *q)
}
}
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct ubd *dev = bdev->bd_disk->private_data;
geo->heads = 128;
geo->sectors = 32;
geo->cylinders = dev->size / (128 * 32 * 512);
return 0;
}
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
......@@ -1070,16 +1082,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
};
switch (cmd) {
struct hd_geometry g;
struct cdrom_volctrl volume;
case HDIO_GETGEO:
if(!loc) return(-EINVAL);
g.heads = 128;
g.sectors = 32;
g.cylinders = dev->size / (128 * 32 * 512);
g.start = get_start_sect(inode->i_bdev);
return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
case HDIO_GET_IDENTITY:
ubd_id.cyls = dev->size / (128 * 32 * 512);
if(copy_to_user((char __user *) arg, (char *) &ubd_id,
......
#include <linux/sched.h> /* for capable() */
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/hdreg.h>
#include <linux/backing-dev.h>
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
......@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
set_device_ro(bdev, n);
unlock_kernel();
return 0;
case HDIO_GETGEO: {
struct hd_geometry geo;
if (!arg)
return -EINVAL;
if (!disk->fops->getgeo)
return -ENOTTY;
/*
* We need to set the startsect first, the driver may
* want to override it.
*/
geo.start = get_start_sect(bdev);
ret = disk->fops->getgeo(bdev, &geo);
if (ret)
return ret;
if (copy_to_user((struct hd_geometry __user *)arg, &geo,
sizeof(geo)))
return -EFAULT;
return 0;
}
}
lock_kernel();
......
......@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
#define MAJOR_NR MFM_ACORN_MAJOR
#define QUEUE (mfm_queue)
#define CURRENT elv_next_request(mfm_queue)
/*
* This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
*/
#ifndef HDIO_GETGEO
#define HDIO_GETGEO 0x301
struct hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
#endif
/*
* Configuration section
......@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
* The 'front' end of the mfm driver follows...
*/
static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
struct hd_geometry *geo = (struct hd_geometry *) arg;
if (cmd != HDIO_GETGEO)
return -EINVAL;
if (!arg)
return -EINVAL;
if (put_user (p->heads, &geo->heads))
return -EFAULT;
if (put_user (p->sectors, &geo->sectors))
return -EFAULT;
if (put_user (p->cylinders, &geo->cylinders))
return -EFAULT;
if (put_user (get_start_sect(inode->i_bdev), &geo->start))
return -EFAULT;
struct mfm_info *p = bdev->bd_disk->private_data;
geo->heads = p->heads;
geo->sectors = p->sectors;
geo->cylinders = p->cylinders;
return 0;
}
......@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
static struct block_device_operations mfm_fops =
{
.owner = THIS_MODULE,
.ioctl = mfm_ioctl,
.getgeo = mfm_getgeo,
};
/*
......
......@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
return 0;
}
static int DAC960_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct gendisk *disk = bdev->bd_disk;
DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data;
struct hd_geometry g;
struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
if (cmd != HDIO_GETGEO || !loc)
return -EINVAL;
if (p->FirmwareType == DAC960_V1_Controller) {
g.heads = p->V1.GeometryTranslationHeads;
g.sectors = p->V1.GeometryTranslationSectors;
g.cylinders = p->V1.LogicalDriveInformation[drive_nr].
LogicalDriveSize / (g.heads * g.sectors);
geo->heads = p->V1.GeometryTranslationHeads;
geo->sectors = p->V1.GeometryTranslationSectors;
geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
LogicalDriveSize / (geo->heads * geo->sectors);
} else {
DAC960_V2_LogicalDeviceInfo_T *i =
p->V2.LogicalDeviceInformation[drive_nr];
switch (i->DriveGeometry) {
case DAC960_V2_Geometry_128_32:
g.heads = 128;
g.sectors = 32;
geo->heads = 128;
geo->sectors = 32;
break;
case DAC960_V2_Geometry_255_63:
g.heads = 255;
g.sectors = 63;
geo->heads = 255;
geo->sectors = 63;
break;
default:
DAC960_Error("Illegal Logical Device Geometry %d\n",
......@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
geo->cylinders = i->ConfigurableDeviceSize /
(geo->heads * geo->sectors);
}
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
return 0;
}
static int DAC960_media_changed(struct gendisk *disk)
......@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
static struct block_device_operations DAC960_BlockDeviceOperations = {
.owner = THIS_MODULE,
.open = DAC960_open,
.ioctl = DAC960_ioctl,
.getgeo = DAC960_getgeo,
.media_changed = DAC960_media_changed,
.revalidate_disk = DAC960_revalidate_disk,
};
......
......@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void )
*
***********************************************************************/
static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct acsi_info_struct *aip = bdev->bd_disk->private_data;
/*
* Just fake some geometry here, it's nonsense anyway
* To make it easy, use Adaptec's usual 64/32 mapping
*/
geo->heads = 64;
geo->sectors = 32;
geo->cylinders = aip->size >> 11;
return 0;
}
static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
......@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
struct gendisk *disk = inode->i_bdev->bd_disk;
struct acsi_info_struct *aip = disk->private_data;
switch (cmd) {
case HDIO_GETGEO:
/* HDIO_GETGEO is supported more for getting the partition's
* start sector... */
{ struct hd_geometry *geo = (struct hd_geometry *)arg;
/* just fake some geometry here, it's nonsense anyway; to make it
* easy, use Adaptec's usual 64/32 mapping */
put_user( 64, &geo->heads );
put_user( 32, &geo->sectors );
put_user( aip->size >> 11, &geo->cylinders );
put_user(get_start_sect(inode->i_bdev), &geo->start);
return 0;
}
case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
put_user( aip->target | (aip->lun << 8),
......@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
.open = acsi_open,
.release = acsi_release,
.ioctl = acsi_ioctl,
.getgeo = acsi_getgeo,
.media_changed = acsi_media_change,
.revalidate_disk= acsi_revalidate,
};
......
......@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q)
redo_fd_request();
}
static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
int drive = MINOR(bdev->bd_dev) & 3;
geo->heads = unit[drive].type->heads;
geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
geo->cylinders = unit[drive].type->tracks;
return 0;
}
static int fd_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param)
{
......@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
static struct floppy_struct getprm;
switch(cmd){
case HDIO_GETGEO:
{
struct hd_geometry loc;
loc.heads = unit[drive].type->heads;
loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
loc.cylinders = unit[drive].type->tracks;
loc.start = 0;
if (copy_to_user((void *)param, (void *)&loc,
sizeof(struct hd_geometry)))
return -EFAULT;
break;
}
case FDFMTBEG:
get_fdc(drive);
if (fd_ref[drive] > 1) {
......@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = amiga_floppy_change,
};
......
......@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
return 0;
}
/* This ioctl implementation expects userland to have the device node
* permissions set so that only priviledged users can open an aoe
* block device directly.
*/
static int
aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg)
aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct aoedev *d;
if (!arg)
return -EINVAL;
struct aoedev *d = bdev->bd_disk->private_data;
d = inode->i_bdev->bd_disk->private_data;
if ((d->flags & DEVFL_UP) == 0) {
printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
return -ENODEV;
}
if (cmd == HDIO_GETGEO) {
d->geo.start = get_start_sect(inode->i_bdev);
if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo))
return 0;
return -EFAULT;
}
printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
return -EINVAL;
geo->cylinders = d->geo.cylinders;
geo->heads = d->geo.heads;
geo->sectors = d->geo.sectors;
return 0;
}
static struct block_device_operations aoe_bdops = {
.open = aoeblk_open,
.release = aoeblk_release,
.ioctl = aoeblk_ioctl,
.getgeo = aoeblk_getgeo,
.owner = THIS_MODULE,
};
......
......@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep);
static int cciss_release(struct inode *inode, struct file *filep);
static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
......@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = {
.open = cciss_open,
.release = cciss_release,
.ioctl = cciss_ioctl,
.getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl,
#endif
......@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
return err;
}
#endif
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
drive_info_struct *drv = get_drv(bdev->bd_disk);
if (!drv->cylinders)
return -ENXIO;
geo->heads = drv->heads;
geo->sectors = drv->sectors;
geo->cylinders = drv->cylinders;
return 0;
}
/*
* ioctl
*/
......@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
#endif /* CCISS_DEBUG */
switch(cmd) {
case HDIO_GETGEO:
{
struct hd_geometry driver_geo;
if (drv->cylinders) {
driver_geo.heads = drv->heads;
driver_geo.sectors = drv->sectors;
driver_geo.cylinders = drv->cylinders;
} else
return -ENXIO;
driver_geo.start= get_start_sect(inode->i_bdev);
if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry)))
return -EFAULT;
return(0);
}
case CCISS_GETPCIINFO:
{
cciss_pci_info_struct pciinfo;
......
......@@ -160,6 +160,7 @@ static int sendcmd(
static int ida_open(struct inode *inode, struct file *filep);
static int ida_release(struct inode *inode, struct file *filep);
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
static void do_ida_request(request_queue_t *q);
......@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = {
.open = ida_open,
.release = ida_release,
.ioctl = ida_ioctl,
.getgeo = ida_getgeo,
.revalidate_disk= ida_revalidate,
};
......@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
h->misc_tflags = 0;
}
static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
drv_info_t *drv = get_drv(bdev->bd_disk);
if (drv->cylinders) {
geo->heads = drv->heads;
geo->sectors = drv->sectors;
geo->cylinders = drv->cylinders;
} else {
geo->heads = 0xff;
geo->sectors = 0x3f;
geo->cylinders = drv->nr_blks / (0xff*0x3f);
}
return 0;
}
/*
* ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller.
......@@ -1133,27 +1152,10 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
int error;
int diskinfo[4];
struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io;
switch(cmd) {
case HDIO_GETGEO:
if (drv->cylinders) {
diskinfo[0] = drv->heads;
diskinfo[1] = drv->sectors;
diskinfo[2] = drv->cylinders;
} else {
diskinfo[0] = 0xff;
diskinfo[1] = 0x3f;
diskinfo[2] = drv->nr_blks / (0xff*0x3f);
}
put_user(diskinfo[0], &geo->heads);
put_user(diskinfo[1], &geo->sectors);
put_user(diskinfo[2], &geo->cylinders);
put_user(get_start_sect(inode->i_bdev), &geo->start);
return 0;
case IDAGETDRVINFO:
if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
return -EFAULT;
......
......@@ -3445,6 +3445,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
return 0;
}
static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(drive_state[drive].fd_device);
struct floppy_struct *g;
int ret;
ret = get_floppy_geometry(drive, type, &g);
if (ret)
return ret;
geo->heads = g->head;
geo->sectors = g->sect;
geo->cylinders = g->track;
return 0;
}
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param)
{
......@@ -3474,23 +3491,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
cmd = FDEJECT;
}
/* generic block device ioctls */
switch (cmd) {
/* the following have been inspired by the corresponding
* code for other block devices. */
struct floppy_struct *g;
case HDIO_GETGEO:
{
struct hd_geometry loc;
ECALL(get_floppy_geometry(drive, type, &g));
loc.heads = g->head;
loc.sectors = g->sect;
loc.cylinders = g->track;
loc.start = 0;
return _COPYOUT(loc);
}
}
/* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_ioctl(&cmd, &size));
......@@ -3938,6 +3938,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
};
......
......@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
return 0;
}
static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct pd_unit *disk = bdev->bd_disk->private_data;
if (disk->alt_geom) {
geo->heads = PD_LOG_HEADS;
geo->sectors = PD_LOG_SECTS;
geo->cylinders = disk->capacity / (geo->heads * geo->sectors);
} else {
geo->heads = disk->heads;
geo->sectors = disk->sectors;
geo->cylinders = disk->cylinders;
}
return 0;
}
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
struct hd_geometry g;
switch (cmd) {
case CDROMEJECT:
if (disk->access == 1)
pd_special_command(disk, pd_eject);
return 0;
case HDIO_GETGEO:
if (disk->alt_geom) {
g.heads = PD_LOG_HEADS;
g.sectors = PD_LOG_SECTS;
g.cylinders = disk->capacity / (g.heads * g.sectors);
} else {
g.heads = disk->heads;
g.sectors = disk->sectors;
g.cylinders = disk->cylinders;
}
g.start = get_start_sect(inode->i_bdev);
if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
return -EFAULT;
return 0;
default:
return -EINVAL;
}
......@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
.open = pd_open,
.release = pd_release,
.ioctl = pd_ioctl,
.getgeo = pd_getgeo,
.media_changed = pd_check_media,
.revalidate_disk= pd_revalidate
};
......
......@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int pf_release(struct inode *inode, struct file *file);
......@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
.open = pf_open,
.release = pf_release,
.ioctl = pf_ioctl,
.getgeo = pf_getgeo,
.media_changed = pf_check_media,
};
......@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
return 0;
}
static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
struct hd_geometry g;
sector_t capacity;
if (cmd == CDROMEJECT) {
if (pf->access == 1) {
pf_eject(pf);
return 0;
}
return -EBUSY;
}
if (cmd != HDIO_GETGEO)
return -EINVAL;
capacity = get_capacity(pf->disk);
struct pf_unit *pf = bdev->bd_disk->private_data;
sector_t capacity = get_capacity(pf->disk);
if (capacity < PF_FD_MAX) {
g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
g.heads = PF_FD_HDS;
g.sectors = PF_FD_SPT;
geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
geo->heads = PF_FD_HDS;
geo->sectors = PF_FD_SPT;
} else {
g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
g.heads = PF_HD_HDS;
g.sectors = PF_HD_SPT;
geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
geo->heads = PF_HD_HDS;
geo->sectors = PF_HD_SPT;
}
if (copy_to_user(geo, &g, sizeof(g)))
return -EFAULT;
return 0;
}
static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
if (cmd != CDROMEJECT)
return -EINVAL;
if (pf->access != 1)
return -EBUSY;
pf_eject(pf);
return 0;
}
......
......@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL;
static void ps2esdi_normal_interrupt_handler(u_int);
static void ps2esdi_initial_reset_int_handler(u_int);
static void ps2esdi_geometry_int_handler(u_int);
static int ps2esdi_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg);
static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
......@@ -132,7 +131,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
static struct block_device_operations ps2esdi_fops =
{
.owner = THIS_MODULE,
.ioctl = ps2esdi_ioctl,
.getgeo = ps2esdi_getgeo,
};
static struct gendisk *ps2esdi_gendisk[2];
......@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
}
static int ps2esdi_ioctl(struct inode *inode,
struct file *file, u_int cmd, u_long arg)
static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
struct ps2esdi_geometry geom;
if (cmd != HDIO_GETGEO)
return -EINVAL;
memset(&geom, 0, sizeof(geom));
geom.heads = p->head;
geom.sectors = p->sect;
geom.cylinders = p->cyl;
geom.start = get_start_sect(inode->i_bdev);
if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
return -EFAULT;
struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
geo->heads = p->head;
geo->sectors = p->sect;
geo->cylinders = p->cyl;
return 0;
}
......