Statistics
| Branch: | Revision:

root / hw / scsi / vmw_pvscsi.c @ 2c9b15ca

History | View | Annotate | Download (33.1 kB)

1 881d588a Dmitry Fleytman
/*
2 881d588a Dmitry Fleytman
 * QEMU VMWARE PVSCSI paravirtual SCSI bus
3 881d588a Dmitry Fleytman
 *
4 881d588a Dmitry Fleytman
 * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
5 881d588a Dmitry Fleytman
 *
6 881d588a Dmitry Fleytman
 * Developed by Daynix Computing LTD (http://www.daynix.com)
7 881d588a Dmitry Fleytman
 *
8 881d588a Dmitry Fleytman
 * Based on implementation by Paolo Bonzini
9 881d588a Dmitry Fleytman
 * http://lists.gnu.org/archive/html/qemu-devel/2011-08/msg00729.html
10 881d588a Dmitry Fleytman
 *
11 881d588a Dmitry Fleytman
 * Authors:
12 881d588a Dmitry Fleytman
 * Paolo Bonzini <pbonzini@redhat.com>
13 881d588a Dmitry Fleytman
 * Dmitry Fleytman <dmitry@daynix.com>
14 881d588a Dmitry Fleytman
 * Yan Vugenfirer <yan@daynix.com>
15 881d588a Dmitry Fleytman
 *
16 881d588a Dmitry Fleytman
 * This work is licensed under the terms of the GNU GPL, version 2.
17 881d588a Dmitry Fleytman
 * See the COPYING file in the top-level directory.
18 881d588a Dmitry Fleytman
 *
19 881d588a Dmitry Fleytman
 * NOTE about MSI-X:
20 881d588a Dmitry Fleytman
 * MSI-X support has been removed for the moment because it leads Windows OS
21 881d588a Dmitry Fleytman
 * to crash on startup. The crash happens because Windows driver requires
22 881d588a Dmitry Fleytman
 * MSI-X shared memory to be part of the same BAR used for rings state
23 881d588a Dmitry Fleytman
 * registers, etc. This is not supported by QEMU infrastructure so separate
24 881d588a Dmitry Fleytman
 * BAR created from MSI-X purposes. Windows driver fails to deal with 2 BARs.
25 881d588a Dmitry Fleytman
 *
26 881d588a Dmitry Fleytman
 */
27 881d588a Dmitry Fleytman
28 881d588a Dmitry Fleytman
#include "hw/scsi/scsi.h"
29 881d588a Dmitry Fleytman
#include <block/scsi.h>
30 881d588a Dmitry Fleytman
#include "hw/pci/msi.h"
31 881d588a Dmitry Fleytman
#include "vmw_pvscsi.h"
32 881d588a Dmitry Fleytman
#include "trace.h"
33 881d588a Dmitry Fleytman
34 881d588a Dmitry Fleytman
35 881d588a Dmitry Fleytman
#define PVSCSI_MSI_OFFSET        (0x50)
36 881d588a Dmitry Fleytman
#define PVSCSI_USE_64BIT         (true)
37 881d588a Dmitry Fleytman
#define PVSCSI_PER_VECTOR_MASK   (false)
38 881d588a Dmitry Fleytman
39 881d588a Dmitry Fleytman
#define PVSCSI_MAX_DEVS                   (64)
40 881d588a Dmitry Fleytman
#define PVSCSI_MSIX_NUM_VECTORS           (1)
41 881d588a Dmitry Fleytman
42 881d588a Dmitry Fleytman
#define PVSCSI_MAX_CMD_DATA_WORDS \
43 881d588a Dmitry Fleytman
    (sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t))
44 881d588a Dmitry Fleytman
45 881d588a Dmitry Fleytman
#define RS_GET_FIELD(rs_pa, field) \
46 881d588a Dmitry Fleytman
    (ldl_le_phys(rs_pa + offsetof(struct PVSCSIRingsState, field)))
47 881d588a Dmitry Fleytman
#define RS_SET_FIELD(rs_pa, field, val) \
48 881d588a Dmitry Fleytman
    (stl_le_phys(rs_pa + offsetof(struct PVSCSIRingsState, field), val))
49 881d588a Dmitry Fleytman
50 881d588a Dmitry Fleytman
#define TYPE_PVSCSI "pvscsi"
51 881d588a Dmitry Fleytman
#define PVSCSI(obj) OBJECT_CHECK(PVSCSIState, (obj), TYPE_PVSCSI)
52 881d588a Dmitry Fleytman
53 881d588a Dmitry Fleytman
typedef struct PVSCSIRingInfo {
54 881d588a Dmitry Fleytman
    uint64_t            rs_pa;
55 881d588a Dmitry Fleytman
    uint32_t            txr_len_mask;
56 881d588a Dmitry Fleytman
    uint32_t            rxr_len_mask;
57 881d588a Dmitry Fleytman
    uint32_t            msg_len_mask;
58 881d588a Dmitry Fleytman
    uint64_t            req_ring_pages_pa[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
59 881d588a Dmitry Fleytman
    uint64_t            cmp_ring_pages_pa[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
60 881d588a Dmitry Fleytman
    uint64_t            msg_ring_pages_pa[PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES];
61 881d588a Dmitry Fleytman
    uint64_t            consumed_ptr;
62 881d588a Dmitry Fleytman
    uint64_t            filled_cmp_ptr;
63 881d588a Dmitry Fleytman
    uint64_t            filled_msg_ptr;
64 881d588a Dmitry Fleytman
} PVSCSIRingInfo;
65 881d588a Dmitry Fleytman
66 881d588a Dmitry Fleytman
typedef struct PVSCSISGState {
67 881d588a Dmitry Fleytman
    hwaddr elemAddr;
68 881d588a Dmitry Fleytman
    hwaddr dataAddr;
69 881d588a Dmitry Fleytman
    uint32_t resid;
70 881d588a Dmitry Fleytman
} PVSCSISGState;
71 881d588a Dmitry Fleytman
72 881d588a Dmitry Fleytman
typedef QTAILQ_HEAD(, PVSCSIRequest) PVSCSIRequestList;
73 881d588a Dmitry Fleytman
74 881d588a Dmitry Fleytman
typedef struct {
75 881d588a Dmitry Fleytman
    PCIDevice parent_obj;
76 881d588a Dmitry Fleytman
    MemoryRegion io_space;
77 881d588a Dmitry Fleytman
    SCSIBus bus;
78 881d588a Dmitry Fleytman
    QEMUBH *completion_worker;
79 881d588a Dmitry Fleytman
    PVSCSIRequestList pending_queue;
80 881d588a Dmitry Fleytman
    PVSCSIRequestList completion_queue;
81 881d588a Dmitry Fleytman
82 881d588a Dmitry Fleytman
    uint64_t reg_interrupt_status;        /* Interrupt status register value */
83 881d588a Dmitry Fleytman
    uint64_t reg_interrupt_enabled;       /* Interrupt mask register value   */
84 881d588a Dmitry Fleytman
    uint64_t reg_command_status;          /* Command status register value   */
85 881d588a Dmitry Fleytman
86 881d588a Dmitry Fleytman
    /* Command data adoption mechanism */
87 881d588a Dmitry Fleytman
    uint64_t curr_cmd;                   /* Last command arrived             */
88 881d588a Dmitry Fleytman
    uint32_t curr_cmd_data_cntr;         /* Amount of data for last command  */
89 881d588a Dmitry Fleytman
90 881d588a Dmitry Fleytman
    /* Collector for current command data */
91 881d588a Dmitry Fleytman
    uint32_t curr_cmd_data[PVSCSI_MAX_CMD_DATA_WORDS];
92 881d588a Dmitry Fleytman
93 881d588a Dmitry Fleytman
    uint8_t rings_info_valid;            /* Whether data rings initialized   */
94 881d588a Dmitry Fleytman
    uint8_t msg_ring_info_valid;         /* Whether message ring initialized */
95 881d588a Dmitry Fleytman
    uint8_t use_msg;                     /* Whether to use message ring      */
96 881d588a Dmitry Fleytman
97 881d588a Dmitry Fleytman
    uint8_t msi_used;    /* Whether MSI support was installed successfully   */
98 881d588a Dmitry Fleytman
99 881d588a Dmitry Fleytman
    PVSCSIRingInfo rings;                /* Data transfer rings manager      */
100 881d588a Dmitry Fleytman
    uint32_t resetting;                  /* Reset in progress                */
101 881d588a Dmitry Fleytman
} PVSCSIState;
102 881d588a Dmitry Fleytman
103 881d588a Dmitry Fleytman
typedef struct PVSCSIRequest {
104 881d588a Dmitry Fleytman
    SCSIRequest *sreq;
105 881d588a Dmitry Fleytman
    PVSCSIState *dev;
106 881d588a Dmitry Fleytman
    uint8_t sense_key;
107 881d588a Dmitry Fleytman
    uint8_t completed;
108 881d588a Dmitry Fleytman
    int lun;
109 881d588a Dmitry Fleytman
    QEMUSGList sgl;
110 881d588a Dmitry Fleytman
    PVSCSISGState sg;
111 881d588a Dmitry Fleytman
    struct PVSCSIRingReqDesc req;
112 881d588a Dmitry Fleytman
    struct PVSCSIRingCmpDesc cmp;
113 881d588a Dmitry Fleytman
    QTAILQ_ENTRY(PVSCSIRequest) next;
114 881d588a Dmitry Fleytman
} PVSCSIRequest;
115 881d588a Dmitry Fleytman
116 881d588a Dmitry Fleytman
/* Integer binary logarithm */
117 881d588a Dmitry Fleytman
static int
118 881d588a Dmitry Fleytman
pvscsi_log2(uint32_t input)
119 881d588a Dmitry Fleytman
{
120 881d588a Dmitry Fleytman
    int log = 0;
121 881d588a Dmitry Fleytman
    assert(input > 0);
122 881d588a Dmitry Fleytman
    while (input >> ++log) {
123 881d588a Dmitry Fleytman
    }
124 881d588a Dmitry Fleytman
    return log;
125 881d588a Dmitry Fleytman
}
126 881d588a Dmitry Fleytman
127 881d588a Dmitry Fleytman
static void
128 881d588a Dmitry Fleytman
pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
129 881d588a Dmitry Fleytman
{
130 881d588a Dmitry Fleytman
    int i;
131 881d588a Dmitry Fleytman
    uint32_t txr_len_log2, rxr_len_log2;
132 881d588a Dmitry Fleytman
    uint32_t req_ring_size, cmp_ring_size;
133 881d588a Dmitry Fleytman
    m->rs_pa = ri->ringsStatePPN << VMW_PAGE_SHIFT;
134 881d588a Dmitry Fleytman
135 881d588a Dmitry Fleytman
    req_ring_size = ri->reqRingNumPages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
136 881d588a Dmitry Fleytman
    cmp_ring_size = ri->cmpRingNumPages * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
137 881d588a Dmitry Fleytman
    txr_len_log2 = pvscsi_log2(req_ring_size - 1);
138 881d588a Dmitry Fleytman
    rxr_len_log2 = pvscsi_log2(cmp_ring_size - 1);
139 881d588a Dmitry Fleytman
140 881d588a Dmitry Fleytman
    m->txr_len_mask = MASK(txr_len_log2);
141 881d588a Dmitry Fleytman
    m->rxr_len_mask = MASK(rxr_len_log2);
142 881d588a Dmitry Fleytman
143 881d588a Dmitry Fleytman
    m->consumed_ptr = 0;
144 881d588a Dmitry Fleytman
    m->filled_cmp_ptr = 0;
145 881d588a Dmitry Fleytman
146 881d588a Dmitry Fleytman
    for (i = 0; i < ri->reqRingNumPages; i++) {
147 881d588a Dmitry Fleytman
        m->req_ring_pages_pa[i] = ri->reqRingPPNs[i] << VMW_PAGE_SHIFT;
148 881d588a Dmitry Fleytman
    }
149 881d588a Dmitry Fleytman
150 881d588a Dmitry Fleytman
    for (i = 0; i < ri->cmpRingNumPages; i++) {
151 881d588a Dmitry Fleytman
        m->cmp_ring_pages_pa[i] = ri->cmpRingPPNs[i] << VMW_PAGE_SHIFT;
152 881d588a Dmitry Fleytman
    }
153 881d588a Dmitry Fleytman
154 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, reqProdIdx, 0);
155 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, reqConsIdx, 0);
156 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, reqNumEntriesLog2, txr_len_log2);
157 881d588a Dmitry Fleytman
158 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, cmpProdIdx, 0);
159 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, cmpConsIdx, 0);
160 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, cmpNumEntriesLog2, rxr_len_log2);
161 881d588a Dmitry Fleytman
162 881d588a Dmitry Fleytman
    trace_pvscsi_ring_init_data(txr_len_log2, rxr_len_log2);
