1 /* $NetBSD: hvs.c,v 1.2 2019/10/01 18:00:08 chs Exp $ */ 2 /* $OpenBSD: hvs.c,v 1.17 2017/08/10 17:22:48 mikeb Exp $ */ 3 4 /*- 5 * Copyright (c) 2009-2012,2016 Microsoft Corp. 6 * Copyright (c) 2012 NetApp Inc. 7 * Copyright (c) 2012 Citrix Inc. 8 * Copyright (c) 2017 Mike Belopuhov <mike@esdenera.com> 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice unmodified, this list of conditions, and the following 16 * disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * The OpenBSD port was done under funding by Esdenera Networks GmbH. 35 */ 36 37 /* #define HVS_DEBUG_IO */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: hvs.c,v 1.2 2019/10/01 18:00:08 chs Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/device.h> 46 #include <sys/buf.h> 47 #include <sys/bus.h> 48 #include <sys/kmem.h> 49 #include <sys/mutex.h> 50 51 #include <uvm/uvm_extern.h> 52 53 #include <dev/hyperv/vmbusvar.h> 54 55 #include <dev/scsipi/scsi_all.h> 56 #include <dev/scsipi/scsiconf.h> 57 #include <dev/scsipi/scsipi_all.h> 58 59 #define HVS_PROTO_VERSION_WIN6 0x200 60 #define HVS_PROTO_VERSION_WIN7 0x402 61 #define HVS_PROTO_VERSION_WIN8 0x501 62 #define HVS_PROTO_VERSION_WIN8_1 0x600 63 #define HVS_PROTO_VERSION_WIN10 0x602 64 65 #define HVS_MSG_IODONE 0x01 66 #define HVS_MSG_DEVGONE 0x02 67 #define HVS_MSG_ENUMERATE 0x0b 68 69 #define HVS_REQ_SCSIIO 0x03 70 #define HVS_REQ_STARTINIT 0x07 71 #define HVS_REQ_FINISHINIT 0x08 72 #define HVS_REQ_QUERYPROTO 0x09 73 #define HVS_REQ_QUERYPROPS 0x0a 74 #define HVS_REQ_CREATEMULTICHANNELS 0x0d 75 76 struct hvs_cmd_hdr { 77 uint32_t hdr_op; 78 uint32_t hdr_flags; 79 uint32_t hdr_status; 80 #define cmd_op cmd_hdr.hdr_op 81 #define cmd_flags cmd_hdr.hdr_flags 82 #define cmd_status cmd_hdr.hdr_status 83 } __packed; 84 85 /* Negotiate version */ 86 struct hvs_cmd_ver { 87 struct hvs_cmd_hdr cmd_hdr; 88 uint16_t cmd_ver; 89 uint16_t cmd_rev; 90 } __packed; 91 92 /* Query channel properties */ 93 struct hvs_chp { 94 uint16_t chp_proto; 95 uint8_t chp_path; 96 uint8_t chp_target; 97 uint16_t chp_maxchan; 98 uint16_t chp_port; 99 uint32_t chp_chflags; 100 #define CHP_CHFLAGS_MULTI_CHANNEL 0x1 101 uint32_t chp_maxfer; 102 uint64_t chp_chanid; 103 } __packed; 104 105 struct hvs_cmd_chp { 106 struct hvs_cmd_hdr cmd_hdr; 107 struct hvs_chp cmd_chp; 108 } __packed; 109 110 #define SENSE_DATA_LEN_WIN7 18 111 #define SENSE_DATA_LEN 20 112 #define MAX_SRB_DATA 20 113 114 /* SCSI Request Block */ 115 struct hvs_srb { 116 uint16_t srb_reqlen; 117 uint8_t srb_iostatus; 118 uint8_t srb_scsistatus; 119 120 uint8_t srb_initiator; 121 uint8_t srb_bus; 122 uint8_t srb_target; 123 uint8_t srb_lun; 124 125 uint8_t srb_cdblen; 126 uint8_t srb_senselen; 127 uint8_t srb_direction; 128 uint8_t _reserved; 129 130 uint32_t srb_datalen; 131 uint8_t srb_data[MAX_SRB_DATA]; 132 } __packed; 133 134 #define SRB_DATA_WRITE 0 135 #define SRB_DATA_READ 1 136 #define SRB_DATA_NONE 2 137 138 #define SRB_STATUS_PENDING 0x00 139 #define SRB_STATUS_SUCCESS 0x01 140 #define SRB_STATUS_ABORTED 0x02 141 #define SRB_STATUS_ERROR 0x04 142 #define SRB_STATUS_INVALID_LUN 0x20 143 #define SRB_STATUS_QUEUE_FROZEN 0x40 144 #define SRB_STATUS_AUTOSENSE_VALID 0x80 145 146 #define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002 147 #define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004 148 #define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008 149 #define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010 150 #define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020 151 #define SRB_FLAGS_DATA_IN 0x00000040 152 #define SRB_FLAGS_DATA_OUT 0x00000080 153 #define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000 154 #define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100 155 #define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200 156 #define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400 157 158 struct hvs_cmd_io { 159 struct hvs_cmd_hdr cmd_hdr; 160 struct hvs_srb cmd_srb; 161 /* Win8 extensions */ 162 uint16_t _reserved; 163 uint8_t cmd_qtag; 164 uint8_t cmd_qaction; 165 uint32_t cmd_srbflags; 166 uint32_t cmd_timeout; 167 uint32_t cmd_qsortkey; 168 } __packed; 169 170 #define HVS_CMD_SIZE 64 171 172 union hvs_cmd { 173 struct hvs_cmd_hdr cmd_hdr; 174 struct hvs_cmd_ver ver; 175 struct hvs_cmd_chp chp; 176 struct hvs_cmd_io io; 177 uint16_t multi_chans_cnt; 178 uint8_t pad[HVS_CMD_SIZE]; 179 } __packed; 180 181 #define HVS_RING_SIZE (20 * PAGE_SIZE) 182 #define HVS_MAX_CCB 128 183 #define HVS_MAX_SGE (MAXPHYS / PAGE_SIZE + 1) 184 185 struct hvs_softc; 186 187 struct hvs_ccb { 188 struct scsipi_xfer *ccb_xfer; /* associated transfer */ 189 union hvs_cmd *ccb_cmd; /* associated command */ 190 union hvs_cmd ccb_rsp; /* response */ 191 bus_dmamap_t ccb_dmap; /* transfer map */ 192 uint64_t ccb_rid; /* request id */ 193 struct vmbus_gpa_range *ccb_sgl; 194 int ccb_nsge; 195 void (*ccb_done)(struct hvs_ccb *); 196 void *ccb_cookie; 197 SIMPLEQ_ENTRY(hvs_ccb) ccb_link; 198 }; 199 SIMPLEQ_HEAD(hvs_ccb_queue, hvs_ccb); 200 201 struct hvs_config; 202 203 struct hvs_softc { 204 device_t sc_dev; 205 bus_dma_tag_t sc_dmat; 206 207 struct vmbus_channel *sc_chan; 208 209 const struct hvs_config *sc_config; 210 211 struct hvs_chp sc_props; 212 213 /* CCBs */ 214 int sc_nccb; 215 struct hvs_ccb *sc_ccbs; 216 struct hvs_ccb_queue sc_ccb_fq; /* free queue */ 217 kmutex_t sc_ccb_fqlck; 218 219 int sc_bus; 220 221 struct scsipi_adapter sc_adapter; 222 struct scsipi_channel sc_channel; 223 device_t sc_scsibus; 224 #if notyet /* XXX subchannel */ 225 u_int sc_nchan; 226 struct vmbus_channel *sc_sel_chan[MAXCPUS]; 227 #endif 228 }; 229 230 static int hvs_match(device_t, cfdata_t, void *); 231 static void hvs_attach(device_t, device_t, void *); 232 static int hvs_detach(device_t, int); 233 234 CFATTACH_DECL_NEW(hvs, sizeof(struct hvs_softc), 235 hvs_match, hvs_attach, hvs_detach, NULL); 236 237 static void hvs_scsipi_request(struct scsipi_channel *, 238 scsipi_adapter_req_t, void *); 239 static void hvs_scsi_cmd_done(struct hvs_ccb *); 240 static int hvs_start(struct hvs_softc *, struct vmbus_channel *, 241 struct hvs_ccb *); 242 static int hvs_poll(struct hvs_softc *, struct vmbus_channel *, 243 struct hvs_ccb *); 244 static void hvs_poll_done(struct hvs_ccb *); 245 static void hvs_intr(void *); 246 static void hvs_scsi_probe(void *arg); 247 static void hvs_scsi_done(struct scsipi_xfer *, int); 248 249 static int hvs_connect(struct hvs_softc *); 250 static void hvs_empty_done(struct hvs_ccb *); 251 252 static int hvs_alloc_ccbs(struct hvs_softc *); 253 static void hvs_free_ccbs(struct hvs_softc *); 254 static struct hvs_ccb * 255 hvs_get_ccb(struct hvs_softc *); 256 static void hvs_put_ccb(struct hvs_softc *, struct hvs_ccb *); 257 258 static const struct hvs_config { 259 uint32_t proto_version; 260 uint16_t reqlen; 261 uint8_t senselen; 262 bool fixup_wrong_response; 263 bool upgrade_spc2_to_spc3; 264 bool use_win8ext_flags; 265 } hvs_config_list[] = { 266 { 267 .proto_version = HVS_PROTO_VERSION_WIN10, 268 .reqlen = sizeof(struct hvs_cmd_io), 269 .senselen = SENSE_DATA_LEN, 270 .fixup_wrong_response = false, 271 .upgrade_spc2_to_spc3 = false, 272 .use_win8ext_flags = true, 273 }, 274 { 275 .proto_version = HVS_PROTO_VERSION_WIN8_1, 276 .reqlen = sizeof(struct hvs_cmd_io), 277 .senselen = SENSE_DATA_LEN, 278 .fixup_wrong_response = true, 279 .upgrade_spc2_to_spc3 = true, 280 .use_win8ext_flags = true, 281 }, 282 { 283 .proto_version = HVS_PROTO_VERSION_WIN8, 284 .reqlen = sizeof(struct hvs_cmd_io), 285 .senselen = SENSE_DATA_LEN, 286 .fixup_wrong_response = true, 287 .upgrade_spc2_to_spc3 = true, 288 .use_win8ext_flags = true, 289 }, 290 { 291 .proto_version = HVS_PROTO_VERSION_WIN7, 292 .reqlen = offsetof(struct hvs_cmd_io, _reserved), 293 .senselen = SENSE_DATA_LEN_WIN7, 294 .fixup_wrong_response = true, 295 .upgrade_spc2_to_spc3 = false, 296 .use_win8ext_flags = false, 297 }, 298 { 299 .proto_version = HVS_PROTO_VERSION_WIN6, 300 .reqlen = offsetof(struct hvs_cmd_io, _reserved), 301 .senselen = SENSE_DATA_LEN_WIN7, 302 .fixup_wrong_response = false, 303 .upgrade_spc2_to_spc3 = false, 304 .use_win8ext_flags = false, 305 }, 306 }; 307 308 #if notyet /* XXX subchannel */ 309 static int hvs_chan_cnt; 310 #endif 311 312 static int 313 hvs_match(device_t parent, cfdata_t cf, void *aux) 314 { 315 struct vmbus_attach_args *aa = aux; 316 317 if (memcmp(aa->aa_type, &hyperv_guid_ide, sizeof(*aa->aa_type)) != 0 && 318 memcmp(aa->aa_type, &hyperv_guid_scsi, sizeof(*aa->aa_type)) != 0) 319 return 0; 320 return 1; 321 } 322 323 static void 324 hvs_attach(device_t parent, device_t self, void *aux) 325 { 326 extern struct cfdata cfdata[]; 327 struct hvs_softc *sc = device_private(self); 328 struct vmbus_attach_args *aa = aux; 329 struct scsipi_adapter *adapt = &sc->sc_adapter; 330 struct scsipi_channel *chan = &sc->sc_channel; 331 const char *bus; 332 bool is_scsi; 333 334 sc->sc_dev = self; 335 sc->sc_chan = aa->aa_chan; 336 sc->sc_dmat = sc->sc_chan->ch_sc->sc_dmat; 337 #if notyet /* XXX subchannel */ 338 sc->sc_nchan = 1; 339 sc->sc_sel_chan[0] = sc->sc_chan; 340 #endif 341 342 if (memcmp(aa->aa_type, &hyperv_guid_scsi, sizeof(*aa->aa_type)) == 0) { 343 is_scsi = true; 344 bus = "SCSI"; 345 } else { 346 is_scsi = false; 347 bus = "IDE"; 348 } 349 350 aprint_naive("\n"); 351 aprint_normal(": Hyper-V StorVSC %s\n", bus); 352 353 if (vmbus_channel_setdeferred(sc->sc_chan, device_xname(self))) { 354 aprint_error_dev(self, 355 "failed to create the interrupt thread\n"); 356 return; 357 } 358 359 if (vmbus_channel_open(sc->sc_chan, HVS_RING_SIZE, &sc->sc_props, 360 sizeof(sc->sc_props), hvs_intr, sc)) { 361 aprint_error_dev(self, "failed to open channel\n"); 362 return; 363 } 364 365 if (hvs_alloc_ccbs(sc)) 366 return; 367 368 if (hvs_connect(sc)) 369 return; 370 371 aprint_normal_dev(self, "protocol %u.%u\n", 372 (sc->sc_config->proto_version >> 8) & 0xff, 373 sc->sc_config->proto_version & 0xff); 374 375 adapt = &sc->sc_adapter; 376 adapt->adapt_dev = self; 377 adapt->adapt_nchannels = 1; 378 adapt->adapt_openings = sc->sc_nccb; 379 adapt->adapt_max_periph = adapt->adapt_openings; 380 adapt->adapt_request = hvs_scsipi_request; 381 adapt->adapt_minphys = minphys; 382 adapt->adapt_flags = SCSIPI_ADAPT_MPSAFE; 383 384 chan = &sc->sc_channel; 385 chan->chan_adapter = adapt; 386 chan->chan_bustype = &scsi_bustype; /* XXX IDE/ATAPI */ 387 chan->chan_channel = 0; 388 chan->chan_ntargets = 2; 389 chan->chan_nluns = is_scsi ? 64 : 1; 390 chan->chan_id = 0; 391 chan->chan_flags = SCSIPI_CHAN_NOSETTLE; 392 chan->chan_defquirks |= PQUIRK_ONLYBIG; 393 394 sc->sc_scsibus = config_found(self, &sc->sc_channel, scsiprint); 395 396 /* 397 * If the driver has successfully attached to an IDE device, 398 * we need to make sure that the same disk is not available to 399 * the system via pciide(4) or piixide(4) causing DUID conflicts 400 * and preventing system from booting. 401 */ 402 if (!is_scsi && sc->sc_scsibus != NULL) { 403 static const char *disable_devices[] = { 404 "wd", 405 }; 406 size_t j; 407 408 for (j = 0; j < __arraycount(disable_devices); j++) { 409 const char *dev = disable_devices[j]; 410 size_t len = strlen(dev); 411 int devno; 412 413 for (devno = 0; cfdata[devno].cf_name != NULL; devno++) { 414 cfdata_t cf = &cfdata[devno]; 415 416 if (strlen(cf->cf_name) != len || 417 strncasecmp(dev, cf->cf_name, len) != 0 || 418 cf->cf_fstate != FSTATE_STAR) 419 continue; 420 421 cf->cf_fstate = FSTATE_DSTAR; 422 } 423 } 424 } 425 } 426 427 static int 428 hvs_detach(device_t self, int flags) 429 { 430 431 /* XXX detach */ 432 433 return 0; 434 } 435 436 #define XS2DMA(xs) \ 437 ((((xs)->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE) | \ 438 (((xs)->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | \ 439 BUS_DMA_STREAMING) 440 441 #define XS2DMAPRE(xs) (((xs)->xs_control & XS_CTL_DATA_IN) ? \ 442 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE) 443 444 #define XS2DMAPOST(xs) (((xs)->xs_control & XS_CTL_DATA_IN) ? \ 445 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE) 446 447 static void 448 hvs_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t request, 449 void *arg) 450 { 451 struct scsipi_adapter *adapt = chan->chan_adapter; 452 struct hvs_softc *sc = device_private(adapt->adapt_dev); 453 struct scsipi_xfer *xs; 454 struct scsipi_xfer_mode *xm; 455 struct scsipi_periph *periph; 456 struct hvs_ccb *ccb; 457 union hvs_cmd cmd; 458 struct hvs_cmd_io *io = &cmd.io; 459 struct hvs_srb *srb = &io->cmd_srb; 460 int i, error; 461 462 switch (request) { 463 default: 464 device_printf(sc->sc_dev, 465 "%s: unhandled request %u\n", __func__, request); 466 return; 467 468 case ADAPTER_REQ_GROW_RESOURCES: 469 /* Not supported. */ 470 return; 471 472 case ADAPTER_REQ_SET_XFER_MODE: 473 xm = arg; 474 xm->xm_mode = PERIPH_CAP_TQING; 475 xm->xm_period = 0; 476 xm->xm_offset = 0; 477 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm); 478 return; 479 480 case ADAPTER_REQ_RUN_XFER: 481 break; 482 } 483 484 xs = arg; 485 486 if (xs->cmdlen > MAX_SRB_DATA) { 487 device_printf(sc->sc_dev, "CDB is too big: %d\n", 488 xs->cmdlen); 489 memset(&xs->sense, 0, sizeof(xs->sense)); 490 xs->sense.scsi_sense.response_code = 491 SSD_RCODE_VALID | SSD_RCODE_CURRENT; 492 xs->sense.scsi_sense.flags = SSD_ILI; 493 xs->sense.scsi_sense.asc = 0x20; 494 hvs_scsi_done(xs, XS_SENSE); 495 return; 496 } 497 498 ccb = hvs_get_ccb(sc); 499 if (ccb == NULL) { 500 device_printf(sc->sc_dev, "failed to allocate ccb\n"); 501 hvs_scsi_done(xs, XS_RESOURCE_SHORTAGE); 502 return; 503 } 504 505 periph = xs->xs_periph; 506 507 memset(&cmd, 0, sizeof(cmd)); 508 509 srb->srb_initiator = chan->chan_id; 510 srb->srb_bus = sc->sc_bus; 511 srb->srb_target = periph->periph_target - 1; 512 srb->srb_lun = periph->periph_lun; 513 srb->srb_cdblen = xs->cmdlen; 514 memcpy(srb->srb_data, xs->cmd, xs->cmdlen); 515 516 if (sc->sc_config->use_win8ext_flags) { 517 io->cmd_timeout = 60; 518 SET(io->cmd_srbflags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); 519 } 520 521 switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) { 522 case XS_CTL_DATA_IN: 523 srb->srb_direction = SRB_DATA_READ; 524 if (sc->sc_config->use_win8ext_flags) 525 SET(io->cmd_srbflags, SRB_FLAGS_DATA_IN); 526 break; 527 case XS_CTL_DATA_OUT: 528 srb->srb_direction = SRB_DATA_WRITE; 529 if (sc->sc_config->use_win8ext_flags) 530 SET(io->cmd_srbflags, SRB_FLAGS_DATA_OUT); 531 break; 532 default: 533 srb->srb_direction = SRB_DATA_NONE; 534 if (sc->sc_config->use_win8ext_flags) 535 SET(io->cmd_srbflags, SRB_FLAGS_NO_DATA_TRANSFER); 536 break; 537 } 538 539 srb->srb_datalen = xs->datalen; 540 srb->srb_reqlen = sc->sc_config->reqlen; 541 srb->srb_senselen = sc->sc_config->senselen; 542 543 cmd.cmd_op = HVS_REQ_SCSIIO; 544 cmd.cmd_flags = VMBUS_CHANPKT_FLAG_RC; 545 546 if (xs->datalen > 0) { 547 error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmap, xs->data, 548 xs->datalen, NULL, XS2DMA(xs)); 549 if (error) { 550 device_printf(sc->sc_dev, 551 "failed to load %d bytes (%d)\n", xs->datalen, 552 error); 553 hvs_put_ccb(sc, ccb); 554 hvs_scsi_done(xs, (error == ENOMEM || error == EAGAIN) ? 555 XS_RESOURCE_SHORTAGE : XS_DRIVER_STUFFUP); 556 return; 557 } 558 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmap, 0, xs->datalen, 559 XS2DMAPRE(xs)); 560 561 ccb->ccb_sgl->gpa_len = xs->datalen; 562 ccb->ccb_sgl->gpa_ofs = (vaddr_t)xs->data & PAGE_MASK; 563 for (i = 0; i < ccb->ccb_dmap->dm_nsegs; i++) 564 ccb->ccb_sgl->gpa_page[i] = 565 atop(ccb->ccb_dmap->dm_segs[i].ds_addr); 566 ccb->ccb_nsge = ccb->ccb_dmap->dm_nsegs; 567 } else 568 ccb->ccb_nsge = 0; 569 570 ccb->ccb_xfer = xs; 571 ccb->ccb_cmd = &cmd; 572 ccb->ccb_done = hvs_scsi_cmd_done; 573 574 #ifdef HVS_DEBUG_IO 575 printf("%s: %u.%u: rid %"PRIu64" opcode %#x control %#x datalen %d\n", 576 device_xname(sc->sc_dev), periph->periph_target, periph->periph_lun, 577 ccb->ccb_rid, xs->cmd->opcode, xs->xs_control, xs->datalen); 578 #endif 579 580 if (xs->xs_control & XS_CTL_POLL) 581 error = hvs_poll(sc, sc->sc_chan, ccb); 582 else 583 error = hvs_start(sc, sc->sc_chan, ccb); 584 if (error) { 585 hvs_put_ccb(sc, ccb); 586 hvs_scsi_done(xs, (error == ENOMEM || error == EAGAIN) ? 587 XS_RESOURCE_SHORTAGE : XS_DRIVER_STUFFUP); 588 } 589 } 590 591 static int 592 hvs_start(struct hvs_softc *sc, struct vmbus_channel *chan, struct hvs_ccb *ccb) 593 { 594 union hvs_cmd *cmd = ccb->ccb_cmd; 595 int error; 596 597 ccb->ccb_cmd = NULL; 598 599 if (ccb->ccb_nsge > 0) { 600 error = vmbus_channel_send_prpl(chan, ccb->ccb_sgl, 601 ccb->ccb_nsge, cmd, HVS_CMD_SIZE, ccb->ccb_rid); 602 if (error) { 603 device_printf(sc->sc_dev, 604 "failed to submit operation %x via prpl\n", 605 cmd->cmd_op); 606 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmap); 607 } 608 } else { 609 error = vmbus_channel_send(chan, cmd, HVS_CMD_SIZE, 610 ccb->ccb_rid, VMBUS_CHANPKT_TYPE_INBAND, 611 VMBUS_CHANPKT_FLAG_RC); 612 if (error) 613 device_printf(sc->sc_dev, 614 "failed to submit operation %x\n", cmd->cmd_op); 615 } 616 617 return error; 618 } 619 620 static void 621 hvs_poll_done(struct hvs_ccb *ccb) 622 { 623 int *rv = ccb->ccb_cookie; 624 625 if (ccb->ccb_cmd) { 626 memcpy(&ccb->ccb_rsp, ccb->ccb_cmd, HVS_CMD_SIZE); 627 ccb->ccb_cmd = &ccb->ccb_rsp; 628 } else 629 memset(&ccb->ccb_rsp, 0, HVS_CMD_SIZE); 630 631 *rv = 0; 632 } 633 634 static int 635 hvs_poll(struct hvs_softc *sc, struct vmbus_channel *chan, struct hvs_ccb *ccb) 636 { 637 void (*done)(struct hvs_ccb *); 638 void *cookie; 639 int s, rv = 1; 640 641 done = ccb->ccb_done; 642 cookie = ccb->ccb_cookie; 643 644 ccb->ccb_done = hvs_poll_done; 645 ccb->ccb_cookie = &rv; 646 647 if (hvs_start(sc, chan, ccb)) { 648 ccb->ccb_cookie = cookie; 649 ccb->ccb_done = done; 650 return -1; 651 } 652 653 while (rv == 1) { 654 delay(10); 655 s = splbio(); 656 hvs_intr(sc); 657 splx(s); 658 } 659 660 ccb->ccb_cookie = cookie; 661 ccb->ccb_done = done; 662 ccb->ccb_done(ccb); 663 664 return 0; 665 } 666 667 static void 668 hvs_intr(void *xsc) 669 { 670 struct hvs_softc *sc = xsc; 671 struct hvs_ccb *ccb; 672 union hvs_cmd cmd; 673 uint64_t rid; 674 uint32_t rlen; 675 int error; 676 677 for (;;) { 678 error = vmbus_channel_recv(sc->sc_chan, &cmd, sizeof(cmd), 679 &rlen, &rid, 0); 680 switch (error) { 681 case 0: 682 break; 683 case EAGAIN: 684 /* No more messages to process */ 685 return; 686 default: 687 device_printf(sc->sc_dev, 688 "error %d while receiving a reply\n", error); 689 return; 690 } 691 if (rlen != sizeof(cmd)) { 692 device_printf(sc->sc_dev, "short read: %u\n", rlen); 693 return; 694 } 695 696 #ifdef HVS_DEBUG_IO 697 printf("%s: rid %"PRIu64" operation %u flags %#x status %#x\n", 698 device_xname(sc->sc_dev), rid, cmd.cmd_op, cmd.cmd_flags, 699 cmd.cmd_status); 700 #endif 701 702 switch (cmd.cmd_op) { 703 case HVS_MSG_IODONE: 704 if (rid >= sc->sc_nccb) { 705 device_printf(sc->sc_dev, 706 "invalid response %#"PRIx64"\n", rid); 707 continue; 708 } 709 ccb = &sc->sc_ccbs[rid]; 710 ccb->ccb_cmd = &cmd; 711 ccb->ccb_done(ccb); 712 break; 713 case HVS_MSG_ENUMERATE: 714 hvs_scsi_probe(sc); 715 break; 716 default: 717 device_printf(sc->sc_dev, 718 "operation %u is not implemented\n", cmd.cmd_op); 719 break; 720 } 721 } 722 } 723 724 static int 725 is_inquiry_valid(struct scsipi_inquiry_data *inq) 726 { 727 728 if ((inq->device & SID_TYPE) == T_NODEVICE) 729 return 0; 730 if ((inq->device & SID_QUAL) == SID_QUAL_LU_NOT_SUPP) 731 return 0; 732 return 1; 733 } 734 735 static void 736 fixup_inquiry(struct scsipi_xfer *xs, struct hvs_srb *srb) 737 { 738 struct scsipi_periph *periph = xs->xs_periph; 739 struct scsipi_channel *chan = periph->periph_channel; 740 struct scsipi_adapter *adapt = chan->chan_adapter; 741 struct hvs_softc *sc = device_private(adapt->adapt_dev); 742 struct scsipi_inquiry_data *inq = (void *)xs->data; 743 int datalen, resplen; 744 char vendor[8]; 745 746 resplen = srb->srb_datalen >= 5 ? inq->additional_length + 5 : 0; 747 datalen = MIN(resplen, srb->srb_datalen); 748 749 /* Fixup wrong response from WS2012 */ 750 if (sc->sc_config->fixup_wrong_response && 751 !is_inquiry_valid(inq) && datalen >= 4 && 752 (inq->version == 0 || inq->response_format == 0)) { 753 inq->version = 0x05; /* SPC-3 */ 754 inq->response_format = SID_FORMAT_ISO; 755 } else if (datalen >= SCSIPI_INQUIRY_LENGTH_SCSI2) { 756 /* 757 * Upgrade SPC2 to SPC3 if host is Win8 or WS2012 R2 758 * to support UNMAP feature. 759 */ 760 strnvisx(vendor, sizeof(vendor), inq->vendor, sizeof(vendor), 761 VIS_TRIM|VIS_SAFE|VIS_OCTAL); 762 if (sc->sc_config->upgrade_spc2_to_spc3 && 763 (inq->version & SID_ANSII) == 0x04 /* SPC-2 */ && 764 !strncmp(vendor, "Msft", 4)) 765 inq->version = 0x05; /* SPC-3 */ 766 } 767 } 768 769 static void 770 hvs_scsi_cmd_done(struct hvs_ccb *ccb) 771 { 772 struct scsipi_xfer *xs = ccb->ccb_xfer; 773 struct scsipi_periph *periph = xs->xs_periph; 774 struct scsipi_channel *chan = periph->periph_channel; 775 struct scsipi_adapter *adapt = chan->chan_adapter; 776 struct hvs_softc *sc = device_private(adapt->adapt_dev); 777 union hvs_cmd *cmd = ccb->ccb_cmd; 778 struct hvs_srb *srb; 779 bus_dmamap_t map; 780 int error; 781 782 map = ccb->ccb_dmap; 783 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, XS2DMAPOST(xs)); 784 bus_dmamap_unload(sc->sc_dmat, map); 785 786 xs = ccb->ccb_xfer; 787 srb = &cmd->io.cmd_srb; 788 789 xs->status = srb->srb_scsistatus & 0xff; 790 791 switch (xs->status) { 792 case SCSI_OK: 793 if ((srb->srb_iostatus & ~(SRB_STATUS_AUTOSENSE_VALID | 794 SRB_STATUS_QUEUE_FROZEN)) != SRB_STATUS_SUCCESS) 795 error = XS_SELTIMEOUT; 796 else 797 error = XS_NOERROR; 798 break; 799 case SCSI_BUSY: 800 case SCSI_QUEUE_FULL: 801 device_printf(sc->sc_dev, "status %#x iostatus %#x (busy)\n", 802 srb->srb_scsistatus, srb->srb_iostatus); 803 error = XS_BUSY; 804 break; 805 case SCSI_CHECK: 806 if (srb->srb_iostatus & SRB_STATUS_AUTOSENSE_VALID) { 807 memcpy(&xs->sense, srb->srb_data, 808 MIN(sizeof(xs->sense), srb->srb_senselen)); 809 error = XS_SENSE; 810 break; 811 } 812 /* FALLTHROUGH */ 813 default: 814 error = XS_DRIVER_STUFFUP; 815 break; 816 } 817 818 if (error == XS_NOERROR) { 819 if (xs->cmd->opcode == INQUIRY) 820 fixup_inquiry(xs, srb); 821 else if (srb->srb_direction != SRB_DATA_NONE) 822 xs->resid = xs->datalen - srb->srb_datalen; 823 } 824 825 hvs_put_ccb(sc, ccb); 826 hvs_scsi_done(xs, error); 827 } 828 829 static void 830 hvs_scsi_probe(void *arg) 831 { 832 struct hvs_softc *sc = arg; 833 834 if (sc->sc_scsibus != NULL) 835 scsi_probe_bus((void *)sc->sc_scsibus, -1, -1); 836 } 837 838 static void 839 hvs_scsi_done(struct scsipi_xfer *xs, int error) 840 { 841 842 xs->error = error; 843 scsipi_done(xs); 844 } 845 846 static int 847 hvs_connect(struct hvs_softc *sc) 848 { 849 union hvs_cmd ucmd; 850 struct hvs_cmd_ver *cmd; 851 struct hvs_chp *chp; 852 struct hvs_ccb *ccb; 853 #if notyet /* XXX subchannel */ 854 struct vmbus_softc *vsc; 855 struct vmbus_channel **subchan; 856 uint32_t version; 857 uint16_t max_subch, req_subch; 858 bool support_multichannel = false; 859 #endif 860 int i; 861 862 ccb = hvs_get_ccb(sc); 863 if (ccb == NULL) { 864 aprint_error_dev(sc->sc_dev, "failed to allocate ccb\n"); 865 return -1; 866 } 867 868 ccb->ccb_done = hvs_empty_done; 869 870 cmd = (struct hvs_cmd_ver *)&ucmd; 871 872 /* 873 * Begin initialization 874 */ 875 876 memset(&ucmd, 0, sizeof(ucmd)); 877 878 cmd->cmd_op = HVS_REQ_STARTINIT; 879 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 880 881 ccb->ccb_cmd = &ucmd; 882 if (hvs_poll(sc, sc->sc_chan, ccb)) { 883 aprint_error_dev(sc->sc_dev, 884 "failed to send initialization command\n"); 885 goto error; 886 } 887 if (ccb->ccb_rsp.cmd_status != 0) { 888 aprint_error_dev(sc->sc_dev, 889 "failed to initialize, status %#x\n", 890 ccb->ccb_rsp.cmd_status); 891 goto error; 892 } 893 894 /* 895 * Negotiate protocol version 896 */ 897 898 memset(&ucmd, 0, sizeof(ucmd)); 899 900 cmd->cmd_op = HVS_REQ_QUERYPROTO; 901 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 902 903 for (i = 0; i < __arraycount(hvs_config_list); i++) { 904 cmd->cmd_ver = hvs_config_list[i].proto_version; 905 906 ccb->ccb_cmd = &ucmd; 907 if (hvs_poll(sc, sc->sc_chan, ccb)) { 908 aprint_error_dev(sc->sc_dev, 909 "failed to send protocol query\n"); 910 goto error; 911 } 912 if (ccb->ccb_rsp.cmd_status == 0) { 913 sc->sc_config = &hvs_config_list[i]; 914 break; 915 } 916 } 917 if (sc->sc_config == NULL) { 918 aprint_error_dev(sc->sc_dev, 919 "failed to negotiate protocol version\n"); 920 goto error; 921 } 922 923 /* 924 * Query channel properties 925 */ 926 927 memset(&ucmd, 0, sizeof(ucmd)); 928 929 cmd->cmd_op = HVS_REQ_QUERYPROPS; 930 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 931 932 ccb->ccb_cmd = &ucmd; 933 if (hvs_poll(sc, sc->sc_chan, ccb)) { 934 aprint_error_dev(sc->sc_dev, 935 "failed to send channel properties query\n"); 936 goto error; 937 } 938 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 939 ccb->ccb_rsp.cmd_status != 0) { 940 aprint_error_dev(sc->sc_dev, 941 "failed to obtain channel properties, status %#x\n", 942 ccb->ccb_rsp.cmd_status); 943 goto error; 944 } 945 chp = &ccb->ccb_rsp.chp.cmd_chp; 946 947 DPRINTF("%s: proto %#x path %u target %u maxchan %u port %u " 948 "chflags %#x maxfer %u chanid %#"PRIx64"\n", 949 device_xname(sc->sc_dev), chp->chp_proto, chp->chp_path, 950 chp->chp_target, chp->chp_maxchan, chp->chp_port, 951 chp->chp_chflags, chp->chp_maxfer, chp->chp_chanid); 952 953 #if notyet /* XXX subchannel */ 954 max_subch = chp->chp_maxchan; 955 if (hvs_chan_cnt > 0 && hvs_chan_cnt < (max_subch + 1)) 956 max_subch = hvs_chan_cnt - 1; 957 958 /* multi-channels feature is supported by WIN8 and above version */ 959 version = sc->sc_chan->ch_sc->sc_proto; 960 if (version != VMBUS_VERSION_WIN7 && version != VMBUS_VERSION_WS2008 && 961 ISSET(chp->chp_chflags, CHP_CHFLAGS_MULTI_CHANNEL)) 962 support_multichannel = true; 963 #endif 964 965 /* XXX */ 966 sc->sc_bus = chp->chp_path; 967 sc->sc_channel.chan_id = chp->chp_target; 968 969 /* 970 * Finish initialization 971 */ 972 973 memset(&ucmd, 0, sizeof(ucmd)); 974 975 cmd->cmd_op = HVS_REQ_FINISHINIT; 976 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 977 978 ccb->ccb_cmd = &ucmd; 979 if (hvs_poll(sc, sc->sc_chan, ccb)) { 980 aprint_error_dev(sc->sc_dev, 981 "failed to send initialization finish\n"); 982 goto error; 983 } 984 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 985 ccb->ccb_rsp.cmd_status != 0) { 986 aprint_error_dev(sc->sc_dev, 987 "failed to finish initialization, status %#x\n", 988 ccb->ccb_rsp.cmd_status); 989 goto error; 990 } 991 992 #if notyet /* XXX subchannel */ 993 if (support_multichannel && max_subch > 0 && ncpu > 1) { 994 req_subch = MIN(max_subch, ncpu - 1); 995 996 memset(&ucmd, 0, sizeof(ucmd)); 997 998 cmd->cmd_op = HVS_REQ_CREATEMULTICHANNELS; 999 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 1000 cmd->u.multi_chans_cnt = req_subch; 1001 1002 ccb->ccb_cmd = &ucmd; 1003 if (hvs_poll(sc, sc->sc_chan, ccb)) { 1004 aprint_error_dev(sc->sc_dev, 1005 "failed to send create multi-channel\n"); 1006 goto out; 1007 } 1008 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 1009 ccb->ccb_rsp.cmd_status != 0) { 1010 aprint_error_dev(sc->sc_dev, 1011 "failed to create multi-channel, status %#x\n", 1012 ccb->ccb_rsp.cmd_status); 1013 goto out; 1014 } 1015 1016 sc->sc_nchan = req_subch + 1; 1017 subchan = vmbus_subchan_get(sc->sc_chan, req_subch); 1018 for (i = 0; i < req_subch; i++) 1019 hsv_subchan_attach(sc, subchan[i]); 1020 vmbus_subchan_rel(subchan, req_subch); 1021 aprint_normal_dev(sc->sc_dev, "using %u channels\n", 1022 sc->sc_nchan); 1023 } 1024 out: 1025 #endif 1026 hvs_put_ccb(sc, ccb); 1027 return 0; 1028 1029 error: 1030 hvs_put_ccb(sc, ccb); 1031 return -1; 1032 } 1033 1034 static void 1035 hvs_empty_done(struct hvs_ccb *ccb) 1036 { 1037 /* nothing */ 1038 } 1039 1040 static int 1041 hvs_alloc_ccbs(struct hvs_softc *sc) 1042 { 1043 const int dmaflags = cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 1044 int i, error; 1045 1046 SIMPLEQ_INIT(&sc->sc_ccb_fq); 1047 mutex_init(&sc->sc_ccb_fqlck, MUTEX_DEFAULT, IPL_BIO); 1048 1049 sc->sc_nccb = HVS_MAX_CCB; 1050 sc->sc_ccbs = kmem_zalloc(sc->sc_nccb * sizeof(struct hvs_ccb), 1051 KM_SLEEP); 1052 1053 for (i = 0; i < sc->sc_nccb; i++) { 1054 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, HVS_MAX_SGE, 1055 PAGE_SIZE, PAGE_SIZE, dmaflags, &sc->sc_ccbs[i].ccb_dmap); 1056 if (error) { 1057 aprint_error_dev(sc->sc_dev, 1058 "failed to create a CCB memory map (%d)\n", error); 1059 goto errout; 1060 } 1061 1062 sc->sc_ccbs[i].ccb_sgl = kmem_zalloc( 1063 sizeof(struct vmbus_gpa_range) * (HVS_MAX_SGE + 1), 1064 KM_SLEEP); 1065 sc->sc_ccbs[i].ccb_rid = i; 1066 hvs_put_ccb(sc, &sc->sc_ccbs[i]); 1067 } 1068 1069 return 0; 1070 1071 errout: 1072 hvs_free_ccbs(sc); 1073 return -1; 1074 } 1075 1076 static void 1077 hvs_free_ccbs(struct hvs_softc *sc) 1078 { 1079 struct hvs_ccb *ccb; 1080 int i; 1081 1082 for (i = 0; i < sc->sc_nccb; i++) { 1083 ccb = &sc->sc_ccbs[i]; 1084 if (ccb->ccb_dmap == NULL) 1085 continue; 1086 1087 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmap, 0, 0, 1088 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1089 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmap); 1090 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmap); 1091 1092 kmem_free(ccb->ccb_sgl, 1093 sizeof(struct vmbus_gpa_range) * (HVS_MAX_SGE + 1)); 1094 } 1095 1096 kmem_free(sc->sc_ccbs, sc->sc_nccb * sizeof(struct hvs_ccb)); 1097 sc->sc_ccbs = NULL; 1098 sc->sc_nccb = 0; 1099 } 1100 1101 static struct hvs_ccb * 1102 hvs_get_ccb(struct hvs_softc *sc) 1103 { 1104 struct hvs_ccb *ccb; 1105 1106 mutex_enter(&sc->sc_ccb_fqlck); 1107 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_fq); 1108 if (ccb != NULL) 1109 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_fq, ccb_link); 1110 mutex_exit(&sc->sc_ccb_fqlck); 1111 1112 return ccb; 1113 } 1114 1115 static void 1116 hvs_put_ccb(struct hvs_softc *sc, struct hvs_ccb *ccb) 1117 { 1118 1119 ccb->ccb_cmd = NULL; 1120 ccb->ccb_xfer = NULL; 1121 ccb->ccb_done = NULL; 1122 ccb->ccb_cookie = NULL; 1123 ccb->ccb_nsge = 0; 1124 1125 mutex_enter(&sc->sc_ccb_fqlck); 1126 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_fq, ccb, ccb_link); 1127 mutex_exit(&sc->sc_ccb_fqlck); 1128 } 1129