xref: /openbsd-src/sys/dev/pv/hvs.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
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