163 881d588a Dmitry Fleytman
164 881d588a Dmitry Fleytman
    /* Flush ring state page changes */
165 881d588a Dmitry Fleytman
    smp_wmb();
166 881d588a Dmitry Fleytman
}
167 881d588a Dmitry Fleytman
168 881d588a Dmitry Fleytman
static void
169 881d588a Dmitry Fleytman
pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
170 881d588a Dmitry Fleytman
{
171 881d588a Dmitry Fleytman
    int i;
172 881d588a Dmitry Fleytman
    uint32_t len_log2;
173 881d588a Dmitry Fleytman
    uint32_t ring_size;
174 881d588a Dmitry Fleytman
175 881d588a Dmitry Fleytman
    ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;
176 881d588a Dmitry Fleytman
    len_log2 = pvscsi_log2(ring_size - 1);
177 881d588a Dmitry Fleytman
178 881d588a Dmitry Fleytman
    m->msg_len_mask = MASK(len_log2);
179 881d588a Dmitry Fleytman
180 881d588a Dmitry Fleytman
    m->filled_msg_ptr = 0;
181 881d588a Dmitry Fleytman
182 881d588a Dmitry Fleytman
    for (i = 0; i < ri->numPages; i++) {
183 881d588a Dmitry Fleytman
        m->msg_ring_pages_pa[i] = ri->ringPPNs[i] << VMW_PAGE_SHIFT;
184 881d588a Dmitry Fleytman
    }
185 881d588a Dmitry Fleytman
186 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, msgProdIdx, 0);
187 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, msgConsIdx, 0);
188 881d588a Dmitry Fleytman
    RS_SET_FIELD(m->rs_pa, msgNumEntriesLog2, len_log2);
189 881d588a Dmitry Fleytman
190 881d588a Dmitry Fleytman
    trace_pvscsi_ring_init_msg(len_log2);
191 881d588a Dmitry Fleytman
192 881d588a Dmitry Fleytman
    /* Flush ring state page changes */
193 881d588a Dmitry Fleytman
    smp_wmb();
