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