Date: Sat, 14 Sep 2013 16:02:39 GMT From: zcore@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r257336 - soc2013/zcore/head/usr.sbin/bhyve Message-ID: <201309141602.r8EG2dvj067398@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309141602.r8EG2dvj067398>
