1 // QEMU VMWARE Paravirtualized SCSI boot support.
3 // Copyright (c) 2013 Ravello Systems LTD (http://ravellosystems.com)
6 // Evgeny Budilovsky <evgeny.budilovsky@ravellosystems.com>
8 // This file may be distributed under the terms of the GNU LGPLv3 license.
10 #include "block.h" // struct drive_s
11 #include "blockcmd.h" // scsi_drive_setup
12 #include "config.h" // CONFIG_*
13 #include "malloc.h" // free
14 #include "output.h" // dprintf
15 #include "pci.h" // foreachpci
16 #include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI
17 #include "pci_regs.h" // PCI_VENDOR_ID
18 #include "pvscsi.h" // pvscsi_setup
19 #include "std/disk.h" // DISK_RET_SUCCESS
20 #include "string.h" // memset
21 #include "util.h" // usleep
22 #include "virtio-ring.h" // PAGE_SHIFT, virt_to_phys
23 #include "x86.h" // writel
25 #define MASK(n) ((1 << (n)) - 1)
27 #define SIMPLE_QUEUE_TAG 0x20
29 #define PVSCSI_INTR_CMPL_0 (1 << 0)
30 #define PVSCSI_INTR_CMPL_1 (1 << 1)
31 #define PVSCSI_INTR_CMPL_MASK MASK(2)
33 #define PVSCSI_INTR_MSG_0 (1 << 2)
34 #define PVSCSI_INTR_MSG_1 (1 << 3)
35 #define PVSCSI_INTR_MSG_MASK (MASK(2) << 2)
36 #define PVSCSI_INTR_ALL_SUPPORTED MASK(4)
38 #define PVSCSI_FLAG_CMD_WITH_SG_LIST (1 << 0)
39 #define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB (1 << 1)
40 #define PVSCSI_FLAG_CMD_DIR_NONE (1 << 2)
41 #define PVSCSI_FLAG_CMD_DIR_TOHOST (1 << 3)
42 #define PVSCSI_FLAG_CMD_DIR_TODEVICE (1 << 4)
44 enum PVSCSIRegOffset {
45 PVSCSI_REG_OFFSET_COMMAND = 0x0,
46 PVSCSI_REG_OFFSET_COMMAND_DATA = 0x4,
47 PVSCSI_REG_OFFSET_COMMAND_STATUS = 0x8,
48 PVSCSI_REG_OFFSET_LAST_STS_0 = 0x100,
49 PVSCSI_REG_OFFSET_LAST_STS_1 = 0x104,
50 PVSCSI_REG_OFFSET_LAST_STS_2 = 0x108,
51 PVSCSI_REG_OFFSET_LAST_STS_3 = 0x10c,
52 PVSCSI_REG_OFFSET_INTR_STATUS = 0x100c,
53 PVSCSI_REG_OFFSET_INTR_MASK = 0x2010,
54 PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014,
55 PVSCSI_REG_OFFSET_DEBUG = 0x3018,
56 PVSCSI_REG_OFFSET_KICK_RW_IO = 0x4018,
61 PVSCSI_CMD_ADAPTER_RESET = 1,
62 PVSCSI_CMD_ISSUE_SCSI = 2,
63 PVSCSI_CMD_SETUP_RINGS = 3,
64 PVSCSI_CMD_RESET_BUS = 4,
65 PVSCSI_CMD_RESET_DEVICE = 5,
66 PVSCSI_CMD_ABORT_CMD = 6,
67 PVSCSI_CMD_CONFIG = 7,
68 PVSCSI_CMD_SETUP_MSG_RING = 8,
69 PVSCSI_CMD_DEVICE_UNPLUG = 9,
73 #define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 32
74 struct PVSCSICmdDescSetupRings {
78 u64 reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
79 u64 cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
82 struct PVSCSIRingCmpDesc {
91 struct PVSCSIRingsState {
94 u32 reqNumEntriesLog2;
98 u32 cmpNumEntriesLog2;
104 u32 msgNumEntriesLog2;
107 struct PVSCSIRingReqDesc {
124 struct pvscsi_ring_dsc_s {
125 struct PVSCSIRingsState *ring_state;
126 struct PVSCSIRingReqDesc *ring_reqs;
127 struct PVSCSIRingCmpDesc *ring_cmps;
130 struct pvscsi_lun_s {
131 struct drive_s drive;
135 struct pvscsi_ring_dsc_s *ring_dsc;
139 pvscsi_write_cmd_desc(void *iobase, u32 cmd, const void *desc, size_t len)
141 const u32 *ptr = desc;
145 writel(iobase + PVSCSI_REG_OFFSET_COMMAND, cmd);
146 for (i = 0; i < len; i++)
147 writel(iobase + PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]);
151 pvscsi_kick_rw_io(void *iobase)
153 writel(iobase + PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
157 pvscsi_wait_intr_cmpl(void *iobase)
159 while (!(readl(iobase + PVSCSI_REG_OFFSET_INTR_STATUS) & PVSCSI_INTR_CMPL_MASK))
161 writel(iobase + PVSCSI_REG_OFFSET_INTR_STATUS, PVSCSI_INTR_CMPL_MASK);
165 pvscsi_init_rings(void *iobase, struct pvscsi_ring_dsc_s **ring_dsc)
167 struct PVSCSICmdDescSetupRings cmd = {0,};
169 struct pvscsi_ring_dsc_s *dsc = memalign_low(sizeof(*dsc), PAGE_SIZE);
176 (struct PVSCSIRingsState *)memalign_low(PAGE_SIZE, PAGE_SIZE);
178 (struct PVSCSIRingReqDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE);
180 (struct PVSCSIRingCmpDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE);
181 if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) {
185 memset(dsc->ring_state, 0, PAGE_SIZE);
186 memset(dsc->ring_reqs, 0, PAGE_SIZE);
187 memset(dsc->ring_cmps, 0, PAGE_SIZE);
189 cmd.reqRingNumPages = 1;
190 cmd.cmpRingNumPages = 1;
191 cmd.ringsStatePPN = virt_to_phys(dsc->ring_state) >> PAGE_SHIFT;
192 cmd.reqRingPPNs[0] = virt_to_phys(dsc->ring_reqs) >> PAGE_SHIFT;
193 cmd.cmpRingPPNs[0] = virt_to_phys(dsc->ring_cmps) >> PAGE_SHIFT;
195 pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS,
200 static void pvscsi_fill_req(struct PVSCSIRingsState *s,
201 struct PVSCSIRingReqDesc *req,
202 u16 target, u16 lun, void *cdbcmd, u16 blocksize,
203 struct disk_op_s *op)
206 req->target = target;
207 memset(req->lun, 0, sizeof(req->lun));
213 memcpy(req->cdb, cdbcmd, 16);
214 req->tag = SIMPLE_QUEUE_TAG;
215 req->flags = cdb_is_read(cdbcmd, blocksize) ?
216 PVSCSI_FLAG_CMD_DIR_TOHOST : PVSCSI_FLAG_CMD_DIR_TODEVICE;
218 req->dataLen = op->count * blocksize;
219 req->dataAddr = (u32)op->buf_fl;
220 s->reqProdIdx = s->reqProdIdx + 1;
224 pvscsi_get_rsp(struct PVSCSIRingsState *s,
225 struct PVSCSIRingCmpDesc *rsp)
227 u32 status = rsp->hostStatus;
228 s->cmpConsIdx = s->cmpConsIdx + 1;
233 pvscsi_cmd(struct pvscsi_lun_s *plun, struct disk_op_s *op,
234 void *cdbcmd, u16 target, u16 lun, u16 blocksize)
236 struct pvscsi_ring_dsc_s *ring_dsc = plun->ring_dsc;
237 struct PVSCSIRingsState *s = ring_dsc->ring_state;
238 u32 req_entries = s->reqNumEntriesLog2;
239 u32 cmp_entries = s->cmpNumEntriesLog2;
240 struct PVSCSIRingReqDesc *req;
241 struct PVSCSIRingCmpDesc *rsp;
244 if (s->reqProdIdx - s->cmpConsIdx >= 1 << req_entries) {
245 dprintf(1, "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n",
246 s->reqProdIdx, s->cmpConsIdx);
247 return DISK_RET_EBADTRACK;
250 req = ring_dsc->ring_reqs + (s->reqProdIdx & MASK(req_entries));
251 pvscsi_fill_req(s, req, target, lun, cdbcmd, blocksize, op);
253 pvscsi_kick_rw_io(plun->iobase);
254 pvscsi_wait_intr_cmpl(plun->iobase);
256 rsp = ring_dsc->ring_cmps + (s->cmpConsIdx & MASK(cmp_entries));
257 status = pvscsi_get_rsp(s, rsp);
259 return status == 0 ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
263 pvscsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
266 return DISK_RET_EBADTRACK;
268 struct pvscsi_lun_s *plun =
269 container_of(op->drive_gf, struct pvscsi_lun_s, drive);
271 return pvscsi_cmd(plun, op, cdbcmd, plun->target, plun->lun, blocksize);
275 pvscsi_add_lun(struct pci_device *pci, void *iobase,
276 struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun)
278 struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun));
283 memset(plun, 0, sizeof(*plun));
284 plun->drive.type = DTYPE_PVSCSI;
285 plun->drive.cntl_id = pci->bdf;
286 plun->target = target;
288 plun->iobase = iobase;
289 plun->ring_dsc = ring_dsc;
291 char *name = znprintf(16, "pvscsi %02x:%02x.%x %d:%d",
292 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
293 pci_bdf_to_fn(pci->bdf), target, lun);
294 int prio = bootprio_find_scsi_device(pci, target, lun);
295 int ret = scsi_drive_setup(&plun->drive, name, prio);
307 pvscsi_scan_target(struct pci_device *pci, void *iobase,
308 struct pvscsi_ring_dsc_s *ring_dsc, u8 target)
310 /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */
311 pvscsi_add_lun(pci, iobase, ring_dsc, target, 0);
315 init_pvscsi(struct pci_device *pci)
317 struct pvscsi_ring_dsc_s *ring_dsc = NULL;
320 void *iobase = (void*)(pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
321 & PCI_BASE_ADDRESS_MEM_MASK);
323 pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
325 dprintf(1, "found pvscsi at %02x:%02x.%x, io @ %p\n",
326 pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
327 pci_bdf_to_fn(bdf), iobase);
329 pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
331 pvscsi_init_rings(iobase, &ring_dsc);
332 for (i = 0; i < 7; i++)
333 pvscsi_scan_target(pci, iobase, ring_dsc, i);
345 dprintf(3, "init pvscsi\n");
347 struct pci_device *pci;
349 if (pci->vendor != PCI_VENDOR_ID_VMWARE
350 || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI)