Changeset View
Changeset View
Standalone View
Standalone View
sys/boot/userboot/userboot/userboot_disk.c
Show All 36 Lines | |||||
#include <bootstrap.h> | #include <bootstrap.h> | ||||
#include "disk.h" | #include "disk.h" | ||||
#include "libuserboot.h" | #include "libuserboot.h" | ||||
struct userdisk_info { | struct userdisk_info { | ||||
uint64_t mediasize; | uint64_t mediasize; | ||||
uint16_t sectorsize; | uint16_t sectorsize; | ||||
int ud_open; /* reference counter */ | |||||
void *ud_bcache; /* buffer cache data */ | |||||
}; | }; | ||||
int userboot_disk_maxunit = 0; | int userboot_disk_maxunit = 0; | ||||
static int userdisk_maxunit = 0; | static int userdisk_maxunit = 0; | ||||
static struct userdisk_info *ud_info; | static struct userdisk_info *ud_info; | ||||
static int userdisk_init(void); | static int userdisk_init(void); | ||||
static void userdisk_cleanup(void); | static void userdisk_cleanup(void); | ||||
static int userdisk_strategy(void *devdata, int flag, daddr_t dblk, | static int userdisk_strategy(void *devdata, int flag, daddr_t dblk, | ||||
size_t size, char *buf, size_t *rsize); | size_t offset, size_t size, char *buf, size_t *rsize); | ||||
static int userdisk_realstrategy(void *devdata, int flag, daddr_t dblk, | |||||
size_t offset, size_t size, char *buf, size_t *rsize); | |||||
static int userdisk_open(struct open_file *f, ...); | static int userdisk_open(struct open_file *f, ...); | ||||
static int userdisk_close(struct open_file *f); | static int userdisk_close(struct open_file *f); | ||||
static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data); | static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data); | ||||
static void userdisk_print(int verbose); | static void userdisk_print(int verbose); | ||||
struct devsw userboot_disk = { | struct devsw userboot_disk = { | ||||
"disk", | "disk", | ||||
DEVT_DISK, | DEVT_DISK, | ||||
Show All 23 Lines | if (ud_info == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
for (i = 0; i < userdisk_maxunit; i++) { | for (i = 0; i < userdisk_maxunit; i++) { | ||||
if (CALLBACK(diskioctl, i, DIOCGSECTORSIZE, | if (CALLBACK(diskioctl, i, DIOCGSECTORSIZE, | ||||
§orsize) != 0 || CALLBACK(diskioctl, i, | §orsize) != 0 || CALLBACK(diskioctl, i, | ||||
DIOCGMEDIASIZE, &mediasize) != 0) | DIOCGMEDIASIZE, &mediasize) != 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
ud_info[i].mediasize = mediasize; | ud_info[i].mediasize = mediasize; | ||||
ud_info[i].sectorsize = sectorsize; | ud_info[i].sectorsize = sectorsize; | ||||
ud_info[i].ud_open = 0; | |||||
ud_info[i].ud_bcache = NULL; | |||||
} | } | ||||
} | } | ||||
bcache_add_dev(userdisk_maxunit); | |||||
return(0); | return(0); | ||||
} | } | ||||
static void | static void | ||||
userdisk_cleanup(void) | userdisk_cleanup(void) | ||||
{ | { | ||||
if (userdisk_maxunit > 0) | if (userdisk_maxunit > 0) | ||||
Show All 37 Lines | userdisk_open(struct open_file *f, ...) | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
va_start(ap, f); | va_start(ap, f); | ||||
dev = va_arg(ap, struct disk_devdesc *); | dev = va_arg(ap, struct disk_devdesc *); | ||||
va_end(ap); | va_end(ap); | ||||
if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit) | if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit) | ||||
return (EIO); | return (EIO); | ||||
ud_info[dev->d_unit].ud_open++; | |||||
if (ud_info[dev->d_unit].ud_bcache == NULL) | |||||
ud_info[dev->d_unit].ud_bcache = bcache_allocate(); | |||||
return (disk_open(dev, ud_info[dev->d_unit].mediasize, | return (disk_open(dev, ud_info[dev->d_unit].mediasize, | ||||
ud_info[dev->d_unit].sectorsize, 0)); | ud_info[dev->d_unit].sectorsize, 0)); | ||||
} | } | ||||
static int | static int | ||||
userdisk_close(struct open_file *f) | userdisk_close(struct open_file *f) | ||||
{ | { | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
dev = (struct disk_devdesc *)f->f_devdata; | dev = (struct disk_devdesc *)f->f_devdata; | ||||
ud_info[dev->d_unit].ud_open--; | |||||
if (ud_info[dev->d_unit].ud_open == 0) { | |||||
bcache_free(ud_info[dev->d_unit].ud_bcache); | |||||
ud_info[dev->d_unit].ud_bcache = NULL; | |||||
} | |||||
return (disk_close(dev)); | return (disk_close(dev)); | ||||
} | } | ||||
static int | static int | ||||
userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size, | userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, | ||||
char *buf, size_t *rsize) | size_t size, char *buf, size_t *rsize) | ||||
{ | { | ||||
struct bcache_devdata bcd; | |||||
struct disk_devdesc *dev; | |||||
dev = (struct disk_devdesc *)devdata; | |||||
bcd.dv_strategy = userdisk_realstrategy; | |||||
bcd.dv_devdata = devdata; | |||||
bcd.dv_cache = ud_info[dev->d_unit].ud_bcache; | |||||
return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, offset, | |||||
size, buf, rsize)); | |||||
} | |||||
static int | |||||
userdisk_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, | |||||
size_t size, char *buf, size_t *rsize) | |||||
{ | |||||
struct disk_devdesc *dev = devdata; | struct disk_devdesc *dev = devdata; | ||||
uint64_t off; | uint64_t off; | ||||
size_t resid; | size_t resid; | ||||
int rc; | int rc; | ||||
if (rw == F_WRITE) | if (rw == F_WRITE) | ||||
return (EROFS); | return (EROFS); | ||||
if (rw != F_READ) | if (rw != F_READ) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (rsize) | if (rsize) | ||||
*rsize = 0; | *rsize = 0; | ||||
off = (dblk + dev->d_offset) * ud_info[dev->d_unit].sectorsize; | off = dblk * ud_info[dev->d_unit].sectorsize; | ||||
rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid); | rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid); | ||||
if (rc) | if (rc) | ||||
return (rc); | return (rc); | ||||
if (rsize) | if (rsize) | ||||
*rsize = size - resid; | *rsize = size - resid; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
userdisk_ioctl(struct open_file *f, u_long cmd, void *data) | userdisk_ioctl(struct open_file *f, u_long cmd, void *data) | ||||
{ | { | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
dev = (struct disk_devdesc *)f->f_devdata; | dev = (struct disk_devdesc *)f->f_devdata; | ||||
return (CALLBACK(diskioctl, dev->d_unit, cmd, data)); | return (CALLBACK(diskioctl, dev->d_unit, cmd, data)); | ||||
} | } |