xref: /openbsd/sys/arch/sparc64/dev/vdsp.c (revision 9b7c3dbb)
1 /*	$OpenBSD: vdsp.c,v 1.42 2016/03/19 12:04:15 natano Exp $	*/
2 /*
3  * Copyright (c) 2009, 2011, 2014 Mark Kettenis
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/conf.h>
20 #include <sys/proc.h>
21 #include <sys/buf.h>
22 #include <sys/device.h>
23 #include <sys/disklabel.h>
24 #include <sys/fcntl.h>
25 #include <sys/lock.h>
26 #include <sys/malloc.h>
27 #include <sys/mutex.h>
28 #include <sys/namei.h>
29 #include <sys/systm.h>
30 #include <sys/task.h>
31 #include <sys/vnode.h>
32 #include <sys/dkio.h>
33 #include <sys/specdev.h>
34 
35 #include <machine/autoconf.h>
36 #include <machine/conf.h>
37 #include <machine/hypervisor.h>
38 #include <machine/mdesc.h>
39 
40 #include <uvm/uvm_extern.h>
41 
42 #include <scsi/scsi_all.h>
43 #include <scsi/scsi_disk.h>
44 #include <scsi/scsiconf.h>
45 
46 #include <isofs/cd9660/iso.h>
47 
48 #include <dev/sun/disklabel.h>
49 
50 #include <sparc64/dev/cbusvar.h>
51 #include <sparc64/dev/ldcvar.h>
52 #include <sparc64/dev/viovar.h>
53 
54 #ifdef VDSP_DEBUG
55 #define DPRINTF(x)	printf x
56 #else
57 #define DPRINTF(x)
58 #endif
59 
60 #define VDSK_TX_ENTRIES			64
61 #define VDSK_RX_ENTRIES			64
62 
63 #define VDSK_MAX_DESCRIPTORS		1024
64 #define VDSK_MAX_DESCRIPTOR_SIZE	512
65 
66 struct vd_attr_info {
67 	struct vio_msg_tag	tag;
68 	uint8_t			xfer_mode;
69 	uint8_t			vd_type;
70 	uint8_t			vd_mtype;
71 	uint8_t			_reserved1;
72 	uint32_t		vdisk_block_size;
73 	uint64_t		operations;
74 	uint64_t		vdisk_size;
75 	uint64_t		max_xfer_sz;
76 	uint64_t		_reserved2[2];
77 };
78 
79 #define VD_DISK_TYPE_SLICE	0x01
80 #define VD_DISK_TYPE_DISK	0x02
81 
82 #define VD_MEDIA_TYPE_FIXED	0x01
83 #define VD_MEDIA_TYPE_CD	0x02
84 #define VD_MEDIA_TYPE_DVD	0x03
85 
86 /* vDisk version 1.0. */
87 #define VD_OP_BREAD		0x01
88 #define VD_OP_BWRITE		0x02
89 #define VD_OP_FLUSH		0x03
90 #define VD_OP_GET_WCE		0x04
91 #define VD_OP_SET_WCE		0x05
92 #define VD_OP_GET_VTOC		0x06
93 #define VD_OP_SET_VTOC		0x07
94 #define VD_OP_GET_DISKGEOM	0x08
95 #define VD_OP_SET_DISKGEOM	0x09
96 #define VD_OP_GET_DEVID		0x0b
97 #define VD_OP_GET_EFI		0x0c
98 #define VD_OP_SET_EFI		0x0d
99 
100 /* vDisk version 1.1 */
101 #define VD_OP_SCSICMD		0x0a
102 #define VD_OP_RESET		0x0e
103 #define VD_OP_GET_ACCESS	0x0f
104 #define VD_OP_SET_ACCESS	0x10
105 #define VD_OP_GET_CAPACITY	0x11
106 
107 /* Sun standard fields. */
108 struct sun_vtoc_preamble {
109 	char	sl_text[128];
110 	u_int	sl_version;	/* label version */
111 	char	sl_volume[8];	/* short volume name */
112 	u_short	sl_nparts;	/* partition count */
113 
114 	struct sun_partinfo sl_part[8];
115 
116 	u_int	sl_bootinfo[3];
117 	u_int	sl_sanity;
118 };
119 
120 struct vd_vtoc_part {
121 	uint16_t	id_tag;
122 	uint16_t	perm;
123 	uint32_t	reserved;
124 	uint64_t	start;
125 	uint64_t	nblocks;
126 
127 };
128 struct vd_vtoc {
129 	uint8_t		volume_name[8];
130 	uint16_t	sector_size;
131 	uint16_t	num_partitions;
132 	uint32_t	reserved;
133 	uint8_t		ascii_label[128];
134 	struct vd_vtoc_part partition[8];
135 };
136 
137 struct vd_diskgeom {
138 	uint16_t	ncyl;
139 	uint16_t	acyl;
140 	uint16_t	bcyl;
141 	uint16_t	nhead;
142 	uint16_t	nsect;
143 	uint16_t	intrlv;
144 	uint16_t	apc;
145 	uint16_t	rpm;
146 	uint16_t	pcyl;
147 	uint16_t	write_reinstruct;
148 	uint16_t	read_reinstruct;
149 };
150 
151 struct vd_desc {
152 	struct vio_dring_hdr	hdr;
153 	uint64_t		req_id;
154 	uint8_t			operation;
155 	uint8_t			slice;
156 	uint16_t		_reserved1;
157 	uint32_t		status;
158 	uint64_t		offset;
159 	uint64_t		size;
160 	uint32_t		ncookies;
161 	uint32_t		_reserved2;
162 	struct ldc_cookie	cookie[1];
163 };
164 
165 #define VD_SLICE_NONE		0xff
166 
167 struct vdsk_desc_msg {
168 	struct vio_msg_tag	tag;
169 	uint64_t		seq_no;
170 	uint64_t		desc_handle;
171 	uint64_t		req_id;
172 	uint8_t			operation;
173 	uint8_t			slice;
174 	uint16_t		_reserved1;
175 	uint32_t		status;
176 	uint64_t		offset;
177 	uint64_t		size;
178 	uint32_t		ncookies;
179 	uint32_t		_reserved2;
180 	struct ldc_cookie	cookie[1];
181 };
182 
183 /*
184  * We support vDisk 1.1.
185  */
186 #define VDSK_MAJOR	1
187 #define VDSK_MINOR	1
188 
189 /*
190  * But we only support a subset of the defined commands.
191  */
192 #define VD_OP_MASK \
193     ((1 << VD_OP_BREAD) | (1 << VD_OP_BWRITE) | (1 << VD_OP_FLUSH) | \
194      (1 << VD_OP_GET_WCE) | (1 << VD_OP_SET_WCE) | \
195      (1 << VD_OP_GET_VTOC) | (1 << VD_OP_SET_VTOC) | \
196      (1 << VD_OP_GET_DISKGEOM))
197 
198 struct vdsp_softc {
199 	struct device	sc_dv;
200 	int		sc_idx;
201 	bus_space_tag_t	sc_bustag;
202 	bus_dma_tag_t	sc_dmatag;
203 
204 	uint64_t	sc_tx_ino;
205 	uint64_t	sc_rx_ino;
206 	void		*sc_tx_ih;
207 	void		*sc_rx_ih;
208 
209 	struct ldc_conn	sc_lc;
210 
211 	uint16_t	sc_vio_state;
212 #define VIO_SND_VER_INFO	0x0001
213 #define VIO_ACK_VER_INFO	0x0002
214 #define VIO_RCV_VER_INFO	0x0004
215 #define VIO_SND_ATTR_INFO	0x0008
216 #define VIO_ACK_ATTR_INFO	0x0010
217 #define VIO_RCV_ATTR_INFO	0x0020
218 #define VIO_SND_DRING_REG	0x0040
219 #define VIO_ACK_DRING_REG	0x0080
220 #define VIO_RCV_DRING_REG	0x0100
221 #define VIO_SND_RDX		0x0200
222 #define VIO_ACK_RDX		0x0400
223 #define VIO_RCV_RDX		0x0800
224 
225 	uint16_t	sc_major;
226 	uint16_t	sc_minor;
227 
228 	uint8_t		sc_xfer_mode;
229 
230 	uint32_t	sc_local_sid;
231 	uint64_t	sc_seq_no;
232 
233 	uint64_t	sc_dring_ident;
234 	uint32_t	sc_num_descriptors;
235 	uint32_t	sc_descriptor_size;
236 	struct ldc_cookie sc_dring_cookie;
237 
238 	struct task	sc_open_task;
239 	struct task	sc_alloc_task;
240 	struct task	sc_close_task;
241 
242 	struct mutex	sc_desc_mtx;
243 	struct vdsk_desc_msg *sc_desc_msg[VDSK_RX_ENTRIES];
244 	int		sc_desc_head;
245 	int		sc_desc_tail;
246 
247 	struct task	sc_read_task;
248 
249 	caddr_t		sc_vd;
250 	struct task	sc_vd_task;
251 	struct vd_desc	**sc_vd_ring;
252 	u_int		sc_vd_prod;
253 	u_int		sc_vd_cons;
254 
255 	uint32_t	sc_vdisk_block_size;
256 	uint64_t	sc_vdisk_size;
257 
258 	struct vnode	*sc_vp;
259 
260 	struct sun_disklabel *sc_label;
261 	uint16_t	sc_ncyl;
262 	uint16_t	sc_acyl;
263 	uint16_t	sc_nhead;
264 	uint16_t	sc_nsect;
265 };
266 
267 int	vdsp_match(struct device *, void *, void *);
268 void	vdsp_attach(struct device *, struct device *, void *);
269 
270 struct cfattach vdsp_ca = {
271 	sizeof(struct vdsp_softc), vdsp_match, vdsp_attach
272 };
273 
274 struct cfdriver vdsp_cd = {
275 	NULL, "vdsp", DV_DULL
276 };
277 
278 int	vdsp_tx_intr(void *);
279 int	vdsp_rx_intr(void *);
280 
281 void	vdsp_rx_data(struct ldc_conn *, struct ldc_pkt *);
282 void	vdsp_rx_vio_ctrl(struct vdsp_softc *, struct vio_msg *);
283 void	vdsp_rx_vio_ver_info(struct vdsp_softc *, struct vio_msg_tag *);
284 void	vdsp_rx_vio_attr_info(struct vdsp_softc *, struct vio_msg_tag *);
285 void	vdsp_rx_vio_dring_reg(struct vdsp_softc *, struct vio_msg_tag *);
286 void	vdsp_rx_vio_rdx(struct vdsp_softc *sc, struct vio_msg_tag *);
287 void	vdsp_rx_vio_data(struct vdsp_softc *sc, struct vio_msg *);
288 void	vdsp_rx_vio_dring_data(struct vdsp_softc *sc,
289 	    struct vio_msg_tag *);
290 void	vdsp_rx_vio_desc_data(struct vdsp_softc *sc, struct vio_msg_tag *);
291 
292 void	vdsp_ldc_reset(struct ldc_conn *);
293 void	vdsp_ldc_start(struct ldc_conn *);
294 
295 void	vdsp_sendmsg(struct vdsp_softc *, void *, size_t, int dowait);
296 
297 void	vdsp_open(void *);
298 void	vdsp_close(void *);
299 void	vdsp_alloc(void *);
300 void	vdsp_readlabel(struct vdsp_softc *);
301 int	vdsp_writelabel(struct vdsp_softc *);
302 int	vdsp_is_iso(struct vdsp_softc *);
303 void	vdsp_read(void *);
304 void	vdsp_read_desc(struct vdsp_softc *, struct vdsk_desc_msg *);
305 void	vdsp_vd_task(void *);
306 void	vdsp_read_dring(void *, void *);
307 void	vdsp_write_dring(void *, void *);
308 void	vdsp_flush_dring(void *, void *);
309 void	vdsp_get_vtoc(void *, void *);
310 void	vdsp_set_vtoc(void *, void *);
311 void	vdsp_get_diskgeom(void *, void *);
312 void	vdsp_unimp(void *, void *);
313 
314 void	vdsp_ack_desc(struct vdsp_softc *, struct vd_desc *);
315 
316 int
317 vdsp_match(struct device *parent, void *match, void *aux)
318 {
319 	struct cbus_attach_args *ca = aux;
320 
321 	if (strcmp(ca->ca_name, "vds-port") == 0)
322 		return (1);
323 
324 	return (0);
325 }
326 
327 void
328 vdsp_attach(struct device *parent, struct device *self, void *aux)
329 {
330 	struct vdsp_softc *sc = (struct vdsp_softc *)self;
331 	struct cbus_attach_args *ca = aux;
332 	struct ldc_conn *lc;
333 
334 	sc->sc_idx = ca->ca_idx;
335 	sc->sc_bustag = ca->ca_bustag;
336 	sc->sc_dmatag = ca->ca_dmatag;
337 	sc->sc_tx_ino = ca->ca_tx_ino;
338 	sc->sc_rx_ino = ca->ca_rx_ino;
339 
340 	printf(": ivec 0x%llx, 0x%llx", sc->sc_tx_ino, sc->sc_rx_ino);
341 
342 	mtx_init(&sc->sc_desc_mtx, IPL_BIO);
343 
344 	/*
345 	 * Un-configure queues before registering interrupt handlers,
346 	 * such that we dont get any stale LDC packets or events.
347 	 */
348 	hv_ldc_tx_qconf(ca->ca_id, 0, 0);
349 	hv_ldc_rx_qconf(ca->ca_id, 0, 0);
350 
351 	sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_ino,
352 	    IPL_BIO, BUS_INTR_ESTABLISH_MPSAFE, vdsp_tx_intr, sc,
353 	    sc->sc_dv.dv_xname);
354 	sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_ino,
355 	    IPL_BIO, BUS_INTR_ESTABLISH_MPSAFE, vdsp_rx_intr, sc,
356 	    sc->sc_dv.dv_xname);
357 	if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
358 		printf(", can't establish interrupt\n");
359 		return;
360 	}
361 
362 	lc = &sc->sc_lc;
363 	lc->lc_id = ca->ca_id;
364 	lc->lc_sc = sc;
365 	lc->lc_reset = vdsp_ldc_reset;
366 	lc->lc_start = vdsp_ldc_start;
367 	lc->lc_rx_data = vdsp_rx_data;
368 
369 	lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VDSK_TX_ENTRIES);
370 	if (lc->lc_txq == NULL) {
371 		printf(", can't allocate tx queue\n");
372 		return;
373 	}
374 
375 	lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VDSK_RX_ENTRIES);
376 	if (lc->lc_rxq == NULL) {
377 		printf(", can't allocate rx queue\n");
378 		goto free_txqueue;
379 	}
380 
381 	task_set(&sc->sc_open_task, vdsp_open, sc);
382 	task_set(&sc->sc_alloc_task, vdsp_alloc, sc);
383 	task_set(&sc->sc_close_task, vdsp_close, sc);
384 	task_set(&sc->sc_read_task, vdsp_read, sc);
385 
386 	printf("\n");
387 
388 	return;
389 
390 #if 0
391 free_rxqueue:
392 	ldc_queue_free(sc->sc_dmatag, lc->lc_rxq);
393 #endif
394 free_txqueue:
395 	ldc_queue_free(sc->sc_dmatag, lc->lc_txq);
396 }
397 
398 int
399 vdsp_tx_intr(void *arg)
400 {
401 	struct vdsp_softc *sc = arg;
402 	struct ldc_conn *lc = &sc->sc_lc;
403 	uint64_t tx_head, tx_tail, tx_state;
404 	int err;
405 
406 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
407 	if (err != H_EOK) {
408 		printf("hv_ldc_rx_get_state %d\n", err);
409 		return (0);
410 	}
411 
412 	if (tx_state != lc->lc_tx_state) {
413 		switch (tx_state) {
414 		case LDC_CHANNEL_DOWN:
415 			DPRINTF(("Tx link down\n"));
416 			break;
417 		case LDC_CHANNEL_UP:
418 			DPRINTF(("Tx link up\n"));
419 			break;
420 		case LDC_CHANNEL_RESET:
421 			DPRINTF(("Tx link reset\n"));
422 			break;
423 		}
424 		lc->lc_tx_state = tx_state;
425 	}
426 
427 	wakeup(lc->lc_txq);
428 	return (1);
429 }
430 
431 int
432 vdsp_rx_intr(void *arg)
433 {
434 	struct vdsp_softc *sc = arg;
435 	struct ldc_conn *lc = &sc->sc_lc;
436 	uint64_t rx_head, rx_tail, rx_state;
437 	struct ldc_pkt *lp;
438 	int err;
439 
440 	err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state);
441 	if (err == H_EINVAL)
442 		return (0);
443 	if (err != H_EOK) {
444 		printf("hv_ldc_rx_get_state %d\n", err);
445 		return (0);
446 	}
447 
448 	if (rx_state != lc->lc_rx_state) {
449 		switch (rx_state) {
450 		case LDC_CHANNEL_DOWN:
451 			DPRINTF(("Rx link down\n"));
452 			lc->lc_tx_seqid = 0;
453 			lc->lc_state = 0;
454 			lc->lc_reset(lc);
455 			break;
456 		case LDC_CHANNEL_UP:
457 			DPRINTF(("Rx link up\n"));
458 			break;
459 		case LDC_CHANNEL_RESET:
460 			DPRINTF(("Rx link reset\n"));
461 			lc->lc_tx_seqid = 0;
462 			lc->lc_state = 0;
463 			lc->lc_reset(lc);
464 			break;
465 		}
466 		lc->lc_rx_state = rx_state;
467 		return (1);
468 	}
469 
470 	if (lc->lc_rx_state == LDC_CHANNEL_DOWN)
471 		return (1);
472 
473 	lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head);
474 	switch (lp->type) {
475 	case LDC_CTRL:
476 		ldc_rx_ctrl(lc, lp);
477 		break;
478 
479 	case LDC_DATA:
480 		ldc_rx_data(lc, lp);
481 		break;
482 
483 	default:
484 		DPRINTF(("0x%02x/0x%02x/0x%02x\n", lp->type, lp->stype,
485 		    lp->ctrl));
486 		ldc_reset(lc);
487 		break;
488 	}
489 
490 	rx_head += sizeof(*lp);
491 	rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1);
492 	err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head);
493 	if (err != H_EOK)
494 		printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
495 
496 	return (1);
497 }
498 
499 void
500 vdsp_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
501 {
502 	struct vio_msg *vm = (struct vio_msg *)lp;
503 
504 	switch (vm->type) {
505 	case VIO_TYPE_CTRL:
506 		if ((lp->env & LDC_FRAG_START) == 0 &&
507 		    (lp->env & LDC_FRAG_STOP) == 0)
508 			return;
509 		vdsp_rx_vio_ctrl(lc->lc_sc, vm);
510 		break;
511 
512 	case VIO_TYPE_DATA:
513 		if((lp->env & LDC_FRAG_START) == 0)
514 			return;
515 		vdsp_rx_vio_data(lc->lc_sc, vm);
516 		break;
517 
518 	default:
519 		DPRINTF(("Unhandled packet type 0x%02x\n", vm->type));
520 		ldc_reset(lc);
521 		break;
522 	}
523 }
524 
525 void
526 vdsp_rx_vio_ctrl(struct vdsp_softc *sc, struct vio_msg *vm)
527 {
528 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
529 
530 	switch (tag->stype_env) {
531 	case VIO_VER_INFO:
532 		vdsp_rx_vio_ver_info(sc, tag);
533 		break;
534 	case VIO_ATTR_INFO:
535 		vdsp_rx_vio_attr_info(sc, tag);
536 		break;
537 	case VIO_DRING_REG:
538 		vdsp_rx_vio_dring_reg(sc, tag);
539 		break;
540 	case VIO_RDX:
541 		vdsp_rx_vio_rdx(sc, tag);
542 		break;
543 	default:
544 		DPRINTF(("CTRL/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
545 		break;
546 	}
547 }
548 
549 void
550 vdsp_rx_vio_ver_info(struct vdsp_softc *sc, struct vio_msg_tag *tag)
551 {
552 	struct vio_ver_info *vi = (struct vio_ver_info *)tag;
553 
554 	switch (vi->tag.stype) {
555 	case VIO_SUBTYPE_INFO:
556 		DPRINTF(("CTRL/INFO/VER_INFO\n"));
557 
558 		/* Make sure we're talking to a virtual disk. */
559 		if (vi->dev_class != VDEV_DISK) {
560 			/* Huh, we're not talking to a disk device? */
561 			printf("%s: peer is not a disk device\n",
562 			    sc->sc_dv.dv_xname);
563 			vi->tag.stype = VIO_SUBTYPE_NACK;
564 			vi->major = 0;
565 			vdsp_sendmsg(sc, vi, sizeof(*vi), 0);
566 			return;
567 		}
568 
569 		if (vi->major != VDSK_MAJOR) {
570 			vi->tag.stype = VIO_SUBTYPE_NACK;
571 			vi->major = VDSK_MAJOR;
572 			vi->minor = VDSK_MINOR;
573 			vdsp_sendmsg(sc, vi, sizeof(*vi), 0);
574 			return;
575 		}
576 
577 		sc->sc_major = vi->major;
578 		sc->sc_minor = vi->minor;
579 		sc->sc_local_sid = vi->tag.sid;
580 
581 		vi->tag.stype = VIO_SUBTYPE_ACK;
582 		if (vi->minor > VDSK_MINOR)
583 			vi->minor = VDSK_MINOR;
584 		vi->dev_class = VDEV_DISK_SERVER;
585 		vdsp_sendmsg(sc, vi, sizeof(*vi), 0);
586 		sc->sc_vio_state |= VIO_RCV_VER_INFO;
587 		break;
588 
589 	case VIO_SUBTYPE_ACK:
590 		DPRINTF(("CTRL/ACK/VER_INFO\n"));
591 		break;
592 
593 	default:
594 		DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype));
595 		break;
596 	}
597 }
598 
599 void
600 vdsp_rx_vio_attr_info(struct vdsp_softc *sc, struct vio_msg_tag *tag)
601 {
602 	struct vd_attr_info *ai = (struct vd_attr_info *)tag;
603 
604 	switch (ai->tag.stype) {
605 	case VIO_SUBTYPE_INFO:
606 		DPRINTF(("CTRL/INFO/ATTR_INFO\n"));
607 
608 		if (ai->xfer_mode != VIO_DESC_MODE &&
609 		    ai->xfer_mode != VIO_DRING_MODE) {
610 			printf("%s: peer uses unsupported xfer mode 0x%02x\n",
611 			    sc->sc_dv.dv_xname, ai->xfer_mode);
612 			ai->tag.stype = VIO_SUBTYPE_NACK;
613 			vdsp_sendmsg(sc, ai, sizeof(*ai), 0);
614 			return;
615 		}
616 		sc->sc_xfer_mode = ai->xfer_mode;
617 		sc->sc_vio_state |= VIO_RCV_ATTR_INFO;
618 
619 		task_add(systq, &sc->sc_open_task);
620 		break;
621 
622 	case VIO_SUBTYPE_ACK:
623 		DPRINTF(("CTRL/ACK/ATTR_INFO\n"));
624 		break;
625 
626 	default:
627 		DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype));
628 		break;
629 	}
630 }
631 
632 void
633 vdsp_rx_vio_dring_reg(struct vdsp_softc *sc, struct vio_msg_tag *tag)
634 {
635 	struct vio_dring_reg *dr = (struct vio_dring_reg *)tag;
636 
637 	switch (dr->tag.stype) {
638 	case VIO_SUBTYPE_INFO:
639 		DPRINTF(("CTRL/INFO/DRING_REG\n"));
640 
641 		if (dr->num_descriptors > VDSK_MAX_DESCRIPTORS ||
642 		    dr->descriptor_size > VDSK_MAX_DESCRIPTOR_SIZE ||
643 		    dr->ncookies > 1) {
644 			dr->tag.stype = VIO_SUBTYPE_NACK;
645 			vdsp_sendmsg(sc, dr, sizeof(*dr), 0);
646 			return;
647 		}
648 		sc->sc_num_descriptors = dr->num_descriptors;
649 		sc->sc_descriptor_size = dr->descriptor_size;
650 		sc->sc_dring_cookie = dr->cookie[0];
651 		sc->sc_vio_state |= VIO_RCV_DRING_REG;
652 
653 		task_add(systq, &sc->sc_alloc_task);
654 		break;
655 
656 	case VIO_SUBTYPE_ACK:
657 		DPRINTF(("CTRL/ACK/DRING_REG\n"));
658 		break;
659 
660 	default:
661 		DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype));
662 		break;
663 	}
664 }
665 
666 void
667 vdsp_rx_vio_rdx(struct vdsp_softc *sc, struct vio_msg_tag *tag)
668 {
669 	switch(tag->stype) {
670 	case VIO_SUBTYPE_INFO:
671 		DPRINTF(("CTRL/INFO/RDX\n"));
672 
673 		tag->stype = VIO_SUBTYPE_ACK;
674 		tag->sid = sc->sc_local_sid;
675 		vdsp_sendmsg(sc, tag, sizeof(*tag), 0);
676 		sc->sc_vio_state |= VIO_RCV_RDX;
677 		break;
678 
679 	case VIO_SUBTYPE_ACK:
680 		DPRINTF(("CTRL/ACK/RDX\n"));
681 		break;
682 
683 	default:
684 		DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype));
685 		break;
686 	}
687 }
688 
689 void
690 vdsp_rx_vio_data(struct vdsp_softc *sc, struct vio_msg *vm)
691 {
692 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
693 
694 	if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX)) {
695 		DPRINTF(("Spurious DATA/0x%02x/0x%04x\n", tag->stype,
696 		    tag->stype_env));
697 		return;
698 	}
699 
700 	switch(tag->stype_env) {
701 	case VIO_DESC_DATA:
702 		vdsp_rx_vio_desc_data(sc, tag);
703 		break;
704 
705 	case VIO_DRING_DATA:
706 		vdsp_rx_vio_dring_data(sc, tag);
707 		break;
708 
709 	default:
710 		DPRINTF(("DATA/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
711 		break;
712 	}
713 }
714 
715 void
716 vdsp_rx_vio_dring_data(struct vdsp_softc *sc, struct vio_msg_tag *tag)
717 {
718 	struct vio_dring_msg *dm = (struct vio_dring_msg *)tag;
719 	struct vd_desc *vd;
720 	vaddr_t va;
721 	paddr_t pa;
722 	uint64_t size, off;
723 	psize_t nbytes;
724 	int err;
725 
726 	switch(tag->stype) {
727 	case VIO_SUBTYPE_INFO:
728 		DPRINTF(("DATA/INFO/DRING_DATA\n"));
729 
730 		if (dm->dring_ident != sc->sc_dring_ident ||
731 		    dm->start_idx >= sc->sc_num_descriptors) {
732 			dm->tag.stype = VIO_SUBTYPE_NACK;
733 			vdsp_sendmsg(sc, dm, sizeof(*dm), 0);
734 			return;
735 		}
736 
737 		off = dm->start_idx * sc->sc_descriptor_size;
738 		vd = (struct vd_desc *)(sc->sc_vd + off);
739 		va = (vaddr_t)vd;
740 		size = sc->sc_descriptor_size;
741 		while (size > 0) {
742 			pmap_extract(pmap_kernel(), va, &pa);
743 			nbytes = MIN(size, PAGE_SIZE - (off & PAGE_MASK));
744 			err = hv_ldc_copy(sc->sc_lc.lc_id, LDC_COPY_IN,
745 			    sc->sc_dring_cookie.addr + off, pa,
746 			    nbytes, &nbytes);
747 			if (err != H_EOK) {
748 				printf("%s: hv_ldc_copy %d\n", __func__, err);
749 				return;
750 			}
751 			va += nbytes;
752 			size -= nbytes;
753 			off += nbytes;
754 		}
755 
756 		sc->sc_vd_ring[sc->sc_vd_prod % sc->sc_num_descriptors] = vd;
757 		membar_producer();
758 		sc->sc_vd_prod++;
759 		task_add(systq, &sc->sc_vd_task);
760 
761 		break;
762 
763 	case VIO_SUBTYPE_ACK:
764 		DPRINTF(("DATA/ACK/DRING_DATA\n"));
765 		break;
766 
767 	case VIO_SUBTYPE_NACK:
768 		DPRINTF(("DATA/NACK/DRING_DATA\n"));
769 		break;
770 
771 	default:
772 		DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype));
773 		break;
774 	}
775 }
776 
777 void
778 vdsp_vd_task(void *xsc)
779 {
780 	struct vdsp_softc *sc = xsc;
781 	struct vd_desc *vd;
782 
783 	while (sc->sc_vd_cons != sc->sc_vd_prod) {
784 		membar_consumer();
785 		vd = sc->sc_vd_ring[sc->sc_vd_cons++ % sc->sc_num_descriptors];
786 
787 		DPRINTF(("%s: operation %x\n", sc->sc_dv.dv_xname,
788 		    vd->operation));
789 		switch (vd->operation) {
790 		case VD_OP_BREAD:
791 			vdsp_read_dring(sc, vd);
792 			break;
793 		case VD_OP_BWRITE:
794 			vdsp_write_dring(sc, vd);
795 			break;
796 		case VD_OP_FLUSH:
797 			vdsp_flush_dring(sc, vd);
798 			break;
799 		case VD_OP_GET_VTOC:
800 			vdsp_get_vtoc(sc, vd);
801 			break;
802 		case VD_OP_SET_VTOC:
803 			vdsp_set_vtoc(sc, vd);
804 			break;
805 		case VD_OP_GET_DISKGEOM:
806 			vdsp_get_diskgeom(sc, vd);
807 			break;
808 		case VD_OP_GET_WCE:
809 		case VD_OP_SET_WCE:
810 		case VD_OP_GET_DEVID:
811 			/*
812 			 * Solaris issues VD_OP_GET_DEVID despite the
813 			 * fact that we don't advertise it.  It seems
814 			 * to be able to handle failure just fine, so
815 			 * we silently ignore it.
816 			 */
817 			vdsp_unimp(sc, vd);
818 			break;
819 		default:
820 			printf("%s: unsupported operation 0x%02x\n",
821 			    sc->sc_dv.dv_xname, vd->operation);
822 			vdsp_unimp(sc, vd);
823 			break;
824 		}
825 	}
826 }
827 
828 void
829 vdsp_rx_vio_desc_data(struct vdsp_softc *sc, struct vio_msg_tag *tag)
830 {
831 	struct vdsk_desc_msg *dm = (struct vdsk_desc_msg *)tag;
832 
833 	switch(tag->stype) {
834 	case VIO_SUBTYPE_INFO:
835 		DPRINTF(("DATA/INFO/DESC_DATA\n"));
836 
837 		switch (dm->operation) {
838 		case VD_OP_BREAD:
839 			mtx_enter(&sc->sc_desc_mtx);
840 			sc->sc_desc_msg[sc->sc_desc_head++] = dm;
841 			sc->sc_desc_head &= (VDSK_RX_ENTRIES - 1);
842 			KASSERT(sc->sc_desc_head != sc->sc_desc_tail);
843 			mtx_leave(&sc->sc_desc_mtx);
844 			task_add(systq, &sc->sc_read_task);
845 			break;
846 		default:
847 			printf("%s: unsupported operation 0x%02x\n",
848 			    sc->sc_dv.dv_xname, dm->operation);
849 			break;
850 		}
851 		break;
852 
853 	case VIO_SUBTYPE_ACK:
854 		DPRINTF(("DATA/ACK/DESC_DATA\n"));
855 		break;
856 
857 	case VIO_SUBTYPE_NACK:
858 		DPRINTF(("DATA/NACK/DESC_DATA\n"));
859 		break;
860 
861 	default:
862 		DPRINTF(("DATA/0x%02x/DESC_DATA\n", tag->stype));
863 		break;
864 	}
865 }
866 
867 void
868 vdsp_ldc_reset(struct ldc_conn *lc)
869 {
870 	struct vdsp_softc *sc = lc->lc_sc;
871 
872 	sc->sc_vio_state = 0;
873 	task_add(systq, &sc->sc_close_task);
874 }
875 
876 void
877 vdsp_ldc_start(struct ldc_conn *lc)
878 {
879 	/* The vDisk client is supposed to initiate the handshake. */
880 }
881 
882 void
883 vdsp_sendmsg(struct vdsp_softc *sc, void *msg, size_t len, int dowait)
884 {
885 	struct ldc_conn *lc = &sc->sc_lc;
886 	int err;
887 
888 	do {
889 		err = ldc_send_unreliable(lc, msg, len);
890 		if (dowait && err == EWOULDBLOCK) {
891 			/*
892 			 * Seems like the hypervisor doesn't actually
893 			 * generate interrupts for transmit queues, so
894 			 * we specify a timeout such that we don't
895 			 * block forever.
896 			 */
897 			err = tsleep(lc->lc_txq, PWAIT, "vdsp", 1);
898 		}
899 	} while (dowait && err == EWOULDBLOCK);
900 }
901 
902 void
903 vdsp_open(void *arg1)
904 {
905 	struct vdsp_softc *sc = arg1;
906 	struct proc *p = curproc;
907 	struct vd_attr_info ai;
908 
909 	if (sc->sc_vp == NULL) {
910 		struct nameidata nd;
911 		struct vattr va;
912 		struct partinfo pi;
913 		const char *name;
914 		dev_t dev;
915 		int error;
916 
917 		name = mdesc_get_prop_str(sc->sc_idx, "vds-block-device");
918 		if (name == NULL)
919 			return;
920 
921 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
922 		error = vn_open(&nd, FREAD | FWRITE, 0);
923 		if (error) {
924 			printf("VOP_OPEN: %s, %d\n", name, error);
925 			return;
926 		}
927 
928 		if (nd.ni_vp->v_type == VBLK) {
929 			dev = nd.ni_vp->v_rdev;
930 			error = (*bdevsw[major(dev)].d_ioctl)(dev,
931 			    DIOCGPART, (caddr_t)&pi, FREAD, curproc);
932 			if (error)
933 				printf("DIOCGPART: %s, %d\n", name, error);
934 			sc->sc_vdisk_block_size = pi.disklab->d_secsize;
935 			sc->sc_vdisk_size = DL_GETPSIZE(pi.part);
936 		} else {
937 			error = VOP_GETATTR(nd.ni_vp, &va, p->p_ucred, p);
938 			if (error)
939 				printf("VOP_GETATTR: %s, %d\n", name, error);
940 			sc->sc_vdisk_block_size = DEV_BSIZE;
941 			sc->sc_vdisk_size = va.va_size / DEV_BSIZE;
942 		}
943 
944 		VOP_UNLOCK(nd.ni_vp, p);
945 		sc->sc_vp = nd.ni_vp;
946 
947 		vdsp_readlabel(sc);
948 	}
949 
950 	bzero(&ai, sizeof(ai));
951 	ai.tag.type = VIO_TYPE_CTRL;
952 	ai.tag.stype = VIO_SUBTYPE_ACK;
953 	ai.tag.stype_env = VIO_ATTR_INFO;
954 	ai.tag.sid = sc->sc_local_sid;
955 	ai.xfer_mode = sc->sc_xfer_mode;
956 	ai.vd_type = VD_DISK_TYPE_DISK;
957 	if (sc->sc_major > 1 || sc->sc_minor >= 1) {
958 		if (vdsp_is_iso(sc))
959 			ai.vd_mtype = VD_MEDIA_TYPE_CD;
960 		else
961 			ai.vd_mtype = VD_MEDIA_TYPE_FIXED;
962 	}
963 	ai.vdisk_block_size = sc->sc_vdisk_block_size;
964 	ai.operations = VD_OP_MASK;
965 	ai.vdisk_size = sc->sc_vdisk_size;
966 	ai.max_xfer_sz = MAXPHYS / sc->sc_vdisk_block_size;
967 	vdsp_sendmsg(sc, &ai, sizeof(ai), 1);
968 }
969 
970 void
971 vdsp_close(void *arg1)
972 {
973 	struct vdsp_softc *sc = arg1;
974 	struct proc *p = curproc;
975 
976 	sc->sc_seq_no = 0;
977 
978 	free(sc->sc_vd, M_DEVBUF, 0);
979 	sc->sc_vd = NULL;
980 	free(sc->sc_vd_ring, M_DEVBUF,
981 	     sc->sc_num_descriptors * sizeof(*sc->sc_vd_ring));
982 	sc->sc_vd_ring = NULL;
983 	free(sc->sc_label, M_DEVBUF, 0);
984 	sc->sc_label = NULL;
985 	if (sc->sc_vp) {
986 		vn_close(sc->sc_vp, FREAD | FWRITE, p->p_ucred, p);
987 		sc->sc_vp = NULL;
988 	}
989 }
990 
991 void
992 vdsp_readlabel(struct vdsp_softc *sc)
993 {
994 	struct proc *p = curproc;
995 	struct iovec iov;
996 	struct uio uio;
997 	int err;
998 
999 	if (sc->sc_vp == NULL)
1000 		return;
1001 
1002 	sc->sc_label = malloc(sizeof(*sc->sc_label), M_DEVBUF, M_WAITOK);
1003 
1004 	iov.iov_base = sc->sc_label;
1005 	iov.iov_len = sizeof(*sc->sc_label);
1006 	uio.uio_iov = &iov;
1007 	uio.uio_iovcnt = 1;
1008 	uio.uio_offset = 0;
1009 	uio.uio_resid = sizeof(*sc->sc_label);
1010 	uio.uio_segflg = UIO_SYSSPACE;
1011 	uio.uio_rw = UIO_READ;
1012 	uio.uio_procp = p;
1013 
1014 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1015 	err = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred);
1016 	VOP_UNLOCK(sc->sc_vp, p);
1017 	if (err) {
1018 		free(sc->sc_label, M_DEVBUF, 0);
1019 		sc->sc_label = NULL;
1020 	}
1021 }
1022 
1023 int
1024 vdsp_writelabel(struct vdsp_softc *sc)
1025 {
1026 	struct proc *p = curproc;
1027 	struct iovec iov;
1028 	struct uio uio;
1029 	int err;
1030 
1031 	if (sc->sc_vp == NULL || sc->sc_label == NULL)
1032 		return (EINVAL);
1033 
1034 	iov.iov_base = sc->sc_label;
1035 	iov.iov_len = sizeof(*sc->sc_label);
1036 	uio.uio_iov = &iov;
1037 	uio.uio_iovcnt = 1;
1038 	uio.uio_offset = 0;
1039 	uio.uio_resid = sizeof(*sc->sc_label);
1040 	uio.uio_segflg = UIO_SYSSPACE;
1041 	uio.uio_rw = UIO_WRITE;
1042 	uio.uio_procp = p;
1043 
1044 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1045 	err = VOP_WRITE(sc->sc_vp, &uio, 0, p->p_ucred);
1046 	VOP_UNLOCK(sc->sc_vp, p);
1047 
1048 	return (err);
1049 }
1050 
1051 int
1052 vdsp_is_iso(struct vdsp_softc *sc)
1053 {
1054 	struct proc *p = curproc;
1055 	struct iovec iov;
1056 	struct uio uio;
1057 	struct iso_volume_descriptor *vdp;
1058 	int err;
1059 
1060 	if (sc->sc_vp == NULL)
1061 		return (0);
1062 
1063 	vdp = malloc(sizeof(*vdp), M_DEVBUF, M_WAITOK);
1064 
1065 	iov.iov_base = vdp;
1066 	iov.iov_len = sizeof(*vdp);
1067 	uio.uio_iov = &iov;
1068 	uio.uio_iovcnt = 1;
1069 	uio.uio_offset = 16 * ISO_DEFAULT_BLOCK_SIZE;
1070 	uio.uio_resid = sizeof(*vdp);
1071 	uio.uio_segflg = UIO_SYSSPACE;
1072 	uio.uio_rw = UIO_READ;
1073 	uio.uio_procp = p;
1074 
1075 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1076 	err = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred);
1077 	VOP_UNLOCK(sc->sc_vp, p);
1078 
1079 	if (err == 0 && memcmp(vdp->id, ISO_STANDARD_ID, sizeof(vdp->id)))
1080 		err = ENOENT;
1081 
1082 	free(vdp, M_DEVBUF, 0);
1083 	return (err == 0);
1084 }
1085 
1086 void
1087 vdsp_alloc(void *arg1)
1088 {
1089 	struct vdsp_softc *sc = arg1;
1090 	struct vio_dring_reg dr;
1091 
1092 	KASSERT(sc->sc_num_descriptors <= VDSK_MAX_DESCRIPTORS);
1093 	KASSERT(sc->sc_descriptor_size <= VDSK_MAX_DESCRIPTOR_SIZE);
1094 	sc->sc_vd = mallocarray(sc->sc_num_descriptors,
1095 	    sc->sc_descriptor_size, M_DEVBUF, M_WAITOK);
1096 	sc->sc_vd_ring = mallocarray(sc->sc_num_descriptors,
1097 	    sizeof(*sc->sc_vd_ring), M_DEVBUF, M_WAITOK);
1098 	task_set(&sc->sc_vd_task, vdsp_vd_task, sc);
1099 
1100 	bzero(&dr, sizeof(dr));
1101 	dr.tag.type = VIO_TYPE_CTRL;
1102 	dr.tag.stype = VIO_SUBTYPE_ACK;
1103 	dr.tag.stype_env = VIO_DRING_REG;
1104 	dr.tag.sid = sc->sc_local_sid;
1105 	dr.dring_ident = ++sc->sc_dring_ident;
1106 	vdsp_sendmsg(sc, &dr, sizeof(dr), 1);
1107 }
1108 
1109 void
1110 vdsp_read(void *arg1)
1111 {
1112 	struct vdsp_softc *sc = arg1;
1113 
1114 	mtx_enter(&sc->sc_desc_mtx);
1115 	while (sc->sc_desc_tail != sc->sc_desc_head) {
1116 		mtx_leave(&sc->sc_desc_mtx);
1117 		vdsp_read_desc(sc, sc->sc_desc_msg[sc->sc_desc_tail]);
1118 		mtx_enter(&sc->sc_desc_mtx);
1119 		sc->sc_desc_tail++;
1120 		sc->sc_desc_tail &= (VDSK_RX_ENTRIES - 1);
1121 	}
1122 	mtx_leave(&sc->sc_desc_mtx);
1123 }
1124 
1125 void
1126 vdsp_read_desc(struct vdsp_softc *sc, struct vdsk_desc_msg *dm)
1127 {
1128 	struct ldc_conn *lc = &sc->sc_lc;
1129 	struct proc *p = curproc;
1130 	struct iovec iov;
1131 	struct uio uio;
1132 	caddr_t buf;
1133 	vaddr_t va;
1134 	paddr_t pa;
1135 	uint64_t size, off;
1136 	psize_t nbytes;
1137 	int err, i;
1138 
1139 	if (sc->sc_vp == NULL)
1140 		return;
1141 
1142 	buf = malloc(dm->size, M_DEVBUF, M_WAITOK);
1143 
1144 	iov.iov_base = buf;
1145 	iov.iov_len = dm->size;
1146 	uio.uio_iov = &iov;
1147 	uio.uio_iovcnt = 1;
1148 	uio.uio_offset = dm->offset * DEV_BSIZE;
1149 	uio.uio_resid = dm->size;
1150 	uio.uio_segflg = UIO_SYSSPACE;
1151 	uio.uio_rw = UIO_READ;
1152 	uio.uio_procp = p;
1153 
1154 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1155 	dm->status = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred);
1156 	VOP_UNLOCK(sc->sc_vp, p);
1157 
1158 	KERNEL_UNLOCK();
1159 	if (dm->status == 0) {
1160 		i = 0;
1161 		va = (vaddr_t)buf;
1162 		size = dm->size;
1163 		off = 0;
1164 		while (size > 0 && i < dm->ncookies) {
1165 			pmap_extract(pmap_kernel(), va, &pa);
1166 			nbytes = MIN(size, dm->cookie[i].size - off);
1167 			nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1168 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT,
1169 			    dm->cookie[i].addr + off, pa, nbytes, &nbytes);
1170 			if (err != H_EOK) {
1171 				printf("%s: hv_ldc_copy: %d\n", __func__, err);
1172 				dm->status = EIO;
1173 				KERNEL_LOCK();
1174 				goto fail;
1175 			}
1176 			va += nbytes;
1177 			size -= nbytes;
1178 			off += nbytes;
1179 			if (off >= dm->cookie[i].size) {
1180 				off = 0;
1181 				i++;
1182 			}
1183 		}
1184 	}
1185 	KERNEL_LOCK();
1186 
1187 fail:
1188 	free(buf, M_DEVBUF, 0);
1189 
1190 	/* ACK the descriptor. */
1191 	dm->tag.stype = VIO_SUBTYPE_ACK;
1192 	dm->tag.sid = sc->sc_local_sid;
1193 	vdsp_sendmsg(sc, dm, sizeof(*dm) +
1194 	    (dm->ncookies - 1) * sizeof(struct ldc_cookie), 1);
1195 }
1196 
1197 void
1198 vdsp_read_dring(void *arg1, void *arg2)
1199 {
1200 	struct vdsp_softc *sc = arg1;
1201 	struct ldc_conn *lc = &sc->sc_lc;
1202 	struct vd_desc *vd = arg2;
1203 	struct proc *p = curproc;
1204 	struct iovec iov;
1205 	struct uio uio;
1206 	caddr_t buf;
1207 	vaddr_t va;
1208 	paddr_t pa;
1209 	uint64_t size, off;
1210 	psize_t nbytes;
1211 	int err, i;
1212 
1213 	if (sc->sc_vp == NULL)
1214 		return;
1215 
1216 	buf = malloc(vd->size, M_DEVBUF, M_WAITOK);
1217 
1218 	iov.iov_base = buf;
1219 	iov.iov_len = vd->size;
1220 	uio.uio_iov = &iov;
1221 	uio.uio_iovcnt = 1;
1222 	uio.uio_offset = vd->offset * DEV_BSIZE;
1223 	uio.uio_resid = vd->size;
1224 	uio.uio_segflg = UIO_SYSSPACE;
1225 	uio.uio_rw = UIO_READ;
1226 	uio.uio_procp = p;
1227 
1228 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1229 	vd->status = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred);
1230 	VOP_UNLOCK(sc->sc_vp, p);
1231 
1232 	KERNEL_UNLOCK();
1233 	if (vd->status == 0) {
1234 		i = 0;
1235 		va = (vaddr_t)buf;
1236 		size = vd->size;
1237 		off = 0;
1238 		while (size > 0 && i < vd->ncookies) {
1239 			pmap_extract(pmap_kernel(), va, &pa);
1240 			nbytes = MIN(size, vd->cookie[i].size - off);
1241 			nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1242 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT,
1243 			    vd->cookie[i].addr + off, pa, nbytes, &nbytes);
1244 			if (err != H_EOK) {
1245 				printf("%s: hv_ldc_copy: %d\n", __func__, err);
1246 				vd->status = EIO;
1247 				KERNEL_LOCK();
1248 				goto fail;
1249 			}
1250 			va += nbytes;
1251 			size -= nbytes;
1252 			off += nbytes;
1253 			if (off >= vd->cookie[i].size) {
1254 				off = 0;
1255 				i++;
1256 			}
1257 		}
1258 	}
1259 	KERNEL_LOCK();
1260 
1261 fail:
1262 	free(buf, M_DEVBUF, 0);
1263 
1264 	/* ACK the descriptor. */
1265 	vd->hdr.dstate = VIO_DESC_DONE;
1266 	vdsp_ack_desc(sc, vd);
1267 }
1268 
1269 void
1270 vdsp_write_dring(void *arg1, void *arg2)
1271 {
1272 	struct vdsp_softc *sc = arg1;
1273 	struct ldc_conn *lc = &sc->sc_lc;
1274 	struct vd_desc *vd = arg2;
1275 	struct proc *p = curproc;
1276 	struct iovec iov;
1277 	struct uio uio;
1278 	caddr_t buf;
1279 	vaddr_t va;
1280 	paddr_t pa;
1281 	uint64_t size, off;
1282 	psize_t nbytes;
1283 	int err, i;
1284 
1285 	if (sc->sc_vp == NULL)
1286 		return;
1287 
1288 	buf = malloc(vd->size, M_DEVBUF, M_WAITOK);
1289 
1290 	KERNEL_UNLOCK();
1291 	i = 0;
1292 	va = (vaddr_t)buf;
1293 	size = vd->size;
1294 	off = 0;
1295 	while (size > 0 && i < vd->ncookies) {
1296 		pmap_extract(pmap_kernel(), va, &pa);
1297 		nbytes = MIN(size, vd->cookie[i].size - off);
1298 		nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1299 		err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
1300 		    vd->cookie[i].addr + off, pa, nbytes, &nbytes);
1301 		if (err != H_EOK) {
1302 			printf("%s: hv_ldc_copy: %d\n", __func__, err);
1303 			vd->status = EIO;
1304 			KERNEL_LOCK();
1305 			goto fail;
1306 		}
1307 		va += nbytes;
1308 		size -= nbytes;
1309 		off += nbytes;
1310 		if (off >= vd->cookie[i].size) {
1311 			off = 0;
1312 			i++;
1313 		}
1314 	}
1315 	KERNEL_LOCK();
1316 
1317 	iov.iov_base = buf;
1318 	iov.iov_len = vd->size;
1319 	uio.uio_iov = &iov;
1320 	uio.uio_iovcnt = 1;
1321 	uio.uio_offset = vd->offset * DEV_BSIZE;
1322 	uio.uio_resid = vd->size;
1323 	uio.uio_segflg = UIO_SYSSPACE;
1324 	uio.uio_rw = UIO_WRITE;
1325 	uio.uio_procp = p;
1326 
1327 	vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p);
1328 	vd->status = VOP_WRITE(sc->sc_vp, &uio, 0, p->p_ucred);
1329 	VOP_UNLOCK(sc->sc_vp, p);
1330 
1331 fail:
1332 	free(buf, M_DEVBUF, 0);
1333 
1334 	/* ACK the descriptor. */
1335 	vd->hdr.dstate = VIO_DESC_DONE;
1336 	vdsp_ack_desc(sc, vd);
1337 }
1338 
1339 void
1340 vdsp_flush_dring(void *arg1, void *arg2)
1341 {
1342 	struct vdsp_softc *sc = arg1;
1343 	struct vd_desc *vd = arg2;
1344 
1345 	if (sc->sc_vp == NULL)
1346 		return;
1347 
1348 	/* ACK the descriptor. */
1349 	vd->status = 0;
1350 	vd->hdr.dstate = VIO_DESC_DONE;
1351 	vdsp_ack_desc(sc, vd);
1352 }
1353 
1354 void
1355 vdsp_get_vtoc(void *arg1, void *arg2)
1356 {
1357 	struct vdsp_softc *sc = arg1;
1358 	struct ldc_conn *lc = &sc->sc_lc;
1359 	struct vd_desc *vd = arg2;
1360 	struct sun_vtoc_preamble *sl;
1361 	struct vd_vtoc *vt;
1362 	vaddr_t va;
1363 	paddr_t pa;
1364 	uint64_t size, off;
1365 	psize_t nbytes;
1366 	int err, i;
1367 
1368 	vt = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
1369 
1370 	if (sc->sc_label == NULL)
1371 		vdsp_readlabel(sc);
1372 
1373 	if (sc->sc_label && sc->sc_label->sl_magic == SUN_DKMAGIC) {
1374 		sl = (struct sun_vtoc_preamble *)sc->sc_label;
1375 
1376 		memcpy(vt->ascii_label, sl->sl_text, sizeof(sl->sl_text));
1377 		memcpy(vt->volume_name, sl->sl_volume, sizeof(sl->sl_volume));
1378 		vt->sector_size = DEV_BSIZE;
1379 		vt->num_partitions = sl->sl_nparts;
1380 		for (i = 0; i < vt->num_partitions; i++) {
1381 			vt->partition[i].id_tag = sl->sl_part[i].spi_tag;
1382 			vt->partition[i].perm = sl->sl_part[i].spi_flag;
1383 			vt->partition[i].start =
1384 			    sc->sc_label->sl_part[i].sdkp_cyloffset *
1385 				sc->sc_label->sl_ntracks *
1386 				sc->sc_label->sl_nsectors;
1387 			vt->partition[i].nblocks =
1388 			    sc->sc_label->sl_part[i].sdkp_nsectors;
1389 		}
1390 	} else {
1391 		uint64_t disk_size;
1392 		int unit;
1393 
1394 		/* Human-readable disk size. */
1395 		disk_size = sc->sc_vdisk_size * sc->sc_vdisk_block_size;
1396 		disk_size >>= 10;
1397 		unit = 'K';
1398 		if (disk_size > (2 << 10)) {
1399 			disk_size >>= 10;
1400 			unit = 'M';
1401 		}
1402 		if (disk_size > (2 << 10)) {
1403 			disk_size >>= 10;
1404 			unit = 'G';
1405 		}
1406 
1407 		snprintf(vt->ascii_label, sizeof(vt->ascii_label),
1408 		    "OpenBSD-DiskImage-%lld%cB cyl %d alt %d hd %d sec %d",
1409 		    disk_size, unit, sc->sc_ncyl, sc->sc_acyl,
1410 		    sc->sc_nhead, sc->sc_nsect);
1411 		vt->sector_size = sc->sc_vdisk_block_size;
1412 		vt->num_partitions = 8;
1413 		vt->partition[2].id_tag = SPTAG_WHOLE_DISK;
1414 		vt->partition[2].nblocks =
1415 		    sc->sc_ncyl * sc->sc_nhead * sc->sc_nsect;
1416 	}
1417 
1418 	i = 0;
1419 	va = (vaddr_t)vt;
1420 	size = roundup(sizeof(*vt), 64);
1421 	off = 0;
1422 	while (size > 0 && i < vd->ncookies) {
1423 		pmap_extract(pmap_kernel(), va, &pa);
1424 		nbytes = MIN(size, vd->cookie[i].size - off);
1425 		nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1426 		err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT,
1427 		    vd->cookie[i].addr + off, pa, nbytes, &nbytes);
1428 		if (err != H_EOK) {
1429 			printf("%s: hv_ldc_copy: %d\n", __func__, err);
1430 			vd->status = EIO;
1431 			goto fail;
1432 		}
1433 		va += nbytes;
1434 		size -= nbytes;
1435 		off += nbytes;
1436 		if (off >= vd->cookie[i].size) {
1437 			off = 0;
1438 			i++;
1439 		}
1440 	}
1441 
1442 	vd->status = 0;
1443 
1444 fail:
1445 	free(vt, M_DEVBUF, 0);
1446 
1447 	/* ACK the descriptor. */
1448 	vd->hdr.dstate = VIO_DESC_DONE;
1449 	vdsp_ack_desc(sc, vd);
1450 }
1451 
1452 void
1453 vdsp_set_vtoc(void *arg1, void *arg2)
1454 {
1455 	struct vdsp_softc *sc = arg1;
1456 	struct ldc_conn *lc = &sc->sc_lc;
1457 	struct vd_desc *vd = arg2;
1458 	struct sun_vtoc_preamble *sl;
1459 	struct vd_vtoc *vt;
1460 	u_short cksum = 0, *sp1, *sp2;
1461 	vaddr_t va;
1462 	paddr_t pa;
1463 	uint64_t size, off;
1464 	psize_t nbytes;
1465 	int err, i;
1466 
1467 	vt = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
1468 
1469 	i = 0;
1470 	va = (vaddr_t)vt;
1471 	size = sizeof(*vt);
1472 	off = 0;
1473 	while (size > 0 && i < vd->ncookies) {
1474 		pmap_extract(pmap_kernel(), va, &pa);
1475 		nbytes = MIN(size, vd->cookie[i].size - off);
1476 		nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1477 		err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
1478 		    vd->cookie[i].addr + off, pa, nbytes, &nbytes);
1479 		if (err != H_EOK) {
1480 			printf("%s: hv_ldc_copy: %d\n", __func__, err);
1481 			vd->status = EIO;
1482 			goto fail;
1483 		}
1484 		va += nbytes;
1485 		size -= nbytes;
1486 		off += nbytes;
1487 		if (off >= vd->cookie[i].size) {
1488 			off = 0;
1489 			i++;
1490 		}
1491 	}
1492 
1493 	if (vt->num_partitions > nitems(sc->sc_label->sl_part)) {
1494 		vd->status = EINVAL;
1495 		goto fail;
1496 	}
1497 
1498 	if (sc->sc_label == NULL || sc->sc_label->sl_magic != SUN_DKMAGIC) {
1499 		sc->sc_label = malloc(sizeof(*sc->sc_label),
1500 		    M_DEVBUF, M_WAITOK | M_ZERO);
1501 
1502 		sc->sc_label->sl_ntracks = sc->sc_nhead;
1503 		sc->sc_label->sl_nsectors = sc->sc_nsect;
1504 		sc->sc_label->sl_ncylinders = sc->sc_ncyl;
1505 		sc->sc_label->sl_acylinders = sc->sc_acyl;
1506 		sc->sc_label->sl_pcylinders = sc->sc_ncyl + sc->sc_acyl;
1507 		sc->sc_label->sl_rpm = 3600;
1508 
1509 		sc->sc_label->sl_magic = SUN_DKMAGIC;
1510 	}
1511 
1512 	sl = (struct sun_vtoc_preamble *)sc->sc_label;
1513 	memcpy(sl->sl_text, vt->ascii_label, sizeof(sl->sl_text));
1514 	sl->sl_version = 0x01;
1515 	memcpy(sl->sl_volume, vt->volume_name, sizeof(sl->sl_volume));
1516 	sl->sl_nparts = vt->num_partitions;
1517 	for (i = 0; i < vt->num_partitions; i++) {
1518 		sl->sl_part[i].spi_tag = vt->partition[i].id_tag;
1519 		sl->sl_part[i].spi_flag = vt->partition[i].perm;
1520 		sc->sc_label->sl_part[i].sdkp_cyloffset =
1521 		    vt->partition[i].start / (sc->sc_nhead * sc->sc_nsect);
1522 		sc->sc_label->sl_part[i].sdkp_nsectors =
1523 		    vt->partition[i].nblocks;
1524 	}
1525 	sl->sl_sanity = 0x600ddeee;
1526 
1527 	/* Compute the checksum. */
1528 	sp1 = (u_short *)sc->sc_label;
1529 	sp2 = (u_short *)(sc->sc_label + 1);
1530 	while (sp1 < sp2)
1531 		cksum ^= *sp1++;
1532 	sc->sc_label->sl_cksum = cksum;
1533 
1534 	vd->status = vdsp_writelabel(sc);
1535 
1536 fail:
1537 	free(vt, M_DEVBUF, 0);
1538 
1539 	/* ACK the descriptor. */
1540 	vd->hdr.dstate = VIO_DESC_DONE;
1541 	vdsp_ack_desc(sc, vd);
1542 }
1543 
1544 void
1545 vdsp_get_diskgeom(void *arg1, void *arg2)
1546 {
1547 	struct vdsp_softc *sc = arg1;
1548 	struct ldc_conn *lc = &sc->sc_lc;
1549 	struct vd_desc *vd = arg2;
1550 	struct vd_diskgeom *vg;
1551 	vaddr_t va;
1552 	paddr_t pa;
1553 	uint64_t size, off;
1554 	psize_t nbytes;
1555 	int err, i;
1556 
1557 	vg = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
1558 
1559 	if (sc->sc_label == NULL)
1560 		vdsp_readlabel(sc);
1561 
1562 	if (sc->sc_label && sc->sc_label->sl_magic == SUN_DKMAGIC) {
1563 		vg->ncyl = sc->sc_label->sl_ncylinders;
1564 		vg->acyl = sc->sc_label->sl_acylinders;
1565 		vg->nhead = sc->sc_label->sl_ntracks;
1566 		vg->nsect = sc->sc_label->sl_nsectors;
1567 		vg->intrlv = sc->sc_label->sl_interleave;
1568 		vg->apc = sc->sc_label->sl_sparespercyl;
1569 		vg->rpm = sc->sc_label->sl_rpm;
1570 		vg->pcyl = sc->sc_label->sl_pcylinders;
1571 	} else {
1572 		uint64_t disk_size, block_size;
1573 
1574 		disk_size = sc->sc_vdisk_size * sc->sc_vdisk_block_size;
1575 		block_size = sc->sc_vdisk_block_size;
1576 
1577 		if (disk_size >= 8L * 1024 * 1024 * 1024) {
1578 			vg->nhead = 96;
1579 			vg->nsect = 768;
1580 		} else if (disk_size >= 2 *1024 * 1024) {
1581 			vg->nhead = 1;
1582 			vg->nsect = 600;
1583 		} else {
1584 			vg->nhead = 1;
1585 			vg->nsect = 200;
1586 		}
1587 
1588 		vg->pcyl = disk_size / (block_size * vg->nhead * vg->nsect);
1589 		if (vg->pcyl == 0)
1590 			vg->pcyl = 1;
1591 		if (vg->pcyl > 2)
1592 			vg->acyl = 2;
1593 		vg->ncyl = vg->pcyl - vg->acyl;
1594 
1595 		vg->rpm = 3600;
1596 	}
1597 
1598 	sc->sc_ncyl = vg->ncyl;
1599 	sc->sc_acyl = vg->acyl;
1600 	sc->sc_nhead = vg->nhead;
1601 	sc->sc_nsect = vg->nsect;
1602 
1603 	i = 0;
1604 	va = (vaddr_t)vg;
1605 	size = roundup(sizeof(*vg), 64);
1606 	off = 0;
1607 	while (size > 0 && i < vd->ncookies) {
1608 		pmap_extract(pmap_kernel(), va, &pa);
1609 		nbytes = MIN(size, vd->cookie[i].size - off);
1610 		nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK));
1611 		err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT,
1612 		    vd->cookie[i].addr + off, pa, nbytes, &nbytes);
1613 		if (err != H_EOK) {
1614 			printf("%s: hv_ldc_copy: %d\n", __func__, err);
1615 			vd->status = EIO;
1616 			goto fail;
1617 		}
1618 		va += nbytes;
1619 		size -= nbytes;
1620 		off += nbytes;
1621 		if (off >= vd->cookie[i].size) {
1622 			off = 0;
1623 			i++;
1624 		}
1625 	}
1626 
1627 	vd->status = 0;
1628 
1629 fail:
1630 	free(vg, M_DEVBUF, 0);
1631 
1632 	/* ACK the descriptor. */
1633 	vd->hdr.dstate = VIO_DESC_DONE;
1634 	vdsp_ack_desc(sc, vd);
1635 }
1636 
1637 void
1638 vdsp_unimp(void *arg1, void *arg2)
1639 {
1640 	struct vdsp_softc *sc = arg1;
1641 	struct vd_desc *vd = arg2;
1642 
1643 	/* ACK the descriptor. */
1644 	vd->status = ENOTSUP;
1645 	vd->hdr.dstate = VIO_DESC_DONE;
1646 	vdsp_ack_desc(sc, vd);
1647 }
1648 
1649 void
1650 vdsp_ack_desc(struct vdsp_softc *sc, struct vd_desc *vd)
1651 {
1652 	struct vio_dring_msg dm;
1653 	vaddr_t va;
1654 	paddr_t pa;
1655 	uint64_t size, off;
1656 	psize_t nbytes;
1657 	int err;
1658 
1659 	va = (vaddr_t)vd;
1660 	off = (caddr_t)vd - sc->sc_vd;
1661 	size = sc->sc_descriptor_size;
1662 	while (size > 0) {
1663 		pmap_extract(pmap_kernel(), va, &pa);
1664 		nbytes = MIN(size, PAGE_SIZE - (off & PAGE_MASK));
1665 		err = hv_ldc_copy(sc->sc_lc.lc_id, LDC_COPY_OUT,
1666 		    sc->sc_dring_cookie.addr + off, pa, nbytes, &nbytes);
1667 		if (err != H_EOK) {
1668 			printf("%s: hv_ldc_copy %d\n", __func__, err);
1669 			return;
1670 		}
1671 		va += nbytes;
1672 		size -= nbytes;
1673 		off += nbytes;
1674 	}
1675 
1676 	/* ACK the descriptor. */
1677 	bzero(&dm, sizeof(dm));
1678 	dm.tag.type = VIO_TYPE_DATA;
1679 	dm.tag.stype = VIO_SUBTYPE_ACK;
1680 	dm.tag.stype_env = VIO_DRING_DATA;
1681 	dm.tag.sid = sc->sc_local_sid;
1682 	dm.seq_no = ++sc->sc_seq_no;
1683 	dm.dring_ident = sc->sc_dring_ident;
1684 	off = (caddr_t)vd - sc->sc_vd;
1685 	dm.start_idx = off / sc->sc_descriptor_size;
1686 	dm.end_idx = off / sc->sc_descriptor_size;
1687 	vdsp_sendmsg(sc, &dm, sizeof(dm), 1);
1688 }
1689 
1690 int
1691 vdspopen(dev_t dev, int flag, int mode, struct proc *p)
1692 {
1693 	struct vdsp_softc *sc;
1694 	struct ldc_conn *lc;
1695 	int unit = minor(dev);
1696 	int err;
1697 
1698 	if (unit >= vdsp_cd.cd_ndevs)
1699 		return (ENXIO);
1700 	sc = vdsp_cd.cd_devs[unit];
1701 	if (sc == NULL)
1702 		return (ENXIO);
1703 
1704 	lc = &sc->sc_lc;
1705 
1706 	err = hv_ldc_tx_qconf(lc->lc_id,
1707 	    lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries);
1708 	if (err != H_EOK)
1709 		printf("%s: hv_ldc_tx_qconf %d\n", __func__, err);
1710 
1711 	err = hv_ldc_rx_qconf(lc->lc_id,
1712 	    lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries);
1713 	if (err != H_EOK)
1714 		printf("%s: hv_ldc_rx_qconf %d\n", __func__, err);
1715 
1716 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_ENABLED);
1717 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_ENABLED);
1718 
1719 	return (0);
1720 }
1721 
1722 int
1723 vdspclose(dev_t dev, int flag, int mode, struct proc *p)
1724 {
1725 	struct vdsp_softc *sc;
1726 	int unit = minor(dev);
1727 
1728 	if (unit >= vdsp_cd.cd_ndevs)
1729 		return (ENXIO);
1730 	sc = vdsp_cd.cd_devs[unit];
1731 	if (sc == NULL)
1732 		return (ENXIO);
1733 
1734 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_DISABLED);
1735 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_DISABLED);
1736 
1737 	hv_ldc_tx_qconf(sc->sc_lc.lc_id, 0, 0);
1738 	hv_ldc_rx_qconf(sc->sc_lc.lc_id, 0, 0);
1739 
1740 	task_add(systq, &sc->sc_close_task);
1741 	return (0);
1742 }
1743 
1744 int
1745 vdspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
1746 {
1747 	struct vdsp_softc *sc;
1748 	int unit = minor(dev);
1749 
1750 	if (unit >= vdsp_cd.cd_ndevs)
1751 		return (ENXIO);
1752 	sc = vdsp_cd.cd_devs[unit];
1753 	if (sc == NULL)
1754 		return (ENXIO);
1755 
1756 	return (ENOTTY);
1757 }
1758