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