socsvn commit: r257339 - soc2013/zcore/head/usr.sbin/bhyve
zcore at FreeBSD.org
zcore at FreeBSD.org
Sat Sep 14 16:04:22 UTC 2013
Author: zcore
Date: Sat Sep 14 16:04:22 2013
New Revision: 257339
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257339
Log:
support ATAPI_READ_BIG
Modified:
soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c
Modified: soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c
==============================================================================
--- soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c Sat Sep 14 16:03:46 2013 (r257338)
+++ soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c Sat Sep 14 16:04:22 2013 (r257339)
@@ -182,6 +182,11 @@
return (val[0] << 8) | val[1];
}
+static inline uint16_t be32_to_cpu(uint8_t *val)
+{
+ return (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
+}
+
static inline void lba_to_msf(uint8_t *buf, int lba)
{
lba += 150;
@@ -666,7 +671,7 @@
uint32_t tfd;
p->sense_key = ATA_SENSE_ILLEGAL_REQUEST;
p->asc = 0x24;
- tfd = (p->sense_key << 4) | ATA_S_READY | ATA_S_ERROR;
+ tfd = (p->sense_key << 12) | ATA_S_READY | ATA_S_ERROR;
cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
ahci_write_fis_d2h(p, slot, cfis, tfd);
return;
@@ -814,7 +819,7 @@
uint32_t tfd;
p->sense_key = ATA_SENSE_ILLEGAL_REQUEST;
p->asc = 0x24;
- tfd = (p->sense_key << 4) | ATA_S_READY | ATA_S_ERROR;
+ tfd = (p->sense_key << 12) | ATA_S_READY | ATA_S_ERROR;
cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
ahci_write_fis_d2h(p, slot, cfis, tfd);
break;
@@ -823,6 +828,59 @@
}
static void
+atapi_read(struct ahci_port *p, int slot, uint8_t *cfis)
+{
+ int i, err;
+ uint64_t lba;
+ uint32_t len;
+ struct ahci_ioreq *aior;
+ struct blockif_req *breq;
+ uint8_t *acmd = cfis + 0x40;
+ struct pci_ahci_softc *sc = p->pr_sc;
+ struct ahci_prdt_entry *prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
+ struct ahci_cmd_hdr *hdr = p->cmd_lst + slot * AHCI_CL_SIZE;
+
+ if (!p->iofree) {
+ p->unhandled_read |= (1 << slot);
+ return;
+ }
+ lba = be32_to_cpu(acmd + 2);
+ len = be16_to_cpu(acmd + 7);
+ if (len == 0) {
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
+ ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
+ }
+ lba *= 2048;
+ len *= 2048;
+
+ /*
+ * Pull request off free list
+ */
+ aior = STAILQ_FIRST(&p->iofhd);
+ assert(aior != NULL);
+ STAILQ_REMOVE_HEAD(&p->iofhd, io_list);
+ p->iofree--;
+ aior->cfis = cfis;
+ aior->slot = slot;
+ aior->len = len;
+ breq = &aior->io_req;
+ breq->br_offset = lba;
+ breq->br_iovcnt = hdr->prdtl;
+
+ /*
+ * Build up the iovec based on the prdt
+ */
+ for (i = 0; i < hdr->prdtl; i++) {
+ breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc),
+ prdt->dba, prdt->dbc + 1);
+ breq->br_iov[i].iov_len = prdt->dbc + 1;
+ prdt++;
+ }
+ err = blockif_read(p->bctx, breq);
+ assert(err == 0);
+}
+
+static void
handle_packet_cmd(struct ahci_port *p, int slot, uint8_t *cfis)
{
uint8_t *acmd = cfis + 0x40;
@@ -853,6 +911,9 @@
case ATAPI_READ_TOC:
atapi_read_toc(p, slot, cfis);
break;
+ case ATAPI_READ_BIG:
+ atapi_read(p, slot, cfis);
+ break;
default:
break;
}
@@ -1023,7 +1084,7 @@
* i/o thread, so the mutex needs to be acquired.
*/
static void
-pci_ahci_ioreq_cb(struct blockif_req *br, int err)
+ata_ioreq_cb(struct blockif_req *br, int err)
{
struct ahci_port *p;
struct pci_ahci_softc *sc;
@@ -1032,7 +1093,7 @@
struct ahci_cmd_hdr *hdr;
int ncq = 0;
- DPRINTF(("ahci_ioreq_cb %d\n", err));
+ DPRINTF(("%s %d\n", __func__, err));
aior = br->br_param;
p = aior->io_pr;
@@ -1095,6 +1156,68 @@
}
static void
+atapi_ioreq_cb(struct blockif_req *br, int err)
+{
+ uint8_t *cfis;
+ uint32_t tfd;
+ struct ahci_port *p;
+ struct pci_ahci_softc *sc;
+ struct ahci_ioreq *aior;
+ struct ahci_cmd_hdr *hdr;
+
+ DPRINTF(("%s %d\n", __func__, err));
+
+ aior = br->br_param;
+ p = aior->io_pr;
+ sc = p->pr_sc;
+ hdr = p->cmd_lst + aior->slot * AHCI_CL_SIZE;
+
+ pthread_mutex_lock(&sc->mtx);
+
+ if (!err) {
+ tfd = ATA_S_READY | ATA_S_DSC;
+ hdr->prdbc = aior->len;
+ } else {
+ p->sense_key = ATA_SENSE_ILLEGAL_REQUEST;
+ p->asc = 0x21;
+ tfd = (p->sense_key << 12) | ATA_S_READY | ATA_S_ERROR;
+ hdr->prdbc = 0;
+ }
+
+ cfis = aior->cfis;
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
+ ahci_write_fis_d2h(p, aior->slot, cfis, tfd);
+
+ /*
+ * Move the blockif request back to the free list
+ */
+ STAILQ_INSERT_TAIL(&p->iofhd, aior, io_list);
+ p->iofree++;
+
+ /*
+ * If the number of oustanding commands has dropped below the
+ * threshold, see if more can be queued up
+ */
+ if (p->ioqsz - p->iofree <= 2 && (p->cmd & AHCI_P_CMD_ST)) {
+ int i;
+ uint32_t unhandled = p->unhandled_read;
+ for (i = 0; (i < 32) && unhandled; i++) {
+ if (!p->iofree)
+ break;
+ if (unhandled & (1 << i)) {
+ handle_slot(p, i);
+ unhandled &= ~(1 << i);
+ }
+ }
+ p->unhandled_read &= unhandled;
+ }
+
+ pthread_mutex_unlock(&sc->mtx);
+ DPRINTF(("%s exit\n", __func__));
+
+}
+
+static void
pci_ahci_ioreq_init(struct ahci_port *pr)
{
struct ahci_ioreq *vr;
@@ -1110,7 +1233,10 @@
for (i = 0; i < pr->ioqsz; i++) {
vr = &pr->ioreq[i];
vr->io_pr = pr;
- vr->io_req.br_callback = pci_ahci_ioreq_cb;
+ if (!pr->atapi)
+ vr->io_req.br_callback = ata_ioreq_cb;
+ else
+ vr->io_req.br_callback = atapi_ioreq_cb;
vr->io_req.br_param = vr;
STAILQ_INSERT_TAIL(&pr->iofhd, vr, io_list);
pr->iofree++;
More information about the svn-soc-all
mailing list