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