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