These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / seabios / src / hw / pvscsi.c
1 // QEMU VMWARE Paravirtualized SCSI boot support.
2 //
3 // Copyright (c) 2013 Ravello Systems LTD (http://ravellosystems.com)
4 //
5 // Authors:
6 //  Evgeny Budilovsky <evgeny.budilovsky@ravellosystems.com>
7 //
8 // This file may be distributed under the terms of the GNU LGPLv3 license.
9
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 "memmap.h" // PAGE_SHIFT, virt_to_phys
15 #include "output.h" // dprintf
16 #include "pci.h" // foreachpci
17 #include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI
18 #include "pci_regs.h" // PCI_VENDOR_ID
19 #include "pvscsi.h" // pvscsi_setup
20 #include "std/disk.h" // DISK_RET_SUCCESS
21 #include "string.h" // memset
22 #include "util.h" // usleep
23 #include "x86.h" // writel
24
25 #define MASK(n) ((1 << (n)) - 1)
26
27 #define SIMPLE_QUEUE_TAG 0x20
28
29 #define PVSCSI_INTR_CMPL_0                 (1 << 0)
30 #define PVSCSI_INTR_CMPL_1                 (1 << 1)
31 #define PVSCSI_INTR_CMPL_MASK              MASK(2)
32
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)
37
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)
43
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,
57 };
58
59 enum PVSCSICommands {
60     PVSCSI_CMD_FIRST             = 0,
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,
70     PVSCSI_CMD_LAST              = 10
71 };
72
73 #define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES        32
74 struct PVSCSICmdDescSetupRings {
75     u32    reqRingNumPages;
76     u32    cmpRingNumPages;
77     u64    ringsStatePPN;
78     u64    reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
79     u64    cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
80 } PACKED;
81
82 struct PVSCSIRingCmpDesc {
83     u64    context;
84     u64    dataLen;
85     u32    senseLen;
86     u16    hostStatus;
87     u16    scsiStatus;
88     u32    pad[2];
89 } PACKED;
90
91 struct PVSCSIRingsState {
92     u32    reqProdIdx;
93     u32    reqConsIdx;
94     u32    reqNumEntriesLog2;
95
96     u32    cmpProdIdx;
97     u32    cmpConsIdx;
98     u32    cmpNumEntriesLog2;
99
100     u8     pad[104];
101
102     u32    msgProdIdx;
103     u32    msgConsIdx;
104     u32    msgNumEntriesLog2;
105 } PACKED;
106
107 struct PVSCSIRingReqDesc {
108     u64    context;
109     u64    dataAddr;
110     u64    dataLen;
111     u64    senseAddr;
112     u32    senseLen;
113     u32    flags;
114     u8     cdb[16];
115     u8     cdbLen;
116     u8     lun[8];
117     u8     tag;
118     u8     bus;
119     u8     target;
120     u8     vcpuHint;
121     u8     unused[59];
122 } PACKED;
123
124 struct pvscsi_ring_dsc_s {
125     struct PVSCSIRingsState *ring_state;
126     struct PVSCSIRingReqDesc *ring_reqs;
127     struct PVSCSIRingCmpDesc *ring_cmps;
128 };
129
130 struct pvscsi_lun_s {
131     struct drive_s drive;
132     void *iobase;
133     u8 target;
134     u8 lun;
135     struct pvscsi_ring_dsc_s *ring_dsc;
136 };
137
138 static void
139 pvscsi_write_cmd_desc(void *iobase, u32 cmd, const void *desc, size_t len)
140 {
141     const u32 *ptr = desc;
142     size_t i;
143
144     len /= sizeof(*ptr);
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]);
148 }
149
150 static void
151 pvscsi_kick_rw_io(void *iobase)
152 {
153     writel(iobase + PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
154 }
155
156 static void
157 pvscsi_wait_intr_cmpl(void *iobase)
158 {
159     while (!(readl(iobase + PVSCSI_REG_OFFSET_INTR_STATUS) & PVSCSI_INTR_CMPL_MASK))
160         usleep(5);
161     writel(iobase + PVSCSI_REG_OFFSET_INTR_STATUS, PVSCSI_INTR_CMPL_MASK);
162 }
163
164 static void
165 pvscsi_init_rings(void *iobase, struct pvscsi_ring_dsc_s **ring_dsc)
166 {
167     struct PVSCSICmdDescSetupRings cmd = {0,};
168
169     struct pvscsi_ring_dsc_s *dsc = memalign_low(sizeof(*dsc), PAGE_SIZE);
170     if (!dsc) {
171         warn_noalloc();
172         return;
173     }
174
175     dsc->ring_state =
176         (struct PVSCSIRingsState *)memalign_low(PAGE_SIZE, PAGE_SIZE);
177     dsc->ring_reqs =
178         (struct PVSCSIRingReqDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE);
179     dsc->ring_cmps =
180         (struct PVSCSIRingCmpDesc *)memalign_low(PAGE_SIZE, PAGE_SIZE);
181     if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) {
182         warn_noalloc();
183         return;
184     }
185     memset(dsc->ring_state, 0, PAGE_SIZE);
186     memset(dsc->ring_reqs, 0, PAGE_SIZE);
187     memset(dsc->ring_cmps, 0, PAGE_SIZE);
188
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;
194
195     pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS,
196                           &cmd, sizeof(cmd));
197     *ring_dsc = dsc;
198 }
199
200 static u32
201 pvscsi_get_rsp(struct PVSCSIRingsState *s,
202                struct PVSCSIRingCmpDesc *rsp)
203 {
204     u32 status = rsp->hostStatus;
205     s->cmpConsIdx = s->cmpConsIdx + 1;
206     return status;
207 }
208
209 int
210 pvscsi_process_op(struct disk_op_s *op)
211 {
212     if (!CONFIG_PVSCSI)
213         return DISK_RET_EBADTRACK;
214     struct pvscsi_lun_s *plun =
215         container_of(op->drive_gf, struct pvscsi_lun_s, drive);
216     struct pvscsi_ring_dsc_s *ring_dsc = plun->ring_dsc;
217     struct PVSCSIRingsState *s = ring_dsc->ring_state;
218     u32 req_entries = s->reqNumEntriesLog2;
219     u32 cmp_entries = s->cmpNumEntriesLog2;
220     struct PVSCSIRingReqDesc *req;
221     struct PVSCSIRingCmpDesc *rsp;
222     u32 status;
223
224     if (s->reqProdIdx - s->cmpConsIdx >= 1 << req_entries) {
225         dprintf(1, "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n",
226                 s->reqProdIdx, s->cmpConsIdx);
227         return DISK_RET_EBADTRACK;
228     }
229
230     req = ring_dsc->ring_reqs + (s->reqProdIdx & MASK(req_entries));
231     int blocksize = scsi_fill_cmd(op, req->cdb, 16);
232     if (blocksize < 0)
233         return default_process_op(op);
234     req->bus = 0;
235     req->target = plun->target;
236     memset(req->lun, 0, sizeof(req->lun));
237     req->lun[1] = plun->lun;
238     req->senseLen = 0;
239     req->senseAddr = 0;
240     req->cdbLen = 16;
241     req->vcpuHint = 0;
242     req->tag = SIMPLE_QUEUE_TAG;
243     req->flags = scsi_is_read(op) ?
244         PVSCSI_FLAG_CMD_DIR_TOHOST : PVSCSI_FLAG_CMD_DIR_TODEVICE;
245     req->dataLen = op->count * blocksize;
246     req->dataAddr = (u32)op->buf_fl;
247     s->reqProdIdx = s->reqProdIdx + 1;
248
249     pvscsi_kick_rw_io(plun->iobase);
250     pvscsi_wait_intr_cmpl(plun->iobase);
251
252     rsp = ring_dsc->ring_cmps + (s->cmpConsIdx & MASK(cmp_entries));
253     status = pvscsi_get_rsp(s, rsp);
254
255     return status == 0 ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
256 }
257
258 static int
259 pvscsi_add_lun(struct pci_device *pci, void *iobase,
260                struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun)
261 {
262     struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun));
263     if (!plun) {
264         warn_noalloc();
265         return -1;
266     }
267     memset(plun, 0, sizeof(*plun));
268     plun->drive.type = DTYPE_PVSCSI;
269     plun->drive.cntl_id = pci->bdf;
270     plun->target = target;
271     plun->lun = lun;
272     plun->iobase = iobase;
273     plun->ring_dsc = ring_dsc;
274
275     char *name = znprintf(16, "pvscsi %02x:%02x.%x %d:%d",
276                           pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
277                           pci_bdf_to_fn(pci->bdf), target, lun);
278     int prio = bootprio_find_scsi_device(pci, target, lun);
279     int ret = scsi_drive_setup(&plun->drive, name, prio);
280     free(name);
281     if (ret)
282         goto fail;
283     return 0;
284
285 fail:
286     free(plun);
287     return -1;
288 }
289
290 static void
291 pvscsi_scan_target(struct pci_device *pci, void *iobase,
292                    struct pvscsi_ring_dsc_s *ring_dsc, u8 target)
293 {
294     /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
295     pvscsi_add_lun(pci, iobase, ring_dsc, target, 0);
296 }
297
298 static void
299 init_pvscsi(struct pci_device *pci)
300 {
301     struct pvscsi_ring_dsc_s *ring_dsc = NULL;
302     int i;
303     u16 bdf = pci->bdf;
304     void *iobase = (void*)(pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
305                            & PCI_BASE_ADDRESS_MEM_MASK);
306
307     pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
308
309     dprintf(1, "found pvscsi at %02x:%02x.%x, io @ %p\n",
310             pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
311             pci_bdf_to_fn(bdf), iobase);
312
313     pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
314
315     pvscsi_init_rings(iobase, &ring_dsc);
316     for (i = 0; i < 7; i++)
317         pvscsi_scan_target(pci, iobase, ring_dsc, i);
318
319     return;
320 }
321
322 void
323 pvscsi_setup(void)
324 {
325     ASSERT32FLAT();
326     if (! CONFIG_PVSCSI)
327         return;
328
329     dprintf(3, "init pvscsi\n");
330
331     struct pci_device *pci;
332     foreachpci(pci) {
333         if (pci->vendor != PCI_VENDOR_ID_VMWARE
334             || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI)
335             continue;
336         init_pvscsi(pci);
337     }
338 }