194 881d588a Dmitry Fleytman
}
195 881d588a Dmitry Fleytman
196 881d588a Dmitry Fleytman
static void
197 881d588a Dmitry Fleytman
pvscsi_ring_cleanup(PVSCSIRingInfo *mgr)
198 881d588a Dmitry Fleytman
{
199 881d588a Dmitry Fleytman
    mgr->rs_pa = 0;
200 881d588a Dmitry Fleytman
    mgr->txr_len_mask = 0;
201 881d588a Dmitry Fleytman
    mgr->rxr_len_mask = 0;
202 881d588a Dmitry Fleytman
    mgr->msg_len_mask = 0;
203 881d588a Dmitry Fleytman
    mgr->consumed_ptr = 0;
204 881d588a Dmitry Fleytman
    mgr->filled_cmp_ptr = 0;
205 881d588a Dmitry Fleytman
    mgr->filled_msg_ptr = 0;
206 881d588a Dmitry Fleytman
    memset(mgr->req_ring_pages_pa, 0, sizeof(mgr->req_ring_pages_pa));
207 881d588a Dmitry Fleytman
    memset(mgr->cmp_ring_pages_pa, 0, sizeof(mgr->cmp_ring_pages_pa));
208 881d588a Dmitry Fleytman
    memset(mgr->msg_ring_pages_pa, 0, sizeof(mgr->msg_ring_pages_pa));
209 881d588a Dmitry Fleytman
}
210 881d588a Dmitry Fleytman
211 881d588a Dmitry Fleytman
static hwaddr
212 881d588a Dmitry Fleytman
pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr)
213 881d588a Dmitry Fleytman
{
214 881d588a Dmitry Fleytman
    uint32_t ready_ptr = RS_GET_FIELD(mgr->rs_pa, reqProdIdx);
215 881d588a Dmitry Fleytman
216 881d588a Dmitry Fleytman
    if (ready_ptr != mgr->consumed_ptr) {
217 881d588a Dmitry Fleytman
        uint32_t next_ready_ptr =
218 881d588a Dmitry Fleytman
            mgr->consumed_ptr++ & mgr->txr_len_mask;
219 881d588a Dmitry Fleytman
        uint32_t next_ready_page =
220 881d588a Dmitry Fleytman
            next_ready_ptr / PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
221 881d588a Dmitry Fleytman
        uint32_t inpage_idx =
222 881d588a Dmitry Fleytman
            next_ready_ptr % PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
223 881d588a Dmitry Fleytman
224 881d588a Dmitry Fleytman
        return mgr->req_ring_pages_pa[next_ready_page] +
225 881d588a Dmitry Fleytman
               inpage_idx * sizeof(PVSCSIRingReqDesc);
226 881d588a Dmitry Fleytman
    } else {
227 881d588a Dmitry Fleytman
        return 0;
228 881d588a Dmitry Fleytman
    }
229 881d588a Dmitry Fleytman
}
230 881d588a Dmitry Fleytman
231 881d588a Dmitry Fleytman
static void
232 881d588a Dmitry Fleytman
pvscsi_ring_flush_req(PVSCSIRingInfo *mgr)
233 881d588a Dmitry Fleytman
{
234 881d588a Dmitry Fleytman
    RS_SET_FIELD(mgr->rs_pa, reqConsIdx, mgr->consumed_ptr);
235 881d588a Dmitry Fleytman
}
236 881d588a Dmitry Fleytman
237 881d588a Dmitry Fleytman
static hwaddr
238 881d588a Dmitry Fleytman
pvscsi_ring_pop_cmp_descr(PVSCSIRingInfo *mgr)
239 881d588a Dmitry Fleytman
{
240 881d588a Dmitry Fleytman
    /*
241 881d588a Dmitry Fleytman
     * According to Linux driver code it explicitly verifies that number
242 881d588a Dmitry Fleytman
     * of requests being processed by device is less then the size of
243 881d588a Dmitry Fleytman
     * completion queue, so device may omit completion queue overflow
244 881d588a Dmitry Fleytman
     * conditions check. We assume that this is true for other (Windows)
245 881d588a Dmitry Fleytman
     * drivers as well.
246 881d588a Dmitry Fleytman
     */
247 881d588a Dmitry Fleytman
248 881d588a Dmitry Fleytman
    uint32_t free_cmp_ptr =
249 881d588a Dmitry Fleytman
        mgr->filled_cmp_ptr++ & mgr->rxr_len_mask;
250 881d588a Dmitry Fleytman
    uint32_t free_cmp_page =
251 881d588a Dmitry Fleytman
        free_cmp_ptr / PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
252 881d588a Dmitry Fleytman
    uint32_t inpage_idx =
253 881d588a Dmitry Fleytman
        free_cmp_ptr % PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
254 881d588a Dmitry Fleytman
    return mgr->cmp_ring_pages_pa[free_cmp_page] +
255 881d588a Dmitry Fleytman
           inpage_idx * sizeof(PVSCSIRingCmpDesc);
256 881d588a Dmitry Fleytman
}
257 881d588a Dmitry Fleytman
258 881d588a Dmitry Fleytman
static hwaddr
259 881d588a Dmitry Fleytman
pvscsi_ring_pop_msg_descr(PVSCSIRingInfo *mgr)
260 881d588a Dmitry Fleytman
{
261 881d588a Dmitry Fleytman
    uint32_t free_msg_ptr =
262 881d588a Dmitry Fleytman
        mgr->filled_msg_ptr++ & mgr->msg_len_mask;
263 881d588a Dmitry Fleytman
    uint32_t free_msg_page =
264 881d588a Dmitry Fleytman
        free_msg_ptr / PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;
265 881d588a Dmitry Fleytman
    uint32_t inpage_idx =
266 881d588a Dmitry Fleytman
        free_msg_ptr % PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;
267 881d588a Dmitry Fleytman
    return mgr->msg_ring_pages_pa[free_msg_page] +
268 881d588a Dmitry Fleytman
           inpage_idx * sizeof(PVSCSIRingMsgDesc);
269 881d588a Dmitry Fleytman
}
270 881d588a Dmitry Fleytman
271 881d588a Dmitry Fleytman
static void
272 881d588a Dmitry Fleytman
pvscsi_ring_flush_cmp(PVSCSIRingInfo *mgr)
273 881d588a Dmitry Fleytman
{
274 881d588a Dmitry Fleytman
    /* Flush descriptor changes */
275 881d588a Dmitry Fleytman
    smp_wmb();
276 881d588a Dmitry Fleytman
277 881d588a Dmitry Fleytman
    trace_pvscsi_ring_flush_cmp(mgr->filled_cmp_ptr);
278 881d588a Dmitry Fleytman
279 881d588a Dmitry Fleytman
    RS_SET_FIELD(mgr->rs_pa, cmpProdIdx, mgr->filled_cmp_ptr);
280 881d588a Dmitry Fleytman
}
281 881d588a Dmitry Fleytman
282 881d588a Dmitry Fleytman
static bool
283 881d588a Dmitry Fleytman
pvscsi_ring_msg_has_room(PVSCSIRingInfo *mgr)
284 881d588a Dmitry Fleytman
{
285 881d588a Dmitry Fleytman
    uint32_t prodIdx = RS_GET_FIELD(mgr->rs_pa, msgProdIdx);
286 881d588a Dmitry Fleytman
    uint32_t consIdx = RS_GET_FIELD(mgr->rs_pa, msgConsIdx);
287 881d588a Dmitry Fleytman
288 881d588a Dmitry Fleytman
    return (prodIdx - consIdx) < (mgr->msg_len_mask + 1);
289 881d588a Dmitry Fleytman
}
290 881d588a Dmitry Fleytman
291 881d588a Dmitry Fleytman
static void
292 881d588a Dmitry Fleytman
pvscsi_ring_flush_msg(PVSCSIRingInfo *mgr)
293 881d588a Dmitry Fleytman
{
294 881d588a Dmitry Fleytman
    /* Flush descriptor changes */
295 881d588a Dmitry Fleytman
    smp_wmb();
296 881d588a Dmitry Fleytman
297 881d588a Dmitry Fleytman
    trace_pvscsi_ring_flush_msg(mgr->filled_msg_ptr);
298 881d588a Dmitry Fleytman
299 881d588a Dmitry Fleytman
    RS_SET_FIELD(mgr->rs_pa, msgProdIdx, mgr->filled_msg_ptr);
300 881d588a Dmitry Fleytman
}
301 881d588a Dmitry Fleytman
302 881d588a Dmitry Fleytman
static void
303 881d588a Dmitry Fleytman
pvscsi_reset_state(PVSCSIState *s)
304 881d588a Dmitry Fleytman
{
305 881d588a Dmitry Fleytman
    s->curr_cmd = PVSCSI_CMD_FIRST;
306 881d588a Dmitry Fleytman
    s->curr_cmd_data_cntr = 0;
307 881d588a Dmitry Fleytman
    s->reg_command_status = PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
308 881d588a Dmitry Fleytman
    s->reg_interrupt_status = 0;
309 881d588a Dmitry Fleytman
    pvscsi_ring_cleanup(&s->rings);
310 881d588a Dmitry Fleytman
    s->rings_info_valid = FALSE;
311 881d588a Dmitry Fleytman
    s->msg_ring_info_valid = FALSE;
312 881d588a Dmitry Fleytman
    QTAILQ_INIT(&s->pending_queue);
313 881d588a Dmitry Fleytman
    QTAILQ_INIT(&s->completion_queue);
314 881d588a Dmitry Fleytman
}
315 881d588a Dmitry Fleytman
316 881d588a Dmitry Fleytman
static void
317 881d588a Dmitry Fleytman
pvscsi_update_irq_status(PVSCSIState *s)
318 881d588a Dmitry Fleytman
{
319 881d588a Dmitry Fleytman
    PCIDevice *d = PCI_DEVICE(s);
320 881d588a Dmitry Fleytman
    bool should_raise = s->reg_interrupt_enabled & s->reg_interrupt_status;
321 881d588a Dmitry Fleytman
322 881d588a Dmitry Fleytman
    trace_pvscsi_update_irq_level(should_raise, s->reg_interrupt_enabled,
323 881d588a Dmitry Fleytman
                                  s->reg_interrupt_status);
324 881d588a Dmitry Fleytman
325 881d588a Dmitry Fleytman
    if (s->msi_used && msi_enabled(d)) {
326 881d588a Dmitry Fleytman
        if (should_raise) {
327 881d588a Dmitry Fleytman
            trace_pvscsi_update_irq_msi();
328 881d588a Dmitry Fleytman
            msi_notify(d, PVSCSI_VECTOR_COMPLETION);
329 881d588a Dmitry Fleytman
        }
330 881d588a Dmitry Fleytman
        return;
331 881d588a Dmitry Fleytman
    }
332 881d588a Dmitry Fleytman
333 881d588a Dmitry Fleytman
    qemu_set_irq(d->irq[0], !!should_raise);
334 881d588a Dmitry Fleytman
}
335 881d588a Dmitry Fleytman
336 881d588a Dmitry Fleytman
static void
337 881d588a Dmitry Fleytman
pvscsi_raise_completion_interrupt(PVSCSIState *s)
338 881d588a Dmitry Fleytman
{
339 881d588a Dmitry Fleytman
    s->reg_interrupt_status |= PVSCSI_INTR_CMPL_0;
340 881d588a Dmitry Fleytman
341 881d588a Dmitry Fleytman
    /* Memory barrier to flush interrupt status register changes*/
342 881d588a Dmitry Fleytman
    smp_wmb();
343 881d588a Dmitry Fleytman
344 881d588a Dmitry Fleytman
    pvscsi_update_irq_status(s);
345 881d588a Dmitry Fleytman
}
346 881d588a Dmitry Fleytman
347 881d588a Dmitry Fleytman
static void
348 881d588a Dmitry Fleytman
pvscsi_raise_message_interrupt(PVSCSIState *s)
349 881d588a Dmitry Fleytman
{
350 881d588a Dmitry Fleytman
    s->reg_interrupt_status |= PVSCSI_INTR_MSG_0;
351 881d588a Dmitry Fleytman
352 881d588a Dmitry Fleytman
    /* Memory barrier to flush interrupt status register changes*/
353 881d588a Dmitry Fleytman
    smp_wmb();
354 881d588a Dmitry Fleytman
355 881d588a Dmitry Fleytman
    pvscsi_update_irq_status(s);
356 881d588a Dmitry Fleytman
}
357 881d588a Dmitry Fleytman
358 881d588a Dmitry Fleytman
static void
359 881d588a Dmitry Fleytman
pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
360 881d588a Dmitry Fleytman
{
361 881d588a Dmitry Fleytman
    hwaddr cmp_descr_pa;
362 881d588a Dmitry Fleytman
363 881d588a Dmitry Fleytman
    cmp_descr_pa = pvscsi_ring_pop_cmp_descr(&s->rings);
364 881d588a Dmitry Fleytman
    trace_pvscsi_cmp_ring_put(cmp_descr_pa);
365 881d588a Dmitry Fleytman
    cpu_physical_memory_write(cmp_descr_pa, (void *)cmp_desc,
366 881d588a Dmitry Fleytman
                              sizeof(*cmp_desc));
367 881d588a Dmitry Fleytman
}
368 881d588a Dmitry Fleytman
369 881d588a Dmitry Fleytman
static void
370 881d588a Dmitry Fleytman
pvscsi_msg_ring_put(PVSCSIState *s, struct PVSCSIRingMsgDesc *msg_desc)
371 881d588a Dmitry Fleytman
{
372 881d588a Dmitry Fleytman
    hwaddr msg_descr_pa;
373 881d588a Dmitry Fleytman
374 881d588a Dmitry Fleytman
    msg_descr_pa = pvscsi_ring_pop_msg_descr(&s->rings);
375 881d588a Dmitry Fleytman
    trace_pvscsi_msg_ring_put(msg_descr_pa);
376 881d588a Dmitry Fleytman
    cpu_physical_memory_write(msg_descr_pa, (void *)msg_desc,
377 881d588a Dmitry Fleytman
                              sizeof(*msg_desc));
378 881d588a Dmitry Fleytman
}
379 881d588a Dmitry Fleytman
380 881d588a Dmitry Fleytman
static void
381 881d588a Dmitry Fleytman
pvscsi_process_completion_queue(void *opaque)
382 881d588a Dmitry Fleytman
{
383 881d588a Dmitry Fleytman
    PVSCSIState *s = opaque;
384 881d588a Dmitry Fleytman
    PVSCSIRequest *pvscsi_req;
385 881d588a Dmitry Fleytman
    bool has_completed = false;
386 881d588a Dmitry Fleytman
387 881d588a Dmitry Fleytman
    while (!QTAILQ_EMPTY(&s->completion_queue)) {
388 881d588a Dmitry Fleytman
        pvscsi_req = QTAILQ_FIRST(&s->completion_queue);
389 881d588a Dmitry Fleytman
        QTAILQ_REMOVE(&s->completion_queue, pvscsi_req, next);
390 881d588a Dmitry Fleytman
        pvscsi_cmp_ring_put(s, &pvscsi_req->cmp);
391 881d588a Dmitry Fleytman
        g_free(pvscsi_req);
392 dcb07809 Stefan Weil
        has_completed = true;
393 881d588a Dmitry Fleytman
    }
394 881d588a Dmitry Fleytman
395 881d588a Dmitry Fleytman
    if (has_completed) {
396 881d588a Dmitry Fleytman
        pvscsi_ring_flush_cmp(&s->rings);
397 881d588a Dmitry Fleytman
        pvscsi_raise_completion_interrupt(s);
398 881d588a Dmitry Fleytman
    }
399 881d588a Dmitry Fleytman
}
400 881d588a Dmitry Fleytman
401 881d588a Dmitry Fleytman
static void
402 881d588a Dmitry Fleytman
pvscsi_reset_adapter(PVSCSIState *s)
403 881d588a Dmitry Fleytman
{
404 881d588a Dmitry Fleytman
    s->resetting++;
405 881d588a Dmitry Fleytman
    qbus_reset_all_fn(&s->bus);
406 881d588a Dmitry Fleytman
    s->resetting--;
407 881d588a Dmitry Fleytman
    pvscsi_process_completion_queue(s);
408 881d588a Dmitry Fleytman
    assert(QTAILQ_EMPTY(&s->pending_queue));
409 881d588a Dmitry Fleytman
    pvscsi_reset_state(s);
410 881d588a Dmitry Fleytman
}
411 881d588a Dmitry Fleytman
412 881d588a Dmitry Fleytman
static void
413 881d588a Dmitry Fleytman
pvscsi_schedule_completion_processing(PVSCSIState *s)
414 881d588a Dmitry Fleytman
{
415 881d588a Dmitry Fleytman
    /* Try putting more complete requests on the ring. */
416 881d588a Dmitry Fleytman
    if (!QTAILQ_EMPTY(&s->completion_queue)) {
417 881d588a Dmitry Fleytman
        qemu_bh_schedule(s->completion_worker);
418 881d588a Dmitry Fleytman
    }
419 881d588a Dmitry Fleytman
}
420 881d588a Dmitry Fleytman
421 881d588a Dmitry Fleytman
static void
422 881d588a Dmitry Fleytman
pvscsi_complete_request(PVSCSIState *s, PVSCSIRequest *r)
423 881d588a Dmitry Fleytman
{
424 881d588a Dmitry Fleytman
    assert(!r->completed);
425 881d588a Dmitry Fleytman
426 881d588a Dmitry Fleytman
    trace_pvscsi_complete_request(r->cmp.context, r->cmp.dataLen,
427 881d588a Dmitry Fleytman
                                  r->sense_key);
428 881d588a Dmitry Fleytman
    if (r->sreq != NULL) {
429 881d588a Dmitry Fleytman
        scsi_req_unref(r->sreq);
430 881d588a Dmitry Fleytman
        r->sreq = NULL;
431 881d588a Dmitry Fleytman
    }
432 881d588a Dmitry Fleytman
    r->completed = 1;
433 881d588a Dmitry Fleytman
    QTAILQ_REMOVE(&s->pending_queue, r, next);
434 881d588a Dmitry Fleytman
    QTAILQ_INSERT_TAIL(&s->completion_queue, r, next);
435 881d588a Dmitry Fleytman
    pvscsi_schedule_completion_processing(s);
436 881d588a Dmitry Fleytman
}
437 881d588a Dmitry Fleytman
438 881d588a Dmitry Fleytman
static QEMUSGList *pvscsi_get_sg_list(SCSIRequest *r)
439 881d588a Dmitry Fleytman
{
440 881d588a Dmitry Fleytman
    PVSCSIRequest *req = r->hba_private;
441 881d588a Dmitry Fleytman
442 881d588a Dmitry Fleytman
    trace_pvscsi_get_sg_list(req->sgl.nsg, req->sgl.size);
443 881d588a Dmitry Fleytman
444 881d588a Dmitry Fleytman
    return &req->sgl;
445 881d588a Dmitry Fleytman
}
446 881d588a Dmitry Fleytman
447 881d588a Dmitry Fleytman
static void
448 881d588a Dmitry Fleytman
pvscsi_get_next_sg_elem(PVSCSISGState *sg)
449 881d588a Dmitry Fleytman
{
450 881d588a Dmitry Fleytman
    struct PVSCSISGElement elem;
451 881d588a Dmitry Fleytman
452 881d588a Dmitry Fleytman
    cpu_physical_memory_read(sg->elemAddr, (void *)&elem, sizeof(elem));
453 881d588a Dmitry Fleytman
    if ((elem.flags & ~PVSCSI_KNOWN_FLAGS) != 0) {
454 881d588a Dmitry Fleytman
        /*
455 881d588a Dmitry Fleytman
            * There is PVSCSI_SGE_FLAG_CHAIN_ELEMENT flag described in
456 881d588a Dmitry Fleytman
            * header file but its value is unknown. This flag requires
457 881d588a Dmitry Fleytman
            * additional processing, so we put warning here to catch it
458 881d588a Dmitry Fleytman
            * some day and make proper implementation
459 881d588a Dmitry Fleytman
            */
460 881d588a Dmitry Fleytman
        trace_pvscsi_get_next_sg_elem(elem.flags);
461 881d588a Dmitry Fleytman
    }
462 881d588a Dmitry Fleytman
463 881d588a Dmitry Fleytman
    sg->elemAddr += sizeof(elem);
464 881d588a Dmitry Fleytman
    sg->dataAddr = elem.addr;
465 881d588a Dmitry Fleytman
    sg->resid = elem.length;
466 881d588a Dmitry Fleytman
}
467 881d588a Dmitry Fleytman
468 881d588a Dmitry Fleytman
static void
469 881d588a Dmitry Fleytman
pvscsi_write_sense(PVSCSIRequest *r, uint8_t *sense, int len)
470 881d588a Dmitry Fleytman
{
471 881d588a Dmitry Fleytman
    r->cmp.senseLen = MIN(r->req.senseLen, len);
472 881d588a Dmitry Fleytman
    r->sense_key = sense[(sense[0] & 2) ? 1 : 2];
473 881d588a Dmitry Fleytman
    cpu_physical_memory_write(r->req.senseAddr, sense, r->cmp.senseLen);
474 881d588a Dmitry Fleytman
}
475 881d588a Dmitry Fleytman
476 881d588a Dmitry Fleytman
static void
477 881d588a Dmitry Fleytman
pvscsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
478 881d588a Dmitry Fleytman
{
479 881d588a Dmitry Fleytman
    PVSCSIRequest *pvscsi_req = req->hba_private;
480 881d588a Dmitry Fleytman
    PVSCSIState *s = pvscsi_req->dev;
481 881d588a Dmitry Fleytman
482 881d588a Dmitry Fleytman
    if (!pvscsi_req) {
483 881d588a Dmitry Fleytman
        trace_pvscsi_command_complete_not_found(req->tag);
484 881d588a Dmitry Fleytman
        return;
485 881d588a Dmitry Fleytman
    }
486 881d588a Dmitry Fleytman
487 881d588a Dmitry Fleytman
    if (resid) {
488 881d588a Dmitry Fleytman
        /* Short transfer.  */
489 881d588a Dmitry Fleytman
        trace_pvscsi_command_complete_data_run();
490 881d588a Dmitry Fleytman
        pvscsi_req->cmp.hostStatus = BTSTAT_DATARUN;
491 881d588a Dmitry Fleytman
    }
492 881d588a Dmitry Fleytman
493 881d588a Dmitry Fleytman
    pvscsi_req->cmp.scsiStatus = status;
494 881d588a Dmitry Fleytman
    if (pvscsi_req->cmp.scsiStatus == CHECK_CONDITION) {
495 881d588a Dmitry Fleytman
        uint8_t sense[SCSI_SENSE_BUF_SIZE];
496 881d588a Dmitry Fleytman
        int sense_len =
497 881d588a Dmitry Fleytman
            scsi_req_get_sense(pvscsi_req->sreq, sense, sizeof(sense));
498 881d588a Dmitry Fleytman
499 881d588a Dmitry Fleytman
        trace_pvscsi_command_complete_sense_len(sense_len);
500 881d588a Dmitry Fleytman
        pvscsi_write_sense(pvscsi_req, sense, sense_len);
501 881d588a Dmitry Fleytman
    }
502 881d588a Dmitry Fleytman
    qemu_sglist_destroy(&pvscsi_req->sgl);
503 881d588a Dmitry Fleytman
    pvscsi_complete_request(s, pvscsi_req);
504 881d588a Dmitry Fleytman
}
505 881d588a Dmitry Fleytman
506 881d588a Dmitry Fleytman
static void
507 881d588a Dmitry Fleytman
pvscsi_send_msg(PVSCSIState *s, SCSIDevice *dev, uint32_t msg_type)
508 881d588a Dmitry Fleytman
{
509 881d588a Dmitry Fleytman
    if (s->msg_ring_info_valid && pvscsi_ring_msg_has_room(&s->rings)) {
510 881d588a Dmitry Fleytman
        PVSCSIMsgDescDevStatusChanged msg = {0};
511 881d588a Dmitry Fleytman
512 881d588a Dmitry Fleytman
        msg.type = msg_type;
513 881d588a Dmitry Fleytman
        msg.bus = dev->channel;
514 881d588a Dmitry Fleytman
        msg.target = dev->id;
515 881d588a Dmitry Fleytman
        msg.lun[1] = dev->lun;
516 881d588a Dmitry Fleytman
517 881d588a Dmitry Fleytman
        pvscsi_msg_ring_put(s, (PVSCSIRingMsgDesc *)&msg);
518 881d588a Dmitry Fleytman
        pvscsi_ring_flush_msg(&s->rings);
519 881d588a Dmitry Fleytman
        pvscsi_raise_message_interrupt(s);
520 881d588a Dmitry Fleytman
    }
521 881d588a Dmitry Fleytman
}
522 881d588a Dmitry Fleytman
523 881d588a Dmitry Fleytman
static void
524 881d588a Dmitry Fleytman
pvscsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
525 881d588a Dmitry Fleytman
{
526 881d588a Dmitry Fleytman
    PVSCSIState *s = container_of(bus, PVSCSIState, bus);
527 881d588a Dmitry Fleytman
    pvscsi_send_msg(s, dev, PVSCSI_MSG_DEV_ADDED);
528 881d588a Dmitry Fleytman
}
529 881d588a Dmitry Fleytman
530 881d588a Dmitry Fleytman
static void
531 881d588a Dmitry Fleytman
pvscsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
532 881d588a Dmitry Fleytman
{
533 881d588a Dmitry Fleytman
    PVSCSIState *s = container_of(bus, PVSCSIState, bus);
534 881d588a Dmitry Fleytman
    pvscsi_send_msg(s, dev, PVSCSI_MSG_DEV_REMOVED);
535 881d588a Dmitry Fleytman
}
536 881d588a Dmitry Fleytman
537 881d588a Dmitry Fleytman
static void
538 881d588a Dmitry Fleytman
pvscsi_request_cancelled(SCSIRequest *req)
539 881d588a Dmitry Fleytman
{
540 881d588a Dmitry Fleytman
    PVSCSIRequest *pvscsi_req = req->hba_private;
541 881d588a Dmitry Fleytman
    PVSCSIState *s = pvscsi_req->dev;
542 881d588a Dmitry Fleytman
543 881d588a Dmitry Fleytman
    if (pvscsi_req->completed) {
544 881d588a Dmitry Fleytman
        return;
545 881d588a Dmitry Fleytman
    }
546 881d588a Dmitry Fleytman
547 881d588a Dmitry Fleytman
   if (pvscsi_req->dev->resetting) {
548 881d588a Dmitry Fleytman
       pvscsi_req->cmp.hostStatus = BTSTAT_BUSRESET;
549 881d588a Dmitry Fleytman
    } else {
550 881d588a Dmitry Fleytman
       pvscsi_req->cmp.hostStatus = BTSTAT_ABORTQUEUE;
551 881d588a Dmitry Fleytman
    }
552 881d588a Dmitry Fleytman
553 881d588a Dmitry Fleytman
    pvscsi_complete_request(s, pvscsi_req);
554 881d588a Dmitry Fleytman
}
555 881d588a Dmitry Fleytman
556 881d588a Dmitry Fleytman
static SCSIDevice*
557 881d588a Dmitry Fleytman
pvscsi_device_find(PVSCSIState *s, int channel, int target,
558 881d588a Dmitry Fleytman
                   uint8_t *requested_lun, uint8_t *target_lun)
