socsvn commit: r256485 - soc2013/zcore/head/usr.sbin/bhyve

zcore at FreeBSD.org zcore at FreeBSD.org
Sun Aug 25 10:16:43 UTC 2013


Author: zcore
Date: Sun Aug 25 10:16:43 2013
New Revision: 256485
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=256485

Log:
  support ATA_ATA_IDENTIFY

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	Sun Aug 25 10:15:54 2013	(r256484)
+++ soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c	Sun Aug 25 10:16:43 2013	(r256485)
@@ -35,6 +35,7 @@
 #include <sys/uio.h>
 #include <sys/ioctl.h>
 #include <sys/disk.h>
+#include <sys/ata.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -168,6 +169,7 @@
 			sc->is |= (1 << i);
 	}
 
+	dprintf("%x %x\n", sc->port[0].is, sc->port[0].ie);
 	DPRINTF(("%s %x\n", __func__, sc->is));
 	if (sc->is && (sc->ghc & AHCI_GHC_IE))
 		pci_generate_msi(sc->asc_pi, 0);
@@ -192,13 +194,20 @@
 		len = 8;
 		irq = AHCI_P_IX_SDB;
 		break;
+	case FIS_TYPE_PIOSETUP:
+		offset = 0x20;
+		len = 20;
+		irq = 0;
+		break;
 	default:
 		WPRINTF(("unsupported fis type %d\n", ft));
 		break;
 	}
 	memcpy(p->rfis + offset, fis, len);
-	p->is |= irq;
-	ahci_generate_intr(p->pr_sc);
+	if (irq) {
+		p->is |= irq;
+		ahci_generate_intr(p->pr_sc);
+	}
 }
 
 static void ahci_write_fis_d2h(struct ahci_port *p)
@@ -274,8 +283,6 @@
 static void
 ahci_port_reset(struct ahci_port *pr)
 {
-	pr->is = 0;
-	pr->ie = 0;
 	pr->ssts = 0;
 	pr->sctl = 0;
 	pr->serr = 0;
@@ -305,8 +312,101 @@
 
 	sc->ghc = AHCI_GHC_AE;
 	sc->is = 0;
-	for (i = 0; i < sc->ports; i++)
+	for (i = 0; i < sc->ports; i++) {
+		sc->port[i].ie = 0;
+		sc->port[i].is = 0;
 		ahci_port_reset(&sc->port[i]);
+	}
+}
+
+static void
+ata_string(uint8_t *dest, const char *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (*src)
+			dest[i ^ 1] = *src++;
+		else
+			dest[i ^ 1] = ' ';
+	}
+}
+
+static void
+handle_cmd(struct ahci_port *p, int slot, uint8_t *cfis,
+		struct ahci_cmd_hdr *hdr)
+{
+	struct pci_ahci_softc *sc = p->pr_sc;
+	struct ahci_prdt_entry *prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
+
+	switch(cfis[2]) {
+	case ATA_ATA_IDENTIFY:
+	{
+		uint16_t buf[256];
+		uint64_t sectors;
+		int i, len;
+		void *from;
+
+		sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
+		memset(buf, 0, sizeof(buf));
+		buf[0] = 0x0040;
+		/* TODO emulate different serial? */
+		ata_string((uint8_t *)(buf+10), "123456", 20);
+		ata_string((uint8_t *)(buf+23), "001", 8);
+		ata_string((uint8_t *)(buf+27), "BHYVE SATA DISK", 40);
+		buf[47] = (0x8000 | 16);
+		buf[48] = 0x1;
+		buf[49] = (1 << 8 | 1 << 9 | 1 << 11);
+		buf[50] = (1 << 14);
+		buf[53] = (1 << 1 | 1 << 2);
+		buf[59] = (0x100 | 16);
+		buf[60] = sectors;
+		buf[61] = (sectors >> 16);
+		buf[63] = 0x7;
+		buf[64] = 0x3;
+		buf[65] = 100;
+		buf[66] = 100;
+		buf[67] = 100;
+		buf[68] = 100;
+		buf[75] = 31;
+		buf[76] = (1 << 8 | 1 << 2);
+		buf[80] = 0x1f0;
+		buf[81] = 0x28;
+		buf[82] = (1 | 1 << 5 | 1 << 14);
+		buf[83] = (1 << 10 | 1 << 12 | 1 << 13 | 1 << 14);
+		buf[84] = (1 << 14);
+		buf[85] = (1 | 1 << 14);
+		buf[86] = (1 << 10 | 1 << 12 | 1 << 13);
+		buf[87] = (1 << 14);
+		buf[88] = (0x7f | 1 << 14);
+		buf[93] = (1 | 1 <<14);
+		buf[100] = sectors;
+		buf[101] = (sectors >> 16);
+		buf[102] = (sectors >> 32);
+		buf[103] = (sectors >> 48);
+		if (hdr->prdtl == 0) {
+			WPRINTF(("wrong prdtl\n"));
+			return;
+		}
+		len = sizeof(buf);
+		from = buf;
+		for (i = 0; i < hdr->prdtl && len; i++) {
+			uint8_t *p = paddr_guest2host(ahci_ctx(sc),
+					prdt->dba, prdt->dbc + 1);
+			memcpy(p, from, prdt->dbc + 1);
+			len -= (prdt->dbc + 1);
+			from += (prdt->dbc + 1);
+			prdt++;
+		}
+		hdr->prdbc = sizeof(buf) - len;
+		p->tfd = ATA_S_DSC | ATA_S_READY;
+		p->is |= AHCI_P_IX_DP;
+		ahci_generate_intr(p->pr_sc);
+		break;
+	}
+	default:
+		break;
+	}
 }
 
 static void
@@ -322,8 +422,9 @@
 	hdr = p->cmd_lst + slot * AHCI_CL_SIZE;
 	cfl = (hdr->flags & 0x1f) * 4;
 	dprintf("cfis length:%d prdt entries: %d\n", cfl, hdr->prdtl);
-	cfis = paddr_guest2host(ahci_ctx(sc), hdr->ctba, cfl);
-	prdt = paddr_guest2host(ahci_ctx(sc), hdr->ctba + 0x80, hdr->prdtl * 16);
+	cfis = paddr_guest2host(ahci_ctx(sc), hdr->ctba,
+			0x80 + hdr->prdtl * sizeof(struct ahci_prdt_entry));
+	prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
 
 	/* dump cfis, will be removed latter */
 	for (i = 0; i < cfl; i++) {
@@ -346,6 +447,7 @@
 
 	if (cfis[1] & 0x80) {
 		dprintf("command cfis\n");
+		handle_cmd(p, slot, cfis, hdr);
 	} else {
 		dprintf("control cfis\n");
 		if (cfis[15] & (1 << 2))


More information about the svn-soc-all mailing list