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