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