From nobody Fri May 3 12:29:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 150724559022675.9198050474622; Thu, 5 Oct 2017 16:19:50 -0700 (PDT) Received: from localhost ([::1]:42326 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e0FQQ-0003nV-Bt for importer@patchew.org; Thu, 05 Oct 2017 19:19:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e0FPZ-0003Fs-Ki for qemu-devel@nongnu.org; Thu, 05 Oct 2017 19:18:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e0FPX-0000Bv-4d for qemu-devel@nongnu.org; Thu, 05 Oct 2017 19:18:37 -0400 Received: from mail-qt0-x244.google.com ([2607:f8b0:400d:c0d::244]:50395) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1e0FPW-0000BH-UX; Thu, 05 Oct 2017 19:18:35 -0400 Received: by mail-qt0-x244.google.com with SMTP id f15so28481507qtf.7; Thu, 05 Oct 2017 16:18:34 -0700 (PDT) Received: by 10.237.38.227 with HTTP; Thu, 5 Oct 2017 16:18:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=IN+6ecl9ZaJbfpBdz0q3YhG7XlB+QXIArZyVCLBfOCk=; b=A/Jg5Y6KVfVYhoYodWb2pRelxv++JPYrCfvE9ocziS5md1JTLCLAZTspAxn4cMW+wp oNo0R2r+YJ6l+iFkG0BRFbY2cgNYlvlsjZlyCuKBniKdvTqiOJZwsH8thPL4WiiS5NcG fCuvbwbMWrjKq+GneIUwONVKi4xbFBGPKGV5JyGsay2OnNHRIsGkEcMjj6uvdH9kjfZT gH16MasXChBF5El695PmXo/W406lEZpD11Y1LjPr6M/ReV0o5R3tZPgM5H0EwyXWrdy2 nS5dnzIseXxmLls2WKUyXNkYjK7kKPOHB2KQWvaZ6RFSEpIdTbfy0fG3GCPn/AjxjWHQ ZLbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=IN+6ecl9ZaJbfpBdz0q3YhG7XlB+QXIArZyVCLBfOCk=; b=MQYK1Fz1RWGp5Pd+4rh+fhAM2VJ1W1xkrbC1E4MDOX2+I4DyiqHm+bzr7JTBtqRPfv FPoBnWH7L9jsZwtTITRrReUxwviUwX216XzVtgGggyACCBx6Eam/s2BqmI5w4JuZK8Z5 0NzAz+K8u/28dKqU7Ckn+dHcMbz5psQ7wdYmxJeBoSp/45jvzpfxUhamMqlXPxiXqRtM VFeaZUWW+pdcbIsfI3Z6IQsYfIjvV11aNhIy2DpuTmRQGzmGthg+muQ/3Oawhh+cfNN6 bec1blkWLut+11PF8tBYQ0tAn1jvxWM5e2IdN3h0azDqgg65TIct1aHWMFiuzJevWFl7 LcPQ== X-Gm-Message-State: AMCzsaVyjKMdgIUrEAl98jo80TpJVMoCKB1d7eYH8MLjvHWtAF5YUWzt brLB02i9ctL0yK2eVDC0/62jv5+F9nzVG1Q5lKPpFg== X-Google-Smtp-Source: AOwi7QDp8iMGqiLFY6+6gm1kWQJh4QzYLh0xWDYtKyYs30+pMOzjd+tRtkegu18LX9m0vUT+WtlgUmCqvtJEZt3eTws= X-Received: by 10.200.7.200 with SMTP id m8mr425043qth.122.1507245513912; Thu, 05 Oct 2017 16:18:33 -0700 (PDT) MIME-Version: 1.0 From: Doug Gale Date: Thu, 5 Oct 2017 19:18:33 -0400 Message-ID: To: qemu-devel X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400d:c0d::244 Subject: [Qemu-devel] Patch to add helpful tracing output for driver authors in NVMe emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: keith.busch@intel.com, kwolf@redhat.com, qemu-block@nongnu.org, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" I added the tracing output in this patch to assist me in implementing an NVMe driver. It helped tremendously. From 1d19086cdef8d492929852d582cb41dcc5026f71 Mon Sep 17 00:00:00 2001 From: Doug Gale Date: Thu, 5 Oct 2017 19:02:03 -0400 Subject: [PATCH] Add tracing output to NVMe emulation to help driver author= s. It is off by default, enable it by uncommenting #define DEBUG_NVME or through CFLAGS Signed-off-by: Doug Gale --- hw/block/nvme.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 177 insertions(+), 14 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 9aa32692a3..74220c0171 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -36,6 +36,14 @@ #include "nvme.h" +//#define DEBUG_NVME + +#ifdef DEBUG_NVME +#define DPRINTF(fmt, ...) fprintf(stderr, "nvme: " fmt "\n", ## __VA_ARGS_= _) +#else +#define DPRINTF(fmt, ...) ((void)0) +#endif + static void nvme_process_sq(void *opaque); static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) @@ -86,10 +94,14 @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->parent_obj))) { + DPRINTF("raising MSI-X IRQ vector %u", cq->vector); msix_notify(&(n->parent_obj), cq->vector); } else { + DPRINTF("pulsing IRQ pin"); pci_irq_pulse(&n->parent_obj); } + } else { + DPRINTF("IRQ is masked"); } } @@ -101,9 +113,11 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, int num_prps =3D (len >> n->page_bits) + 1; if (!prp1) { + DPRINTF("Invalid PRP!"); return NVME_INVALID_FIELD | NVME_DNR; } else if (n->cmbsz && prp1 >=3D n->ctrl_mem.addr && prp1 < n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size)) { + DPRINTF("PRP in controller memory"); qsg->nsg =3D 0; qemu_iovec_init(iov, num_prps); qemu_iovec_add(iov, (void *)&n->cmbuf[prp1 - n->ctrl_mem.addr], trans_len); @@ -168,6 +182,7 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, unmap: qemu_sglist_destroy(qsg); + DPRINTF("invalid SGL!"); return NVME_INVALID_FIELD | NVME_DNR; } @@ -178,16 +193,22 @@ static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, QEMUIOVector iov; uint16_t status =3D NVME_SUCCESS; + DPRINTF("DMA read, prp1=3D0x%"PRIx64" prp2=3D0x%"PRIx64, + prp1, prp2); + if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) { + DPRINTF("DMA read invalid PRP field!"); return NVME_INVALID_FIELD | NVME_DNR; } if (qsg.nsg > 0) { if (dma_buf_read(ptr, len, &qsg)) { + DPRINTF("DMA read invalid SGL field!"); status =3D NVME_INVALID_FIELD | NVME_DNR; } qemu_sglist_destroy(&qsg); } else { if (qemu_iovec_to_buf(&iov, 0, ptr, len) !=3D len) { + DPRINTF("invalid field!"); status =3D NVME_INVALID_FIELD | NVME_DNR; } qemu_iovec_destroy(&iov); @@ -274,6 +295,7 @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, uint32_t aio_nlb =3D nlb << (data_shift - BDRV_SECTOR_BITS); if (slba + nlb > ns->id_ns.nsze) { + DPRINTF("Invalid LBA!"); return NVME_LBA_RANGE | NVME_DNR; } @@ -301,13 +323,19 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, int is_write =3D rw->opcode =3D=3D NVME_CMD_WRITE ? 1 : 0; enum BlockAcctType acct =3D is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_R= EAD; + DPRINTF("%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64, + is_write ? "write" : "read", + nlb, data_size, slba); + if ((slba + nlb) > ns->id_ns.nsze) { block_acct_invalid(blk_get_stats(n->conf.blk), acct); + DPRINTF("Invalid LBA!"); return NVME_LBA_RANGE | NVME_DNR; } if (nvme_map_prp(&req->qsg, &req->iov, prp1, prp2, data_size, n)) { block_acct_invalid(blk_get_stats(n->conf.blk), acct); + DPRINTF("Invalid PRP!"); return NVME_INVALID_FIELD | NVME_DNR; } @@ -337,6 +365,7 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) uint32_t nsid =3D le32_to_cpu(cmd->nsid); if (nsid =3D=3D 0 || nsid > n->num_namespaces) { + DPRINTF("Invalid namespace!"); return NVME_INVALID_NSID | NVME_DNR; } @@ -350,6 +379,7 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) case NVME_CMD_READ: return nvme_rw(n, ns, cmd, req); default: + DPRINTF("Invalid opcode!"); return NVME_INVALID_OPCODE | NVME_DNR; } } @@ -374,9 +404,12 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd) uint16_t qid =3D le16_to_cpu(c->qid); if (!qid || nvme_check_sqid(n, qid)) { + DPRINTF("invalid submission queue deletion! qid=3D%u", qid); return NVME_INVALID_QID | NVME_DNR; } + DPRINTF("submission queue deleted, qid=3D%u", qid); + sq =3D n->sq[qid]; while (!QTAILQ_EMPTY(&sq->out_req_list)) { req =3D QTAILQ_FIRST(&sq->out_req_list); @@ -439,21 +472,31 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *= cmd) uint16_t qflags =3D le16_to_cpu(c->sq_flags); uint64_t prp1 =3D le64_to_cpu(c->prp1); + DPRINTF("attempting to create submission queue" + ", addr=3D0x%"PRIx64", cqid=3D%u, size=3D%u", + prp1, cqid, qsize); + if (!cqid || nvme_check_cqid(n, cqid)) { + DPRINTF("...invalid completion queue id!"); return NVME_INVALID_CQID | NVME_DNR; } if (!sqid || !nvme_check_sqid(n, sqid)) { + DPRINTF("...invalid submission queue id!"); return NVME_INVALID_QID | NVME_DNR; } if (!qsize || qsize > NVME_CAP_MQES(n->bar.cap)) { + DPRINTF("...invalid queue size!"); return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR; } if (!prp1 || prp1 & (n->page_size - 1)) { + DPRINTF("...invalid address!"); return NVME_INVALID_FIELD | NVME_DNR; } if (!(NVME_SQ_FLAGS_PC(qflags))) { + DPRINTF("...invalid flags!"); return NVME_INVALID_FIELD | NVME_DNR; } + DPRINTF("...success"); sq =3D g_malloc0(sizeof(*sq)); nvme_init_sq(sq, n, prp1, sqid, cqid, qsize + 1); return NVME_SUCCESS; @@ -477,13 +520,16 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd) uint16_t qid =3D le16_to_cpu(c->qid); if (!qid || nvme_check_cqid(n, qid)) { + DPRINTF("Invalid completion queue ID!"); return NVME_INVALID_CQID | NVME_DNR; } cq =3D n->cq[qid]; if (!QTAILQ_EMPTY(&cq->sq_list)) { + DPRINTF("invalid completion queue deletion! id=3D%u", qid); return NVME_INVALID_QUEUE_DEL; } + DPRINTF("deleted completion queue, id=3D%u", qid); nvme_free_cq(cq, n); return NVME_SUCCESS; } @@ -516,21 +562,32 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *= cmd) uint16_t qflags =3D le16_to_cpu(c->cq_flags); uint64_t prp1 =3D le64_to_cpu(c->prp1); + DPRINTF("attempting to create completion queue" + ", addr=3D0x%"PRIx64", cqid=3D%u" + ", vector=3D%u, size=3D%u, intr_en=3D%u", + prp1, cqid, vector, qsize, NVME_CQ_FLAGS_IEN(qflags)); + if (!cqid || !nvme_check_cqid(n, cqid)) { + DPRINTF("...invalid completion queue id!"); return NVME_INVALID_CQID | NVME_DNR; } if (!qsize || qsize > NVME_CAP_MQES(n->bar.cap)) { + DPRINTF("...invalid queue size!"); return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR; } if (!prp1) { + DPRINTF("...invalid address!"); return NVME_INVALID_FIELD | NVME_DNR; } if (vector > n->num_queues) { + DPRINTF("...invalid interrupt vector!"); return NVME_INVALID_IRQ_VECTOR | NVME_DNR; } if (!(NVME_CQ_FLAGS_PC(qflags))) { + DPRINTF("...invalid flags!"); return NVME_INVALID_FIELD | NVME_DNR; } + DPRINTF("...success"); cq =3D g_malloc0(sizeof(*cq)); nvme_init_cq(cq, n, prp1, cqid, vector, qsize + 1, @@ -555,10 +612,16 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c) uint64_t prp2 =3D le64_to_cpu(c->prp2); if (nsid =3D=3D 0 || nsid > n->num_namespaces) { + DPRINTF("...invalid namespace ID!"); return NVME_INVALID_NSID | NVME_DNR; } ns =3D &n->namespaces[nsid - 1]; + + DPRINTF("identify namespace, nlbaf=3D%u", ns->id_ns.nlbaf); + DPRINTF("identify namespace, lbaf[0]=3D0x%"PRIx32, + *(uint32_t*)&ns->id_ns.lbaf[0]); + return nvme_dma_read_prp(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns), prp1, prp2); } @@ -595,12 +658,18 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *c= md) switch (le32_to_cpu(c->cns)) { case 0x00: + DPRINTF("...identify namespace %u", + le32_to_cpu(c->nsid)); return nvme_identify_ns(n, c); case 0x01: + DPRINTF("...identify controller"); return nvme_identify_ctrl(n, c); case 0x02: + DPRINTF("...identify namespace list, after %u", + le32_to_cpu(c->nsid)); return nvme_identify_nslist(n, c); default: + DPRINTF("...invalid CNS: %u!", le32_to_cpu(c->cns)); return NVME_INVALID_FIELD | NVME_DNR; } } @@ -618,6 +687,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) result =3D cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); break; default: + DPRINTF("Invalid field!"); return NVME_INVALID_FIELD | NVME_DNR; } @@ -635,10 +705,15 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) blk_set_enable_write_cache(n->conf.blk, dw11 & 1); break; case NVME_NUMBER_OF_QUEUES: + DPRINTF("Requested cq_count=3D%u, sq_count=3D%u," + " responding with cq_count=3D%u, sq_count=3D%u", + (dw11 & 0xFFFF) + 1, ((dw11 >> 16) & 0xFFFF) + 1, + n->num_queues - 1, n->num_queues - 1); req->cqe.result =3D cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); break; default: + DPRINTF("Invalid field!"); return NVME_INVALID_FIELD | NVME_DNR; } return NVME_SUCCESS; @@ -648,20 +723,28 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { switch (cmd->opcode) { case NVME_ADM_CMD_DELETE_SQ: + DPRINTF("received admin command: delete submission queue"); return nvme_del_sq(n, cmd); case NVME_ADM_CMD_CREATE_SQ: + DPRINTF("received admin command: create submission queue"); return nvme_create_sq(n, cmd); case NVME_ADM_CMD_DELETE_CQ: + DPRINTF("received admin command: delete completion queue"); return nvme_del_cq(n, cmd); case NVME_ADM_CMD_CREATE_CQ: + DPRINTF("received admin command: create completion queue"); return nvme_create_cq(n, cmd); case NVME_ADM_CMD_IDENTIFY: + DPRINTF("received admin command: identify"); return nvme_identify(n, cmd); case NVME_ADM_CMD_SET_FEATURES: + DPRINTF("received admin command: set features"); return nvme_set_feature(n, cmd, req); case NVME_ADM_CMD_GET_FEATURES: + DPRINTF("received admin command: get features"); return nvme_get_feature(n, cmd, req); default: + DPRINTF("received admin command: invalid opcode!"); return NVME_INVALID_OPCODE | NVME_DNR; } } @@ -721,15 +804,70 @@ static int nvme_start_ctrl(NvmeCtrl *n) uint32_t page_bits =3D NVME_CC_MPS(n->bar.cc) + 12; uint32_t page_size =3D 1 << page_bits; - if (n->cq[0] || n->sq[0] || !n->bar.asq || !n->bar.acq || - n->bar.asq & (page_size - 1) || n->bar.acq & (page_size - 1) || - NVME_CC_MPS(n->bar.cc) < NVME_CAP_MPSMIN(n->bar.cap) || - NVME_CC_MPS(n->bar.cc) > NVME_CAP_MPSMAX(n->bar.cap) || - NVME_CC_IOCQES(n->bar.cc) < NVME_CTRL_CQES_MIN(n->id_ctrl.cqes= ) || - NVME_CC_IOCQES(n->bar.cc) > NVME_CTRL_CQES_MAX(n->id_ctrl.cqes= ) || - NVME_CC_IOSQES(n->bar.cc) < NVME_CTRL_SQES_MIN(n->id_ctrl.sqes= ) || - NVME_CC_IOSQES(n->bar.cc) > NVME_CTRL_SQES_MAX(n->id_ctrl.sqes= ) || - !NVME_AQA_ASQS(n->bar.aqa) || !NVME_AQA_ACQS(n->bar.aqa)) { + if (n->cq[0]) { + DPRINTF("nvme_start_ctrl failed because cq[0]"); + return -1; + } + if (n->sq[0]) { + DPRINTF("nvme_start_ctrl failed because sq[0]"); + return -1; + } + if (!n->bar.asq) { + DPRINTF("nvme_start_ctrl failed because !bar.asq"); + return -1; + } + if (!n->bar.acq) { + DPRINTF("nvme_start_ctrl failed because !bar.acq"); + return -1; + } + if (n->bar.asq & (page_size - 1)) { + DPRINTF("nvme_start_ctrl failed because" + " bar.asq is not page aligned"); + return -1; + } + if (n->bar.acq & (page_size - 1)) { + DPRINTF("nvme_start_ctrl failed because" + " bar.acq is not page aligned"); + return -1; + } + if (NVME_CC_MPS(n->bar.cc) < NVME_CAP_MPSMIN(n->bar.cap)) { + DPRINTF("nvme_start_ctrl failed because" + " page size is too small"); + return -1; + } + if (NVME_CC_MPS(n->bar.cc) > NVME_CAP_MPSMAX(n->bar.cap)) { + DPRINTF("nvme_start_ctrl failed because" + " page size is too large"); + return -1; + } + if (NVME_CC_IOCQES(n->bar.cc) < NVME_CTRL_CQES_MIN(n->id_ctrl.cqes)) { + DPRINTF("nvme_start_ctrl failed because" + " completion queue entry size is too small"); + return -1; + } + if (NVME_CC_IOCQES(n->bar.cc) > NVME_CTRL_CQES_MAX(n->id_ctrl.cqes)) { + DPRINTF("nvme_start_ctrl failed because" + " completion queue entry size is too large"); + return -1; + } + if (NVME_CC_IOSQES(n->bar.cc) < NVME_CTRL_SQES_MIN(n->id_ctrl.sqes)) { + DPRINTF("nvme_start_ctrl failed because" + " submit queue entry size is too small"); + return -1; + } + if (NVME_CC_IOSQES(n->bar.cc) > NVME_CTRL_SQES_MAX(n->id_ctrl.sqes)) { + DPRINTF("nvme_start_ctrl failed because" + " submit queue entry size is too large"); + return -1; + } + if (!NVME_AQA_ASQS(n->bar.aqa)) { + DPRINTF("nvme_start_ctrl failed because" + " admin submit queue size is zero"); + return -1; + } + if (!NVME_AQA_ACQS(n->bar.aqa)) { + DPRINTF("nvme_start_ctrl failed because" + " admin completion queue size is zero"); return -1; } @@ -749,16 +887,25 @@ static int nvme_start_ctrl(NvmeCtrl *n) static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, unsigned size) { + DPRINTF("wrote pci config offset=3D0x%"PRIx64" data=3D0x%"PRIx64"", + offset, data); + switch (offset) { case 0xc: + DPRINTF("...interrupt mask set 0x%"PRIx64"", + data & 0xffffffff); n->bar.intms |=3D data & 0xffffffff; n->bar.intmc =3D n->bar.intms; break; case 0x10: + DPRINTF("...interrupt mask clr 0x%"PRIx64"", + data & 0xffffffff); n->bar.intms &=3D ~(data & 0xffffffff); n->bar.intmc =3D n->bar.intms; break; case 0x14: + DPRINTF("...controller config 0x%"PRIx64"", + data & 0xffffffff); /* Windows first sends data, then sends enable bit */ if (!NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc) && !NVME_CC_SHN(data) && !NVME_CC_SHN(n->bar.cc)) @@ -769,39 +916,55 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, if (NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc)) { n->bar.cc =3D data; if (nvme_start_ctrl(n)) { + DPRINTF("...nvme_start_ctrl failed!"); n->bar.csts =3D NVME_CSTS_FAILED; } else { + DPRINTF("...nvme_start_ctrl success, now ready!"); n->bar.csts =3D NVME_CSTS_READY; } } else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) { + DPRINTF("...enable bit cleared"); nvme_clear_ctrl(n); n->bar.csts &=3D ~NVME_CSTS_READY; } if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) { - nvme_clear_ctrl(n); - n->bar.cc =3D data; - n->bar.csts |=3D NVME_CSTS_SHST_COMPLETE; + DPRINTF("...shutdown complete"); + nvme_clear_ctrl(n); + n->bar.cc =3D data; + n->bar.csts |=3D NVME_CSTS_SHST_COMPLETE; } else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) { - n->bar.csts &=3D ~NVME_CSTS_SHST_COMPLETE; - n->bar.cc =3D data; + DPRINTF("...no shutdown, normal operation"); + n->bar.csts &=3D ~NVME_CSTS_SHST_COMPLETE; + n->bar.cc =3D data; } break; case 0x24: + DPRINTF("...admin queue attributes set to %u", + (uint32_t)(data & 0xffffffff)); n->bar.aqa =3D data & 0xffffffff; break; case 0x28: + DPRINTF("...admin submission queue address set to %"PRIx64, + data); n->bar.asq =3D data; break; case 0x2c: + DPRINTF("...admin submission queue high half of address set to %x", + (uint32_t)(data & 0xffffffff)); n->bar.asq |=3D data << 32; break; case 0x30: + DPRINTF("...admin completion queue address set to %"PRIx64, + data); n->bar.acq =3D data; break; case 0x34: + DPRINTF("...admin completion queue high half of address set to %x", + (uint32_t)(data & 0xffffffff)); n->bar.acq |=3D data << 32; break; default: + DPRINTF("...ignored!"); break; } } --=20 2.11.0