Implement simple ops for umass_disk

The initial IOCTL implementation supports reading disk physical
geometry.
Two additional functions were added. They allow reading/writing raw
data to the disk (default partition).

Submitted by:  Wojciech Macek <wma@semihalf.com>
Obtained from: Semihalf
Sponsored by:  Juniper Networks Inc.
Differential Revision: https://reviews.freebsd.org/D4143
This commit is contained in:
Zbigniew Bodek 2015-11-27 18:17:53 +00:00
parent 09a37b41c5
commit bbcfaa4eb8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=291402
3 changed files with 72 additions and 1 deletions

View File

@ -232,6 +232,42 @@ disk_print(struct disk_devdesc *dev, char *prefix, int verbose)
ptable_iterate(od->table, &pa, ptable_print);
}
int
disk_read(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks)
{
struct open_disk *od;
int ret;
od = (struct open_disk *)dev->d_opendata;
ret = dev->d_dev->dv_strategy(dev, F_READ, dev->d_offset + offset,
blocks * od->sectorsize, buf, NULL);
return (ret);
}
int
disk_write(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks)
{
struct open_disk *od;
int ret;
od = (struct open_disk *)dev->d_opendata;
ret = dev->d_dev->dv_strategy(dev, F_WRITE, dev->d_offset + offset,
blocks * od->sectorsize, buf, NULL);
return (ret);
}
int
disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *buf)
{
if (dev->d_dev->dv_ioctl)
return ((*dev->d_dev->dv_ioctl)(dev->d_opendata, cmd, buf));
return (ENXIO);
}
int
disk_open(struct disk_devdesc *dev, off_t mediasize, u_int sectorsize,
u_int flags)

View File

@ -89,6 +89,11 @@ struct disk_devdesc
off_t d_offset;
};
enum disk_ioctl {
IOCTL_GET_BLOCKS,
IOCTL_GET_BLOCK_SIZE
};
/*
* Parse disk metadata and initialise dev->d_offset.
*/
@ -97,6 +102,11 @@ extern int disk_open(struct disk_devdesc *dev, off_t mediasize,
#define DISK_F_NOCACHE 0x0001 /* Do not use metadata caching */
extern int disk_close(struct disk_devdesc *dev);
extern void disk_cleanup(const struct devsw *d_dev);
extern int disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *buf);
extern int disk_read(struct disk_devdesc *dev, void *buf, off_t offset,
u_int blocks);
extern int disk_write(struct disk_devdesc *dev, void *buf, off_t offset,
u_int blocks);
/*
* Print information about slices on a disk.

View File

@ -47,6 +47,7 @@ static int umass_disk_init(void);
static int umass_disk_open(struct open_file *,...);
static int umass_disk_close(struct open_file *);
static void umass_disk_cleanup(void);
static int umass_disk_ioctl(struct open_file *, u_long, void *);
static int umass_disk_strategy(void *, int, daddr_t, size_t, char *, size_t *);
static void umass_disk_print(int);
@ -57,7 +58,7 @@ struct devsw umass_disk = {
.dv_strategy = umass_disk_strategy,
.dv_open = umass_disk_open,
.dv_close = umass_disk_close,
.dv_ioctl = noioctl,
.dv_ioctl = umass_disk_ioctl,
.dv_print = umass_disk_print,
.dv_cleanup = umass_disk_cleanup,
};
@ -135,6 +136,30 @@ umass_disk_open(struct open_file *f,...)
return (umass_disk_open_sub(dev));
}
static int
umass_disk_ioctl(struct open_file *f __unused, u_long cmd, void *buf)
{
uint32_t nblock;
uint32_t blocksize;
switch (cmd) {
case IOCTL_GET_BLOCK_SIZE:
case IOCTL_GET_BLOCKS:
if (usb_msc_read_capacity(umass_uaa.device, 0,
&nblock, &blocksize) != 0)
return (EINVAL);
if (cmd == IOCTL_GET_BLOCKS)
*(uint32_t*)buf = nblock;
else
*(uint32_t*)buf = blocksize;
return (0);
default:
return (ENXIO);
}
}
static int
umass_disk_close(struct open_file *f)
{