diff options
author | Peter Grehan <grehan@FreeBSD.org> | 2014-07-15 00:25:54 +0000 |
---|---|---|
committer | Peter Grehan <grehan@FreeBSD.org> | 2014-07-15 00:25:54 +0000 |
commit | c4813fadf1a19da97ccd0e6f0250611e3ba4211f (patch) | |
tree | aeb64b137797417667e3bf4462976ce138bd0a8e | |
parent | d634b1f709fa192cb8ff6ebbb0d869aac4f90865 (diff) | |
download | src-c4813fadf1a19da97ccd0e6f0250611e3ba4211f.tar.gz src-c4813fadf1a19da97ccd0e6f0250611e3ba4211f.zip |
Add a call to synthesize a C/H/S value for block emulations
that require it (ahci). The algorithm used is from the VHD
specification.
Notes
Notes:
svn path=/head/; revision=268638
-rw-r--r-- | usr.sbin/bhyve/block_if.c | 49 | ||||
-rw-r--r-- | usr.sbin/bhyve/block_if.h | 2 |
2 files changed, 51 insertions, 0 deletions
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c index b29bc7856e86..1ec0344f3fca 100644 --- a/usr.sbin/bhyve/block_if.c +++ b/usr.sbin/bhyve/block_if.c @@ -390,6 +390,55 @@ blockif_close(struct blockif_ctxt *bc) } /* + * Return virtual C/H/S values for a given block. Use the algorithm + * outlined in the VHD specification to calculate values. + */ +void +blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h, uint8_t *s) +{ + off_t sectors; /* total sectors of the block dev */ + off_t hcyl; /* cylinders times heads */ + uint16_t secpt; /* sectors per track */ + uint8_t heads; + + assert(bc->bc_magic == BLOCKIF_SIG); + + sectors = bc->bc_size / bc->bc_sectsz; + + /* Clamp the size to the largest possible with CHS */ + if (sectors > 65535UL*16*255) + sectors = 65535UL*16*255; + + if (sectors >= 65536UL*16*63) { + secpt = 255; + heads = 16; + hcyl = sectors / secpt; + } else { + secpt = 17; + hcyl = sectors / secpt; + heads = (hcyl + 1023) / 1024; + + if (heads < 4) + heads = 4; + + if (hcyl >= (heads * 1024) || heads > 16) { + secpt = 31; + heads = 16; + hcyl = sectors / secpt; + } + if (hcyl >= (heads * 1024)) { + secpt = 63; + heads = 16; + hcyl = sectors / secpt; + } + } + + *c = hcyl / heads; + *h = heads; + *s = secpt; +} + +/* * Accessors */ off_t diff --git a/usr.sbin/bhyve/block_if.h b/usr.sbin/bhyve/block_if.h index e0c0bb1f8c8b..c2c21f657446 100644 --- a/usr.sbin/bhyve/block_if.h +++ b/usr.sbin/bhyve/block_if.h @@ -52,6 +52,8 @@ struct blockif_req { struct blockif_ctxt; struct blockif_ctxt *blockif_open(const char *optstr, const char *ident); off_t blockif_size(struct blockif_ctxt *bc); +void blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h, + uint8_t *s); int blockif_sectsz(struct blockif_ctxt *bc); int blockif_queuesz(struct blockif_ctxt *bc); int blockif_is_ro(struct blockif_ctxt *bc); |