socsvn commit: r257336 - soc2013/zcore/head/usr.sbin/bhyve
zcore at FreeBSD.org
zcore at FreeBSD.org
Sat Sep 14 16:02:39 UTC 2013
Author: zcore
Date: Sat Sep 14 16:02:39 2013
New Revision: 257336
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257336
Log:
support ATAPI_READ_TOC
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:01:40 2013 (r257335)
+++ soc2013/zcore/head/usr.sbin/bhyve/pci_ahci.c Sat Sep 14 16:02:39 2013 (r257336)
@@ -171,6 +171,25 @@
((val & 0xff000000) >> 24);
}
+static inline uint32_t cpu_to_be16(uint16_t val)
+{
+ return ((val & 0xff) << 8) |
+ ((val & 0xff00) >> 8);
+}
+
+static inline uint16_t be16_to_cpu(uint8_t *val)
+{
+ return (val[0] << 8) | val[1];
+}
+
+static inline void lba_to_msf(uint8_t *buf, int lba)
+{
+ lba += 150;
+ buf[0] = (lba / 75) / 60;
+ buf[1] = (lba / 75) % 60;
+ buf[2] = lba % 75;
+}
+
/*
* generate HBA intr depending on whether or not ports within
* the controller have an interrupt pending.
@@ -605,6 +624,7 @@
len = sizeof(buf);
if (len > acmd[4])
len = acmd[4];
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
write_prdt(p, slot, cfis, buf, len);
ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
}
@@ -619,11 +639,187 @@
sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
ptr[0] = cpu_to_be32(sectors - 1);
ptr[1] = cpu_to_be32(2048);
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
write_prdt(p, slot, cfis, buf, sizeof(buf));
ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
}
static void
+atapi_read_toc(struct ahci_port *p, int slot, uint8_t *cfis)
+{
+ int len;
+ uint8_t format, *acmd = cfis + 0x40;
+
+ len = be16_to_cpu(acmd + 7);
+ format = acmd[9] >> 6;
+ switch (format) {
+ case 0:
+ {
+ int msf, size;
+ uint64_t sectors;
+ uint8_t start_track, buf[20], *bp;
+
+ msf = (acmd[1] >> 1) & 1;
+ start_track = acmd[6];
+ if (start_track > 1 && start_track != 0xaa) {
+ uint32_t tfd;
+ p->sense_key = ATA_SENSE_ILLEGAL_REQUEST;
+ p->asc = 0x24;
+ tfd = (p->sense_key << 4) | 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;
+ }
+ bp = buf + 2;
+ *bp++ = 1;
+ *bp++ = 1;
+ if (start_track <= 1) {
+ *bp++ = 0;
+ *bp++ = 0x14;
+ *bp++ = 1;
+ *bp++ = 0;
+ if (msf) {
+ *bp++ = 0;
+ lba_to_msf(bp, 0);
+ bp += 3;
+ } else {
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ }
+ }
+ *bp++ = 0;
+ *bp++ = 0x14;
+ *bp++ = 0xaa;
+ *bp++ = 0;
+ sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
+ if (msf) {
+ *bp++ = 0;
+ lba_to_msf(bp, sectors);
+ bp += 3;
+ } else {
+ *(uint32_t *)bp = cpu_to_be32(sectors);
+ bp += 4;
+ }
+ size = bp - buf;
+ *(uint16_t*)buf = cpu_to_be16(size - 2);
+ if (len > size)
+ len = size;
+ write_prdt(p, slot, cfis, buf, len);
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
+ ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
+ break;
+ }
+ case 1:
+ {
+ uint8_t buf[12];
+
+ memset(buf, 0, sizeof(buf));
+ buf[1] = 0xa;
+ buf[2] = 0x1;
+ buf[3] = 0x1;
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+ write_prdt(p, slot, cfis, buf, len);
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
+ ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
+ break;
+ }
+ case 2:
+ {
+ int msf, size;
+ uint64_t sectors;
+ uint8_t start_track, *bp, buf[50];
+
+ msf = (acmd[1] >> 1) & 1;
+ start_track = acmd[6];
+ bp = buf + 2;
+ *bp++ = 1;
+ *bp++ = 1;
+
+ *bp++ = 1;
+ *bp++ = 0x14;
+ *bp++ = 0;
+ *bp++ = 0xa0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 1;
+ *bp++ = 0;
+ *bp++ = 0;
+
+ *bp++ = 1;
+ *bp++ = 0x14;
+ *bp++ = 0;
+ *bp++ = 0xa1;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 1;
+ *bp++ = 0;
+ *bp++ = 0;
+
+ *bp++ = 1;
+ *bp++ = 0x14;
+ *bp++ = 0;
+ *bp++ = 0xa2;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
+ if (msf) {
+ *bp++ = 0;
+ lba_to_msf(bp, sectors);
+ bp += 3;
+ } else {
+ *(uint32_t *)bp = cpu_to_be32(sectors);
+ bp += 4;
+ }
+
+ *bp++ = 1;
+ *bp++ = 0x14;
+ *bp++ = 0;
+ *bp++ = 1;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ if (msf) {
+ *bp++ = 0;
+ lba_to_msf(bp, 0);
+ bp += 3;
+ } else {
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ *bp++ = 0;
+ }
+
+ size = bp - buf;
+ *(uint16_t*)buf = cpu_to_be16(size - 2);
+ if (len > size)
+ len = size;
+ write_prdt(p, slot, cfis, buf, len);
+ cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
+ ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
+ break;
+ }
+ default:
+ {
+ uint32_t tfd;
+ p->sense_key = ATA_SENSE_ILLEGAL_REQUEST;
+ p->asc = 0x24;
+ tfd = (p->sense_key << 4) | 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;
+ }
+ }
+}
+
+static void
handle_packet_cmd(struct ahci_port *p, int slot, uint8_t *cfis)
{
uint8_t *acmd = cfis + 0x40;
@@ -641,11 +837,9 @@
ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
break;
case ATAPI_INQUIRY:
- cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
atapi_inquiry(p, slot, cfis);
break;
case ATAPI_READ_CAPACITY:
- cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
atapi_read_capacity(p, slot, cfis);
break;
case ATAPI_PREVENT_ALLOW:
@@ -653,6 +847,9 @@
cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC);
break;
+ case ATAPI_READ_TOC:
+ atapi_read_toc(p, slot, cfis);
+ break;
default:
break;
}
More information about the svn-soc-all
mailing list