socsvn commit: r257080 - soc2013/zcore/head/usr.sbin/bhyve
zcore at FreeBSD.org
zcore at FreeBSD.org
Sat Sep 7 16:04:26 UTC 2013
Author: zcore
Date: Sat Sep 7 16:04:26 2013
New Revision: 257080
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257080
Log:
support ATA_READ_DMA
Modified:
soc2013/zcore/head/usr.sbin/bhyve/block_if.h
soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c
Modified: soc2013/zcore/head/usr.sbin/bhyve/block_if.h
==============================================================================
--- soc2013/zcore/head/usr.sbin/bhyve/block_if.h Sat Sep 7 15:16:30 2013 (r257079)
+++ soc2013/zcore/head/usr.sbin/bhyve/block_if.h Sat Sep 7 16:04:26 2013 (r257080)
@@ -32,7 +32,9 @@
#include <sys/uio.h>
#include <sys/unistd.h>
-#define BLOCKIF_IOV_MAX 32 /* XXX */
+#include "ahci.h"
+
+#define BLOCKIF_IOV_MAX AHCI_SG_ENTRIES /* XXX */
struct blockif_req {
struct iovec br_iov[BLOCKIF_IOV_MAX];
Modified: soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c
==============================================================================
--- soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c Sat Sep 7 15:16:30 2013 (r257079)
+++ soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c Sat Sep 7 16:04:26 2013 (r257080)
@@ -79,10 +79,11 @@
struct ahci_ioreq {
struct blockif_req io_req;
struct ahci_port *io_pr;
- uint32_t io_genid;
STAILQ_ENTRY(ahci_ioreq) io_list;
- int io_didx;
- uint8_t *io_status;
+ uint8_t *cfis;
+ int slot;
+ uint8_t status;
+ uint8_t error;
};
struct ahci_port {
@@ -93,6 +94,7 @@
int atapi;
int reset;
int mult_sectors;
+ uint32_t unhandled;
uint8_t xfermode;
uint32_t clb;
@@ -212,7 +214,34 @@
}
}
-static void ahci_write_fis_d2h(struct ahci_port *p)
+static void ahci_write_fis_d2h(struct ahci_port *p, struct ahci_ioreq *aior)
+{
+ uint8_t fis[20];
+ uint8_t *cfis = aior->cfis;
+
+ memset(fis, 0, sizeof(fis));
+ fis[0] = FIS_TYPE_REGD2H;
+ fis[1] = (1 << 6);
+ fis[2] = aior->status;
+ fis[3] = aior->error;
+ fis[4] = cfis[4];
+ fis[5] = cfis[5];
+ fis[6] = cfis[6];
+ fis[7] = cfis[7];
+ fis[8] = cfis[8];
+ fis[9] = cfis[9];
+ fis[10] = cfis[10];
+ fis[11] = cfis[11];
+ fis[12] = cfis[12];
+ fis[13] = cfis[13];
+ if (aior->error & ATA_S_ERROR)
+ p->is |= AHCI_P_IX_TFE;
+ p->tfd = (aior->error << 8) | aior->status;
+ p->ci &= ~(1 << aior->slot);
+ ahci_write_fis(p, FIS_TYPE_REGD2H, fis);
+}
+
+static void ahci_write_reset_fis_d2h(struct ahci_port *p)
{
uint8_t fis[20];
@@ -228,60 +257,6 @@
ahci_write_fis(p, FIS_TYPE_REGD2H, fis);
}
-/*
- * blockif callback routine - this runs in the context of the blockif
- * i/o thread, so the mutex needs to be acquired.
- */
-static void
-pci_ahci_ioreq_cb(struct blockif_req *br, int err)
-{
- struct ahci_port *pr;
- struct pci_ahci_softc *sc;
- struct ahci_ioreq *vio;
-
- vio = br->br_param;
- pr = vio->io_pr;
- sc = pr->pr_sc;
-
- DPRINTF(("ahci_ioreq_cb %d\n", err));
- pthread_mutex_lock(&sc->mtx);
-
- /* TODO */
-
- ahci_generate_intr(sc);
- /*
- * Move the blockif request back to the free list
- */
- STAILQ_INSERT_TAIL(&pr->iofhd, vio, io_list);
- pr->iofree++;
-
- pthread_mutex_unlock(&sc->mtx);
- DPRINTF(("%s exit\n", __func__));
-}
-
-static void
-pci_ahci_ioreq_init(struct ahci_port *pr)
-{
- struct ahci_ioreq *vr;
- int i;
-
- pr->ioqsz = blockif_queuesz(pr->bctx);
- pr->ioreq = calloc(pr->ioqsz, sizeof(struct ahci_ioreq));
- STAILQ_INIT(&pr->iofhd);
-
- /*
- * Add all i/o request entries to the free queue
- */
- for (i = 0; i < pr->ioqsz; i++) {
- vr = &pr->ioreq[i];
- vr->io_pr = pr;
- vr->io_req.br_callback = pci_ahci_ioreq_cb;
- vr->io_req.br_param = vr;
- STAILQ_INSERT_TAIL(&pr->iofhd, vr, io_list);
- pr->iofree++;
- }
-}
-
static void
ahci_port_reset(struct ahci_port *pr)
{
@@ -305,7 +280,7 @@
pr->tfd |= ATA_S_READY;
} else
pr->sig = PxSIG_ATAPI;
- ahci_write_fis_d2h(pr);
+ ahci_write_reset_fis_d2h(pr);
}
static void
@@ -336,8 +311,59 @@
}
static void
-handle_cmd(struct ahci_port *p, int slot, uint8_t *cfis,
- struct ahci_cmd_hdr *hdr)
+read_dma(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;
+ 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;
+
+ lba = ((cfis[7] & 0xf) << 24) | (cfis[6] << 16) |
+ (cfis[5] << 8) | cfis[4];
+ lba *= blockif_sectsz(p->bctx);
+
+ if (!cfis[12])
+ len = 256;
+ else
+ len = cfis[12];
+ len *= blockif_sectsz(p->bctx);
+
+ /*
+ * Pull request off free list
+ */
+ if (!p->iofree) {
+ p->unhandled |= (1 << slot);
+ return;
+ }
+ aior = STAILQ_FIRST(&p->iofhd);
+ assert(aior != NULL);
+ STAILQ_REMOVE_HEAD(&p->iofhd, io_list);
+ p->iofree--;
+ aior->cfis = cfis;
+ aior->slot = slot;
+ 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_cmd(struct ahci_port *p, int slot, uint8_t *cfis)
{
struct pci_ahci_softc *sc = p->pr_sc;
struct ahci_prdt_entry *prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
@@ -349,6 +375,7 @@
uint64_t sectors;
int i, len;
void *from;
+ struct ahci_cmd_hdr *hdr;
sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
memset(buf, 0, sizeof(buf));
@@ -392,6 +419,7 @@
buf[101] = (sectors >> 16);
buf[102] = (sectors >> 32);
buf[103] = (sectors >> 48);
+ hdr = p->cmd_lst + slot * AHCI_CL_SIZE;
if (hdr->prdtl == 0) {
WPRINTF(("wrong prdtl\n"));
return;
@@ -409,6 +437,7 @@
hdr->prdbc = sizeof(buf) - len;
p->tfd = ATA_S_DSC | ATA_S_READY;
p->is |= AHCI_P_IX_DP;
+ p->ci &= ~(1 << slot);
ahci_generate_intr(sc);
break;
}
@@ -441,6 +470,7 @@
break;
}
p->is |= AHCI_P_IX_DP;
+ p->ci &= ~(1 << slot);
ahci_generate_intr(sc);
break;
}
@@ -454,8 +484,12 @@
p->tfd = ATA_S_DSC | ATA_S_READY;
}
p->is |= AHCI_P_IX_DP;
+ p->ci &= ~(1 << slot);
ahci_generate_intr(sc);
break;
+ case ATA_READ_DMA:
+ read_dma(p, slot, cfis);
+ break;
default:
break;
}
@@ -499,7 +533,7 @@
if (cfis[1] & 0x80) {
dprintf("command cfis\n");
- handle_cmd(p, slot, cfis, hdr);
+ handle_cmd(p, slot, cfis);
} else {
dprintf("control cfis\n");
if (cfis[15] & (1 << 2))
@@ -508,6 +542,7 @@
p->reset = 0;
ahci_port_reset(p);
}
+ p->ci &= ~(1 << slot);
}
}
@@ -515,19 +550,86 @@
handle_port(struct ahci_port *p)
{
int i;
- struct pci_ahci_softc *sc;
- if (!(p->cmd & AHCI_P_CMD_ST) || !p->ci)
+ if (!(p->cmd & AHCI_P_CMD_ST))
return;
- sc = p->pr_sc;
-
for (i = 0; (i < 32) && p->ci; i++) {
- if (p->ci & (1 << i)) {
+ if (p->ci & (1 << i))
handle_slot(p, i);
- p->ci &= ~(1 << i);
+ }
+}
+
+/*
+ * blockif callback routine - this runs in the context of the blockif
+ * i/o thread, so the mutex needs to be acquired.
+ */
+static void
+pci_ahci_ioreq_cb(struct blockif_req *br, int err)
+{
+ struct ahci_port *p;
+ struct pci_ahci_softc *sc;
+ struct ahci_ioreq *aior;
+
+ aior = br->br_param;
+ p = aior->io_pr;
+ sc = p->pr_sc;
+
+ DPRINTF(("ahci_ioreq_cb %d\n", err));
+ pthread_mutex_lock(&sc->mtx);
+
+ if (err) {
+ aior->status = ATA_S_READY | ATA_S_ERROR;
+ aior->error = ATA_E_ABORT;
+ } else {
+ aior->status = ATA_S_READY | ATA_S_DSC;
+ aior->error = 0;
+ }
+ ahci_write_fis_d2h(p, aior);
+
+ /*
+ * 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;
+ for (i = 0; (i < 32) && p->unhandled; i++) {
+ if (p->unhandled & (1 << i))
+ handle_slot(p, i);
}
}
+
+ pthread_mutex_unlock(&sc->mtx);
+ DPRINTF(("%s exit\n", __func__));
+}
+
+static void
+pci_ahci_ioreq_init(struct ahci_port *pr)
+{
+ struct ahci_ioreq *vr;
+ int i;
+
+ pr->ioqsz = blockif_queuesz(pr->bctx);
+ pr->ioreq = calloc(pr->ioqsz, sizeof(struct ahci_ioreq));
+ STAILQ_INIT(&pr->iofhd);
+
+ /*
+ * Add all i/o request entries to the free queue
+ */
+ for (i = 0; i < pr->ioqsz; i++) {
+ vr = &pr->ioreq[i];
+ vr->io_pr = pr;
+ vr->io_req.br_callback = pci_ahci_ioreq_cb;
+ vr->io_req.br_param = vr;
+ STAILQ_INSERT_TAIL(&pr->iofhd, vr, io_list);
+ pr->iofree++;
+ }
}
static int
@@ -563,14 +665,17 @@
pi->pi_arg = sc;
sc->asc_pi = pi;
- for (i = 0; i < AHCI_MAX_PORTS; i++)
- sc->port[i].pr_sc = sc;
- /*
- * Allocate blockif request structures and add them
- * to the free list
- */
sc->port[0].bctx = bctxt;
- pci_ahci_ioreq_init(&sc->port[0]);
+
+ for (i = 0; i < AHCI_MAX_PORTS; i++) {
+ sc->port[i].pr_sc = sc;
+ /*
+ * Allocate blockif request structures and add them
+ * to the free list
+ */
+ if (sc->port[i].bctx)
+ pci_ahci_ioreq_init(&sc->port[i]);
+ }
pthread_mutex_init(&sc->mtx, NULL);
More information about the svn-soc-all
mailing list