xref: /openbsd-src/sys/arch/sparc64/dev/vnet.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /*	$OpenBSD: vnet.c,v 1.17 2009/08/09 11:40:58 deraadt Exp $	*/
2 /*
3  * Copyright (c) 2009 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 "bpfilter.h"
19 
20 #include <sys/param.h>
21 #include <sys/device.h>
22 #include <sys/malloc.h>
23 #include <sys/mbuf.h>
24 #include <sys/socket.h>
25 #include <sys/sockio.h>
26 #include <sys/systm.h>
27 
28 #include <machine/autoconf.h>
29 #include <machine/hypervisor.h>
30 #include <machine/openfirm.h>
31 
32 #include <net/if.h>
33 #include <net/if_dl.h>
34 #include <net/if_media.h>
35 #include <net/if_types.h>
36 
37 #include <netinet/in.h>
38 #include <netinet/if_ether.h>
39 
40 #if NBPFILTER > 0
41 #include <net/bpf.h>
42 #endif
43 
44 #include <uvm/uvm.h>
45 
46 #include <sparc64/dev/cbusvar.h>
47 #include <sparc64/dev/ldcvar.h>
48 #include <sparc64/dev/viovar.h>
49 
50 /* XXX the following declaration should be elsewhere */
51 extern void myetheraddr(u_char *);
52 
53 #ifdef VNET_DEBUG
54 #define DPRINTF(x)	printf x
55 #else
56 #define DPRINTF(x)
57 #endif
58 
59 #define VNET_TX_ENTRIES		32
60 #define VNET_RX_ENTRIES		32
61 
62 struct vnet_attr_info {
63 	struct vio_msg_tag	tag;
64 	uint8_t			xfer_mode;
65 	uint8_t			addr_type;
66 	uint16_t		ack_freq;
67 	uint32_t		_reserved1;
68 	uint64_t		addr;
69 	uint64_t		mtu;
70 	uint64_t		_reserved2[3];
71 };
72 
73 /* Address types. */
74 #define VNET_ADDR_ETHERMAC	0x01
75 
76 /* Sub-Type envelopes. */
77 #define VNET_MCAST_INFO		0x0101
78 
79 #define VNET_NUM_MCAST		7
80 
81 struct vnet_mcast_info {
82 	struct vio_msg_tag	tag;
83 	uint8_t			set;
84 	uint8_t			count;
85 	uint8_t			mcast_addr[VNET_NUM_MCAST][ETHER_ADDR_LEN];
86 	uint32_t		_reserved;
87 };
88 
89 struct vnet_desc {
90 	struct vio_dring_hdr	hdr;
91 	uint32_t		nbytes;
92 	uint32_t		ncookies;
93 	struct ldc_cookie	cookie[2];
94 };
95 
96 struct vnet_dring {
97 	bus_dmamap_t		vd_map;
98 	bus_dma_segment_t	vd_seg;
99 	struct vnet_desc	*vd_desc;
100 	int			vd_nentries;
101 };
102 
103 struct vnet_dring *vnet_dring_alloc(bus_dma_tag_t, int);
104 void	vnet_dring_free(bus_dma_tag_t, struct vnet_dring *);
105 
106 /*
107  * For now, we only support vNet 1.0.
108  */
109 #define VNET_MAJOR	1
110 #define VNET_MINOR	0
111 
112 /*
113  * The vNet protocol wants the IP header to be 64-bit aligned, so
114  * define out own variant of ETHER_ALIGN.
115  */
116 #define VNET_ETHER_ALIGN	6
117 
118 struct vnet_soft_desc {
119 	int		vsd_map_idx;
120 	caddr_t		vsd_buf;
121 };
122 
123 struct vnet_softc {
124 	struct device	sc_dv;
125 	bus_space_tag_t	sc_bustag;
126 	bus_dma_tag_t	sc_dmatag;
127 
128 	void		*sc_tx_ih;
129 	void		*sc_rx_ih;
130 
131 	struct ldc_conn	sc_lc;
132 
133 	uint16_t	sc_vio_state;
134 #define VIO_SND_VER_INFO	0x0001
135 #define VIO_ACK_VER_INFO	0x0002
136 #define VIO_RCV_VER_INFO	0x0004
137 #define VIO_SND_ATTR_INFO	0x0008
138 #define VIO_ACK_ATTR_INFO	0x0010
139 #define VIO_RCV_ATTR_INFO	0x0020
140 #define VIO_SND_DRING_REG	0x0040
141 #define VIO_ACK_DRING_REG	0x0080
142 #define VIO_RCV_DRING_REG	0x0100
143 #define VIO_SND_RDX		0x0200
144 #define VIO_ACK_RDX		0x0400
145 #define VIO_RCV_RDX		0x0800
146 #define VIO_ESTABLISHED		0x0fff
147 
148 	uint32_t	sc_local_sid;
149 	uint64_t	sc_dring_ident;
150 	uint64_t	sc_seq_no;
151 
152 	int		sc_tx_cnt;
153 	int		sc_tx_prod;
154 	int		sc_tx_cons;
155 
156 	struct ldc_map	*sc_lm;
157 	struct vnet_dring *sc_vd;
158 	struct vnet_soft_desc *sc_vsd;
159 
160 	size_t		sc_peer_desc_size;
161 	struct ldc_cookie sc_peer_dring_cookie;
162 	int		sc_peer_dring_nentries;
163 
164 	struct pool	sc_pool;
165 
166 	struct arpcom	sc_ac;
167 	struct ifmedia	sc_media;
168 };
169 
170 int	vnet_match(struct device *, void *, void *);
171 void	vnet_attach(struct device *, struct device *, void *);
172 
173 struct cfattach vnet_ca = {
174 	sizeof(struct vnet_softc), vnet_match, vnet_attach
175 };
176 
177 struct cfdriver vnet_cd = {
178 	NULL, "vnet", DV_IFNET
179 };
180 
181 int	vnet_tx_intr(void *);
182 int	vnet_rx_intr(void *);
183 
184 void	vio_rx_data(struct ldc_conn *, struct ldc_pkt *);
185 void	vnet_rx_vio_ctrl(struct vnet_softc *, struct vio_msg *);
186 void	vnet_rx_vio_ver_info(struct vnet_softc *, struct vio_msg_tag *);
187 void	vnet_rx_vio_attr_info(struct vnet_softc *, struct vio_msg_tag *);
188 void	vnet_rx_vio_dring_reg(struct vnet_softc *, struct vio_msg_tag *);
189 void	vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *);
190 void	vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *);
191 void	vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *);
192 
193 void	vnet_ldc_reset(struct ldc_conn *);
194 void	vnet_ldc_start(struct ldc_conn *);
195 
196 void	vio_sendmsg(struct vnet_softc *, void *, size_t);
197 void	vnet_send_ver_info(struct vnet_softc *, uint16_t, uint16_t);
198 void	vnet_send_attr_info(struct vnet_softc *);
199 void	vnet_send_dring_reg(struct vnet_softc *);
200 void	vio_send_rdx(struct vnet_softc *);
201 
202 void	vnet_start(struct ifnet *);
203 int	vnet_ioctl(struct ifnet *, u_long, caddr_t);
204 void	vnet_watchdog(struct ifnet *);
205 
206 int	vnet_media_change(struct ifnet *);
207 void	vnet_media_status(struct ifnet *, struct ifmediareq *);
208 
209 void	vnet_link_state(struct vnet_softc *sc);
210 
211 void	vnet_setmulti(struct vnet_softc *, int);
212 
213 void	vnet_init(struct ifnet *);
214 void	vnet_stop(struct ifnet *);
215 
216 int
217 vnet_match(struct device *parent, void *match, void *aux)
218 {
219 	struct cbus_attach_args *ca = aux;
220 
221 	if (strcmp(ca->ca_name, "network") == 0)
222 		return (1);
223 
224 	return (0);
225 }
226 
227 void
228 vnet_attach(struct device *parent, struct device *self, void *aux)
229 {
230 	struct vnet_softc *sc = (struct vnet_softc *)self;
231 	struct cbus_attach_args *ca = aux;
232 	struct ldc_conn *lc;
233 	struct ifnet *ifp;
234 	uint64_t sysino[2];
235 
236 	sc->sc_bustag = ca->ca_bustag;
237 	sc->sc_dmatag = ca->ca_dmatag;
238 
239 	if (OF_getprop(ca->ca_node, "local-mac-address", sc->sc_ac.ac_enaddr,
240 	    ETHER_ADDR_LEN) <= 0)
241 		myetheraddr(sc->sc_ac.ac_enaddr);
242 
243 	if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sysino[0]) ||
244 	    cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sysino[1])) {
245 		printf(": can't map interrupt\n");
246 		return;
247 	}
248 	printf(": ivec 0x%lx, 0x%lx", sysino[0], sysino[1]);
249 
250 	/*
251 	 * Un-configure queues before registering interrupt handlers,
252 	 * such that we dont get any stale LDC packets or events.
253 	 */
254 	hv_ldc_tx_qconf(ca->ca_id, 0, 0);
255 	hv_ldc_rx_qconf(ca->ca_id, 0, 0);
256 
257 	sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sysino[0], IPL_NET,
258 	    0, vnet_tx_intr, sc, sc->sc_dv.dv_xname);
259 	sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sysino[1], IPL_NET,
260 	    0, vnet_rx_intr, sc, sc->sc_dv.dv_xname);
261 	if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
262 		printf(", can't establish interrupt\n");
263 		return;
264 	}
265 
266 	lc = &sc->sc_lc;
267 	lc->lc_id = ca->ca_id;
268 	lc->lc_sc = sc;
269 	lc->lc_reset = vnet_ldc_reset;
270 	lc->lc_start = vnet_ldc_start;
271 	lc->lc_rx_data = vio_rx_data;
272 
273 	lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VNET_TX_ENTRIES);
274 	if (lc->lc_txq == NULL) {
275 		printf(", can't allocate tx queue\n");
276 		return;
277 	}
278 
279 	lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VNET_RX_ENTRIES);
280 	if (lc->lc_rxq == NULL) {
281 		printf(", can't allocate rx queue\n");
282 		goto free_txqueue;
283 	}
284 
285 	/*
286 	 * Each interface gets its own pool.
287 	 */
288 	pool_init(&sc->sc_pool, 2048, 0, 0, 0, sc->sc_dv.dv_xname, NULL);
289 
290 	ifp = &sc->sc_ac.ac_if;
291 	ifp->if_softc = sc;
292 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
293 	ifp->if_ioctl = vnet_ioctl;
294 	ifp->if_start = vnet_start;
295 	ifp->if_watchdog = vnet_watchdog;
296 	strlcpy(ifp->if_xname, sc->sc_dv.dv_xname, IFNAMSIZ);
297 	IFQ_SET_MAXLEN(&ifp->if_snd, 31); /* XXX */
298 	IFQ_SET_READY(&ifp->if_snd);
299 
300 	ifmedia_init(&sc->sc_media, 0, vnet_media_change, vnet_media_status);
301 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
302 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
303 
304 	if_attach(ifp);
305 	ether_ifattach(ifp);
306 
307 	printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
308 	return;
309 
310 free_txqueue:
311 	ldc_queue_free(sc->sc_dmatag, lc->lc_txq);
312 }
313 
314 int
315 vnet_tx_intr(void *arg)
316 {
317 	struct vnet_softc *sc = arg;
318 	struct ldc_conn *lc = &sc->sc_lc;
319 	uint64_t tx_head, tx_tail, tx_state;
320 
321 	hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
322 	if (tx_state != lc->lc_tx_state) {
323 		switch (tx_state) {
324 		case LDC_CHANNEL_DOWN:
325 			DPRINTF(("Tx link down\n"));
326 			break;
327 		case LDC_CHANNEL_UP:
328 			DPRINTF(("Tx link up\n"));
329 			break;
330 		case LDC_CHANNEL_RESET:
331 			DPRINTF(("Tx link reset\n"));
332 			break;
333 		}
334 		lc->lc_tx_state = tx_state;
335 	}
336 
337 	return (1);
338 }
339 
340 int
341 vnet_rx_intr(void *arg)
342 {
343 	struct vnet_softc *sc = arg;
344 	struct ldc_conn *lc = &sc->sc_lc;
345 	uint64_t rx_head, rx_tail, rx_state;
346 	struct ldc_pkt *lp;
347 	uint64_t *msg;
348 	int err;
349 
350 	err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state);
351 	if (err == H_EINVAL)
352 		return (0);
353 	if (err != H_EOK) {
354 		printf("hv_ldc_rx_get_state %d\n", err);
355 		return (0);
356 	}
357 
358 	if (rx_state != lc->lc_rx_state) {
359 		sc->sc_tx_cnt = sc->sc_tx_prod = sc->sc_tx_cons = 0;
360 		sc->sc_vio_state = 0;
361 		lc->lc_tx_seqid = 0;
362 		lc->lc_state = 0;
363 		switch (rx_state) {
364 		case LDC_CHANNEL_DOWN:
365 			DPRINTF(("Rx link down\n"));
366 			break;
367 		case LDC_CHANNEL_UP:
368 			DPRINTF(("Rx link up\n"));
369 			ldc_send_vers(lc);
370 			break;
371 		case LDC_CHANNEL_RESET:
372 			DPRINTF(("Rx link reset\n"));
373 			break;
374 		}
375 		lc->lc_rx_state = rx_state;
376 		return (1);
377 	}
378 
379 	msg = (uint64_t *)(lc->lc_rxq->lq_va + rx_head);
380 	lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head);
381 	switch (lp->type) {
382 	case LDC_CTRL:
383 		ldc_rx_ctrl(lc, lp);
384 		break;
385 
386 	case LDC_DATA:
387 		ldc_rx_data(lc, lp);
388 		break;
389 
390 	default:
391 		DPRINTF(("%0x02/%0x02/%0x02\n", lp->type, lp->stype,
392 		    lp->ctrl));
393 		ldc_reset(lc);
394 		break;
395 	}
396 
397 	if (lc->lc_state == 0)
398 		return (1);
399 
400 	rx_head += sizeof(*lp);
401 	rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1);
402 	err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head);
403 	if (err != H_EOK)
404 		printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
405 
406 	return (1);
407 }
408 
409 void
410 vio_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
411 {
412 	struct vio_msg *vm = (struct vio_msg *)lp;
413 
414 	switch (vm->type) {
415 	case VIO_TYPE_CTRL:
416 		if ((lp->env & LDC_FRAG_START) == 0 &&
417 		    (lp->env & LDC_FRAG_STOP) == 0)
418 			return;
419 		vnet_rx_vio_ctrl(lc->lc_sc, vm);
420 		break;
421 
422 	case VIO_TYPE_DATA:
423 		if((lp->env & LDC_FRAG_START) == 0)
424 			return;
425 		vnet_rx_vio_data(lc->lc_sc, vm);
426 		break;
427 
428 	default:
429 		DPRINTF(("Unhandled packet type 0x%02x\n", vm->type));
430 		ldc_reset(lc);
431 		break;
432 	}
433 }
434 
435 void
436 vnet_rx_vio_ctrl(struct vnet_softc *sc, struct vio_msg *vm)
437 {
438 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
439 
440 	switch (tag->stype_env) {
441 	case VIO_VER_INFO:
442 		vnet_rx_vio_ver_info(sc, tag);
443 		break;
444 	case VIO_ATTR_INFO:
445 		vnet_rx_vio_attr_info(sc, tag);
446 		break;
447 	case VIO_DRING_REG:
448 		vnet_rx_vio_dring_reg(sc, tag);
449 		break;
450 	case VIO_RDX:
451 		vnet_rx_vio_rdx(sc, tag);
452 		break;
453 	default:
454 		DPRINTF(("CTRL/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
455 		break;
456 	}
457 }
458 
459 void
460 vnet_rx_vio_ver_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
461 {
462 	struct vio_ver_info *vi = (struct vio_ver_info *)tag;
463 
464 	switch (vi->tag.stype) {
465 	case VIO_SUBTYPE_INFO:
466 		DPRINTF(("CTRL/INFO/VER_INFO\n"));
467 
468 		/* Make sure we're talking to a virtual network device. */
469 		if (vi->dev_class != VDEV_NETWORK &&
470 		    vi->dev_class != VDEV_NETWORK_SWITCH) {
471 			/* Huh, we're not talking to a network device? */
472 			printf("Not a network device\n");
473 			vi->tag.stype = VIO_SUBTYPE_NACK;
474 			vio_sendmsg(sc, vi, sizeof(*vi));
475 			return;
476 		}
477 
478 		if (vi->major != VNET_MAJOR) {
479 			vi->tag.stype = VIO_SUBTYPE_NACK;
480 			vi->major = VNET_MAJOR;
481 			vi->minor = VNET_MINOR;
482 			vio_sendmsg(sc, vi, sizeof(*vi));
483 			return;
484 		}
485 
486 		vi->tag.stype = VIO_SUBTYPE_ACK;
487 		vi->tag.sid = sc->sc_local_sid;
488 		vi->minor = VNET_MINOR;
489 		vio_sendmsg(sc, vi, sizeof(*vi));
490 		sc->sc_vio_state |= VIO_RCV_VER_INFO;
491 		break;
492 
493 	case VIO_SUBTYPE_ACK:
494 		DPRINTF(("CTRL/ACK/VER_INFO\n"));
495 		if (!ISSET(sc->sc_vio_state, VIO_SND_VER_INFO)) {
496 			ldc_reset(&sc->sc_lc);
497 			break;
498 		}
499 		sc->sc_vio_state |= VIO_ACK_VER_INFO;
500 		break;
501 
502 	default:
503 		DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype));
504 		break;
505 	}
506 
507 	if (ISSET(sc->sc_vio_state, VIO_RCV_VER_INFO) &&
508 	    ISSET(sc->sc_vio_state, VIO_ACK_VER_INFO))
509 		vnet_send_attr_info(sc);
510 }
511 
512 void
513 vnet_rx_vio_attr_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
514 {
515 	struct vnet_attr_info *ai = (struct vnet_attr_info *)tag;
516 
517 	switch (ai->tag.stype) {
518 	case VIO_SUBTYPE_INFO:
519 		DPRINTF(("CTRL/INFO/ATTR_INFO\n"));
520 
521 		ai->tag.stype = VIO_SUBTYPE_ACK;
522 		ai->tag.sid = sc->sc_local_sid;
523 		vio_sendmsg(sc, ai, sizeof(*ai));
524 		sc->sc_vio_state |= VIO_RCV_ATTR_INFO;
525 		break;
526 
527 	case VIO_SUBTYPE_ACK:
528 		DPRINTF(("CTRL/ACK/ATTR_INFO\n"));
529 		if (!ISSET(sc->sc_vio_state, VIO_SND_ATTR_INFO)) {
530 			ldc_reset(&sc->sc_lc);
531 			break;
532 		}
533 		sc->sc_vio_state |= VIO_ACK_ATTR_INFO;
534 		break;
535 
536 	default:
537 		DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype));
538 		break;
539 	}
540 
541 	if (ISSET(sc->sc_vio_state, VIO_RCV_ATTR_INFO) &&
542 	    ISSET(sc->sc_vio_state, VIO_ACK_ATTR_INFO))
543 		vnet_send_dring_reg(sc);
544 }
545 
546 void
547 vnet_rx_vio_dring_reg(struct vnet_softc *sc, struct vio_msg_tag *tag)
548 {
549 	struct vio_dring_reg *dr = (struct vio_dring_reg *)tag;
550 
551 	switch (dr->tag.stype) {
552 	case VIO_SUBTYPE_INFO:
553 		DPRINTF(("CTRL/INFO/DRING_REG\n"));
554 
555 		sc->sc_peer_dring_nentries = dr->num_descriptors;
556 		sc->sc_peer_desc_size = dr->descriptor_size;
557 		sc->sc_peer_dring_cookie = dr->cookie[0];
558 
559 		dr->tag.stype = VIO_SUBTYPE_ACK;
560 		dr->tag.sid = sc->sc_local_sid;
561 		vio_sendmsg(sc, dr, sizeof(*dr));
562 		sc->sc_vio_state |= VIO_RCV_DRING_REG;
563 		break;
564 
565 	case VIO_SUBTYPE_ACK:
566 		DPRINTF(("CTRL/ACK/DRING_REG\n"));
567 		if (!ISSET(sc->sc_vio_state, VIO_SND_DRING_REG)) {
568 			ldc_reset(&sc->sc_lc);
569 			break;
570 		}
571 
572 		sc->sc_dring_ident = dr->dring_ident;
573 		sc->sc_seq_no = 1;
574 
575 		sc->sc_vio_state |= VIO_ACK_DRING_REG;
576 		break;
577 
578 	default:
579 		DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype));
580 		break;
581 	}
582 
583 	if (ISSET(sc->sc_vio_state, VIO_RCV_DRING_REG) &&
584 	    ISSET(sc->sc_vio_state, VIO_ACK_DRING_REG))
585 		vio_send_rdx(sc);
586 }
587 
588 void
589 vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *tag)
590 {
591 	struct ifnet *ifp = &sc->sc_ac.ac_if;
592 
593 	switch(tag->stype) {
594 	case VIO_SUBTYPE_INFO:
595 		DPRINTF(("CTRL/INFO/RDX\n"));
596 
597 		tag->stype = VIO_SUBTYPE_ACK;
598 		tag->sid = sc->sc_local_sid;
599 		vio_sendmsg(sc, tag, sizeof(*tag));
600 		sc->sc_vio_state |= VIO_RCV_RDX;
601 		break;
602 
603 	case VIO_SUBTYPE_ACK:
604 		DPRINTF(("CTRL/ACK/RDX\n"));
605 		if (!ISSET(sc->sc_vio_state, VIO_SND_RDX)) {
606 			ldc_reset(&sc->sc_lc);
607 			break;
608 		}
609 		sc->sc_vio_state |= VIO_ACK_RDX;
610 		break;
611 
612 	default:
613 		DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype));
614 		break;
615 	}
616 
617 	if (sc->sc_vio_state == VIO_ESTABLISHED) {
618 		/* Link is up! */
619 		vnet_link_state(sc);
620 
621 		/* Configure multicast now that we can. */
622 		vnet_setmulti(sc, 1);
623 		vnet_start(ifp);
624 	}
625 }
626 
627 void
628 vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *vm)
629 {
630 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
631 
632 	if (sc->sc_vio_state != VIO_ESTABLISHED) {
633 		DPRINTF(("Spurious DATA/0x%02x/0x%04x\n", tag->stype,
634 		    tag->stype_env));
635 		return;
636 	}
637 
638 	switch(tag->stype_env) {
639 	case VIO_DRING_DATA:
640 		vnet_rx_vio_dring_data(sc, tag);
641 		break;
642 
643 	default:
644 		DPRINTF(("DATA/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
645 		break;
646 	}
647 }
648 
649 void
650 vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
651 {
652 	struct vio_dring_msg *dm = (struct vio_dring_msg *)tag;
653 	struct ldc_conn *lc = &sc->sc_lc;
654 	struct ifnet *ifp = &sc->sc_ac.ac_if;
655 	struct mbuf *m;
656 	paddr_t pa;
657 	psize_t nbytes;
658 	int err;
659 
660 	switch(tag->stype) {
661 	case VIO_SUBTYPE_INFO:
662 	{
663 		struct vnet_desc desc;
664 		uint64_t cookie;
665 		paddr_t desc_pa;
666 		int idx, ack_end_idx = -1;
667 
668 		idx = dm->start_idx;
669 		for (;;) {
670 			cookie = sc->sc_peer_dring_cookie.addr;
671 			cookie += idx * sc->sc_peer_desc_size;
672 			nbytes = sc->sc_peer_desc_size;
673 			pmap_extract(pmap_kernel(), (vaddr_t)&desc, &desc_pa);
674 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN, cookie,
675 			    desc_pa, nbytes, &nbytes);
676 			if (err != H_EOK) {
677 				printf("hv_ldc_copy_in %d\n", err);
678 				break;
679 			}
680 
681 			if (desc.hdr.dstate != VIO_DESC_READY)
682 				break;
683 
684 			m = MCLGETI(NULL, M_DONTWAIT, &sc->sc_ac.ac_if,
685 			    MCLBYTES);
686 			if (!m)
687 				break;
688 			ifp->if_ipackets++;
689 			m->m_pkthdr.rcvif = ifp;
690 			m->m_len = m->m_pkthdr.len = desc.nbytes;
691 			nbytes = roundup(desc.nbytes + VNET_ETHER_ALIGN, 8);
692 
693 			pmap_extract(pmap_kernel(), (vaddr_t)m->m_data, &pa);
694 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
695 			    desc.cookie[0].addr, pa, nbytes, &nbytes);
696 			if (err != H_EOK) {
697 				m_freem(m);
698 				goto skip;
699 			}
700 			m->m_data += VNET_ETHER_ALIGN;
701 
702 #if NBPFILTER > 0
703 			if (ifp->if_bpf)
704 				bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
705 #endif /* NBPFILTER > 0 */
706 
707 			/* Pass it on. */
708 			ether_input_mbuf(ifp, m);
709 
710 		skip:
711 			desc.hdr.dstate = VIO_DESC_DONE;
712 			nbytes = sc->sc_peer_desc_size;
713 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, cookie,
714 			    desc_pa, nbytes, &nbytes);
715 			if (err != H_EOK)
716 				printf("hv_ldc_copy_out %d\n", err);
717 
718 			ack_end_idx = idx;
719 			if (++idx == sc->sc_peer_dring_nentries)
720 				idx = 0;
721 		}
722 
723 		if (ack_end_idx == -1) {
724 			dm->tag.stype = VIO_SUBTYPE_NACK;
725 		} else {
726 			dm->tag.stype = VIO_SUBTYPE_ACK;
727 			dm->end_idx = ack_end_idx;
728 		}
729 		dm->tag.sid = sc->sc_local_sid;
730 		dm->proc_state = VIO_DP_STOPPED;
731 		vio_sendmsg(sc, dm, sizeof(*dm));
732 		break;
733 	}
734 
735 	case VIO_SUBTYPE_ACK:
736 	{
737 		struct ldc_map *map = sc->sc_lm;
738 		int cons;
739 
740 		cons = sc->sc_tx_cons;
741 		while (sc->sc_vd->vd_desc[cons].hdr.dstate == VIO_DESC_DONE) {
742 			map->lm_slot[sc->sc_vsd[cons].vsd_map_idx].entry = 0;
743 			map->lm_count--;
744 
745 			pool_put(&sc->sc_pool, sc->sc_vsd[cons].vsd_buf);
746 
747 			sc->sc_vd->vd_desc[cons++].hdr.dstate = VIO_DESC_FREE;
748 			cons &= (sc->sc_vd->vd_nentries - 1);
749 			sc->sc_tx_cnt--;
750 		}
751 		sc->sc_tx_cons = cons;
752 
753 		if (sc->sc_tx_cnt < sc->sc_vd->vd_nentries)
754 			ifp->if_flags &= ~IFF_OACTIVE;
755 
756 		vnet_start(ifp);
757 		break;
758 	}
759 
760 	case VIO_SUBTYPE_NACK:
761 		DPRINTF(("DATA/NACK/DRING_DATA\n"));
762 		break;
763 
764 	default:
765 		DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype));
766 		break;
767 	}
768 }
769 
770 void
771 vnet_ldc_reset(struct ldc_conn *lc)
772 {
773 	struct vnet_softc *sc = lc->lc_sc;
774 
775 	sc->sc_vio_state = 0;
776 	vnet_link_state(sc);
777 }
778 
779 void
780 vnet_ldc_start(struct ldc_conn *lc)
781 {
782 	struct vnet_softc *sc = lc->lc_sc;
783 
784 	vnet_send_ver_info(sc, VNET_MAJOR, VNET_MINOR);
785 }
786 
787 void
788 vio_sendmsg(struct vnet_softc *sc, void *msg, size_t len)
789 {
790 	struct ldc_conn *lc = &sc->sc_lc;
791 	struct ldc_pkt *lp;
792 	uint64_t tx_head, tx_tail, tx_state;
793 	int err;
794 
795 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
796 	if (err != H_EOK)
797 		return;
798 
799 	lp = (struct ldc_pkt *)(lc->lc_txq->lq_va + tx_tail);
800 	bzero(lp, sizeof(struct ldc_pkt));
801 	lp->type = LDC_DATA;
802 	lp->stype = LDC_INFO;
803 	KASSERT((len & ~LDC_LEN_MASK) == 0);
804 	lp->env = len | LDC_FRAG_STOP | LDC_FRAG_START;
805 	lp->seqid = lc->lc_tx_seqid++;
806 	bcopy(msg, &lp->major, len);
807 
808 	tx_tail += sizeof(*lp);
809 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
810 	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
811 	if (err != H_EOK)
812 		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
813 }
814 
815 void
816 vnet_send_ver_info(struct vnet_softc *sc, uint16_t major, uint16_t minor)
817 {
818 	struct vio_ver_info vi;
819 
820 	bzero(&vi, sizeof(vi));
821 	vi.tag.type = VIO_TYPE_CTRL;
822 	vi.tag.stype = VIO_SUBTYPE_INFO;
823 	vi.tag.stype_env = VIO_VER_INFO;
824 	vi.tag.sid = sc->sc_local_sid;
825 	vi.major = major;
826 	vi.minor = minor;
827 	vi.dev_class = VDEV_NETWORK;
828 	vio_sendmsg(sc, &vi, sizeof(vi));
829 
830 	sc->sc_vio_state |= VIO_SND_VER_INFO;
831 }
832 
833 void
834 vnet_send_attr_info(struct vnet_softc *sc)
835 {
836 	struct vnet_attr_info ai;
837 	int i;
838 
839 	bzero(&ai, sizeof(ai));
840 	ai.tag.type = VIO_TYPE_CTRL;
841 	ai.tag.stype = VIO_SUBTYPE_INFO;
842 	ai.tag.stype_env = VIO_ATTR_INFO;
843 	ai.tag.sid = sc->sc_local_sid;
844 	ai.xfer_mode = VIO_DRING_MODE;
845 	ai.addr_type = VNET_ADDR_ETHERMAC;
846 	ai.ack_freq = 0;
847 	ai.addr = 0;
848 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
849 		ai.addr <<= 8;
850 		ai.addr |= sc->sc_ac.ac_enaddr[i];
851 	}
852 	ai.mtu = ETHER_MAX_LEN - ETHER_CRC_LEN;
853 	vio_sendmsg(sc, &ai, sizeof(ai));
854 
855 	sc->sc_vio_state |= VIO_SND_ATTR_INFO;
856 }
857 
858 void
859 vnet_send_dring_reg(struct vnet_softc *sc)
860 {
861 	struct vio_dring_reg dr;
862 
863 	bzero(&dr, sizeof(dr));
864 	dr.tag.type = VIO_TYPE_CTRL;
865 	dr.tag.stype = VIO_SUBTYPE_INFO;
866 	dr.tag.stype_env = VIO_DRING_REG;
867 	dr.tag.sid = sc->sc_local_sid;
868 	dr.dring_ident = 0;
869 	dr.num_descriptors = sc->sc_vd->vd_nentries;
870 	dr.descriptor_size = sizeof(struct vnet_desc);
871 	dr.options = VIO_TX_RING;
872 	dr.ncookies = 1;
873 	dr.cookie[0].addr = 0;
874 	dr.cookie[0].size = PAGE_SIZE;
875 	vio_sendmsg(sc, &dr, sizeof(dr));
876 
877 	sc->sc_vio_state |= VIO_SND_DRING_REG;
878 };
879 
880 void
881 vio_send_rdx(struct vnet_softc *sc)
882 {
883 	struct vio_msg_tag tag;
884 
885 	tag.type = VIO_TYPE_CTRL;
886 	tag.stype = VIO_SUBTYPE_INFO;
887 	tag.stype_env = VIO_RDX;
888 	tag.sid = sc->sc_local_sid;
889 	vio_sendmsg(sc, &tag, sizeof(tag));
890 
891 	sc->sc_vio_state |= VIO_SND_RDX;
892 }
893 
894 void
895 vnet_start(struct ifnet *ifp)
896 {
897 	struct vnet_softc *sc = ifp->if_softc;
898 	struct ldc_conn *lc = &sc->sc_lc;
899 	struct ldc_map *map = sc->sc_lm;
900 	struct vio_dring_msg dm;
901 	struct mbuf *m;
902 	paddr_t pa;
903 	caddr_t buf;
904 	uint64_t tx_head, tx_tail, tx_state;
905 	int err, desc;
906 
907 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
908 		return;
909 
910 	if (IFQ_IS_EMPTY(&ifp->if_snd))
911 		return;
912 
913 	/*
914 	 * We cannot transmit packets until a VIO connection has been
915 	 * established.
916 	 */
917 	if (sc->sc_vio_state != VIO_ESTABLISHED)
918 		return;
919 
920 	/*
921 	 * Make sure there is room in the LDC transmit queue to send a
922 	 * DRING_DATA message.
923 	 */
924 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
925 	if (err != H_EOK)
926 		return;
927 	tx_tail += sizeof(struct ldc_pkt);
928 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(struct ldc_pkt)) - 1);
929 	if (tx_tail == tx_head) {
930 		ifp->if_flags |= IFF_OACTIVE;
931 		return;
932 	}
933 
934 	desc = sc->sc_tx_prod;
935 	while (sc->sc_vd->vd_desc[desc].hdr.dstate == VIO_DESC_FREE) {
936 		IFQ_POLL(&ifp->if_snd, m);
937 		if (m == NULL)
938 			break;
939 
940 		if (sc->sc_tx_cnt >= sc->sc_vd->vd_nentries ||
941 		    map->lm_count >= map->lm_nentries) {
942 			ifp->if_flags |= IFF_OACTIVE;
943 			break;
944 		}
945 
946 		buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
947 		if (buf == NULL) {
948 			ifp->if_flags |= IFF_OACTIVE;
949 			break;
950 		}
951 		m_copydata(m, 0, m->m_pkthdr.len, buf + VNET_ETHER_ALIGN);
952 		IFQ_DEQUEUE(&ifp->if_snd, m);
953 
954 #if NBPFILTER > 0
955 		/*
956 		 * If BPF is listening on this interface, let it see the
957 		 * packet before we commit it to the wire.
958 		 */
959 		if (ifp->if_bpf)
960 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
961 #endif
962 
963 		pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
964 		KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
965 		while (map->lm_slot[map->lm_next].entry != 0) {
966 			map->lm_next++;
967 			map->lm_next &= (map->lm_nentries - 1);
968 		}
969 		map->lm_slot[map->lm_next].entry = (pa & LDC_MTE_RA_MASK);
970 		map->lm_slot[map->lm_next].entry |= LDC_MTE_CPR;
971 		map->lm_count++;
972 
973 		sc->sc_vd->vd_desc[desc].nbytes = max(m->m_pkthdr.len, 60);
974 		sc->sc_vd->vd_desc[desc].ncookies = 1;
975 		sc->sc_vd->vd_desc[desc].cookie[0].addr =
976 		    map->lm_next << PAGE_SHIFT | (pa & PAGE_MASK);
977 		sc->sc_vd->vd_desc[desc].cookie[0].size = 2048;
978 		membar(Sync);
979 		sc->sc_vd->vd_desc[desc].hdr.dstate = VIO_DESC_READY;
980 
981 		sc->sc_vsd[desc].vsd_map_idx = map->lm_next;
982 		sc->sc_vsd[desc].vsd_buf = buf;
983 
984 		desc++;
985 		desc &= (sc->sc_vd->vd_nentries - 1);
986 		sc->sc_tx_cnt++;
987 
988 		m_freem(m);
989 	}
990 
991 	if (desc != sc->sc_tx_prod) {
992 		bzero(&dm, sizeof(dm));
993 		dm.tag.type = VIO_TYPE_DATA;
994 		dm.tag.stype = VIO_SUBTYPE_INFO;
995 		dm.tag.stype_env = VIO_DRING_DATA;
996 		dm.tag.sid = sc->sc_local_sid;
997 		dm.seq_no = sc->sc_seq_no++;
998 		dm.dring_ident = sc->sc_dring_ident;
999 		dm.start_idx = sc->sc_tx_prod;
1000 		dm.end_idx = -1;
1001 		vio_sendmsg(sc, &dm, sizeof(dm));
1002 	}
1003 
1004 	sc->sc_tx_prod = desc;
1005 }
1006 
1007 int
1008 vnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1009 {
1010 	struct vnet_softc *sc = ifp->if_softc;
1011 	struct ifaddr *ifa = (struct ifaddr *)data;
1012 	struct ifreq *ifr = (struct ifreq *)data;
1013 	int s, error = 0;
1014 
1015 	s = splnet();
1016 
1017 	switch (cmd) {
1018 	case SIOCSIFADDR:
1019 		ifp->if_flags |= IFF_UP;
1020 #ifdef INET
1021 		if (ifa->ifa_addr->sa_family == AF_INET)
1022 			arp_ifinit(&sc->sc_ac, ifa);
1023 #endif
1024 		/* FALLTHROUGH */
1025 	case SIOCSIFFLAGS:
1026 		if (ifp->if_flags & IFF_UP) {
1027 			if ((ifp->if_flags & IFF_RUNNING) == 0)
1028 				vnet_init(ifp);
1029 		} else {
1030 			if (ifp->if_flags & IFF_RUNNING)
1031 				vnet_stop(ifp);
1032 		}
1033 		break;
1034 
1035 	case SIOCGIFMEDIA:
1036 	case SIOCSIFMEDIA:
1037 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1038 		break;
1039 
1040 	case SIOCADDMULTI:
1041 	case SIOCDELMULTI:
1042 		/*
1043 		 * XXX Removing all multicast addresses and adding
1044 		 * most of them back, is somewhat retarded.
1045 		 */
1046 		vnet_setmulti(sc, 0);
1047 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
1048 		vnet_setmulti(sc, 1);
1049 		if (error == ENETRESET)
1050 			error = 0;
1051 		break;
1052 
1053 	default:
1054 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
1055 	}
1056 
1057 	splx(s);
1058 	return (error);
1059 }
1060 
1061 void
1062 vnet_watchdog(struct ifnet *ifp)
1063 {
1064 }
1065 
1066 int
1067 vnet_media_change(struct ifnet *ifp)
1068 {
1069 	return (0);
1070 }
1071 
1072 void
1073 vnet_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1074 {
1075 	imr->ifm_active = IFM_ETHER | IFM_AUTO;
1076 	imr->ifm_status = IFM_AVALID;
1077 
1078 	if (LINK_STATE_IS_UP(ifp->if_link_state) &&
1079 	    ifp->if_flags & IFF_UP)
1080 		imr->ifm_status |= IFM_ACTIVE;
1081 }
1082 
1083 void
1084 vnet_link_state(struct vnet_softc *sc)
1085 {
1086 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1087 	int link_state = LINK_STATE_DOWN;
1088 
1089 	if (sc->sc_vio_state == VIO_ESTABLISHED)
1090 		link_state = LINK_STATE_FULL_DUPLEX;
1091 	if (ifp->if_link_state != link_state) {
1092 		ifp->if_link_state = link_state;
1093 		if_link_state_change(ifp);
1094 	}
1095 }
1096 
1097 void
1098 vnet_setmulti(struct vnet_softc *sc, int set)
1099 {
1100 	struct arpcom *ac = &sc->sc_ac;
1101 	struct ether_multi *enm;
1102 	struct ether_multistep step;
1103 	struct vnet_mcast_info mi;
1104 	int count = 0;
1105 
1106 	if (sc->sc_vio_state != VIO_ESTABLISHED)
1107 		return;
1108 
1109 	bzero(&mi, sizeof(mi));
1110 	mi.tag.type = VIO_TYPE_CTRL;
1111 	mi.tag.stype = VIO_SUBTYPE_INFO;
1112 	mi.tag.stype_env = VNET_MCAST_INFO;
1113 	mi.tag.sid = sc->sc_local_sid;
1114 	mi.set = set ? 1 : 0;
1115 	ETHER_FIRST_MULTI(step, ac, enm);
1116 	while (enm != NULL) {
1117 		/* XXX What about multicast ranges? */
1118 		bcopy(enm->enm_addrlo, mi.mcast_addr[count], ETHER_ADDR_LEN);
1119 		ETHER_NEXT_MULTI(step, enm);
1120 
1121 		count++;
1122 		if (count < VNET_NUM_MCAST)
1123 			continue;
1124 
1125 		mi.count = VNET_NUM_MCAST;
1126 		vio_sendmsg(sc, &mi, sizeof(mi));
1127 		count = 0;
1128 	}
1129 
1130 	if (count > 0) {
1131 		mi.count = count;
1132 		vio_sendmsg(sc, &mi, sizeof(mi));
1133 	}
1134 }
1135 
1136 void
1137 vnet_init(struct ifnet *ifp)
1138 {
1139 	struct vnet_softc *sc = ifp->if_softc;
1140 	struct ldc_conn *lc = &sc->sc_lc;
1141 	int err;
1142 
1143 	sc->sc_lm = ldc_map_alloc(sc->sc_dmatag, 2048);
1144 	if (sc->sc_lm == NULL)
1145 		return;
1146 
1147 	err = hv_ldc_set_map_table(lc->lc_id,
1148 	    sc->sc_lm->lm_map->dm_segs[0].ds_addr, sc->sc_lm->lm_nentries);
1149 	if (err != H_EOK) {
1150 		printf("hv_ldc_set_map_table %d\n", err);
1151 		return;
1152 	}
1153 
1154 	sc->sc_vd = vnet_dring_alloc(sc->sc_dmatag, 128);
1155 	if (sc->sc_vd == NULL)
1156 		return;
1157 	sc->sc_vsd = malloc(128 * sizeof(*sc->sc_vsd), M_DEVBUF, M_NOWAIT);
1158 	if (sc->sc_vsd == NULL)
1159 		return;
1160 
1161 	sc->sc_lm->lm_slot[0].entry = sc->sc_vd->vd_map->dm_segs[0].ds_addr;
1162 	sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK;
1163 	sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW;
1164 	sc->sc_lm->lm_next = 1;
1165 	sc->sc_lm->lm_count = 1;
1166 
1167 	err = hv_ldc_tx_qconf(lc->lc_id,
1168 	    lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries);
1169 	if (err != H_EOK)
1170 		printf("hv_ldc_tx_qconf %d\n", err);
1171 
1172 	err = hv_ldc_rx_qconf(lc->lc_id,
1173 	    lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries);
1174 	if (err != H_EOK)
1175 		printf("hv_ldc_rx_qconf %d\n", err);
1176 
1177 	ldc_send_vers(lc);
1178 
1179 	ifp->if_flags |= IFF_RUNNING;
1180 	ifp->if_flags &= ~IFF_OACTIVE;
1181 }
1182 
1183 void
1184 vnet_stop(struct ifnet *ifp)
1185 {
1186 	struct vnet_softc *sc = ifp->if_softc;
1187 	struct ldc_conn *lc = &sc->sc_lc;
1188 
1189 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1190 
1191 	hv_ldc_tx_qconf(lc->lc_id, 0, 0);
1192 	hv_ldc_rx_qconf(lc->lc_id, 0, 0);
1193 	lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN;
1194 
1195 	vnet_dring_free(sc->sc_dmatag, sc->sc_vd);
1196 
1197 	hv_ldc_set_map_table(lc->lc_id, 0, 0);
1198 	ldc_map_free(sc->sc_dmatag, sc->sc_lm);
1199 }
1200 
1201 struct vnet_dring *
1202 vnet_dring_alloc(bus_dma_tag_t t, int nentries)
1203 {
1204 	struct vnet_dring *vd;
1205 	bus_size_t size;
1206 	caddr_t va;
1207 	int nsegs;
1208 	int i;
1209 
1210 	vd = malloc(sizeof(struct vnet_dring), M_DEVBUF, M_NOWAIT);
1211 	if (vd == NULL)
1212 		return NULL;
1213 
1214 	size = roundup(nentries * sizeof(struct vnet_desc), PAGE_SIZE);
1215 
1216 	if (bus_dmamap_create(t, size, 1, size, 0,
1217 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &vd->vd_map) != 0)
1218 		return (NULL);
1219 
1220 	if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &vd->vd_seg, 1,
1221 	    &nsegs, BUS_DMA_NOWAIT) != 0)
1222 		goto destroy;
1223 
1224 	if (bus_dmamem_map(t, &vd->vd_seg, 1, size, &va,
1225 	    BUS_DMA_NOWAIT) != 0)
1226 		goto free;
1227 
1228 	if (bus_dmamap_load(t, vd->vd_map, va, size, NULL,
1229 	    BUS_DMA_NOWAIT) != 0)
1230 		goto unmap;
1231 
1232 	vd->vd_desc = (struct vnet_desc *)va;
1233 	vd->vd_nentries = nentries;
1234 	bzero(vd->vd_desc, nentries * sizeof(struct vnet_desc));
1235 	for (i = 0; i < vd->vd_nentries; i++)
1236 		vd->vd_desc[i].hdr.dstate = VIO_DESC_FREE;
1237 	return (vd);
1238 
1239 unmap:
1240 	bus_dmamem_unmap(t, va, size);
1241 free:
1242 	bus_dmamem_free(t, &vd->vd_seg, 1);
1243 destroy:
1244 	bus_dmamap_destroy(t, vd->vd_map);
1245 
1246 	return (NULL);
1247 }
1248 
1249 void
1250 vnet_dring_free(bus_dma_tag_t t, struct vnet_dring *vd)
1251 {
1252 	bus_size_t size;
1253 
1254 	size = vd->vd_nentries * sizeof(struct vnet_desc);
1255 	size = roundup(size, PAGE_SIZE);
1256 
1257 	bus_dmamap_unload(t, vd->vd_map);
1258 	bus_dmamem_unmap(t, (caddr_t)vd->vd_desc, size);
1259 	bus_dmamem_free(t, &vd->vd_seg, 1);
1260 	bus_dmamap_destroy(t, vd->vd_map);
1261 	free(vd, M_DEVBUF);
1262 }
1263