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 >= SID_SCSI2_HDRLEN ? 594 SID_SCSI2_HDRLEN + inq->additional_length : 0; 595 datalen = MIN(resplen, srb->srb_datalen); 596 xs->resid = xs->datalen - datalen; 597 598 /* Fixup wrong response from WS2012 */ 599 if ((sc->sc_proto == HVS_PROTO_VERSION_WIN8_1 || 600 sc->sc_proto == HVS_PROTO_VERSION_WIN8 || 601 sc->sc_proto == HVS_PROTO_VERSION_WIN7) && 602 !is_inquiry_valid(inq) && datalen >= 4 && 603 (inq->version == 0 || inq->response_format == 0)) { 604 inq->version = SCSI_REV_SPC3; 605 inq->response_format = SID_SCSI2_RESPONSE; 606 } else if (datalen >= SID_SCSI2_HDRLEN + SID_SCSI2_ALEN) { 607 /* 608 * Upgrade SPC2 to SPC3 if host is Win8 or WS2012 R2 609 * to support UNMAP feature. 610 */ 611 scsi_strvis(vendor, inq->vendor, sizeof(vendor)); 612 if ((sc->sc_proto == HVS_PROTO_VERSION_WIN8_1 || 613 sc->sc_proto == HVS_PROTO_VERSION_WIN8) && 614 (SID_ANSII_REV(inq) == SCSI_REV_SPC2) && 615 !strncmp(vendor, "Msft", 4)) 616 inq->version = SCSI_REV_SPC3; 617 } 618 } 619 620 void 621 hvs_scsi_cmd_done(struct hvs_ccb *ccb) 622 { 623 struct scsi_xfer *xs = ccb->ccb_xfer; 624 struct hvs_softc *sc = xs->sc_link->bus->sb_adapter_softc; 625 union hvs_cmd *cmd = ccb->ccb_cmd; 626 struct hvs_srb *srb; 627 bus_dmamap_t map; 628 int error; 629 630 map = ccb->ccb_dmap; 631 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 632 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 633 bus_dmamap_unload(sc->sc_dmat, map); 634 635 xs = ccb->ccb_xfer; 636 srb = &cmd->io.cmd_srb; 637 638 xs->status = srb->srb_scsistatus & 0xff; 639 640 switch (xs->status) { 641 case SCSI_OK: 642 if ((srb->srb_iostatus & ~(SRB_STATUS_AUTOSENSE_VALID | 643 SRB_STATUS_QUEUE_FROZEN)) != SRB_STATUS_SUCCESS) 644 error = XS_SELTIMEOUT; 645 else 646 error = XS_NOERROR; 647 break; 648 case SCSI_BUSY: 649 case SCSI_QUEUE_FULL: 650 printf("%s: status %#x iostatus %#x (busy)\n", 651 sc->sc_dev.dv_xname, srb->srb_scsistatus, 652 srb->srb_iostatus); 653 error = XS_BUSY; 654 break; 655 case SCSI_CHECK: 656 if (srb->srb_iostatus & SRB_STATUS_AUTOSENSE_VALID) { 657 memcpy(&xs->sense, srb->srb_data, 658 MIN(sizeof(xs->sense), srb->srb_senselen)); 659 error = XS_SENSE; 660 break; 661 } 662 /* FALLTHROUGH */ 663 default: 664 error = XS_DRIVER_STUFFUP; 665 } 666 667 if (error == XS_NOERROR) { 668 if (xs->cmd.opcode == INQUIRY) 669 fixup_inquiry(xs, srb); 670 else if (srb->srb_direction != SRB_DATA_NONE) 671 xs->resid = xs->datalen - srb->srb_datalen; 672 } 673 674 KERNEL_LOCK(); 675 hvs_scsi_done(xs, error); 676 KERNEL_UNLOCK(); 677 } 678 679 void 680 hvs_scsi_probe(void *arg) 681 { 682 struct hvs_softc *sc = arg; 683 684 if (sc->sc_scsibus) 685 scsi_probe_bus((void *)sc->sc_scsibus); 686 } 687 688 void 689 hvs_scsi_done(struct scsi_xfer *xs, int error) 690 { 691 int s; 692 693 KERNEL_ASSERT_LOCKED(); 694 695 xs->error = error; 696 697 s = splbio(); 698 scsi_done(xs); 699 splx(s); 700 } 701 702 int 703 hvs_connect(struct hvs_softc *sc) 704 { 705 const uint32_t protos[] = { 706 HVS_PROTO_VERSION_WIN10, 707 HVS_PROTO_VERSION_WIN8_1, 708 HVS_PROTO_VERSION_WIN8, 709 HVS_PROTO_VERSION_WIN7, 710 HVS_PROTO_VERSION_WIN6 711 }; 712 union hvs_cmd ucmd; 713 struct hvs_cmd_ver *cmd; 714 struct hvs_chp *chp; 715 struct hvs_ccb *ccb; 716 int i; 717 718 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 719 if (ccb == NULL) { 720 printf(": failed to allocate ccb\n"); 721 return (-1); 722 } 723 724 ccb->ccb_done = hvs_empty_done; 725 726 cmd = (struct hvs_cmd_ver *)&ucmd; 727 728 /* 729 * Begin initialization 730 */ 731 732 memset(&ucmd, 0, sizeof(ucmd)); 733 734 cmd->cmd_op = HVS_REQ_STARTINIT; 735 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 736 737 ccb->ccb_cmd = &ucmd; 738 if (hvs_poll(sc, ccb)) { 739 printf(": failed to send initialization command\n"); 740 scsi_io_put(&sc->sc_iopool, ccb); 741 return (-1); 742 } 743 if (ccb->ccb_rsp.cmd_status != 0) { 744 printf(": failed to initialize, status %#x\n", 745 ccb->ccb_rsp.cmd_status); 746 scsi_io_put(&sc->sc_iopool, ccb); 747 return (-1); 748 } 749 750 /* 751 * Negotiate protocol version 752 */ 753 754 memset(&ucmd, 0, sizeof(ucmd)); 755 756 cmd->cmd_op = HVS_REQ_QUERYPROTO; 757 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 758 759 for (i = 0; i < nitems(protos); i++) { 760 cmd->cmd_ver = protos[i]; 761 762 ccb->ccb_cmd = &ucmd; 763 if (hvs_poll(sc, ccb)) { 764 printf(": failed to send protocol query\n"); 765 scsi_io_put(&sc->sc_iopool, ccb); 766 return (-1); 767 } 768 if (ccb->ccb_rsp.cmd_status == 0) { 769 sc->sc_proto = protos[i]; 770 break; 771 } 772 } 773 if (!sc->sc_proto) { 774 printf(": failed to negotiate protocol version\n"); 775 scsi_io_put(&sc->sc_iopool, ccb); 776 return (-1); 777 } 778 779 /* 780 * Query channel properties 781 */ 782 783 memset(&ucmd, 0, sizeof(ucmd)); 784 785 cmd->cmd_op = HVS_REQ_QUERYPROPS; 786 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 787 788 ccb->ccb_cmd = &ucmd; 789 if (hvs_poll(sc, ccb)) { 790 printf(": failed to send channel properties query\n"); 791 scsi_io_put(&sc->sc_iopool, ccb); 792 return (-1); 793 } 794 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 795 ccb->ccb_rsp.cmd_status != 0) { 796 printf(": failed to obtain channel properties, status %#x\n", 797 ccb->ccb_rsp.cmd_status); 798 scsi_io_put(&sc->sc_iopool, ccb); 799 return (-1); 800 } 801 chp = &ccb->ccb_rsp.chp.cmd_chp; 802 803 DPRINTF(": proto %#x path %u target %u maxchan %u", 804 chp->chp_proto, chp->chp_path, chp->chp_target, 805 chp->chp_maxchan); 806 DPRINTF(" port %u chflags %#x maxfer %u chanid %#llx", 807 chp->chp_port, chp->chp_chflags, chp->chp_maxfer, 808 chp->chp_chanid); 809 810 /* XXX */ 811 sc->sc_bus = chp->chp_path; 812 sc->sc_initiator = chp->chp_target; 813 814 /* 815 * Finish initialization 816 */ 817 818 memset(&ucmd, 0, sizeof(ucmd)); 819 820 cmd->cmd_op = HVS_REQ_FINISHINIT; 821 cmd->cmd_flags = VMBUS_CHANPKT_FLAG_RC; 822 823 ccb->ccb_cmd = &ucmd; 824 if (hvs_poll(sc, ccb)) { 825 printf(": failed to send initialization finish\n"); 826 scsi_io_put(&sc->sc_iopool, ccb); 827 return (-1); 828 } 829 if (ccb->ccb_rsp.cmd_op != HVS_MSG_IODONE || 830 ccb->ccb_rsp.cmd_status != 0) { 831 printf(": failed to finish initialization, status %#x\n", 832 ccb->ccb_rsp.cmd_status); 833 scsi_io_put(&sc->sc_iopool, ccb); 834 return (-1); 835 } 836 837 scsi_io_put(&sc->sc_iopool, ccb); 838 839 return (0); 840 } 841 842 void 843 hvs_empty_done(struct hvs_ccb *ccb) 844 { 845 /* nothing */ 846 } 847 848 int 849 hvs_alloc_ccbs(struct hvs_softc *sc) 850 { 851 int i, error; 852 853 SIMPLEQ_INIT(&sc->sc_ccb_fq); 854 mtx_init(&sc->sc_ccb_fqlck, IPL_BIO); 855 856 sc->sc_nccb = HVS_MAX_CCB; 857 858 sc->sc_ccbs = mallocarray(sc->sc_nccb, sizeof(struct hvs_ccb), 859 M_DEVBUF, M_ZERO | M_NOWAIT); 860 if (sc->sc_ccbs == NULL) { 861 printf(": failed to allocate CCBs\n"); 862 return (-1); 863 } 864 865 for (i = 0; i < sc->sc_nccb; i++) { 866 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, HVS_MAX_SGE, 867 PAGE_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT, 868 &sc->sc_ccbs[i].ccb_dmap); 869 if (error) { 870 printf(": failed to create a CCB memory map (%d)\n", 871 error); 872 goto errout; 873 } 874 875 sc->sc_ccbs[i].ccb_sgl = malloc(sizeof(struct vmbus_gpa_range) * 876 (HVS_MAX_SGE + 1), M_DEVBUF, M_ZERO | M_NOWAIT); 877 if (sc->sc_ccbs[i].ccb_sgl == NULL) { 878 printf(": failed to allocate SGL array\n"); 879 goto errout; 880 } 881 882 sc->sc_ccbs[i].ccb_rid = i; 883 hvs_put_ccb(sc, &sc->sc_ccbs[i]); 884 } 885 886 scsi_iopool_init(&sc->sc_iopool, sc, hvs_get_ccb, hvs_put_ccb); 887 888 return (0); 889 890 errout: 891 hvs_free_ccbs(sc); 892 return (-1); 893 } 894 895 void 896 hvs_free_ccbs(struct hvs_softc *sc) 897 { 898 struct hvs_ccb *ccb; 899 int i; 900 901 for (i = 0; i < sc->sc_nccb; i++) { 902 ccb = &sc->sc_ccbs[i]; 903 if (ccb->ccb_dmap == NULL) 904 continue; 905 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmap, 0, 0, 906 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 907 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmap); 908 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmap); 909 910 free(ccb->ccb_sgl, M_DEVBUF, sizeof(struct vmbus_gpa_range) * 911 (HVS_MAX_SGE + 1)); 912 } 913 914 free(sc->sc_ccbs, M_DEVBUF, sc->sc_nccb * sizeof(struct hvs_ccb)); 915 sc->sc_ccbs = NULL; 916 sc->sc_nccb = 0; 917 } 918 919 void * 920 hvs_get_ccb(void *xsc) 921 { 922 struct hvs_softc *sc = xsc; 923 struct hvs_ccb *ccb; 924 925 mtx_enter(&sc->sc_ccb_fqlck); 926 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_fq); 927 if (ccb != NULL) 928 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_fq, ccb_link); 929 mtx_leave(&sc->sc_ccb_fqlck); 930 931 return (ccb); 932 } 933 934 void 935 hvs_put_ccb(void *xsc, void *io) 936 { 937 struct hvs_softc *sc = xsc; 938 struct hvs_ccb *ccb = io; 939 940 ccb->ccb_cmd = NULL; 941 ccb->ccb_xfer = NULL; 942 ccb->ccb_done = NULL; 943 ccb->ccb_cookie = NULL; 944 ccb->ccb_nsge = 0; 945 946 mtx_enter(&sc->sc_ccb_fqlck); 947 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_fq, ccb, ccb_link); 948 mtx_leave(&sc->sc_ccb_fqlck); 949 } 950