From owner-svn-soc-all@FreeBSD.ORG Sat Sep 7 16:04:26 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 9AFA5A66 for ; Sat, 7 Sep 2013 16:04:26 +0000 (UTC) (envelope-from zcore@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 8709D27EC for ; Sat, 7 Sep 2013 16:04:26 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r87G4Q7U057577 for ; Sat, 7 Sep 2013 16:04:26 GMT (envelope-from zcore@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r87G4Qe2057568 for svn-soc-all@FreeBSD.org; Sat, 7 Sep 2013 16:04:26 GMT (envelope-from zcore@FreeBSD.org) Date: Sat, 7 Sep 2013 16:04:26 GMT Message-Id: <201309071604.r87G4Qe2057568@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to zcore@FreeBSD.org using -f From: zcore@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r257080 - soc2013/zcore/head/usr.sbin/bhyve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Sep 2013 16:04:26 -0000 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 #include -#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);