Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 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 | |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 10 | #include "block.h" // struct drive_s |
| 11 | #include "blockcmd.h" // scsi_drive_setup |
| 12 | #include "config.h" // CONFIG_* |
| 13 | #include "malloc.h" // free |
Kevin O'Connor | eee06e0 | 2015-09-29 10:14:58 -0400 | [diff] [blame] | 14 | #include "memmap.h" // PAGE_SHIFT, virt_to_phys |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 15 | #include "output.h" // dprintf |
Kevin O'Connor | 4d8510c | 2016-02-03 01:28:20 -0500 | [diff] [blame] | 16 | #include "pcidevice.h" // foreachpci |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 17 | #include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI |
| 18 | #include "pci_regs.h" // PCI_VENDOR_ID |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 19 | #include "pvscsi.h" // pvscsi_setup |
Kevin O'Connor | 79bafa1 | 2016-04-05 13:04:07 -0400 | [diff] [blame] | 20 | #include "stacks.h" // run_thread |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 21 | #include "std/disk.h" // DISK_RET_SUCCESS |
| 22 | #include "string.h" // memset |
| 23 | #include "util.h" // usleep |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 24 | #include "x86.h" // writel |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 25 | |
| 26 | #define MASK(n) ((1 << (n)) - 1) |
| 27 | |
| 28 | #define SIMPLE_QUEUE_TAG 0x20 |
| 29 | |
| 30 | #define PVSCSI_INTR_CMPL_0 (1 << 0) |
| 31 | #define PVSCSI_INTR_CMPL_1 (1 << 1) |
| 32 | #define PVSCSI_INTR_CMPL_MASK MASK(2) |
| 33 | |
| 34 | #define PVSCSI_INTR_MSG_0 (1 << 2) |
| 35 | #define PVSCSI_INTR_MSG_1 (1 << 3) |
| 36 | #define PVSCSI_INTR_MSG_MASK (MASK(2) << 2) |
| 37 | #define PVSCSI_INTR_ALL_SUPPORTED MASK(4) |
| 38 | |
| 39 | #define PVSCSI_FLAG_CMD_WITH_SG_LIST (1 << 0) |
| 40 | #define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB (1 << 1) |
| 41 | #define PVSCSI_FLAG_CMD_DIR_NONE (1 << 2) |
| 42 | #define PVSCSI_FLAG_CMD_DIR_TOHOST (1 << 3) |
| 43 | #define PVSCSI_FLAG_CMD_DIR_TODEVICE (1 << 4) |
| 44 | |
| 45 | enum PVSCSIRegOffset { |
| 46 | PVSCSI_REG_OFFSET_COMMAND = 0x0, |
| 47 | PVSCSI_REG_OFFSET_COMMAND_DATA = 0x4, |
| 48 | PVSCSI_REG_OFFSET_COMMAND_STATUS = 0x8, |
| 49 | PVSCSI_REG_OFFSET_LAST_STS_0 = 0x100, |
| 50 | PVSCSI_REG_OFFSET_LAST_STS_1 = 0x104, |
| 51 | PVSCSI_REG_OFFSET_LAST_STS_2 = 0x108, |
| 52 | PVSCSI_REG_OFFSET_LAST_STS_3 = 0x10c, |
| 53 | PVSCSI_REG_OFFSET_INTR_STATUS = 0x100c, |
| 54 | PVSCSI_REG_OFFSET_INTR_MASK = 0x2010, |
| 55 | PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014, |
| 56 | PVSCSI_REG_OFFSET_DEBUG = 0x3018, |
| 57 | PVSCSI_REG_OFFSET_KICK_RW_IO = 0x4018, |
| 58 | }; |
| 59 | |
| 60 | enum PVSCSICommands { |
| 61 | PVSCSI_CMD_FIRST = 0, |
| 62 | PVSCSI_CMD_ADAPTER_RESET = 1, |
| 63 | PVSCSI_CMD_ISSUE_SCSI = 2, |
| 64 | PVSCSI_CMD_SETUP_RINGS = 3, |
| 65 | PVSCSI_CMD_RESET_BUS = 4, |
| 66 | PVSCSI_CMD_RESET_DEVICE = 5, |
| 67 | PVSCSI_CMD_ABORT_CMD = 6, |
| 68 | PVSCSI_CMD_CONFIG = 7, |
| 69 | PVSCSI_CMD_SETUP_MSG_RING = 8, |
| 70 | PVSCSI_CMD_DEVICE_UNPLUG = 9, |
| 71 | PVSCSI_CMD_LAST = 10 |
| 72 | }; |
| 73 | |
| 74 | #define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 32 |
| 75 | struct PVSCSICmdDescSetupRings { |
| 76 | u32 reqRingNumPages; |
| 77 | u32 cmpRingNumPages; |
| 78 | u64 ringsStatePPN; |
| 79 | u64 reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; |
| 80 | u64 cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; |
| 81 | } PACKED; |
| 82 | |
| 83 | struct PVSCSIRingCmpDesc { |
| 84 | u64 context; |
| 85 | u64 dataLen; |
| 86 | u32 senseLen; |
| 87 | u16 hostStatus; |
| 88 | u16 scsiStatus; |
| 89 | u32 pad[2]; |
| 90 | } PACKED; |
| 91 | |
| 92 | struct PVSCSIRingsState { |
| 93 | u32 reqProdIdx; |
| 94 | u32 reqConsIdx; |
| 95 | u32 reqNumEntriesLog2; |
| 96 | |
| 97 | u32 cmpProdIdx; |
| 98 | u32 cmpConsIdx; |
| 99 | u32 cmpNumEntriesLog2; |
| 100 | |
| 101 | u8 pad[104]; |
| 102 | |
| 103 | u32 msgProdIdx; |
| 104 | u32 msgConsIdx; |
| 105 | u32 msgNumEntriesLog2; |
| 106 | } PACKED; |
| 107 | |
| 108 | struct PVSCSIRingReqDesc { |
| 109 | u64 context; |
| 110 | u64 dataAddr; |
| 111 | u64 dataLen; |
| 112 | u64 senseAddr; |
| 113 | u32 senseLen; |
| 114 | u32 flags; |
| 115 | u8 cdb[16]; |
| 116 | u8 cdbLen; |
| 117 | u8 lun[8]; |
| 118 | u8 tag; |
| 119 | u8 bus; |
| 120 | u8 target; |
| 121 | u8 vcpuHint; |
| 122 | u8 unused[59]; |
| 123 | } PACKED; |
| 124 | |
| 125 | struct pvscsi_ring_dsc_s { |
| 126 | struct PVSCSIRingsState *ring_state; |
| 127 | struct PVSCSIRingReqDesc *ring_reqs; |
| 128 | struct PVSCSIRingCmpDesc *ring_cmps; |
| 129 | }; |
| 130 | |
| 131 | struct pvscsi_lun_s { |
| 132 | struct drive_s drive; |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 133 | void *iobase; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 134 | u8 target; |
| 135 | u8 lun; |
| 136 | struct pvscsi_ring_dsc_s *ring_dsc; |
| 137 | }; |
| 138 | |
| 139 | static void |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 140 | pvscsi_write_cmd_desc(void *iobase, u32 cmd, const void *desc, size_t len) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 141 | { |
| 142 | const u32 *ptr = desc; |
| 143 | size_t i; |
| 144 | |
| 145 | len /= sizeof(*ptr); |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 146 | writel(iobase + PVSCSI_REG_OFFSET_COMMAND, cmd); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 147 | for (i = 0; i < len; i++) |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 148 | writel(iobase + PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | static void |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 152 | pvscsi_kick_rw_io(void *iobase) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 153 | { |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 154 | writel(iobase + PVSCSI_REG_OFFSET_KICK_RW_IO, 0); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | static void |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 158 | pvscsi_wait_intr_cmpl(void *iobase) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 159 | { |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 160 | while (!(readl(iobase + PVSCSI_REG_OFFSET_INTR_STATUS) & PVSCSI_INTR_CMPL_MASK)) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 161 | usleep(5); |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 162 | writel(iobase + PVSCSI_REG_OFFSET_INTR_STATUS, PVSCSI_INTR_CMPL_MASK); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | static void |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 166 | pvscsi_init_rings(void *iobase, struct pvscsi_ring_dsc_s **ring_dsc) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 167 | { |
| 168 | struct PVSCSICmdDescSetupRings cmd = {0,}; |
| 169 | |
Liran Alon | 628b2e6 | 2018-11-13 17:53:40 +0200 | [diff] [blame] | 170 | struct pvscsi_ring_dsc_s *dsc = malloc_high(sizeof(*dsc)); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 171 | if (!dsc) { |
| 172 | warn_noalloc(); |
| 173 | return; |
| 174 | } |
| 175 | |
| 176 | dsc->ring_state = |
Dana Rubin | 8bc6d9f | 2016-08-04 14:22:31 +0300 | [diff] [blame] | 177 | (struct PVSCSIRingsState *)memalign_high(PAGE_SIZE, PAGE_SIZE); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 178 | dsc->ring_reqs = |
Dana Rubin | 8bc6d9f | 2016-08-04 14:22:31 +0300 | [diff] [blame] | 179 | (struct PVSCSIRingReqDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 180 | dsc->ring_cmps = |
Dana Rubin | 8bc6d9f | 2016-08-04 14:22:31 +0300 | [diff] [blame] | 181 | (struct PVSCSIRingCmpDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 182 | if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) { |
| 183 | warn_noalloc(); |
| 184 | return; |
| 185 | } |
| 186 | memset(dsc->ring_state, 0, PAGE_SIZE); |
| 187 | memset(dsc->ring_reqs, 0, PAGE_SIZE); |
| 188 | memset(dsc->ring_cmps, 0, PAGE_SIZE); |
| 189 | |
| 190 | cmd.reqRingNumPages = 1; |
| 191 | cmd.cmpRingNumPages = 1; |
| 192 | cmd.ringsStatePPN = virt_to_phys(dsc->ring_state) >> PAGE_SHIFT; |
| 193 | cmd.reqRingPPNs[0] = virt_to_phys(dsc->ring_reqs) >> PAGE_SHIFT; |
| 194 | cmd.cmpRingPPNs[0] = virt_to_phys(dsc->ring_cmps) >> PAGE_SHIFT; |
| 195 | |
| 196 | pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS, |
| 197 | &cmd, sizeof(cmd)); |
| 198 | *ring_dsc = dsc; |
| 199 | } |
| 200 | |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 201 | static u32 |
| 202 | pvscsi_get_rsp(struct PVSCSIRingsState *s, |
| 203 | struct PVSCSIRingCmpDesc *rsp) |
| 204 | { |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 205 | u32 status = rsp->hostStatus; |
| 206 | s->cmpConsIdx = s->cmpConsIdx + 1; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 207 | return status; |
| 208 | } |
| 209 | |
Kevin O'Connor | 2dd0832 | 2015-07-07 12:35:34 -0400 | [diff] [blame] | 210 | int |
| 211 | pvscsi_process_op(struct disk_op_s *op) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 212 | { |
Kevin O'Connor | 2dd0832 | 2015-07-07 12:35:34 -0400 | [diff] [blame] | 213 | if (!CONFIG_PVSCSI) |
| 214 | return DISK_RET_EBADTRACK; |
| 215 | struct pvscsi_lun_s *plun = |
Kevin O'Connor | e5a0b61 | 2017-07-11 12:24:50 -0400 | [diff] [blame] | 216 | container_of(op->drive_fl, struct pvscsi_lun_s, drive); |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 217 | struct pvscsi_ring_dsc_s *ring_dsc = plun->ring_dsc; |
| 218 | struct PVSCSIRingsState *s = ring_dsc->ring_state; |
| 219 | u32 req_entries = s->reqNumEntriesLog2; |
| 220 | u32 cmp_entries = s->cmpNumEntriesLog2; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 221 | struct PVSCSIRingReqDesc *req; |
| 222 | struct PVSCSIRingCmpDesc *rsp; |
| 223 | u32 status; |
| 224 | |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 225 | if (s->reqProdIdx - s->cmpConsIdx >= 1 << req_entries) { |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 226 | dprintf(1, "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n", |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 227 | s->reqProdIdx, s->cmpConsIdx); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 228 | return DISK_RET_EBADTRACK; |
| 229 | } |
| 230 | |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 231 | req = ring_dsc->ring_reqs + (s->reqProdIdx & MASK(req_entries)); |
Kevin O'Connor | 2dd0832 | 2015-07-07 12:35:34 -0400 | [diff] [blame] | 232 | int blocksize = scsi_fill_cmd(op, req->cdb, 16); |
| 233 | if (blocksize < 0) |
| 234 | return default_process_op(op); |
Kevin O'Connor | 113f5d2 | 2015-07-07 12:24:50 -0400 | [diff] [blame] | 235 | req->bus = 0; |
Kevin O'Connor | 2dd0832 | 2015-07-07 12:35:34 -0400 | [diff] [blame] | 236 | req->target = plun->target; |
Kevin O'Connor | 113f5d2 | 2015-07-07 12:24:50 -0400 | [diff] [blame] | 237 | memset(req->lun, 0, sizeof(req->lun)); |
Kevin O'Connor | 2dd0832 | 2015-07-07 12:35:34 -0400 | [diff] [blame] | 238 | req->lun[1] = plun->lun; |
Kevin O'Connor | 113f5d2 | 2015-07-07 12:24:50 -0400 | [diff] [blame] | 239 | req->senseLen = 0; |
| 240 | req->senseAddr = 0; |
| 241 | req->cdbLen = 16; |
| 242 | req->vcpuHint = 0; |
Kevin O'Connor | 113f5d2 | 2015-07-07 12:24:50 -0400 | [diff] [blame] | 243 | req->tag = SIMPLE_QUEUE_TAG; |
Kevin O'Connor | 5dcd1ee | 2015-07-07 14:43:01 -0400 | [diff] [blame] | 244 | req->flags = scsi_is_read(op) ? |
Kevin O'Connor | 113f5d2 | 2015-07-07 12:24:50 -0400 | [diff] [blame] | 245 | PVSCSI_FLAG_CMD_DIR_TOHOST : PVSCSI_FLAG_CMD_DIR_TODEVICE; |
| 246 | req->dataLen = op->count * blocksize; |
| 247 | req->dataAddr = (u32)op->buf_fl; |
| 248 | s->reqProdIdx = s->reqProdIdx + 1; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 249 | |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 250 | pvscsi_kick_rw_io(plun->iobase); |
| 251 | pvscsi_wait_intr_cmpl(plun->iobase); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 252 | |
Kevin O'Connor | 60f3b80 | 2013-12-27 12:08:50 -0500 | [diff] [blame] | 253 | rsp = ring_dsc->ring_cmps + (s->cmpConsIdx & MASK(cmp_entries)); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 254 | status = pvscsi_get_rsp(s, rsp); |
| 255 | |
| 256 | return status == 0 ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK; |
| 257 | } |
| 258 | |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 259 | static int |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 260 | pvscsi_add_lun(struct pci_device *pci, void *iobase, |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 261 | struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun) |
| 262 | { |
| 263 | struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun)); |
| 264 | if (!plun) { |
| 265 | warn_noalloc(); |
| 266 | return -1; |
| 267 | } |
| 268 | memset(plun, 0, sizeof(*plun)); |
| 269 | plun->drive.type = DTYPE_PVSCSI; |
| 270 | plun->drive.cntl_id = pci->bdf; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 271 | plun->target = target; |
| 272 | plun->lun = lun; |
| 273 | plun->iobase = iobase; |
| 274 | plun->ring_dsc = ring_dsc; |
| 275 | |
Kevin O'Connor | 937ca6f | 2016-02-03 03:27:36 -0500 | [diff] [blame] | 276 | char *name = znprintf(MAXDESCSIZE, "pvscsi %pP %d:%d", pci, target, lun); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 277 | int prio = bootprio_find_scsi_device(pci, target, lun); |
| 278 | int ret = scsi_drive_setup(&plun->drive, name, prio); |
| 279 | free(name); |
| 280 | if (ret) |
| 281 | goto fail; |
| 282 | return 0; |
| 283 | |
| 284 | fail: |
| 285 | free(plun); |
| 286 | return -1; |
| 287 | } |
| 288 | |
| 289 | static void |
Kevin O'Connor | 4b400a1 | 2013-12-24 00:46:15 -0500 | [diff] [blame] | 290 | pvscsi_scan_target(struct pci_device *pci, void *iobase, |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 291 | struct pvscsi_ring_dsc_s *ring_dsc, u8 target) |
| 292 | { |
Roman Kagan | 0a6e0a8 | 2017-04-26 17:18:06 +0300 | [diff] [blame] | 293 | /* pvscsi has no more than a single lun per target */ |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 294 | pvscsi_add_lun(pci, iobase, ring_dsc, target, 0); |
| 295 | } |
| 296 | |
| 297 | static void |
Kevin O'Connor | 79bafa1 | 2016-04-05 13:04:07 -0400 | [diff] [blame] | 298 | init_pvscsi(void *data) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 299 | { |
Kevin O'Connor | 79bafa1 | 2016-04-05 13:04:07 -0400 | [diff] [blame] | 300 | struct pci_device *pci = data; |
Kevin O'Connor | 03f3b3e | 2016-02-02 22:21:49 -0500 | [diff] [blame] | 301 | void *iobase = pci_enable_membar(pci, PCI_BASE_ADDRESS_0); |
| 302 | if (!iobase) |
| 303 | return; |
| 304 | pci_enable_busmaster(pci); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 305 | |
Kevin O'Connor | 7b67300 | 2016-02-03 03:03:15 -0500 | [diff] [blame] | 306 | dprintf(1, "found pvscsi at %pP, io @ %p\n", pci, iobase); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 307 | |
| 308 | pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0); |
| 309 | |
Kevin O'Connor | 03f3b3e | 2016-02-02 22:21:49 -0500 | [diff] [blame] | 310 | struct pvscsi_ring_dsc_s *ring_dsc = NULL; |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 311 | pvscsi_init_rings(iobase, &ring_dsc); |
Kevin O'Connor | 03f3b3e | 2016-02-02 22:21:49 -0500 | [diff] [blame] | 312 | int i; |
Shmuel Eiderman | b448032 | 2018-11-01 17:14:42 +0200 | [diff] [blame] | 313 | for (i = 0; i < 64; i++) |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 314 | pvscsi_scan_target(pci, iobase, ring_dsc, i); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | void |
| 318 | pvscsi_setup(void) |
| 319 | { |
| 320 | ASSERT32FLAT(); |
| 321 | if (! CONFIG_PVSCSI) |
| 322 | return; |
| 323 | |
| 324 | dprintf(3, "init pvscsi\n"); |
| 325 | |
| 326 | struct pci_device *pci; |
| 327 | foreachpci(pci) { |
| 328 | if (pci->vendor != PCI_VENDOR_ID_VMWARE |
| 329 | || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI) |
| 330 | continue; |
Kevin O'Connor | 79bafa1 | 2016-04-05 13:04:07 -0400 | [diff] [blame] | 331 | run_thread(init_pvscsi, pci); |
Evgeny Budilovsky | 83d60b3 | 2013-10-14 18:03:36 +0300 | [diff] [blame] | 332 | } |
| 333 | } |