1 /*- 2 * Copyright (c) 2009-2012,2016 Microsoft Corp. 3 * Copyright (c) 2012 NetApp Inc. 4 * Copyright (c) 2012 Citrix Inc. 5 * Copyright (c) 2017 Mike Belopuhov <mike@esdenera.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * The OpenBSD port was done under funding by Esdenera Networks GmbH. 32 */ 33 34 /* #define HVS_DEBUG_IO */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/atomic.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 #include <sys/task.h> 42 43 #include <machine/bus.h> 44 45 #include <uvm/uvm_extern.h> 46 47 #include <dev/pv/hypervreg.h> 48 #include <dev/pv/hypervvar.h> 49 50 #include <scsi/scsi_all.h> 51 #include <scsi/scsiconf.h> 52 53 #define HVS_PROTO_VERSION_WIN6 0x200 54 #define HVS_PROTO_VERSION_WIN7 0x402 55 #define HVS_PROTO_VERSION_WIN8 0x501 56 #define HVS_PROTO_VERSION_WIN8_1 0x600 57 #define HVS_PROTO_VERSION_WIN10 0x602 58 59 #define HVS_MSG_IODONE 0x01 60 #define HVS_MSG_DEVGONE 0x02 61 #define HVS_MSG_ENUMERATE 0x0b 62 63 #define HVS_REQ_SCSIIO 0x03 64 #define HVS_REQ_STARTINIT 0x07 65 #define HVS_REQ_FINISHINIT 0x08 66 #define HVS_REQ_QUERYPROTO 0x09 67 #define HVS_REQ_QUERYPROPS 0x0a 68 69 struct hvs_cmd_hdr { 70 uint32_t hdr_op; 71 uint32_t hdr_flags; 72 uint32_t hdr_status; 73 #define cmd_op cmd_hdr.hdr_op 74 #define cmd_flags cmd_hdr.hdr_flags 75 #define cmd_status cmd_hdr.hdr_status 76 } __packed; 77 78 /* Negotiate version */ 79 struct hvs_cmd_ver { 80 struct hvs_cmd_hdr cmd_hdr; 81 uint16_t cmd_ver; 82 uint16_t cmd_rev; 83 } __packed; 84 85 /* Query channel properties */ 86 struct hvs_chp { 87 uint16_t chp_proto; 88 uint8_t chp_path; 89 uint8_t chp_target; 90 uint16_t chp_maxchan; 91 uint16_t chp_port; 92 uint32_t chp_chflags; 93 uint32_t chp_maxfer; 94 uint64_t chp_chanid; 95 } __packed; 96 97 struct hvs_cmd_chp { 98 struct hvs_cmd_hdr cmd_hdr; 99 struct hvs_chp cmd_chp; 100 } __packed; 101 102 #define SENSE_DATA_LEN_WIN7 18 103 #define SENSE_DATA_LEN 20 104 #define MAX_SRB_DATA 20 105 106 /* SCSI Request Block */ 107 struct hvs_srb { 108 uint16_t srb_reqlen; 109 uint8_t srb_iostatus; 110 uint8_t srb_scsistatus; 111 112 uint8_t srb_initiator; 113 uint8_t srb_bus; 114 uint8_t srb_target; 115 uint8_t srb_lun; 116 117 uint8_t srb_cdblen; 118 uint8_t srb_senselen; 119 uint8_t srb_direction; 120 uint8_t _reserved; 121 122 uint32_t srb_datalen; 123 uint8_t srb_data[MAX_SRB_DATA]; 124 } __packed; 125 126 #define SRB_DATA_WRITE 0 127 #define SRB_DATA_READ 1 128 #define SRB_DATA_NONE 2 129 130 #define SRB_STATUS_PENDING 0x00 131 #define SRB_STATUS_SUCCESS 0x01 132 #define SRB_STATUS_ABORTED 0x02 133 #define SRB_STATUS_ERROR 0x04 134 #define SRB_STATUS_INVALID_LUN 0x20 135 #define SRB_STATUS_QUEUE_FROZEN 0x40 136 #define SRB_STATUS_AUTOSENSE_VALID 0x80 137 138 #define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002 139 #define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004 140 #define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008 141 #define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010 142 #define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020 143 #define SRB_FLAGS_DATA_IN 0x00000040 144 #define SRB_FLAGS_DATA_OUT 0x00000080 145 #define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000 146 #define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100 147 #define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200 148 #define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400 149 150 struct hvs_cmd_io { 151 struct hvs_cmd_hdr cmd_hdr; 152 struct hvs_srb cmd_srb; 153 /* Win8 extensions */ 154 uint16_t _reserved; 155 uint8_t cmd_qtag; 156 uint8_t cmd_qaction; 157 uint32_t cmd_srbflags; 158 uint32_t cmd_timeout; 159 uint32_t cmd_qsortkey; 160 } __packed; 161 162 #define HVS_CMD_SIZE 64 163 164 union hvs_cmd { 165 struct hvs_cmd_hdr cmd_hdr; 166 struct hvs_cmd_ver ver; 167 struct hvs_cmd_chp chp; 168 struct hvs_cmd_io io; 169 uint8_t pad[HVS_CMD_SIZE]; 170 } __packed; 171 172 #define HVS_RING_SIZE (20 * PAGE_SIZE) 173 #define HVS_MAX_CCB 128 174 #define HVS_MAX_SGE (MAXPHYS / PAGE_SIZE + 1) 175 176 struct hvs_softc; 177 178 struct hvs_ccb { 179 struct scsi_xfer *ccb_xfer; /* associated transfer */ 180 union hvs_cmd *ccb_cmd; /* associated command */ 181 union hvs_cmd ccb_rsp; /* response */ 182 bus_dmamap_t ccb_dmap; /* transfer map */ 183 uint64_t ccb_rid; /* request id */ 184 struct vmbus_gpa_range *ccb_sgl; 185 int ccb_nsge; 186 void (*ccb_done)(struct hvs_ccb *); 187 void *ccb_cookie; 188 SIMPLEQ_ENTRY(hvs_ccb) ccb_link; 189 }; 190 SIMPLEQ_HEAD(hvs_ccb_queue, hvs_ccb); 191 192 struct hvs_softc { 193 struct device sc_dev; 194 struct hv_softc *sc_hvsc; 195 struct hv_channel *sc_chan; 196 bus_dma_tag_t sc_dmat; 197 198 int sc_proto; 199 int sc_flags; 200 #define HVSF_SCSI 0x0001 201 #define HVSF_W8PLUS 0x0002 202 struct hvs_chp sc_props; 203 204 /* CCBs */ 205 int sc_nccb; 206 struct hvs_ccb *sc_ccbs; 207 struct hvs_ccb_queue sc_ccb_fq; /* free queue */ 208 struct mutex sc_ccb_fqlck; 209 210 int sc_bus; 211 int sc_initiator; 212 213 struct scsi_iopool sc_iopool; 214 struct device *sc_scsibus; 215 struct task sc_probetask; 216 }; 217 218 int hvs_match(struct device *, void *, void *); 219 void hvs_attach(struct device *, struct device *, void *); 220 221 void hvs_scsi_cmd(struct scsi_xfer *); 222 void hvs_scsi_cmd_done(struct hvs_ccb *); 223 int hvs_start(struct hvs_softc *, struct hvs_ccb *); 224 int hvs_poll(struct hvs_softc *, struct hvs_ccb *); 225 void hvs_poll_done(struct hvs_ccb *); 226 void hvs_intr(void *); 227 void hvs_scsi_probe(void *arg); 228 void hvs_scsi_done(struct scsi_xfer *, int); 229 230 int hvs_connect(struct hvs_softc *); 231 void hvs_empty_done(struct hvs_ccb *); 232 233 int hvs_alloc_ccbs(struct hvs_softc *); 234 void hvs_free_ccbs(struct hvs_softc *); 235 void *hvs_get_ccb(void *); 236 void hvs_put_ccb(void *, void *); 237 238 struct cfdriver hvs_cd = { 239 NULL, "hvs", DV_DULL 240 }; 241 242 const struct cfattach hvs_ca = { 243 sizeof(struct hvs_softc), hvs_match, hvs_attach 244 }; 245 246 const struct scsi_adapter hvs_switch = { 247 hvs_scsi_cmd, NULL, NULL, NULL, NULL 248 }; 249 250 int 251 hvs_match(struct device *parent, void *match, void *aux) 252 { 253 struct hv_attach_args *aa = aux; 254 255 if (strcmp("ide", aa->aa_ident) && 256 strcmp("scsi", aa->aa_ident)) 257 return (0); 258 259 return (1); 260 } 261 262 void 263 hvs_attach(struct device *parent, struct device *self, void *aux) 264 { 265 struct hv_attach_args *aa = aux; 266 struct hvs_softc *sc = (struct hvs_softc *)self; 267 struct scsibus_attach_args saa; 268 extern int pciide_skip_ata; 269 270 sc->sc_hvsc = (struct hv_softc *)parent; 271 sc->sc_chan = aa->aa_chan; 272 sc->sc_dmat = aa->aa_dmat; 273 274 printf(" channel %u: %s", sc->sc_chan->ch_id, aa->aa_ident); 275 276 if (strcmp("scsi", aa->aa_ident) == 0) 277 sc->sc_flags |= HVSF_SCSI; 278 279 if (hv_channel_setdeferred(sc->sc_chan, sc->sc_dev.dv_xname)) { 280 printf(": failed to create the interrupt thread\n"); 281 return; 282 } 283 284 if (hv_channel_open(sc->sc_chan, HVS_RING_SIZE, &sc->sc_props, 285 sizeof(sc->sc_props), hvs_intr, sc)) { 286 printf(": failed to open channel\n"); 287 return; 288 } 289 290 hv_evcount_attach(sc->sc_chan, sc->sc_dev.dv_xname); 291 292 if (hvs_alloc_ccbs(sc)) 293 return; 294 295 if (hvs_connect(sc)) 296 return; 297 298 printf(", protocol %u.%u\n", (sc->sc_proto >> 8) & 0xff, 299 sc->sc_proto & 0xff); 300 301 if (sc->sc_proto >= HVS_PROTO_VERSION_WIN8) 302 sc->sc_flags |= HVSF_W8PLUS; 303 304 task_set(&sc->sc_probetask, hvs_scsi_probe, sc); 305 306 saa.saa_adapter = &hvs_switch; 307 saa.saa_adapter_softc = self; 308 saa.saa_luns = sc->sc_flags & HVSF_SCSI ? 64 : 1; 309 saa.saa_adapter_buswidth = 2; 310 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 311 saa.saa_openings = sc->sc_nccb; 312 saa.saa_pool = &sc->sc_iopool; 313 saa.saa_quirks = saa.saa_flags = 0; 314 saa.saa_wwpn = saa.saa_wwnn = 0; 315 316 sc->sc_scsibus = config_found(self, &saa, scsiprint); 317 318 /* 319 * If the driver has successfully attached to an IDE 320 * device, we need to make sure that the same disk is 321 * not available to the system via pciide(4) causing 322 * DUID conflicts and preventing system from booting. 323 */ 324 if (!(sc->sc_flags & HVSF_SCSI) && sc->sc_scsibus) 325 pciide_skip_ata = 1; 326 } 327 328 void 329 hvs_scsi_cmd(struct scsi_xfer *xs) 330 { 331 struct scsi_link *link = xs->sc_link; 332 struct hvs_softc *sc = link->bus->sb_adapter_softc; 333 struct hvs_ccb *ccb = xs->io; 334 union hvs_cmd cmd; 335 struct hvs_cmd_io *io = &cmd.io; 336 struct hvs_srb *srb = &io->cmd_srb; 337 int i, rv, flags = BUS_DMA_NOWAIT; 338 339 if (xs->cmdlen > MAX_SRB_DATA) { 340 printf("%s: CDB is too big: %d\n", sc->sc_dev.dv_xname, 341 xs->cmdlen); 342 memset(&xs->sense, 0, sizeof(xs->sense)); 343 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 344 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 345 xs->sense.add_sense_code = 0x20; 346 hvs_scsi_done(xs, XS_SENSE); 347 return; 348 } 349 350 KERNEL_UNLOCK(); 351 352 memset(&cmd, 0, sizeof(cmd)); 353 354 srb->srb_initiator = sc->sc_initiator; 355 srb->srb_bus = sc->sc_bus; 356 srb->srb_target = link->target; 357 srb->srb_lun = link->lun; 358 359 srb->srb_cdblen = xs->cmdlen; 360 memcpy(srb->srb_data, &xs->cmd, xs->cmdlen); 361 362 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 363 case SCSI_DATA_IN: 364 srb->srb_direction = SRB_DATA_READ; 365 if (sc->sc_flags & HVSF_W8PLUS) 366 io->cmd_srbflags |= SRB_FLAGS_DATA_IN; 367 flags |= BUS_DMA_WRITE; 368 break; 369 case SCSI_DATA_OUT: 370 srb->srb_direction = SRB_DATA_WRITE; 371 if (sc->sc_flags & HVSF_W8PLUS) 372 io->cmd_srbflags |= SRB_FLAGS_DATA_OUT; 373 flags |= BUS_DMA_READ; 374 break; 375 default: 376 srb->srb_direction = SRB_DATA_NONE; 377 if (sc->sc_flags & HVSF_W8PLUS) 378 io->cmd_srbflags |= SRB_FLAGS_NO_DATA_TRANSFER; 379 break; 380 } 381 382 srb->srb_datalen = xs->datalen; 383 384 if (sc->sc_flags & HVSF_W8PLUS) { 385 srb->srb_reqlen = sizeof(*io); 386 srb->srb_senselen = SENSE_DATA_LEN; 387 } else { 388 srb->srb_reqlen = sizeof(struct hvs_cmd_hdr) + 389 sizeof(struct hvs_srb); 390 srb->srb_senselen = SENSE_DATA_LEN_WIN7; 391 } 392 393 cmd.cmd_op = HVS_REQ_SCSIIO; 394 cmd.cmd_flags = VMBUS_CHANPKT_FLAG_RC; 395 396 if (xs->datalen > 0) { 397 rv = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmap, xs->data, 398 xs->datalen, NULL, flags); 399 if (rv) { 400 printf("%s: failed to load %d bytes (%d)\n", 401 sc->sc_dev.dv_xname, xs->datalen, rv); 402 KERNEL_LOCK(); 403 hvs_scsi_done(xs, XS_DRIVER_STUFFUP); 404 return; 405 } 406 407 ccb->ccb_sgl->gpa_len = xs->datalen; 408 ccb->ccb_sgl->gpa_ofs = (vaddr_t)xs->data & PAGE_MASK; 409 for (i = 0; i < ccb->ccb_dmap->dm_nsegs; i++) 410 ccb->ccb_sgl->gpa_page[i] = 411 atop(ccb->ccb_dmap->dm_segs[i].ds_addr); 412 ccb->ccb_nsge = ccb->ccb_dmap->dm_nsegs; 413 } else 414 ccb->ccb_nsge = 0; 415 416 ccb->ccb_xfer = xs; 417 ccb->ccb_cmd = &cmd; 418 ccb->ccb_done = hvs_scsi_cmd_done; 419 420 #ifdef HVS_DEBUG_IO 421 DPRINTF("%s: %u.%u: rid %llu opcode %#x flags %#x datalen %d\n", 422 sc->sc_dev.dv_xname, link->target, link->lun, ccb->ccb_rid, 423 xs->cmd.opcode, xs->flags, xs->datalen); 424 #endif 425 426 if (xs->flags & SCSI_POLL) 427 rv = hvs_poll(sc, ccb); 428 else 429 rv = hvs_start(sc, ccb); 430 if (rv) { 431 KERNEL_LOCK(); 432 hvs_scsi_done(xs, XS_DRIVER_STUFFUP); 433 return; 434 } 435 436 KERNEL_LOCK(); 437 } 438 439 int 440 hvs_start(struct hvs_softc *sc, struct hvs_ccb *ccb) 441 { 442 union hvs_cmd *cmd = ccb->ccb_cmd; 443 int rv; 444 445 ccb->ccb_cmd = NULL; 446 447 if (ccb->ccb_nsge > 0) { 448 rv = hv_channel_send_prpl(sc->sc_chan, ccb->ccb_sgl, 449 ccb->ccb_nsge, cmd, HVS_CMD_SIZE, ccb->ccb_rid); 450 if (rv) { 451 printf("%s: failed to submit operation %x via prpl\n", 452 sc->sc_dev.dv_xname, cmd->cmd_op); 453 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmap); 454 } 455 } else { 456 rv = hv_channel_send(sc->sc_chan, cmd, HVS_CMD_SIZE, 457 ccb->ccb_rid, VMBUS_CHANPKT_TYPE_INBAND, 458 VMBUS_CHANPKT_FLAG_RC); 459 if (rv) 460 printf("%s: failed to submit operation %x\n", 461 sc->sc_dev.dv_xname, cmd->cmd_op); 462 } 463 464 return (rv); 465 } 466 467 void 468 hvs_poll_done(struct hvs_ccb *ccb) 469 { 470 int *rv = ccb->ccb_cookie; 471 472 if (ccb->ccb_cmd) { 473 memcpy(&ccb->ccb_rsp, ccb->ccb_cmd, HVS_CMD_SIZE); 474 ccb->ccb_cmd = &ccb->ccb_rsp; 475 } else 476 memset(&ccb->ccb_rsp, 0, HVS_CMD_SIZE); 477 478 *rv = 0; 479 } 480 481 int 482 hvs_poll(struct hvs_softc *sc, struct hvs_ccb *ccb) 483 { 484 void (*done)(struct hvs_ccb *); 485 void *cookie; 486 int s, rv = 1; 487 488 done = ccb->ccb_done; 489 cookie = ccb->ccb_cookie; 490 491 ccb->ccb_done = hvs_poll_done; 492 ccb->ccb_cookie = &rv; 493 494 if (hvs_start(sc, ccb)) { 495 ccb->ccb_cookie = cookie; 496 ccb->ccb_done = done; 497 return (-1); 498 } 499 500 while (rv == 1) { 501 delay(10); 502 s = splbio(); 503 hvs_intr(sc); 504 splx(s); 505 } 506 507 ccb->ccb_cookie = cookie; 508 ccb->ccb_done = done; 509 ccb->ccb_done(ccb); 510 511 return (0); 512 } 513 514 void 515 hvs_intr(void *xsc) 516 { 517 struct hvs_softc *sc = xsc; 518 struct hvs_ccb *ccb; 519 union hvs_cmd cmd; 520 uint64_t rid; 521 uint32_t rlen; 522 int rv; 523 524 for (;;) { 525 rv = hv_channel_recv(sc->sc_chan, &cmd, sizeof(cmd), &rlen, 526 &rid, 0); 527 switch (rv) { 528 case 0: 529 break; 530 case EAGAIN: 531 /* No more messages to process */ 532 return; 533 default: 534 printf("%s: error %d while receiving a reply\n", 535 sc->sc_dev.dv_xname, rv); 536 return; 537 } 538 if (rlen != sizeof(cmd)) { 539 printf("%s: short read: %u\n", sc->sc_dev.dv_xname, 540 rlen); 541 return; 542 } 543 544 #ifdef HVS_DEBUG_IO 545 DPRINTF("%s: rid %llu operation %u flags %#x status %#x\n", 546 sc->sc_dev.dv_xname, rid, cmd.cmd_op, cmd.cmd_flags, 547 cmd.cmd_status); 548 #endif 549 550 switch (cmd.cmd_op) { 551 case HVS_MSG_IODONE: 552 if (rid >= sc->sc_nccb) { 553 printf("%s: invalid response %#llx\n", 554 sc->sc_dev.dv_xname, rid); 555 continue; 556 } 557 ccb = &sc->sc_ccbs[rid]; 558 ccb->ccb_cmd = &cmd; 559 ccb->ccb_done(ccb); 560 break; 561 case HVS_MSG_ENUMERATE: 562 task_add(systq, &sc->sc_probetask); 563 break; 564 default: 565 printf("%s: operation %u is not implemented\n", 566 sc->sc_dev.dv_xname, cmd.cmd_op); 567 } 568 } 569 } 570 571 static inline int 572 is_inquiry_valid(struct scsi_inquiry_data *inq) 573 { 574 if ((inq->device & SID_TYPE) == T_NODEVICE) 575 return (0); 576 if ((inq->device & SID_QUAL) == SID_QUAL_BAD_LU) 577 return (0); 578 return (1); 579 } 580 581 static inline void 582 fixup_inquiry(struct scsi_xfer *xs, struct hvs_srb *srb) 583 { 584 struct hvs_softc *sc = xs->sc_link->bus->sb_adapter_softc; 585 struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)xs->data; 586 int datalen, resplen; 587 char vendor[8]; 588 589 resplen = srb->srb_datalen >= SID_SCSI2_HDRLEN ? 590 SID_SCSI2_HDRLEN + inq->additional_length : 0; 591 datalen = MIN(resplen, srb->srb_datalen); 592 xs->resid = xs->datalen - datalen; 593 594 /* Fixup wrong response from WS2012 */ 595 if ((sc->sc_proto == HVS_PROTO_VERSION_WIN8_1 || 596 sc->sc_proto == HVS_PROTO_VERSION_WIN8 || 597 sc->sc_proto == HVS_PROTO_VERSION_WIN7) && 598 !is_inquiry_valid(inq) && datalen >= 4 && 599 (inq->version == 0 || inq->response_format == 0)) { 600 inq->version = SCSI_REV_SPC3; 601 inq->response_format = SID_SCSI2_RESPONSE; 602 } else if (datalen >= SID_SCSI2_HDRLEN + SID_SCSI2_ALEN) { 603 /* 604 * Upgrade SPC2 to SPC3 if host is Win8 or WS2012 R2 605 * to support UNMAP feature. 606 */ 607 scsi_strvis(vendor, inq->vendor, sizeof(vendor)); 608 if ((sc->sc_proto == HVS_PROTO_VERSION_WIN8_1 || 609 sc->sc_proto == HVS_PROTO_VERSION_WIN8) && 610 (SID_ANSII_REV(inq) == SCSI_REV_SPC2) && 611 !strncmp(vendor, "Msft", 4)) 612 inq->version = SCSI_REV_SPC3; 613 } 614 } 615 616 void 617 hvs_scsi_cmd_done(struct hvs_ccb *ccb) 618 { 619 struct scsi_xfer *xs = ccb->ccb_xfer; 620 struct hvs_softc *sc = xs->sc_link->bus->sb_adapter_softc; 621 union hvs_cmd *cmd = ccb->ccb_cmd; 622 struct hvs_srb *srb; 623 bus_dmamap_t map; 624 int error; 625 626 map = ccb->ccb_dmap; 627 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 628 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 629 bus_dmamap_unload(sc->sc_dmat, map); 630 631 xs = ccb->ccb_xfer; 632 srb = &cmd->io.cmd_srb; 633 634 xs->status = srb->srb_scsistatus & 0xff; 635 636 switch (xs->status) { 637 case SCSI_OK: 638 if ((srb->srb_iostatus & ~(SRB_STATUS_AUTOSENSE_VALID | 639 SRB_STATUS_QUEUE_FROZEN)) != SRB_STATUS_SUCCESS) 640 error = XS_SELTIMEOUT; 641 else 642 error = XS_NOERROR; 643 break; 644 case SCSI_BUSY: 645 case SCSI_QUEUE_FULL: 646 printf("%s: status %#x iostatus %#x (busy)\n", 647 sc->sc_dev.dv_xname, srb->srb_scsistatus, 648 srb->srb_iostatus); 649 error = XS_BUSY; 650 break; 651 case SCSI_CHECK: 652 if (srb->srb_iostatus & SRB_STATUS_AUTOSENSE_VALID) { 653 memcpy(&xs->sense, srb->srb_data, 654 MIN(sizeof(xs->sense), srb->srb_senselen)); 655 error = XS_SENSE; 656 break; 657 } 658 /* FALLTHROUGH */ 659 default: 660 error = XS_DRIVER_STUFFUP; 661 } 662 663 if (error == XS_NOERROR) { 664 if (xs->cmd.opcode == INQUIRY) 665 fixup_inquiry(xs, srb); 666 else if (srb->srb_direction != SRB_DATA_NONE) 667 xs->resid = xs->datalen - srb->srb_datalen; 668 } 669 670 KERNEL_LOCK(); 671 hvs_scsi_done(xs, error); 672 KERNEL_UNLOCK(); 673 } 674 675 void 676 hvs_scsi_probe(void *arg) 677 { 678 struct hvs_softc *sc = arg; 679 680 if (sc->sc_scsibus) 681 scsi_probe_bus((void *)sc->sc_scsibus); 682 } 683 684 void 685 hvs_scsi_done(struct scsi_xfer *xs, int error) 686 { 687 int s; 688 689 KERNEL_ASSERT_LOCKED(); 690 691 xs->error = error; 692 693 s = splbio(); 694 scsi_done(xs); 695 splx(s); 696 } 697 698 int 699 hvs_connect(struct hvs_softc *sc) 700 { 701 const uint32_t protos[] = { 702 HVS_PROTO_VERSION_WIN10, 703 HVS_PROTO_VERSION_WIN8_1, 704 HVS_PROTO_VERSION_WIN8, 705 HVS_PROTO_VERSION_WIN7, 706 HVS_PROTO_VERSION_WIN6 707 }; 708 union hvs_cmd ucmd; 709 struct hvs_cmd_ver *cmd; 710 struct hvs_chp *chp; 711 struct hvs_ccb *ccb; 712 int i; 713 714 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 715 if (ccb == NULL) { 716 printf(": failed to allocate ccb\n"); 717 return (-1); 718 } 719 720 ccb->ccb_done = hvs_empty_done; 721 722 cmd = (struct hvs_cmd_ver *)&ucmd; 723 724 /* 725 * Begin initialization 726 */ 727 728 memset(&ucmd, 0, sizeof(ucmd)); 729 730 cmd->cmd_op = HVS_REQ_STARTINIT; 731 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 732 733 ccb->ccb_cmd = &ucmd; 734 if (hvs_poll(sc, ccb)) { 735 printf(": failed to send initialization command\n"); 736 scsi_io_put(&sc->sc_iopool, ccb); 737 return (-1); 738 } 739 if (ccb->ccb_rsp.cmd_status != 0) { 740 printf(": failed to initialize, status %#x\n", 741 ccb->ccb_rsp.cmd_status); 742 scsi_io_put(&sc->sc_iopool, ccb); 743 return (-1); 744 } 745 746 /* 747 * Negotiate protocol version 748 */ 749 750 memset(&ucmd, 0, sizeof(ucmd)); 751 752 cmd->cmd_op = HVS_REQ_QUERYPROTO; 753 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 754 755 for (i = 0; i < nitems(protos); i++) { 756 cmd->cmd_ver = protos[i]; 757 758 ccb->ccb_cmd = &ucmd; 759 if (hvs_poll(sc, ccb)) { 760 printf(": failed to send protocol query\n"); 761 scsi_io_put(&sc->sc_iopool, ccb); 762 return (-1); 763 } 764 if (ccb->ccb_rsp.cmd_status == 0) { 765 sc->sc_proto = protos[i]; 766 break; 767 } 768 } 769 if (!sc->sc_proto) { 770 printf(": failed to negotiate protocol version\n"); 771 scsi_io_put(&sc->sc_iopool, ccb); 772 return (-1); 773 } 774 775 /* 776 * Query channel properties 777 */ 778 779 memset(&ucmd, 0, sizeof(ucmd)); 780 781 cmd->cmd_op = HVS_REQ_QUERYPROPS; 782 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 783 784 ccb->ccb_cmd = &ucmd; 785 if (hvs_poll(sc, ccb)) { 786 printf(": failed to send channel properties query\n"); 787 scsi_io_put(&sc->sc_iopool, ccb); 788 return (-1); 789 } 790 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 791 ccb->ccb_rsp.cmd_status != 0) { 792 printf(": failed to obtain channel properties, status %#x\n", 793 ccb->ccb_rsp.cmd_status); 794 scsi_io_put(&sc->sc_iopool, ccb); 795 return (-1); 796 } 797 chp = &ccb->ccb_rsp.chp.cmd_chp; 798 799 DPRINTF(": proto %#x path %u target %u maxchan %u", 800 chp->chp_proto, chp->chp_path, chp->chp_target, 801 chp->chp_maxchan); 802 DPRINTF(" port %u chflags %#x maxfer %u chanid %#llx", 803 chp->chp_port, chp->chp_chflags, chp->chp_maxfer, 804 chp->chp_chanid); 805 806 /* XXX */ 807 sc->sc_bus = chp->chp_path; 808 sc->sc_initiator = chp->chp_target; 809 810 /* 811 * Finish initialization 812 */ 813 814 memset(&ucmd, 0, sizeof(ucmd)); 815 816 cmd->cmd_op = HVS_REQ_FINISHINIT; 817 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 818 819 ccb->ccb_cmd = &ucmd; 820 if (hvs_poll(sc, ccb)) { 821 printf(": failed to send initialization finish\n"); 822 scsi_io_put(&sc->sc_iopool, ccb); 823 return (-1); 824 } 825 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 826 ccb->ccb_rsp.cmd_status != 0) { 827 printf(": failed to finish initialization, status %#x\n", 828 ccb->ccb_rsp.cmd_status); 829 scsi_io_put(&sc->sc_iopool, ccb); 830 return (-1); 831 } 832 833 scsi_io_put(&sc->sc_iopool, ccb); 834 835 return (0); 836 } 837 838 void 839 hvs_empty_done(struct hvs_ccb *ccb) 840 { 841 /* nothing */ 842 } 843 844 int 845 hvs_alloc_ccbs(struct hvs_softc *sc) 846 { 847 int i, error; 848 849 SIMPLEQ_INIT(&sc->sc_ccb_fq); 850 mtx_init(&sc->sc_ccb_fqlck, IPL_BIO); 851 852 sc->sc_nccb = HVS_MAX_CCB; 853 854 sc->sc_ccbs = mallocarray(sc->sc_nccb, sizeof(struct hvs_ccb), 855 M_DEVBUF, M_ZERO | M_NOWAIT); 856 if (sc->sc_ccbs == NULL) { 857 printf(": failed to allocate CCBs\n"); 858 return (-1); 859 } 860 861 for (i = 0; i < sc->sc_nccb; i++) { 862 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, HVS_MAX_SGE, 863 PAGE_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT, 864 &sc->sc_ccbs[i].ccb_dmap); 865 if (error) { 866 printf(": failed to create a CCB memory map (%d)\n", 867 error); 868 goto errout; 869 } 870 871 sc->sc_ccbs[i].ccb_sgl = malloc(sizeof(struct vmbus_gpa_range) * 872 (HVS_MAX_SGE + 1), M_DEVBUF, M_ZERO | M_NOWAIT); 873 if (sc->sc_ccbs[i].ccb_sgl == NULL) { 874 printf(": failed to allocate SGL array\n"); 875 goto errout; 876 } 877 878 sc->sc_ccbs[i].ccb_rid = i; 879 hvs_put_ccb(sc, &sc->sc_ccbs[i]); 880 } 881 882 scsi_iopool_init(&sc->sc_iopool, sc, hvs_get_ccb, hvs_put_ccb); 883 884 return (0); 885 886 errout: 887 hvs_free_ccbs(sc); 888 return (-1); 889 } 890 891 void 892 hvs_free_ccbs(struct hvs_softc *sc) 893 { 894 struct hvs_ccb *ccb; 895 int i; 896 897 for (i = 0; i < sc->sc_nccb; i++) { 898 ccb = &sc->sc_ccbs[i]; 899 if (ccb->ccb_dmap == NULL) 900 continue; 901 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmap, 0, 0, 902 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 903 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmap); 904 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmap); 905 906 free(ccb->ccb_sgl, M_DEVBUF, sizeof(struct vmbus_gpa_range) * 907 (HVS_MAX_SGE + 1)); 908 } 909 910 free(sc->sc_ccbs, M_DEVBUF, sc->sc_nccb * sizeof(struct hvs_ccb)); 911 sc->sc_ccbs = NULL; 912 sc->sc_nccb = 0; 913 } 914 915 void * 916 hvs_get_ccb(void *xsc) 917 { 918 struct hvs_softc *sc = xsc; 919 struct hvs_ccb *ccb; 920 921 mtx_enter(&sc->sc_ccb_fqlck); 922 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_fq); 923 if (ccb != NULL) 924 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_fq, ccb_link); 925 mtx_leave(&sc->sc_ccb_fqlck); 926 927 return (ccb); 928 } 929 930 void 931 hvs_put_ccb(void *xsc, void *io) 932 { 933 struct hvs_softc *sc = xsc; 934 struct hvs_ccb *ccb = io; 935 936 ccb->ccb_cmd = NULL; 937 ccb->ccb_xfer = NULL; 938 ccb->ccb_done = NULL; 939 ccb->ccb_cookie = NULL; 940 ccb->ccb_nsge = 0; 941 942 mtx_enter(&sc->sc_ccb_fqlck); 943 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_fq, ccb, ccb_link); 944 mtx_leave(&sc->sc_ccb_fqlck); 945 } 946