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
hvs_match(struct device * parent,void * match,void * aux)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
hvs_attach(struct device * parent,struct device * self,void * aux)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
hvs_scsi_cmd(struct scsi_xfer * xs)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
hvs_start(struct hvs_softc * sc,struct hvs_ccb * ccb)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
hvs_poll_done(struct hvs_ccb * ccb)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
hvs_poll(struct hvs_softc * sc,struct hvs_ccb * ccb)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
hvs_intr(void * xsc)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
is_inquiry_valid(struct scsi_inquiry_data * inq)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
fixup_inquiry(struct scsi_xfer * xs,struct hvs_srb * srb)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
hvs_scsi_cmd_done(struct hvs_ccb * ccb)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
hvs_scsi_probe(void * arg)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
hvs_scsi_done(struct scsi_xfer * xs,int error)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
hvs_connect(struct hvs_softc * sc)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
hvs_empty_done(struct hvs_ccb * ccb)839 hvs_empty_done(struct hvs_ccb *ccb)
840 {
841 /* nothing */
842 }
843
844 int
hvs_alloc_ccbs(struct hvs_softc * sc)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
hvs_free_ccbs(struct hvs_softc * sc)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 *
hvs_get_ccb(void * xsc)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
hvs_put_ccb(void * xsc,void * io)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