559 881d588a Dmitry Fleytman
{
560 881d588a Dmitry Fleytman
    if (requested_lun[0] || requested_lun[2] || requested_lun[3] ||
561 881d588a Dmitry Fleytman
        requested_lun[4] || requested_lun[5] || requested_lun[6] ||
562 881d588a Dmitry Fleytman
        requested_lun[7] || (target > PVSCSI_MAX_DEVS)) {
563 881d588a Dmitry Fleytman
        return NULL;
564 881d588a Dmitry Fleytman
    } else {
565 881d588a Dmitry Fleytman
        *target_lun = requested_lun[1];
566 881d588a Dmitry Fleytman
        return scsi_device_find(&s->bus, channel, target, *target_lun);
567 881d588a Dmitry Fleytman
    }
568 881d588a Dmitry Fleytman
}
569 881d588a Dmitry Fleytman
570 881d588a Dmitry Fleytman
static PVSCSIRequest *
571 881d588a Dmitry Fleytman
pvscsi_queue_pending_descriptor(PVSCSIState *s, SCSIDevice **d,
572 881d588a Dmitry Fleytman
                                struct PVSCSIRingReqDesc *descr)
573 881d588a Dmitry Fleytman
{
574 881d588a Dmitry Fleytman
    PVSCSIRequest *pvscsi_req;
575 881d588a Dmitry Fleytman
    uint8_t lun;
576 881d588a Dmitry Fleytman
577 881d588a Dmitry Fleytman
    pvscsi_req = g_malloc0(sizeof(*pvscsi_req));
578 881d588a Dmitry Fleytman
    pvscsi_req->dev = s;
579 881d588a Dmitry Fleytman
    pvscsi_req->req = *descr;
580 881d588a Dmitry Fleytman
    pvscsi_req->cmp.context = pvscsi_req->req.context;
581 881d588a Dmitry Fleytman
    QTAILQ_INSERT_TAIL(&s->pending_queue, pvscsi_req, next);
582 881d588a Dmitry Fleytman
583 881d588a Dmitry Fleytman
    *d = pvscsi_device_find(s, descr->bus, descr->target, descr->lun, &lun);
584 881d588a Dmitry Fleytman
    if (*d) {
585 881d588a Dmitry Fleytman
        pvscsi_req->lun = lun;
586 881d588a Dmitry Fleytman
    }
587 881d588a Dmitry Fleytman
588 881d588a Dmitry Fleytman
    return pvscsi_req;
589 881d588a Dmitry Fleytman
}
590 881d588a Dmitry Fleytman
591 881d588a Dmitry Fleytman
static void
592 881d588a Dmitry Fleytman
pvscsi_convert_sglist(PVSCSIRequest *r)
593 881d588a Dmitry Fleytman
{
594 881d588a Dmitry Fleytman
    int chunk_size;
595 881d588a Dmitry Fleytman
    uint64_t data_length = r->req.dataLen;
596 881d588a Dmitry Fleytman
    PVSCSISGState sg = r->sg;
597 881d588a Dmitry Fleytman
    while (data_length) {
598 881d588a Dmitry Fleytman
        while (!sg.resid) {
599 881d588a Dmitry Fleytman
            pvscsi_get_next_sg_elem(&sg);
600 881d588a Dmitry Fleytman
            trace_pvscsi_convert_sglist(r->req.context, r->sg.dataAddr,
601 881d588a Dmitry Fleytman
                                        r->sg.resid);
602 881d588a Dmitry Fleytman
        }
603 881d588a Dmitry Fleytman
        assert(data_length > 0);
604 881d588a Dmitry Fleytman
        chunk_size = MIN((unsigned) data_length, sg.resid);
605 881d588a Dmitry Fleytman
        if (chunk_size) {
606 881d588a Dmitry Fleytman
            qemu_sglist_add(&r->sgl, sg.dataAddr, chunk_size);
607 881d588a Dmitry Fleytman
        }
608 881d588a Dmitry Fleytman
609 881d588a Dmitry Fleytman
        sg.dataAddr += chunk_size;
610 881d588a Dmitry Fleytman
        data_length -= chunk_size;
611 881d588a Dmitry Fleytman
        sg.resid -= chunk_size;
612 881d588a Dmitry Fleytman
    }
613 881d588a Dmitry Fleytman
}
614 881d588a Dmitry Fleytman
615 881d588a Dmitry Fleytman
static void
616 881d588a Dmitry Fleytman
pvscsi_build_sglist(PVSCSIState *s, PVSCSIRequest *r)
617 881d588a Dmitry Fleytman
{
618 881d588a Dmitry Fleytman
    PCIDevice *d = PCI_DEVICE(s);
619 881d588a Dmitry Fleytman
620 df32fd1c Paolo Bonzini
    pci_dma_sglist_init(&r->sgl, d, 1);
621 881d588a Dmitry Fleytman
    if (r->req.flags & PVSCSI_FLAG_CMD_WITH_SG_LIST) {
622 881d588a Dmitry Fleytman
        pvscsi_convert_sglist(r);
623 881d588a Dmitry Fleytman
    } else {
624 881d588a Dmitry Fleytman
        qemu_sglist_add(&r->sgl, r->req.dataAddr, r->req.dataLen);
625 881d588a Dmitry Fleytman
    }
626 881d588a Dmitry Fleytman
}
627 881d588a Dmitry Fleytman
628 881d588a Dmitry Fleytman
static void
629 881d588a Dmitry Fleytman
pvscsi_process_request_descriptor(PVSCSIState *s,
630 881d588a Dmitry Fleytman
                                  struct PVSCSIRingReqDesc *descr)
