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