提交 a885c8c4 编写于 作者: C Christoph Hellwig 提交者: 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: NChristoph 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: NAdrian Bunk <bunk@stusta.de>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 5b0ed2c6
...@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp); ...@@ -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_release(struct inode * inode, struct file * file);
static int ubd_ioctl(struct inode * inode, struct file * file, static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
#define MAX_DEV (8) #define MAX_DEV (8)
...@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = { ...@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
.open = ubd_open, .open = ubd_open,
.release = ubd_release, .release = ubd_release,
.ioctl = ubd_ioctl, .ioctl = ubd_ioctl,
.getgeo = ubd_getgeo,
}; };
/* Protected by the queue_lock */ /* Protected by the queue_lock */
...@@ -1058,6 +1060,16 @@ static void do_ubd_request(request_queue_t *q) ...@@ -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, static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -1070,16 +1082,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, ...@@ -1070,16 +1082,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
}; };
switch (cmd) { switch (cmd) {
struct hd_geometry g;
struct cdrom_volctrl volume; 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: case HDIO_GET_IDENTITY:
ubd_id.cyls = dev->size / (128 * 32 * 512); ubd_id.cyls = dev->size / (128 * 32 * 512);
if(copy_to_user((char __user *) arg, (char *) &ubd_id, if(copy_to_user((char __user *) arg, (char *) &ubd_id,
......
#include <linux/sched.h> /* for capable() */ #include <linux/sched.h> /* for capable() */
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/hdreg.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
...@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, ...@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
set_device_ro(bdev, n); set_device_ro(bdev, n);
unlock_kernel(); unlock_kernel();
return 0; 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(); lock_kernel();
......
...@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock); ...@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
#define MAJOR_NR MFM_ACORN_MAJOR #define MAJOR_NR MFM_ACORN_MAJOR
#define QUEUE (mfm_queue) #define QUEUE (mfm_queue)
#define CURRENT elv_next_request(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 * Configuration section
...@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void) ...@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
* The 'front' end of the mfm driver follows... * 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 mfm_info *p = bdev->bd_disk->private_data;
struct hd_geometry *geo = (struct hd_geometry *) arg;
if (cmd != HDIO_GETGEO) geo->heads = p->heads;
return -EINVAL; geo->sectors = p->sectors;
if (!arg) geo->cylinders = p->cylinders;
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;
return 0; return 0;
} }
...@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, ...@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
static struct block_device_operations mfm_fops = static struct block_device_operations mfm_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = mfm_ioctl, .getgeo = mfm_getgeo,
}; };
/* /*
......
...@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file) ...@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int DAC960_ioctl(struct inode *inode, struct file *file, static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
unsigned int cmd, unsigned long arg)
{ {
struct gendisk *disk = inode->i_bdev->bd_disk; struct gendisk *disk = bdev->bd_disk;
DAC960_Controller_T *p = disk->queue->queuedata; DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data; 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) { if (p->FirmwareType == DAC960_V1_Controller) {
g.heads = p->V1.GeometryTranslationHeads; geo->heads = p->V1.GeometryTranslationHeads;
g.sectors = p->V1.GeometryTranslationSectors; geo->sectors = p->V1.GeometryTranslationSectors;
g.cylinders = p->V1.LogicalDriveInformation[drive_nr]. geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
LogicalDriveSize / (g.heads * g.sectors); LogicalDriveSize / (geo->heads * geo->sectors);
} else { } else {
DAC960_V2_LogicalDeviceInfo_T *i = DAC960_V2_LogicalDeviceInfo_T *i =
p->V2.LogicalDeviceInformation[drive_nr]; p->V2.LogicalDeviceInformation[drive_nr];
switch (i->DriveGeometry) { switch (i->DriveGeometry) {
case DAC960_V2_Geometry_128_32: case DAC960_V2_Geometry_128_32:
g.heads = 128; geo->heads = 128;
g.sectors = 32; geo->sectors = 32;
break; break;
case DAC960_V2_Geometry_255_63: case DAC960_V2_Geometry_255_63:
g.heads = 255; geo->heads = 255;
g.sectors = 63; geo->sectors = 63;
break; break;
default: default:
DAC960_Error("Illegal Logical Device Geometry %d\n", DAC960_Error("Illegal Logical Device Geometry %d\n",
...@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file, ...@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
return -EINVAL; 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 0;
return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
} }
static int DAC960_media_changed(struct gendisk *disk) static int DAC960_media_changed(struct gendisk *disk)
...@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk) ...@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
static struct block_device_operations DAC960_BlockDeviceOperations = { static struct block_device_operations DAC960_BlockDeviceOperations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = DAC960_open, .open = DAC960_open,
.ioctl = DAC960_ioctl, .getgeo = DAC960_getgeo,
.media_changed = DAC960_media_changed, .media_changed = DAC960_media_changed,
.revalidate_disk = DAC960_revalidate_disk, .revalidate_disk = DAC960_revalidate_disk,
}; };
......
...@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void ) ...@@ -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, static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg ) unsigned int cmd, unsigned long arg )
...@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file, ...@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
struct gendisk *disk = inode->i_bdev->bd_disk; struct gendisk *disk = inode->i_bdev->bd_disk;
struct acsi_info_struct *aip = disk->private_data; struct acsi_info_struct *aip = disk->private_data;
switch (cmd) { 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: case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */ /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
put_user( aip->target | (aip->lun << 8), put_user( aip->target | (aip->lun << 8),
...@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = { ...@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
.open = acsi_open, .open = acsi_open,
.release = acsi_release, .release = acsi_release,
.ioctl = acsi_ioctl, .ioctl = acsi_ioctl,
.getgeo = acsi_getgeo,
.media_changed = acsi_media_change, .media_changed = acsi_media_change,
.revalidate_disk= acsi_revalidate, .revalidate_disk= acsi_revalidate,
}; };
......
...@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q) ...@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q)
redo_fd_request(); 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, static int fd_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param) unsigned int cmd, unsigned long param)
{ {
...@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, ...@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
static struct floppy_struct getprm; static struct floppy_struct getprm;
switch(cmd){ 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: case FDFMTBEG:
get_fdc(drive); get_fdc(drive);
if (fd_ref[drive] > 1) { if (fd_ref[drive] > 1) {
...@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = { ...@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open, .open = floppy_open,
.release = floppy_release, .release = floppy_release,
.ioctl = fd_ioctl, .ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = amiga_floppy_change, .media_changed = amiga_floppy_change,
}; };
......
...@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) ...@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
return 0; 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 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; struct aoedev *d = bdev->bd_disk->private_data;
if (!arg)
return -EINVAL;
d = inode->i_bdev->bd_disk->private_data;
if ((d->flags & DEVFL_UP) == 0) { if ((d->flags & DEVFL_UP) == 0) {
printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
return -ENODEV; return -ENODEV;
} }
if (cmd == HDIO_GETGEO) { geo->cylinders = d->geo.cylinders;
d->geo.start = get_start_sect(inode->i_bdev); geo->heads = d->geo.heads;
if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo)) geo->sectors = d->geo.sectors;
return 0; return 0;
return -EFAULT;
}
printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
return -EINVAL;
} }
static struct block_device_operations aoe_bdops = { static struct block_device_operations aoe_bdops = {
.open = aoeblk_open, .open = aoeblk_open,
.release = aoeblk_release, .release = aoeblk_release,
.ioctl = aoeblk_ioctl, .getgeo = aoeblk_getgeo,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep); ...@@ -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_release(struct inode *inode, struct file *filep);
static int cciss_ioctl(struct inode *inode, struct file *filep, static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg); 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 revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk); static int cciss_revalidate(struct gendisk *disk);
...@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = { ...@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = {
.open = cciss_open, .open = cciss_open,
.release = cciss_release, .release = cciss_release,
.ioctl = cciss_ioctl, .ioctl = cciss_ioctl,
.getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl, .compat_ioctl = cciss_compat_ioctl,
#endif #endif
...@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned ...@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
return err; return err;
} }
#endif #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 * ioctl
*/ */
...@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
#endif /* CCISS_DEBUG */ #endif /* CCISS_DEBUG */
switch(cmd) { 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: case CCISS_GETPCIINFO:
{ {
cciss_pci_info_struct pciinfo; cciss_pci_info_struct pciinfo;
......
...@@ -160,6 +160,7 @@ static int sendcmd( ...@@ -160,6 +160,7 @@ static int sendcmd(
static int ida_open(struct inode *inode, struct file *filep); static int ida_open(struct inode *inode, struct file *filep);
static int ida_release(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_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 int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
static void do_ida_request(request_queue_t *q); static void do_ida_request(request_queue_t *q);
...@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = { ...@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = {
.open = ida_open, .open = ida_open,
.release = ida_release, .release = ida_release,
.ioctl = ida_ioctl, .ioctl = ida_ioctl,
.getgeo = ida_getgeo,
.revalidate_disk= ida_revalidate, .revalidate_disk= ida_revalidate,
}; };
...@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata) ...@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
h->misc_tflags = 0; 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, * ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller. * 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, ...@@ -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); drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
int error; 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 __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io; ida_ioctl_t *my_io;
switch(cmd) { 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: case IDAGETDRVINFO:
if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t))) if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
return -EFAULT; return -EFAULT;
......
...@@ -3445,6 +3445,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) ...@@ -3445,6 +3445,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
return 0; 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, static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param) unsigned long param)
{ {
...@@ -3474,23 +3491,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -3474,23 +3491,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
cmd = FDEJECT; 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 */ /* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) { if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_ioctl(&cmd, &size)); ECALL(normalize_ioctl(&cmd, &size));
...@@ -3938,6 +3938,7 @@ static struct block_device_operations floppy_fops = { ...@@ -3938,6 +3938,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open, .open = floppy_open,
.release = floppy_release, .release = floppy_release,
.ioctl = fd_ioctl, .ioctl = fd_ioctl,
.getgeo = fd_getgeo,
.media_changed = check_floppy_change, .media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate, .revalidate_disk = floppy_revalidate,
}; };
......
...@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file) ...@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
return 0; 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, static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct pd_unit *disk = inode->i_bdev->bd_disk->private_data; 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) { switch (cmd) {
case CDROMEJECT: case CDROMEJECT:
if (disk->access == 1) if (disk->access == 1)
pd_special_command(disk, pd_eject); pd_special_command(disk, pd_eject);
return 0; 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: default:
return -EINVAL; return -EINVAL;
} }
...@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = { ...@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
.open = pd_open, .open = pd_open,
.release = pd_release, .release = pd_release,
.ioctl = pd_ioctl, .ioctl = pd_ioctl,
.getgeo = pd_getgeo,
.media_changed = pd_check_media, .media_changed = pd_check_media,
.revalidate_disk= pd_revalidate .revalidate_disk= pd_revalidate
}; };
......
...@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file); ...@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
static void do_pf_request(request_queue_t * q); static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode, struct file *file, static int pf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg); 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); static int pf_release(struct inode *inode, struct file *file);
...@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = { ...@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
.open = pf_open, .open = pf_open,
.release = pf_release, .release = pf_release,
.ioctl = pf_ioctl, .ioctl = pf_ioctl,
.getgeo = pf_getgeo,
.media_changed = pf_check_media, .media_changed = pf_check_media,
}; };
...@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file) ...@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
return 0; 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 pf_unit *pf = bdev->bd_disk->private_data;
struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; sector_t capacity = get_capacity(pf->disk);
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);
if (capacity < PF_FD_MAX) { if (capacity < PF_FD_MAX) {
g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
g.heads = PF_FD_HDS; geo->heads = PF_FD_HDS;
g.sectors = PF_FD_SPT; geo->sectors = PF_FD_SPT;
} else { } else {
g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
g.heads = PF_HD_HDS; geo->heads = PF_HD_HDS;
g.sectors = PF_HD_SPT; 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; return 0;
} }
......
...@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL; ...@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL;
static void ps2esdi_normal_interrupt_handler(u_int); static void ps2esdi_normal_interrupt_handler(u_int);
static void ps2esdi_initial_reset_int_handler(u_int); static void ps2esdi_initial_reset_int_handler(u_int);
static void ps2esdi_geometry_int_handler(u_int); static void ps2esdi_geometry_int_handler(u_int);
static int ps2esdi_ioctl(struct inode *inode, struct file *file, static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
u_int cmd, u_long arg);
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); 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] = ...@@ -132,7 +131,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
static struct block_device_operations ps2esdi_fops = static struct block_device_operations ps2esdi_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = ps2esdi_ioctl, .getgeo = ps2esdi_getgeo,
}; };
static struct gendisk *ps2esdi_gendisk[2]; static struct gendisk *ps2esdi_gendisk[2];
...@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code) ...@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
} }
static int ps2esdi_ioctl(struct inode *inode, static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
struct file *file, u_int cmd, u_long arg)
{ {
struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data; struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
struct ps2esdi_geometry geom;
geo->heads = p->head;
if (cmd != HDIO_GETGEO) geo->sectors = p->sect;
return -EINVAL; geo->cylinders = p->cyl;
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;
return 0; return 0;
} }
......
...@@ -407,8 +407,7 @@ struct carm_array_info { ...@@ -407,8 +407,7 @@ struct carm_array_info {
static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static void carm_remove_one (struct pci_dev *pdev); static void carm_remove_one (struct pci_dev *pdev);
static int carm_bdev_ioctl(struct inode *ino, struct file *fil, static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
unsigned int cmd, unsigned long arg);
static struct pci_device_id carm_pci_tbl[] = { static struct pci_device_id carm_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
...@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = { ...@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
static struct block_device_operations carm_bd_ops = { static struct block_device_operations carm_bd_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = carm_bdev_ioctl, .getgeo = carm_bdev_getgeo,
}; };
static unsigned int carm_host_id; static unsigned int carm_host_id;
...@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc; ...@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
static int carm_bdev_ioctl(struct inode *ino, struct file *fil, static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
unsigned int cmd, unsigned long arg)
{ {
void __user *usermem = (void __user *) arg; struct carm_port *port = bdev->bd_disk->private_data;
struct carm_port *port = ino->i_bdev->bd_disk->private_data;
struct hd_geometry geom;
switch (cmd) { geo->heads = (u8) port->dev_geom_head;
case HDIO_GETGEO: geo->sectors = (u8) port->dev_geom_sect;
if (!usermem) geo->cylinders = port->dev_geom_cyl;
return -EINVAL; return 0;
geom.heads = (u8) port->dev_geom_head;
geom.sectors = (u8) port->dev_geom_sect;
geom.cylinders = port->dev_geom_cyl;
geom.start = get_start_sect(ino->i_bdev);
if (copy_to_user(usermem, &geom, sizeof(geom)))
return -EFAULT;
return 0;
default:
break;
}
return -EOPNOTSUPP;
} }
static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE }; static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
......
...@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk) ...@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk)
set_capacity(disk, card->mm_size << 1); set_capacity(disk, card->mm_size << 1);
return 0; return 0;
} }
/*
----------------------------------------------------------------------------------- static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-- mm_ioctl
-----------------------------------------------------------------------------------
*/
static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
{ {
if (cmd == HDIO_GETGEO) { struct cardinfo *card = bdev->bd_disk->private_data;
struct cardinfo *card = i->i_bdev->bd_disk->private_data; int size = card->mm_size * (1024 / MM_HARDSECT);
int size = card->mm_size * (1024 / MM_HARDSECT);
struct hd_geometry geo;
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
* whatever cylinders.
*/
geo.heads = 64;
geo.sectors = 32;
geo.start = get_start_sect(i->i_bdev);
geo.cylinders = size / (geo.heads * geo.sectors);
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
}
return -EINVAL; /*
* get geometry: we have to fake one... trim the size to a
* multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
* whatever cylinders.
*/
geo->heads = 64;
geo->sectors = 32;
geo->cylinders = size / (geo->heads * geo->sectors);
return 0;
} }
/* /*
----------------------------------------------------------------------------------- -----------------------------------------------------------------------------------
-- mm_check_change -- mm_check_change
...@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk) ...@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk)
*/ */
static struct block_device_operations mm_fops = { static struct block_device_operations mm_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = mm_ioctl, .getgeo = mm_getgeo,
.revalidate_disk= mm_revalidate, .revalidate_disk= mm_revalidate,
.media_changed = mm_check_change, .media_changed = mm_check_change,
}; };
......
...@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil) ...@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil)
/* External ioctl entry point. /* External ioctl entry point.
*/ */
static int viodasd_ioctl(struct inode *ino, struct file *fil, static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
unsigned int cmd, unsigned long arg)
{ {
unsigned char sectors; struct gendisk *disk = bdev->bd_disk;
unsigned char heads; struct viodasd_device *d = disk->private_data;
unsigned short cylinders;
struct hd_geometry *geo;
struct gendisk *gendisk;
struct viodasd_device *d;
switch (cmd) { geo->sectors = d->sectors ? d->sectors : 0;
case HDIO_GETGEO: geo->heads = d->tracks ? d->tracks : 64;
geo = (struct hd_geometry *)arg; geo->cylinders = d->cylinders ? d->cylinders :
if (geo == NULL) get_capacity(disk) / (geo->cylinders * geo->heads);
return -EINVAL;
if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
return -EFAULT;
gendisk = ino->i_bdev->bd_disk;
d = gendisk->private_data;
sectors = d->sectors;
if (sectors == 0)
sectors = 32;
heads = d->tracks;
if (heads == 0)
heads = 64;
cylinders = d->cylinders;
if (cylinders == 0)
cylinders = get_capacity(gendisk) / (sectors * heads);
if (__put_user(sectors, &geo->sectors) ||
__put_user(heads, &geo->heads) ||
__put_user(cylinders, &geo->cylinders) ||
__put_user(get_start_sect(ino->i_bdev), &geo->start))
return -EFAULT;
return 0;
}
return -EINVAL; return 0;
} }
/* /*
...@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = { ...@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = viodasd_open, .open = viodasd_open,
.release = viodasd_release, .release = viodasd_release,
.ioctl = viodasd_ioctl, .getgeo = viodasd_getgeo,
}; };
/* /*
......
...@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock); ...@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock);
static struct gendisk *xd_gendisk[2]; static struct gendisk *xd_gendisk[2];
static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static struct block_device_operations xd_fops = { static struct block_device_operations xd_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = xd_ioctl, .ioctl = xd_ioctl,
.getgeo = xd_getgeo,
}; };
static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors; static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
...@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q) ...@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q)
} }
} }
static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
XD_INFO *p = bdev->bd_disk->private_data;
geo->heads = p->heads;
geo->sectors = p->sectors;
geo->cylinders = p->cylinders;
return 0;
}
/* xd_ioctl: handle device ioctl's */ /* xd_ioctl: handle device ioctl's */
static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{ {
XD_INFO *p = inode->i_bdev->bd_disk->private_data;
switch (cmd) { switch (cmd) {
case HDIO_GETGEO:
{
struct hd_geometry g;
struct hd_geometry __user *geom= (void __user *)arg;
g.heads = p->heads;
g.sectors = p->sectors;
g.cylinders = p->cylinders;
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
}
case HDIO_SET_DMA: case HDIO_SET_DMA:
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (xdc_busy) return -EBUSY; if (xdc_busy) return -EBUSY;
......
...@@ -1130,6 +1130,17 @@ static int idedisk_release(struct inode *inode, struct file *filp) ...@@ -1130,6 +1130,17 @@ static int idedisk_release(struct inode *inode, struct file *filp)
return 0; return 0;
} }
static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
ide_drive_t *drive = idkp->drive;
geo->heads = drive->bios_head;
geo->sectors = drive->bios_sect;
geo->cylinders = (u16)drive->bios_cyl; /* truncate */
return 0;
}
static int idedisk_ioctl(struct inode *inode, struct file *file, static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -1164,6 +1175,7 @@ static struct block_device_operations idedisk_ops = { ...@@ -1164,6 +1175,7 @@ static struct block_device_operations idedisk_ops = {
.open = idedisk_open, .open = idedisk_open,
.release = idedisk_release, .release = idedisk_release,
.ioctl = idedisk_ioctl, .ioctl = idedisk_ioctl,
.getgeo = idedisk_getgeo,
.media_changed = idedisk_media_changed, .media_changed = idedisk_media_changed,
.revalidate_disk= idedisk_revalidate_disk .revalidate_disk= idedisk_revalidate_disk
}; };
......
...@@ -2031,6 +2031,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp) ...@@ -2031,6 +2031,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
return 0; return 0;
} }
static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
ide_drive_t *drive = floppy->drive;
geo->heads = drive->bios_head;
geo->sectors = drive->bios_sect;
geo->cylinders = (u16)drive->bios_cyl; /* truncate */
return 0;
}
static int idefloppy_ioctl(struct inode *inode, struct file *file, static int idefloppy_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -2120,6 +2131,7 @@ static struct block_device_operations idefloppy_ops = { ...@@ -2120,6 +2131,7 @@ static struct block_device_operations idefloppy_ops = {
.open = idefloppy_open, .open = idefloppy_open,
.release = idefloppy_release, .release = idefloppy_release,
.ioctl = idefloppy_ioctl, .ioctl = idefloppy_ioctl,
.getgeo = idefloppy_getgeo,
.media_changed = idefloppy_media_changed, .media_changed = idefloppy_media_changed,
.revalidate_disk= idefloppy_revalidate_disk .revalidate_disk= idefloppy_revalidate_disk
}; };
......
...@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ...@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
up(&ide_setting_sem); up(&ide_setting_sem);
switch (cmd) { switch (cmd) {
case HDIO_GETGEO:
{
struct hd_geometry geom;
if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
geom.heads = drive->bios_head;
geom.sectors = drive->bios_sect;
geom.cylinders = (u16)drive->bios_cyl; /* truncate */
geom.start = get_start_sect(bdev);
if (copy_to_user(p, &geom, sizeof(struct hd_geometry)))
return -EFAULT;
return 0;
}
case HDIO_OBSOLETE_IDENTITY: case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY: case HDIO_GET_IDENTITY:
if (bdev != bdev->bd_contains) if (bdev != bdev->bd_contains)
......
...@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q) ...@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q)
enable_irq(HD_IRQ); enable_irq(HD_IRQ);
} }
static int hd_ioctl(struct inode * inode, struct file * file, static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
unsigned int cmd, unsigned long arg)
{ {
struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; struct hd_i_struct *disk = bdev->bd_disk->private_data;
struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
struct hd_geometry g; geo->heads = disk->head;
geo->sectors = disk->sect;
if (cmd != HDIO_GETGEO) geo->cylinders = disk->cyl;
return -EINVAL; return 0;
if (!loc)
return -EINVAL;
g.heads = disk->head;
g.sectors = disk->sect;
g.cylinders = disk->cyl;
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
} }
/* /*
...@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} }
static struct block_device_operations hd_fops = { static struct block_device_operations hd_fops = {
.ioctl = hd_ioctl, .getgeo = hd_getgeo,
}; };
/* /*
......
...@@ -3598,12 +3598,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev) ...@@ -3598,12 +3598,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
return 0; return 0;
} }
static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
mddev_t *mddev = bdev->bd_disk->private_data;
geo->heads = 2;
geo->sectors = 4;
geo->cylinders = get_capacity(mddev->gendisk) / 8;
return 0;
}
static int md_ioctl(struct inode *inode, struct file *file, static int md_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int err = 0; int err = 0;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
struct hd_geometry __user *loc = argp;
mddev_t *mddev = NULL; mddev_t *mddev = NULL;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -3765,24 +3774,6 @@ static int md_ioctl(struct inode *inode, struct file *file, ...@@ -3765,24 +3774,6 @@ static int md_ioctl(struct inode *inode, struct file *file,
* 4 sectors (with a BIG number of cylinders...). This drives * 4 sectors (with a BIG number of cylinders...). This drives
* dosfs just mad... ;-) * dosfs just mad... ;-)
*/ */
case HDIO_GETGEO:
if (!loc) {
err = -EINVAL;
goto abort_unlock;
}
err = put_user (2, (char __user *) &loc->heads);
if (err)
goto abort_unlock;
err = put_user (4, (char __user *) &loc->sectors);
if (err)
goto abort_unlock;
err = put_user(get_capacity(mddev->gendisk)/8,
(short __user *) &loc->cylinders);
if (err)
goto abort_unlock;
err = put_user (get_start_sect(inode->i_bdev),
(long __user *) &loc->start);
goto done_unlock;
} }
/* /*
...@@ -3911,6 +3902,7 @@ static struct block_device_operations md_fops = ...@@ -3911,6 +3902,7 @@ static struct block_device_operations md_fops =
.open = md_open, .open = md_open,
.release = md_release, .release = md_release,
.ioctl = md_ioctl, .ioctl = md_ioctl,
.getgeo = md_getgeo,
.media_changed = md_media_changed, .media_changed = md_media_changed,
.revalidate_disk= md_revalidate, .revalidate_disk= md_revalidate,
}; };
......
...@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file) ...@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
i2o_block_biosparam(get_capacity(bdev->bd_disk),
&geo->cylinders, &geo->heads, &geo->sectors);
return 0;
}
/** /**
* i2o_block_ioctl - Issue device specific ioctl calls. * i2o_block_ioctl - Issue device specific ioctl calls.
* @cmd: ioctl command * @cmd: ioctl command
...@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, ...@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
{ {
struct gendisk *disk = inode->i_bdev->bd_disk; struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2o_block_device *dev = disk->private_data; struct i2o_block_device *dev = disk->private_data;
void __user *argp = (void __user *)arg;
/* Anyone capable of this syscall can do *real bad* things */ /* Anyone capable of this syscall can do *real bad* things */
...@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, ...@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
return -EPERM; return -EPERM;
switch (cmd) { switch (cmd) {
case HDIO_GETGEO:
{
struct hd_geometry g;
i2o_block_biosparam(get_capacity(disk),
&g.cylinders, &g.heads, &g.sectors);
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
}
case BLKI2OGRSTRAT: case BLKI2OGRSTRAT:
return put_user(dev->rcache, (int __user *)arg); return put_user(dev->rcache, (int __user *)arg);
case BLKI2OGWSTRAT: case BLKI2OGWSTRAT:
...@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = { ...@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = {
.open = i2o_block_open, .open = i2o_block_open,
.release = i2o_block_release, .release = i2o_block_release,
.ioctl = i2o_block_ioctl, .ioctl = i2o_block_ioctl,
.getgeo = i2o_block_getgeo,
.media_changed = i2o_block_media_changed .media_changed = i2o_block_media_changed
}; };
......
...@@ -113,31 +113,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp) ...@@ -113,31 +113,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp)
} }
static int static int
mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{ {
struct block_device *bdev = inode->i_bdev; geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
geo->heads = 4;
if (cmd == HDIO_GETGEO) { geo->sectors = 16;
struct hd_geometry geo; return 0;
memset(&geo, 0, sizeof(struct hd_geometry));
geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
geo.heads = 4;
geo.sectors = 16;
geo.start = get_start_sect(bdev);
return copy_to_user((void __user *)arg, &geo, sizeof(geo))
? -EFAULT : 0;
}
return -ENOTTY;
} }
static struct block_device_operations mmc_bdops = { static struct block_device_operations mmc_bdops = {
.open = mmc_blk_open, .open = mmc_blk_open,
.release = mmc_blk_release, .release = mmc_blk_release,
.ioctl = mmc_blk_ioctl, .getgeo = mmc_blk_getgeo,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f) ...@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f)
return ret; return ret;
} }
static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
if (dev->tr->getgeo)
return dev->tr->getgeo(dev, geo);
return -ENOTTY;
}
static int blktrans_ioctl(struct inode *inode, struct file *file, static int blktrans_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
...@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file, ...@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
return tr->flush(dev); return tr->flush(dev);
/* The core code did the work, we had nothing to do. */ /* The core code did the work, we had nothing to do. */
return 0; return 0;
case HDIO_GETGEO:
if (tr->getgeo) {
struct hd_geometry g;
int ret;
memset(&g, 0, sizeof(g));
ret = tr->getgeo(dev, &g);
if (ret)
return ret;
g.start = get_start_sect(inode->i_bdev);
if (copy_to_user((void __user *)arg, &g, sizeof(g)))
return -EFAULT;
return 0;
} /* else */
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = { ...@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = {
.open = blktrans_open, .open = blktrans_open,
.release = blktrans_release, .release = blktrans_release,
.ioctl = blktrans_ioctl, .ioctl = blktrans_ioctl,
.getgeo = blktrans_getgeo,
}; };
int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/hdreg.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -1723,12 +1724,34 @@ dasd_release(struct inode *inp, struct file *filp) ...@@ -1723,12 +1724,34 @@ dasd_release(struct inode *inp, struct file *filp)
return 0; return 0;
} }
/*
* Return disk geometry.
*/
static int
dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct dasd_device *device;
device = bdev->bd_disk->private_data;
if (!device)
return -ENODEV;
if (!device->discipline ||
!device->discipline->fill_geometry)
return -EINVAL;
device->discipline->fill_geometry(device, geo);
geo->start = get_start_sect(bdev) >> device->s2b_shift;
return 0;
}
struct block_device_operations struct block_device_operations
dasd_device_operations = { dasd_device_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = dasd_open, .open = dasd_open,
.release = dasd_release, .release = dasd_release,
.ioctl = dasd_ioctl, .ioctl = dasd_ioctl,
.getgeo = dasd_getgeo,
}; };
......
...@@ -485,33 +485,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) ...@@ -485,33 +485,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
return rc; return rc;
} }
/*
* Return disk geometry.
*/
static int
dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
{
struct hd_geometry geo = { 0, };
struct dasd_device *device;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
if (device == NULL || device->discipline == NULL ||
device->discipline->fill_geometry == NULL)
return -EINVAL;
geo = (struct hd_geometry) {};
device->discipline->fill_geometry(device, &geo);
geo.start = get_start_sect(bdev) >> device->s2b_shift;
if (copy_to_user((struct hd_geometry __user *) args, &geo,
sizeof (struct hd_geometry)))
return -EFAULT;
return 0;
}
/* /*
* List of static ioctls. * List of static ioctls.
*/ */
...@@ -528,7 +501,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = ...@@ -528,7 +501,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
{ BIODASDPRRST, dasd_ioctl_reset_profile }, { BIODASDPRRST, dasd_ioctl_reset_profile },
{ BLKROSET, dasd_ioctl_set_ro }, { BLKROSET, dasd_ioctl_set_ro },
{ DASDAPIVER, dasd_ioctl_api_version }, { DASDAPIVER, dasd_ioctl_api_version },
{ HDIO_GETGEO, dasd_ioctl_getgeo },
{ -1, NULL } { -1, NULL }
}; };
......
...@@ -328,31 +328,27 @@ static int xpram_make_request(request_queue_t *q, struct bio *bio) ...@@ -328,31 +328,27 @@ static int xpram_make_request(request_queue_t *q, struct bio *bio)
return 0; return 0;
} }
static int xpram_ioctl (struct inode *inode, struct file *filp, static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
unsigned int cmd, unsigned long arg)
{ {
struct hd_geometry __user *geo;
unsigned long size; unsigned long size;
if (cmd != HDIO_GETGEO)
return -EINVAL;
/* /*
* get geometry: we have to fake one... trim the size to a * get geometry: we have to fake one... trim the size to a
* multiple of 64 (32k): tell we have 16 sectors, 4 heads, * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
* whatever cylinders. Tell also that data starts at sector. 4. * whatever cylinders. Tell also that data starts at sector. 4.
*/ */
geo = (struct hd_geometry __user *) arg;
size = (xpram_pages * 8) & ~0x3f; size = (xpram_pages * 8) & ~0x3f;
put_user(size >> 6, &geo->cylinders); geo->cylinders = size >> 6;
put_user(4, &geo->heads); geo->heads = 4;
put_user(16, &geo->sectors); geo->sectors = 16;
put_user(4, &geo->start); geo->start = 4;
return 0; return 0;
} }
static struct block_device_operations xpram_devops = static struct block_device_operations xpram_devops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = xpram_ioctl, .getgeo = xpram_getgeo,
}; };
/* /*
......
...@@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp) ...@@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp)
return 0; return 0;
} }
static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc) static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{ {
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdp = sdkp->device; struct scsi_device *sdp = sdkp->device;
...@@ -545,15 +545,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user * ...@@ -545,15 +545,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *
else else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo); scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
if (put_user(diskinfo[0], &loc->heads)) geo->heads = diskinfo[0];
return -EFAULT; geo->sectors = diskinfo[1];
if (put_user(diskinfo[1], &loc->sectors)) geo->cylinders = diskinfo[2];
return -EFAULT;
if (put_user(diskinfo[2], &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)get_start_sect(bdev),
(unsigned long __user *)&loc->start))
return -EFAULT;
return 0; return 0;
} }
...@@ -593,12 +587,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp, ...@@ -593,12 +587,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
if (!scsi_block_when_processing_errors(sdp) || !error) if (!scsi_block_when_processing_errors(sdp) || !error)
return error; return error;
if (cmd == HDIO_GETGEO) {
if (!arg)
return -EINVAL;
return sd_hdio_getgeo(bdev, p);
}
/* /*
* Send SCSI addressing ioctls directly to mid level, send other * Send SCSI addressing ioctls directly to mid level, send other
* ioctls to block level and then onto mid level if they can't be * ioctls to block level and then onto mid level if they can't be
...@@ -800,6 +788,7 @@ static struct block_device_operations sd_fops = { ...@@ -800,6 +788,7 @@ static struct block_device_operations sd_fops = {
.open = sd_open, .open = sd_open,
.release = sd_release, .release = sd_release,
.ioctl = sd_ioctl, .ioctl = sd_ioctl,
.getgeo = sd_getgeo,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = sd_compat_ioctl, .compat_ioctl = sd_compat_ioctl,
#endif #endif
......
...@@ -224,6 +224,7 @@ extern int dir_notify_enable; ...@@ -224,6 +224,7 @@ extern int dir_notify_enable;
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
struct hd_geometry;
struct iovec; struct iovec;
struct nameidata; struct nameidata;
struct kiocb; struct kiocb;
...@@ -962,6 +963,7 @@ struct block_device_operations { ...@@ -962,6 +963,7 @@ struct block_device_operations {
int (*direct_access) (struct block_device *, sector_t, unsigned long *); int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *); int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *); int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
struct module *owner; struct module *owner;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册