631 881d588a Dmitry Fleytman
{
632 881d588a Dmitry Fleytman
    SCSIDevice *d;
633 881d588a Dmitry Fleytman
    PVSCSIRequest *r = pvscsi_queue_pending_descriptor(s, &d, descr);
634 881d588a Dmitry Fleytman
    int64_t n;
635 881d588a Dmitry Fleytman
636 881d588a Dmitry Fleytman
    trace_pvscsi_process_req_descr(descr->cdb[0], descr->context);
637 881d588a Dmitry Fleytman
638 881d588a Dmitry Fleytman
    if (!d) {
639 881d588a Dmitry Fleytman
        r->cmp.hostStatus = BTSTAT_SELTIMEO;
640 881d588a Dmitry Fleytman
        trace_pvscsi_process_req_descr_unknown_device();
641 881d588a Dmitry Fleytman
        pvscsi_complete_request(s, r);
642 881d588a Dmitry Fleytman
        return;
643 881d588a Dmitry Fleytman
    }
644 881d588a Dmitry Fleytman
645 881d588a Dmitry Fleytman
    if (descr->flags & PVSCSI_FLAG_CMD_WITH_SG_LIST) {
646 881d588a Dmitry Fleytman
        r->sg.elemAddr = descr->dataAddr;
647 881d588a Dmitry Fleytman
    }
648 881d588a Dmitry Fleytman
649 881d588a Dmitry Fleytman
    r->sreq = scsi_req_new(d, descr->context, r->lun, descr->cdb, r);
650 881d588a Dmitry Fleytman
    if (r->sreq->cmd.mode == SCSI_XFER_FROM_DEV &&
651 881d588a Dmitry Fleytman
        (descr->flags & PVSCSI_FLAG_CMD_DIR_TODEVICE)) {
652 881d588a Dmitry Fleytman
        r->cmp.hostStatus = BTSTAT_BADMSG;
653 881d588a Dmitry Fleytman
        trace_pvscsi_process_req_descr_invalid_dir();
654 881d588a Dmitry Fleytman
        scsi_req_cancel(r->sreq);
655 881d588a Dmitry Fleytman
        return;
656 881d588a Dmitry Fleytman
    }
657 881d588a Dmitry Fleytman
    if (r->sreq->cmd.mode == SCSI_XFER_TO_DEV &&
658 881d588a Dmitry Fleytman
        (descr->flags & PVSCSI_FLAG_CMD_DIR_TOHOST)) {
659 881d588a Dmitry Fleytman
        r->cmp.hostStatus = BTSTAT_BADMSG;
660 881d588a Dmitry Fleytman
        trace_pvscsi_process_req_descr_invalid_dir();
661 881d588a Dmitry Fleytman
        scsi_req_cancel(r->sreq);
662 881d588a Dmitry Fleytman
        return;
663 881d588a Dmitry Fleytman
    }
664 881d588a Dmitry Fleytman
665 881d588a Dmitry Fleytman
    pvscsi_build_sglist(s, r);
666 881d588a Dmitry Fleytman
    n = scsi_req_enqueue(r->sreq);
667 881d588a Dmitry Fleytman
668 881d588a Dmitry Fleytman
    if (n) {
669 881d588a Dmitry Fleytman
        scsi_req_continue(r->sreq);
670 881d588a Dmitry Fleytman
    }
671 881d588a Dmitry Fleytman
}
672 881d588a Dmitry Fleytman
673 881d588a Dmitry Fleytman
static void
674 881d588a Dmitry Fleytman
pvscsi_process_io(PVSCSIState *s)
675 881d588a Dmitry Fleytman
{
676 881d588a Dmitry Fleytman
    PVSCSIRingReqDesc descr;
677 881d588a Dmitry Fleytman
    hwaddr next_descr_pa;
678 881d588a Dmitry Fleytman
679 881d588a Dmitry Fleytman
    assert(s->rings_info_valid);
680 881d588a Dmitry Fleytman
    while ((next_descr_pa = pvscsi_ring_pop_req_descr(&s->rings)) != 0) {
681 881d588a Dmitry Fleytman
682 881d588a Dmitry Fleytman
        /* Only read after production index verification */
683 881d588a Dmitry Fleytman
        smp_rmb();
684 881d588a Dmitry Fleytman
685 881d588a Dmitry Fleytman
        trace_pvscsi_process_io(next_descr_pa);
686 881d588a Dmitry Fleytman
        cpu_physical_memory_read(next_descr_pa, &descr, sizeof(descr));
687 881d588a Dmitry Fleytman
        pvscsi_process_request_descriptor(s, &descr);
688 881d588a Dmitry Fleytman
    }
689 881d588a Dmitry Fleytman
690 881d588a Dmitry Fleytman
    pvscsi_ring_flush_req(&s->rings);
691 881d588a Dmitry Fleytman
}
692 881d588a Dmitry Fleytman
693 881d588a Dmitry Fleytman
static void
694 881d588a Dmitry Fleytman
pvscsi_dbg_dump_tx_rings_config(PVSCSICmdDescSetupRings *rc)
695 881d588a Dmitry Fleytman
{
696 881d588a Dmitry Fleytman
    int i;
697 881d588a Dmitry Fleytman
    trace_pvscsi_tx_rings_ppn("Rings State", rc->ringsStatePPN);
698 881d588a Dmitry Fleytman
699 881d588a Dmitry Fleytman
    trace_pvscsi_tx_rings_num_pages("Request Ring", rc->reqRingNumPages);
700 881d588a Dmitry Fleytman
    for (i = 0; i < rc->reqRingNumPages; i++) {
701 881d588a Dmitry Fleytman
        trace_pvscsi_tx_rings_ppn("Request Ring", rc->reqRingPPNs[i]);
702 881d588a Dmitry Fleytman
    }
703 881d588a Dmitry Fleytman
704 881d588a Dmitry Fleytman
    trace_pvscsi_tx_rings_num_pages("Confirm Ring", rc->cmpRingNumPages);
705 881d588a Dmitry Fleytman
    for (i = 0; i < rc->cmpRingNumPages; i++) {
706 881d588a Dmitry Fleytman
        trace_pvscsi_tx_rings_ppn("Confirm Ring", rc->reqRingPPNs[i]);
707 881d588a Dmitry Fleytman
    }
708 881d588a Dmitry Fleytman
}
709 881d588a Dmitry Fleytman
710 881d588a Dmitry Fleytman
static uint64_t
711 881d588a Dmitry Fleytman
pvscsi_on_cmd_config(PVSCSIState *s)
712 881d588a Dmitry Fleytman
{
713 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_noimpl("PVSCSI_CMD_CONFIG");
714 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_FAILED;
715 881d588a Dmitry Fleytman
}
716 881d588a Dmitry Fleytman
717 881d588a Dmitry Fleytman
static uint64_t
718 881d588a Dmitry Fleytman
pvscsi_on_cmd_unplug(PVSCSIState *s)
719 881d588a Dmitry Fleytman
{
720 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_noimpl("PVSCSI_CMD_DEVICE_UNPLUG");
721 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_FAILED;
722 881d588a Dmitry Fleytman
}
723 881d588a Dmitry Fleytman
724 881d588a Dmitry Fleytman
static uint64_t
725 881d588a Dmitry Fleytman
pvscsi_on_issue_scsi(PVSCSIState *s)
726 881d588a Dmitry Fleytman
{
727 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_noimpl("PVSCSI_CMD_ISSUE_SCSI");
728 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_FAILED;
729 881d588a Dmitry Fleytman
}
730 881d588a Dmitry Fleytman
731 881d588a Dmitry Fleytman
static uint64_t
732 881d588a Dmitry Fleytman
pvscsi_on_cmd_setup_rings(PVSCSIState *s)
733 881d588a Dmitry Fleytman
{
734 881d588a Dmitry Fleytman
    PVSCSICmdDescSetupRings *rc =
735 881d588a Dmitry Fleytman
        (PVSCSICmdDescSetupRings *) s->curr_cmd_data;
736 881d588a Dmitry Fleytman
737 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
738 881d588a Dmitry Fleytman
739 881d588a Dmitry Fleytman
    pvscsi_dbg_dump_tx_rings_config(rc);
740 881d588a Dmitry Fleytman
    pvscsi_ring_init_data(&s->rings, rc);
741 881d588a Dmitry Fleytman
    s->rings_info_valid = TRUE;
742 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
743 881d588a Dmitry Fleytman
}
744 881d588a Dmitry Fleytman
745 881d588a Dmitry Fleytman
static uint64_t
746 881d588a Dmitry Fleytman
pvscsi_on_cmd_abort(PVSCSIState *s)
747 881d588a Dmitry Fleytman
{
748 881d588a Dmitry Fleytman
    PVSCSICmdDescAbortCmd *cmd = (PVSCSICmdDescAbortCmd *) s->curr_cmd_data;
749 881d588a Dmitry Fleytman
    PVSCSIRequest *r, *next;
750 881d588a Dmitry Fleytman
751 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_abort(cmd->context, cmd->target);
752 881d588a Dmitry Fleytman
753 881d588a Dmitry Fleytman
    QTAILQ_FOREACH_SAFE(r, &s->pending_queue, next, next) {
754 881d588a Dmitry Fleytman
        if (r->req.context == cmd->context) {
755 881d588a Dmitry Fleytman
            break;
756 881d588a Dmitry Fleytman
        }
757 881d588a Dmitry Fleytman
    }
758 881d588a Dmitry Fleytman
    if (r) {
759 881d588a Dmitry Fleytman
        assert(!r->completed);
760 881d588a Dmitry Fleytman
        r->cmp.hostStatus = BTSTAT_ABORTQUEUE;
761 881d588a Dmitry Fleytman
        scsi_req_cancel(r->sreq);
762 881d588a Dmitry Fleytman
    }
763 881d588a Dmitry Fleytman
764 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
765 881d588a Dmitry Fleytman
}
766 881d588a Dmitry Fleytman
767 881d588a Dmitry Fleytman
static uint64_t
768 881d588a Dmitry Fleytman
pvscsi_on_cmd_unknown(PVSCSIState *s)
769 881d588a Dmitry Fleytman
{
770 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_unknown_data(s->curr_cmd_data[0]);
771 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_FAILED;
772 881d588a Dmitry Fleytman
}
773 881d588a Dmitry Fleytman
774 881d588a Dmitry Fleytman
static uint64_t
775 881d588a Dmitry Fleytman
pvscsi_on_cmd_reset_device(PVSCSIState *s)
776 881d588a Dmitry Fleytman
{
777 881d588a Dmitry Fleytman
    uint8_t target_lun = 0;
778 881d588a Dmitry Fleytman
    struct PVSCSICmdDescResetDevice *cmd =
779 881d588a Dmitry Fleytman
        (struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
780 881d588a Dmitry Fleytman
    SCSIDevice *sdev;
781 881d588a Dmitry Fleytman
782 881d588a Dmitry Fleytman
    sdev = pvscsi_device_find(s, 0, cmd->target, cmd->lun, &target_lun);
783 881d588a Dmitry Fleytman
784 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_reset_dev(cmd->target, (int) target_lun, sdev);
785 881d588a Dmitry Fleytman
786 881d588a Dmitry Fleytman
    if (sdev != NULL) {
787 881d588a Dmitry Fleytman
        s->resetting++;
788 881d588a Dmitry Fleytman
        device_reset(&sdev->qdev);
789 881d588a Dmitry Fleytman
        s->resetting--;
790 881d588a Dmitry Fleytman
        return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
791 881d588a Dmitry Fleytman
    }
792 881d588a Dmitry Fleytman
793 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_FAILED;
794 881d588a Dmitry Fleytman
}
795 881d588a Dmitry Fleytman
796 881d588a Dmitry Fleytman
static uint64_t
797 881d588a Dmitry Fleytman
pvscsi_on_cmd_reset_bus(PVSCSIState *s)
798 881d588a Dmitry Fleytman
{
799 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_RESET_BUS");
800 881d588a Dmitry Fleytman
801 881d588a Dmitry Fleytman
    s->resetting++;
802 881d588a Dmitry Fleytman
    qbus_reset_all_fn(&s->bus);
803 881d588a Dmitry Fleytman
    s->resetting--;
804 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
805 881d588a Dmitry Fleytman
}
806 881d588a Dmitry Fleytman
807 881d588a Dmitry Fleytman
static uint64_t
808 881d588a Dmitry Fleytman
pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
809 881d588a Dmitry Fleytman
{
810 881d588a Dmitry Fleytman
    PVSCSICmdDescSetupMsgRing *rc =
811 881d588a Dmitry Fleytman
        (PVSCSICmdDescSetupMsgRing *) s->curr_cmd_data;
812 881d588a Dmitry Fleytman
813 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_MSG_RING");
814 881d588a Dmitry Fleytman
815 881d588a Dmitry Fleytman
    if (!s->use_msg) {
816 881d588a Dmitry Fleytman
        return PVSCSI_COMMAND_PROCESSING_FAILED;
817 881d588a Dmitry Fleytman
    }
818 881d588a Dmitry Fleytman
819 881d588a Dmitry Fleytman
    if (s->rings_info_valid) {
820 881d588a Dmitry Fleytman
        pvscsi_ring_init_msg(&s->rings, rc);
821 881d588a Dmitry Fleytman
        s->msg_ring_info_valid = TRUE;
822 881d588a Dmitry Fleytman
    }
823 881d588a Dmitry Fleytman
    return sizeof(PVSCSICmdDescSetupMsgRing) / sizeof(uint32_t);
824 881d588a Dmitry Fleytman
}
825 881d588a Dmitry Fleytman
826 881d588a Dmitry Fleytman
static uint64_t
827 881d588a Dmitry Fleytman
pvscsi_on_cmd_adapter_reset(PVSCSIState *s)
828 881d588a Dmitry Fleytman
{
829 881d588a Dmitry Fleytman
    trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_ADAPTER_RESET");
830 881d588a Dmitry Fleytman
831 881d588a Dmitry Fleytman
    pvscsi_reset_adapter(s);
832 881d588a Dmitry Fleytman
    return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
833 881d588a Dmitry Fleytman
}
834 881d588a Dmitry Fleytman
835 881d588a Dmitry Fleytman
static const struct {
836 881d588a Dmitry Fleytman
    int       data_size;
837 881d588a Dmitry Fleytman
    uint64_t  (*handler_fn)(PVSCSIState *s);
838 881d588a Dmitry Fleytman
} pvscsi_commands[] = {
839 881d588a Dmitry Fleytman
    [PVSCSI_CMD_FIRST] = {
840 881d588a Dmitry Fleytman
        .data_size = 0,
841 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_unknown,
842 881d588a Dmitry Fleytman
    },
843 881d588a Dmitry Fleytman
844 881d588a Dmitry Fleytman
    /* Not implemented, data size defined based on what arrives on windows */
845 881d588a Dmitry Fleytman
    [PVSCSI_CMD_CONFIG] = {
846 881d588a Dmitry Fleytman
        .data_size = 6 * sizeof(uint32_t),
847 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_config,
848 881d588a Dmitry Fleytman
    },
849 881d588a Dmitry Fleytman
850 881d588a Dmitry Fleytman
    /* Command not implemented, data size is unknown */
851 881d588a Dmitry Fleytman
    [PVSCSI_CMD_ISSUE_SCSI] = {
852 881d588a Dmitry Fleytman
        .data_size = 0,
853 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_issue_scsi,
854 881d588a Dmitry Fleytman
    },
855 881d588a Dmitry Fleytman
856 881d588a Dmitry Fleytman
    /* Command not implemented, data size is unknown */
857 881d588a Dmitry Fleytman
    [PVSCSI_CMD_DEVICE_UNPLUG] = {
858 881d588a Dmitry Fleytman
        .data_size = 0,
859 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_unplug,
860 881d588a Dmitry Fleytman
    },
861 881d588a Dmitry Fleytman
862 881d588a Dmitry Fleytman
    [PVSCSI_CMD_SETUP_RINGS] = {
863 881d588a Dmitry Fleytman
        .data_size = sizeof(PVSCSICmdDescSetupRings),
864 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_setup_rings,
865 881d588a Dmitry Fleytman
    },
866 881d588a Dmitry Fleytman
867 881d588a Dmitry Fleytman
    [PVSCSI_CMD_RESET_DEVICE] = {
868 881d588a Dmitry Fleytman
        .data_size = sizeof(struct PVSCSICmdDescResetDevice),
869 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_reset_device,
870 881d588a Dmitry Fleytman
    },
871 881d588a Dmitry Fleytman
872 881d588a Dmitry Fleytman
    [PVSCSI_CMD_RESET_BUS] = {
873 881d588a Dmitry Fleytman
        .data_size = 0,
874 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_reset_bus,
875 881d588a Dmitry Fleytman
    },
876 881d588a Dmitry Fleytman
877 881d588a Dmitry Fleytman
    [PVSCSI_CMD_SETUP_MSG_RING] = {
878 881d588a Dmitry Fleytman
        .data_size = sizeof(PVSCSICmdDescSetupMsgRing),
879 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_setup_msg_ring,
880 881d588a Dmitry Fleytman
    },
881 881d588a Dmitry Fleytman
882 881d588a Dmitry Fleytman
    [PVSCSI_CMD_ADAPTER_RESET] = {
883 881d588a Dmitry Fleytman
        .data_size = 0,
884 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_adapter_reset,
885 881d588a Dmitry Fleytman
    },
886 881d588a Dmitry Fleytman
887 881d588a Dmitry Fleytman
    [PVSCSI_CMD_ABORT_CMD] = {
888 881d588a Dmitry Fleytman
        .data_size = sizeof(struct PVSCSICmdDescAbortCmd),
889 881d588a Dmitry Fleytman
        .handler_fn = pvscsi_on_cmd_abort,
890 881d588a Dmitry Fleytman
    },
891 881d588a Dmitry Fleytman
};
892 881d588a Dmitry Fleytman
893 881d588a Dmitry Fleytman
static void
894 881d588a Dmitry Fleytman
pvscsi_do_command_processing(PVSCSIState *s)
895 881d588a Dmitry Fleytman
{
896 881d588a Dmitry Fleytman
    size_t bytes_arrived = s->curr_cmd_data_cntr * sizeof(uint32_t);
897 881d588a Dmitry Fleytman
898 881d588a Dmitry Fleytman
    assert(s->curr_cmd < PVSCSI_CMD_LAST);
899 881d588a Dmitry Fleytman
    if (bytes_arrived >= pvscsi_commands[s->curr_cmd].data_size) {
900 881d588a Dmitry Fleytman
        s->reg_command_status = pvscsi_commands[s->curr_cmd].handler_fn(s);
901 881d588a Dmitry Fleytman
        s->curr_cmd = PVSCSI_CMD_FIRST;
902 881d588a Dmitry Fleytman
        s->curr_cmd_data_cntr   = 0;
903 881d588a Dmitry Fleytman
    }
904 881d588a Dmitry Fleytman
}
905 881d588a Dmitry Fleytman
906 881d588a Dmitry Fleytman
static void
907 881d588a Dmitry Fleytman
pvscsi_on_command_data(PVSCSIState *s, uint32_t value)
908 881d588a Dmitry Fleytman
{
909 881d588a Dmitry Fleytman
    size_t bytes_arrived = s->curr_cmd_data_cntr * sizeof(uint32_t);
910 881d588a Dmitry Fleytman
911 881d588a Dmitry Fleytman
    assert(bytes_arrived < sizeof(s->curr_cmd_data));
912 881d588a Dmitry Fleytman
    s->curr_cmd_data[s->curr_cmd_data_cntr++] = value;
913 881d588a Dmitry Fleytman
914 881d588a Dmitry Fleytman
    pvscsi_do_command_processing(s);
915 881d588a Dmitry Fleytman
}
916 881d588a Dmitry Fleytman
917 881d588a Dmitry Fleytman
static void
918 881d588a Dmitry Fleytman
pvscsi_on_command(PVSCSIState *s, uint64_t cmd_id)
919 881d588a Dmitry Fleytman
{
920 881d588a Dmitry Fleytman
    if ((cmd_id > PVSCSI_CMD_FIRST) && (cmd_id < PVSCSI_CMD_LAST)) {
921 881d588a Dmitry Fleytman
        s->curr_cmd = cmd_id;
922 881d588a Dmitry Fleytman
    } else {
923 881d588a Dmitry Fleytman
        s->curr_cmd = PVSCSI_CMD_FIRST;
924 881d588a Dmitry Fleytman
        trace_pvscsi_on_cmd_unknown(cmd_id);
925 881d588a Dmitry Fleytman
    }
926 881d588a Dmitry Fleytman
927 881d588a Dmitry Fleytman
    s->curr_cmd_data_cntr = 0;
928 881d588a Dmitry Fleytman
    s->reg_command_status = PVSCSI_COMMAND_NOT_ENOUGH_DATA;
929 881d588a Dmitry Fleytman
930 881d588a Dmitry Fleytman
    pvscsi_do_command_processing(s);
931 881d588a Dmitry Fleytman
}
932 881d588a Dmitry Fleytman
933 881d588a Dmitry Fleytman
static void
934 881d588a Dmitry Fleytman
pvscsi_io_write(void *opaque, hwaddr addr,
935 881d588a Dmitry Fleytman
                uint64_t val, unsigned size)
936 881d588a Dmitry Fleytman
{
937 881d588a Dmitry Fleytman
    PVSCSIState *s = opaque;
938 881d588a Dmitry Fleytman
939 881d588a Dmitry Fleytman
    switch (addr) {
940 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_COMMAND:
941 881d588a Dmitry Fleytman
        pvscsi_on_command(s, val);
942 881d588a Dmitry Fleytman
        break;
943 881d588a Dmitry Fleytman
944 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_COMMAND_DATA:
945 881d588a Dmitry Fleytman
        pvscsi_on_command_data(s, (uint32_t) val);
946 881d588a Dmitry Fleytman
        break;
947 881d588a Dmitry Fleytman
948 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_INTR_STATUS:
949 881d588a Dmitry Fleytman
        trace_pvscsi_io_write("PVSCSI_REG_OFFSET_INTR_STATUS", val);
950 881d588a Dmitry Fleytman
        s->reg_interrupt_status &= ~val;
951 881d588a Dmitry Fleytman
        pvscsi_update_irq_status(s);
952 881d588a Dmitry Fleytman
        pvscsi_schedule_completion_processing(s);
953 881d588a Dmitry Fleytman
        break;
954 881d588a Dmitry Fleytman
955 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_INTR_MASK:
956 881d588a Dmitry Fleytman
        trace_pvscsi_io_write("PVSCSI_REG_OFFSET_INTR_MASK", val);
957 881d588a Dmitry Fleytman
        s->reg_interrupt_enabled = val;
958 881d588a Dmitry Fleytman
        pvscsi_update_irq_status(s);
959 881d588a Dmitry Fleytman
        break;
960 881d588a Dmitry Fleytman
961 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_KICK_NON_RW_IO:
962 881d588a Dmitry Fleytman
        trace_pvscsi_io_write("PVSCSI_REG_OFFSET_KICK_NON_RW_IO", val);
963 881d588a Dmitry Fleytman
        pvscsi_process_io(s);
964 881d588a Dmitry Fleytman
        break;
965 881d588a Dmitry Fleytman
966 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_KICK_RW_IO:
967 881d588a Dmitry Fleytman
        trace_pvscsi_io_write("PVSCSI_REG_OFFSET_KICK_RW_IO", val);
968 881d588a Dmitry Fleytman
        pvscsi_process_io(s);
969 881d588a Dmitry Fleytman
        break;
970 881d588a Dmitry Fleytman
971 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_DEBUG:
972 881d588a Dmitry Fleytman
        trace_pvscsi_io_write("PVSCSI_REG_OFFSET_DEBUG", val);
973 881d588a Dmitry Fleytman
        break;
974 881d588a Dmitry Fleytman
975 881d588a Dmitry Fleytman
    default:
976 881d588a Dmitry Fleytman
        trace_pvscsi_io_write_unknown(addr, size, val);
977 881d588a Dmitry Fleytman
        break;
978 881d588a Dmitry Fleytman
    }
979 881d588a Dmitry Fleytman
980 881d588a Dmitry Fleytman
}
981 881d588a Dmitry Fleytman
982 881d588a Dmitry Fleytman
static uint64_t
983 881d588a Dmitry Fleytman
pvscsi_io_read(void *opaque, hwaddr addr, unsigned size)
984 881d588a Dmitry Fleytman
{
985 881d588a Dmitry Fleytman
    PVSCSIState *s = opaque;
986 881d588a Dmitry Fleytman
987 881d588a Dmitry Fleytman
    switch (addr) {
988 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_INTR_STATUS:
989 881d588a Dmitry Fleytman
        trace_pvscsi_io_read("PVSCSI_REG_OFFSET_INTR_STATUS",
990 881d588a Dmitry Fleytman
                             s->reg_interrupt_status);
991 881d588a Dmitry Fleytman
        return s->reg_interrupt_status;
992 881d588a Dmitry Fleytman
993 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_INTR_MASK:
994 881d588a Dmitry Fleytman
        trace_pvscsi_io_read("PVSCSI_REG_OFFSET_INTR_MASK",
995 881d588a Dmitry Fleytman
                             s->reg_interrupt_status);
996 881d588a Dmitry Fleytman
        return s->reg_interrupt_enabled;
997 881d588a Dmitry Fleytman
998 881d588a Dmitry Fleytman
    case PVSCSI_REG_OFFSET_COMMAND_STATUS:
999 881d588a Dmitry Fleytman
        trace_pvscsi_io_read("PVSCSI_REG_OFFSET_COMMAND_STATUS",
1000 881d588a Dmitry Fleytman
                             s->reg_interrupt_status);
1001 881d588a Dmitry Fleytman
        return s->reg_command_status;
1002 881d588a Dmitry Fleytman
1003 881d588a Dmitry Fleytman
    default:
1004 881d588a Dmitry Fleytman
        trace_pvscsi_io_read_unknown(addr, size);
1005 881d588a Dmitry Fleytman
        return 0;
1006 881d588a Dmitry Fleytman
    }
1007 881d588a Dmitry Fleytman
}
1008 881d588a Dmitry Fleytman
1009 881d588a Dmitry Fleytman
1010 881d588a Dmitry Fleytman
static bool
1011 881d588a Dmitry Fleytman
pvscsi_init_msi(PVSCSIState *s)
1012 881d588a Dmitry Fleytman
{
1013 881d588a Dmitry Fleytman
    int res;
1014 881d588a Dmitry Fleytman
    PCIDevice *d = PCI_DEVICE(s);
1015 881d588a Dmitry Fleytman
1016 881d588a Dmitry Fleytman
    res = msi_init(d, PVSCSI_MSI_OFFSET, PVSCSI_MSIX_NUM_VECTORS,
1017 881d588a Dmitry Fleytman
                   PVSCSI_USE_64BIT, PVSCSI_PER_VECTOR_MASK);
1018 881d588a Dmitry Fleytman
    if (res < 0) {
1019 881d588a Dmitry Fleytman
        trace_pvscsi_init_msi_fail(res);
1020 881d588a Dmitry Fleytman
        s->msi_used = false;
1021 881d588a Dmitry Fleytman
    } else {
1022 881d588a Dmitry Fleytman
        s->msi_used = true;
1023 881d588a Dmitry Fleytman
    }
1024 881d588a Dmitry Fleytman
1025 881d588a Dmitry Fleytman
    return s->msi_used;
1026 881d588a Dmitry Fleytman
}
1027 881d588a Dmitry Fleytman
1028 881d588a Dmitry Fleytman
static void
1029 881d588a Dmitry Fleytman
pvscsi_cleanup_msi(PVSCSIState *s)
1030 881d588a Dmitry Fleytman
{
1031 881d588a Dmitry Fleytman
    PCIDevice *d = PCI_DEVICE(s);
1032 881d588a Dmitry Fleytman
1033 881d588a Dmitry Fleytman
    if (s->msi_used) {
1034 881d588a Dmitry Fleytman
        msi_uninit(d);
1035 881d588a Dmitry Fleytman
    }
1036 881d588a Dmitry Fleytman
}
1037 881d588a Dmitry Fleytman
1038 881d588a Dmitry Fleytman
static const MemoryRegionOps pvscsi_ops = {
1039 881d588a Dmitry Fleytman
        .read = pvscsi_io_read,
1040 881d588a Dmitry Fleytman
        .write = pvscsi_io_write,
1041 881d588a Dmitry Fleytman
        .endianness = DEVICE_LITTLE_ENDIAN,
1042 881d588a Dmitry Fleytman
        .impl = {
1043 881d588a Dmitry Fleytman
                .min_access_size = 4,
1044 881d588a Dmitry Fleytman
                .max_access_size = 4,
1045 881d588a Dmitry Fleytman
        },
1046 881d588a Dmitry Fleytman
};
1047 881d588a Dmitry Fleytman
1048 881d588a Dmitry Fleytman
static const struct SCSIBusInfo pvscsi_scsi_info = {
1049 881d588a Dmitry Fleytman
        .tcq = true,
1050 881d588a Dmitry Fleytman
        .max_target = PVSCSI_MAX_DEVS,
1051 881d588a Dmitry Fleytman
        .max_channel = 0,
1052 881d588a Dmitry Fleytman
        .max_lun = 0,
1053 881d588a Dmitry Fleytman
1054 881d588a Dmitry Fleytman
        .get_sg_list = pvscsi_get_sg_list,
1055 881d588a Dmitry Fleytman
        .complete = pvscsi_command_complete,
1056 881d588a Dmitry Fleytman
        .cancel = pvscsi_request_cancelled,
1057 881d588a Dmitry Fleytman
        .hotplug = pvscsi_hotplug,
1058 881d588a Dmitry Fleytman
        .hot_unplug = pvscsi_hot_unplug,
1059 881d588a Dmitry Fleytman
};
1060 881d588a Dmitry Fleytman
1061 881d588a Dmitry Fleytman
static int
1062 881d588a Dmitry Fleytman
pvscsi_init(PCIDevice *pci_dev)
1063 881d588a Dmitry Fleytman
{
1064 881d588a Dmitry Fleytman
    PVSCSIState *s = PVSCSI(pci_dev);
1065 881d588a Dmitry Fleytman
1066 881d588a Dmitry Fleytman
    trace_pvscsi_state("init");
1067 881d588a Dmitry Fleytman
1068 881d588a Dmitry Fleytman
    /* PCI subsystem ID */
1069 881d588a Dmitry Fleytman
    pci_dev->config[PCI_SUBSYSTEM_ID] = 0x00;
1070 881d588a Dmitry Fleytman
    pci_dev->config[PCI_SUBSYSTEM_ID + 1] = 0x10;
1071 881d588a Dmitry Fleytman
1072 881d588a Dmitry Fleytman
    /* PCI latency timer = 255 */
1073 881d588a Dmitry Fleytman
    pci_dev->config[PCI_LATENCY_TIMER] = 0xff;
1074 881d588a Dmitry Fleytman
1075 881d588a Dmitry Fleytman
    /* Interrupt pin A */
1076 881d588a Dmitry Fleytman
    pci_config_set_interrupt_pin(pci_dev->config, 1);
1077 881d588a Dmitry Fleytman
1078 2c9b15ca Paolo Bonzini
    memory_region_init_io(&s->io_space, NULL, &pvscsi_ops, s,
1079 881d588a Dmitry Fleytman
                          "pvscsi-io", PVSCSI_MEM_SPACE_SIZE);
1080 881d588a Dmitry Fleytman
    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_space);
1081 881d588a Dmitry Fleytman
1082 881d588a Dmitry Fleytman
    pvscsi_init_msi(s);
1083 881d588a Dmitry Fleytman
1084 881d588a Dmitry Fleytman
    s->completion_worker = qemu_bh_new(pvscsi_process_completion_queue, s);
1085 881d588a Dmitry Fleytman
    if (!s->completion_worker) {
1086 881d588a Dmitry Fleytman
        pvscsi_cleanup_msi(s);
1087 881d588a Dmitry Fleytman
        memory_region_destroy(&s->io_space);
1088 881d588a Dmitry Fleytman
        return -ENOMEM;
1089 881d588a Dmitry Fleytman
    }
1090 881d588a Dmitry Fleytman
1091 11fc853c KONRAD Frederic
    scsi_bus_new(&s->bus, &pci_dev->qdev, &pvscsi_scsi_info, NULL);
1092 881d588a Dmitry Fleytman
    pvscsi_reset_state(s);
1093 881d588a Dmitry Fleytman
1094 881d588a Dmitry Fleytman
    return 0;
1095 881d588a Dmitry Fleytman
}
1096 881d588a Dmitry Fleytman
1097 881d588a Dmitry Fleytman
static void
1098 881d588a Dmitry Fleytman
pvscsi_uninit(PCIDevice *pci_dev)
1099 881d588a Dmitry Fleytman
{
1100 881d588a Dmitry Fleytman
    PVSCSIState *s = PVSCSI(pci_dev);
1101 881d588a Dmitry Fleytman
1102 881d588a Dmitry Fleytman
    trace_pvscsi_state("uninit");
1103 881d588a Dmitry Fleytman
    qemu_bh_delete(s->completion_worker);
1104 881d588a Dmitry Fleytman
1105 881d588a Dmitry Fleytman
    pvscsi_cleanup_msi(s);
1106 881d588a Dmitry Fleytman
1107 881d588a Dmitry Fleytman
    memory_region_destroy(&s->io_space);
1108 881d588a Dmitry Fleytman
}
1109 881d588a Dmitry Fleytman
1110 881d588a Dmitry Fleytman
static void
1111 881d588a Dmitry Fleytman
pvscsi_reset(DeviceState *dev)
1112 881d588a Dmitry Fleytman
{
1113 881d588a Dmitry Fleytman
    PCIDevice *d = PCI_DEVICE(dev);
1114 881d588a Dmitry Fleytman
    PVSCSIState *s = PVSCSI(d);
1115 881d588a Dmitry Fleytman
1116 881d588a Dmitry Fleytman
    trace_pvscsi_state("reset");
1117 881d588a Dmitry Fleytman
    pvscsi_reset_adapter(s);
1118 881d588a Dmitry Fleytman
}
1119 881d588a Dmitry Fleytman
1120 881d588a Dmitry Fleytman
static void
1121 881d588a Dmitry Fleytman
pvscsi_pre_save(void *opaque)
1122 881d588a Dmitry Fleytman
{
1123 881d588a Dmitry Fleytman
    PVSCSIState *s = (PVSCSIState *) opaque;
1124 881d588a Dmitry Fleytman
1125 881d588a Dmitry Fleytman
    trace_pvscsi_state("presave");
1126 881d588a Dmitry Fleytman
1127 881d588a Dmitry Fleytman
    assert(QTAILQ_EMPTY(&s->pending_queue));
1128 881d588a Dmitry Fleytman
    assert(QTAILQ_EMPTY(&s->completion_queue));
1129 881d588a Dmitry Fleytman
}
1130 881d588a Dmitry Fleytman
1131 881d588a Dmitry Fleytman
static int
1132 881d588a Dmitry Fleytman
pvscsi_post_load(void *opaque, int version_id)
1133 881d588a Dmitry Fleytman
{
1134 881d588a Dmitry Fleytman
    trace_pvscsi_state("postload");
1135 881d588a Dmitry Fleytman
    return 0;
1136 881d588a Dmitry Fleytman
}
1137 881d588a Dmitry Fleytman
1138 881d588a Dmitry Fleytman
static const VMStateDescription vmstate_pvscsi = {
1139 881d588a Dmitry Fleytman
    .name = TYPE_PVSCSI,
1140 881d588a Dmitry Fleytman
    .version_id = 0,
1141 881d588a Dmitry Fleytman
    .minimum_version_id = 0,
1142 881d588a Dmitry Fleytman
    .minimum_version_id_old = 0,
1143 881d588a Dmitry Fleytman
    .pre_save = pvscsi_pre_save,
1144 881d588a Dmitry Fleytman
    .post_load = pvscsi_post_load,
1145 881d588a Dmitry Fleytman
    .fields      = (VMStateField[]) {
1146 881d588a Dmitry Fleytman
        VMSTATE_PCI_DEVICE(parent_obj, PVSCSIState),
1147 881d588a Dmitry Fleytman
        VMSTATE_UINT8(msi_used, PVSCSIState),
1148 881d588a Dmitry Fleytman
        VMSTATE_UINT32(resetting, PVSCSIState),
1149 881d588a Dmitry Fleytman
        VMSTATE_UINT64(reg_interrupt_status, PVSCSIState),
1150 881d588a Dmitry Fleytman
        VMSTATE_UINT64(reg_interrupt_enabled, PVSCSIState),
1151 881d588a Dmitry Fleytman
        VMSTATE_UINT64(reg_command_status, PVSCSIState),
1152 881d588a Dmitry Fleytman
        VMSTATE_UINT64(curr_cmd, PVSCSIState),
1153 881d588a Dmitry Fleytman
        VMSTATE_UINT32(curr_cmd_data_cntr, PVSCSIState),
1154 881d588a Dmitry Fleytman
        VMSTATE_UINT32_ARRAY(curr_cmd_data, PVSCSIState,
1155 881d588a Dmitry Fleytman
                             ARRAY_SIZE(((PVSCSIState *)NULL)->curr_cmd_data)),
1156 881d588a Dmitry Fleytman
        VMSTATE_UINT8(rings_info_valid, PVSCSIState),
1157 881d588a Dmitry Fleytman
        VMSTATE_UINT8(msg_ring_info_valid, PVSCSIState),
1158 881d588a Dmitry Fleytman
        VMSTATE_UINT8(use_msg, PVSCSIState),
1159 881d588a Dmitry Fleytman
1160 881d588a Dmitry Fleytman
        VMSTATE_UINT64(rings.rs_pa, PVSCSIState),
1161 881d588a Dmitry Fleytman
        VMSTATE_UINT32(rings.txr_len_mask, PVSCSIState),
1162 881d588a Dmitry Fleytman
        VMSTATE_UINT32(rings.rxr_len_mask, PVSCSIState),
1163 881d588a Dmitry Fleytman
        VMSTATE_UINT64_ARRAY(rings.req_ring_pages_pa, PVSCSIState,
1164 881d588a Dmitry Fleytman
                             PVSCSI_SETUP_RINGS_MAX_NUM_PAGES),
1165 881d588a Dmitry Fleytman
        VMSTATE_UINT64_ARRAY(rings.cmp_ring_pages_pa, PVSCSIState,
1166 881d588a Dmitry Fleytman
                             PVSCSI_SETUP_RINGS_MAX_NUM_PAGES),
1167 881d588a Dmitry Fleytman
        VMSTATE_UINT64(rings.consumed_ptr, PVSCSIState),
1168 881d588a Dmitry Fleytman
        VMSTATE_UINT64(rings.filled_cmp_ptr, PVSCSIState),
1169 881d588a Dmitry Fleytman
1170 881d588a Dmitry Fleytman
        VMSTATE_END_OF_LIST()
1171 881d588a Dmitry Fleytman
    }
1172 881d588a Dmitry Fleytman
};
1173 881d588a Dmitry Fleytman
1174 881d588a Dmitry Fleytman
static void
1175 881d588a Dmitry Fleytman
pvscsi_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
1176 881d588a Dmitry Fleytman
{
1177 881d588a Dmitry Fleytman
    pci_default_write_config(pci, addr, val, len);
1178 881d588a Dmitry Fleytman
    msi_write_config(pci, addr, val, len);
1179 881d588a Dmitry Fleytman
}
1180 881d588a Dmitry Fleytman
1181 881d588a Dmitry Fleytman
static Property pvscsi_properties[] = {
1182 881d588a Dmitry Fleytman
    DEFINE_PROP_UINT8("use_msg", PVSCSIState, use_msg, 1),
1183 881d588a Dmitry Fleytman
    DEFINE_PROP_END_OF_LIST(),
1184 881d588a Dmitry Fleytman
};
1185 881d588a Dmitry Fleytman
1186 881d588a Dmitry Fleytman
static void pvscsi_class_init(ObjectClass *klass, void *data)
1187 881d588a Dmitry Fleytman
{
1188 881d588a Dmitry Fleytman
    DeviceClass *dc = DEVICE_CLASS(klass);
1189 881d588a Dmitry Fleytman
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1190 881d588a Dmitry Fleytman
1191 881d588a Dmitry Fleytman
    k->init = pvscsi_init;
1192 881d588a Dmitry Fleytman
    k->exit = pvscsi_uninit;
1193 881d588a Dmitry Fleytman
    k->vendor_id = PCI_VENDOR_ID_VMWARE;
1194 881d588a Dmitry Fleytman
    k->device_id = PCI_DEVICE_ID_VMWARE_PVSCSI;
1195 881d588a Dmitry Fleytman
    k->class_id = PCI_CLASS_STORAGE_SCSI;
1196 881d588a Dmitry Fleytman
    k->subsystem_id = 0x1000;
1197 881d588a Dmitry Fleytman
    dc->reset = pvscsi_reset;
1198 881d588a Dmitry Fleytman
    dc->vmsd = &vmstate_pvscsi;
1199 881d588a Dmitry Fleytman
    dc->props = pvscsi_properties;
1200 881d588a Dmitry Fleytman
    k->config_write = pvscsi_write_config;
1201 881d588a Dmitry Fleytman
}
1202 881d588a Dmitry Fleytman
1203 881d588a Dmitry Fleytman
static const TypeInfo pvscsi_info = {
1204 881d588a Dmitry Fleytman
    .name          = "pvscsi",
1205 881d588a Dmitry Fleytman
    .parent        = TYPE_PCI_DEVICE,
1206 881d588a Dmitry Fleytman
    .instance_size = sizeof(PVSCSIState),
1207 881d588a Dmitry Fleytman
    .class_init    = pvscsi_class_init,
1208 881d588a Dmitry Fleytman
};
1209 881d588a Dmitry Fleytman
1210 881d588a Dmitry Fleytman
static void
1211 881d588a Dmitry Fleytman
pvscsi_register_types(void)
1212 881d588a Dmitry Fleytman
{
1213 881d588a Dmitry Fleytman
    type_register_static(&pvscsi_info);
1214 881d588a Dmitry Fleytman
}
1215 881d588a Dmitry Fleytman
1216 881d588a Dmitry Fleytman
type_init(pvscsi_register_types);