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