Home | History | Annotate | Line # | Download | only in dev
vnet.c revision 1.1
      1 /*	$OpenBSD: vnet.c,v 1.62 2020/07/10 13:26:36 patrick Exp $	*/
      2 /*
      3  * Copyright (c) 2009, 2015 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 #if 0
     19 FIXME openbsd
     20 #include "bpfilter.h"
     21 #endif
     22 
     23 #include <sys/kmem.h>
     24 #include <sys/param.h>
     25 #include <sys/atomic.h>
     26 #include <sys/device.h>
     27 #include <sys/malloc.h>
     28 #include <sys/pool.h>
     29 #include <sys/mbuf.h>
     30 #include <sys/socket.h>
     31 #include <sys/sockio.h>
     32 #include <sys/systm.h>
     33 #if 0
     34 FIXME openbsd
     35 #include <sys/timeout.h>
     36 #endif
     37 
     38 #include <machine/autoconf.h>
     39 #include <machine/hypervisor.h>
     40 #include <machine/openfirm.h>
     41 
     42 #include <net/if.h>
     43 #include <net/if_media.h>
     44 
     45 #include <netinet/in.h>
     46 #include <net/if_ether.h>
     47 
     48 #if NBPFILTER > 0
     49 #include <net/bpf.h>
     50 #endif
     51 
     52 #include <uvm/uvm_extern.h>
     53 
     54 #include <sparc64/dev/cbusvar.h>
     55 #include <sparc64/dev/ldcvar.h>
     56 #include <sparc64/dev/viovar.h>
     57 
     58 #ifdef VNET_DEBUG
     59 #define DPRINTF(x)	printf x
     60 #else
     61 #define DPRINTF(x)
     62 #endif
     63 
     64 #define VNET_TX_ENTRIES		32
     65 #define VNET_RX_ENTRIES		32
     66 
     67 struct vnet_attr_info {
     68 	struct vio_msg_tag	tag;
     69 	uint8_t			xfer_mode;
     70 	uint8_t			addr_type;
     71 	uint16_t		ack_freq;
     72 	uint32_t		_reserved1;
     73 	uint64_t		addr;
     74 	uint64_t		mtu;
     75 	uint64_t		_reserved2[3];
     76 };
     77 
     78 /* Address types. */
     79 #define VNET_ADDR_ETHERMAC	0x01
     80 
     81 /* Sub-Type envelopes. */
     82 #define VNET_MCAST_INFO		0x0101
     83 
     84 #define VNET_NUM_MCAST		7
     85 
     86 struct vnet_mcast_info {
     87 	struct vio_msg_tag	tag;
     88 	uint8_t			set;
     89 	uint8_t			count;
     90 	uint8_t			mcast_addr[VNET_NUM_MCAST][ETHER_ADDR_LEN];
     91 	uint32_t		_reserved;
     92 };
     93 
     94 struct vnet_desc {
     95 	struct vio_dring_hdr	hdr;
     96 	uint32_t		nbytes;
     97 	uint32_t		ncookies;
     98 	struct ldc_cookie	cookie[2];
     99 };
    100 
    101 struct vnet_desc_msg {
    102 	struct vio_msg_tag	tag;
    103 	uint64_t		seq_no;
    104 	uint64_t		desc_handle;
    105 	uint32_t		nbytes;
    106 	uint32_t		ncookies;
    107 	struct ldc_cookie	cookie[1];
    108 };
    109 
    110 struct vnet_dring {
    111 	bus_dmamap_t		vd_map;
    112 	bus_dma_segment_t	vd_seg;
    113 	struct vnet_desc	*vd_desc;
    114 	int			vd_nentries;
    115 };
    116 
    117 struct vnet_dring *vnet_dring_alloc(bus_dma_tag_t, int);
    118 void	vnet_dring_free(bus_dma_tag_t, struct vnet_dring *);
    119 
    120 /*
    121  * For now, we only support vNet 1.0.
    122  */
    123 #define VNET_MAJOR	1
    124 #define VNET_MINOR	0
    125 
    126 /*
    127  * The vNet protocol wants the IP header to be 64-bit aligned, so
    128  * define out own variant of ETHER_ALIGN.
    129  */
    130 #define VNET_ETHER_ALIGN	6
    131 
    132 struct vnet_soft_desc {
    133 	int		vsd_map_idx;
    134 #if 0
    135 FIXME openbsd
    136 	caddr_t		vsd_buf;
    137 #else
    138 	unsigned char *vsd_buf;
    139 #endif
    140 };
    141 
    142 struct vnet_softc {
    143 	struct device	sc_dv;
    144 	bus_space_tag_t	sc_bustag;
    145 	bus_dma_tag_t	sc_dmatag;
    146 
    147 	uint64_t	sc_tx_ino;
    148 	uint64_t	sc_rx_ino;
    149 	void		*sc_tx_ih;
    150 	void		*sc_rx_ih;
    151 
    152 	struct ldc_conn	sc_lc;
    153 
    154 	uint16_t	sc_vio_state;
    155 #define VIO_SND_VER_INFO	0x0001
    156 #define VIO_ACK_VER_INFO	0x0002
    157 #define VIO_RCV_VER_INFO	0x0004
    158 #define VIO_SND_ATTR_INFO	0x0008
    159 #define VIO_ACK_ATTR_INFO	0x0010
    160 #define VIO_RCV_ATTR_INFO	0x0020
    161 #define VIO_SND_DRING_REG	0x0040
    162 #define VIO_ACK_DRING_REG	0x0080
    163 #define VIO_RCV_DRING_REG	0x0100
    164 #define VIO_SND_RDX		0x0200
    165 #define VIO_ACK_RDX		0x0400
    166 #define VIO_RCV_RDX		0x0800
    167 
    168 #if 0
    169 FIXME openbsd
    170 	struct timeout	sc_handshake_to;
    171 #endif
    172 
    173 	uint8_t		sc_xfer_mode;
    174 
    175 	uint32_t	sc_local_sid;
    176 	uint64_t	sc_dring_ident;
    177 	uint64_t	sc_seq_no;
    178 
    179 	u_int		sc_tx_prod;
    180 	u_int		sc_tx_cons;
    181 
    182 	u_int		sc_peer_state;
    183 
    184 	struct ldc_map	*sc_lm;
    185 	struct vnet_dring *sc_vd;
    186 	struct vnet_soft_desc *sc_vsd;
    187 #define VNET_NUM_SOFT_DESC	128
    188 
    189 	size_t		sc_peer_desc_size;
    190 	struct ldc_cookie sc_peer_dring_cookie;
    191 	int		sc_peer_dring_nentries;
    192 
    193 	struct pool	sc_pool;
    194 
    195 	struct ethercom	sc_ethercom;
    196 	struct ifmedia	sc_media;
    197 	u_int8_t sc_macaddr[ETHER_ADDR_LEN];
    198 };
    199 
    200 int vnet_match (device_t, cfdata_t, void *);
    201 void vnet_attach (device_t, device_t, void *);
    202 
    203 CFATTACH_DECL_NEW(vnet, sizeof(struct vnet_softc),
    204     vnet_match, vnet_attach, NULL, NULL);
    205 
    206 int	vnet_tx_intr(void *);
    207 int	vnet_rx_intr(void *);
    208 void	vnet_handshake(void *);
    209 
    210 void	vio_rx_data(struct ldc_conn *, struct ldc_pkt *);
    211 void	vnet_rx_vio_ctrl(struct vnet_softc *, struct vio_msg *);
    212 void	vnet_rx_vio_ver_info(struct vnet_softc *, struct vio_msg_tag *);
    213 void	vnet_rx_vio_attr_info(struct vnet_softc *, struct vio_msg_tag *);
    214 void	vnet_rx_vio_dring_reg(struct vnet_softc *, struct vio_msg_tag *);
    215 void	vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *);
    216 void	vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *);
    217 void	vnet_rx_vio_desc_data(struct vnet_softc *sc, struct vio_msg_tag *);
    218 void	vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *);
    219 
    220 void	vnet_ldc_reset(struct ldc_conn *);
    221 void	vnet_ldc_start(struct ldc_conn *);
    222 
    223 void	vnet_sendmsg(struct vnet_softc *, void *, size_t);
    224 void	vnet_send_ver_info(struct vnet_softc *, uint16_t, uint16_t);
    225 void	vnet_send_attr_info(struct vnet_softc *);
    226 void	vnet_send_dring_reg(struct vnet_softc *);
    227 void	vio_send_rdx(struct vnet_softc *);
    228 void	vnet_send_dring_data(struct vnet_softc *, uint32_t);
    229 
    230 void	vnet_start(struct ifnet *);
    231 void	vnet_start_desc(struct ifnet *);
    232 int		vnet_ioctl (struct ifnet *, u_long, void *);
    233 void	vnet_watchdog(struct ifnet *);
    234 
    235 int		vnet_media_change(struct ifnet *);
    236 void	vnet_media_status(struct ifnet *, struct ifmediareq *);
    237 
    238 void	vnet_link_state(struct vnet_softc *sc);
    239 
    240 void	vnet_setmulti(struct vnet_softc *, int);
    241 
    242 void	vnet_init(struct ifnet *);
    243 void	vnet_stop(struct ifnet *);
    244 
    245 int vnet_match(device_t parent, cfdata_t match, void *aux)
    246 {
    247 
    248 	struct cbus_attach_args *ca = aux;
    249 	if (strcmp(ca->ca_name, "network") == 0)
    250 		return (1);
    251 
    252 	return (0);
    253 }
    254 
    255 void
    256 vnet_attach(struct device *parent, struct device *self, void *aux)
    257 {
    258 	struct vnet_softc *sc = device_private(self);
    259 	struct cbus_attach_args *ca = aux;
    260 	struct ldc_conn *lc;
    261 	struct ifnet *ifp;
    262 
    263 	sc->sc_bustag = ca->ca_bustag;
    264 	sc->sc_dmatag = ca->ca_dmatag;
    265 	sc->sc_tx_ino = ca->ca_tx_ino;
    266 	sc->sc_rx_ino = ca->ca_rx_ino;
    267 
    268 	printf(": ivec 0x%lx, 0x%lx", sc->sc_tx_ino, sc->sc_rx_ino);
    269 
    270 	/*
    271 	 * Un-configure queues before registering interrupt handlers,
    272 	 * such that we dont get any stale LDC packets or events.
    273 	 */
    274 	hv_ldc_tx_qconf(ca->ca_id, 0, 0);
    275 	hv_ldc_rx_qconf(ca->ca_id, 0, 0);
    276 
    277 #if 0
    278 FIXME openbsd
    279 	sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_ino,
    280 	    IPL_NET, BUS_INTR_ESTABLISH_MPSAFE, vnet_tx_intr,
    281 	    sc, sc->sc_dv.dv_xname);
    282 	sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_ino,
    283 	    IPL_NET, BUS_INTR_ESTABLISH_MPSAFE, vnet_rx_intr,
    284 	    sc, sc->sc_dv.dv_xname);
    285 	if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
    286 		printf(", can't establish interrupt\n");
    287 		return;
    288 	}
    289 #else
    290 	sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_ino,
    291 	    IPL_NET, vnet_tx_intr, sc);
    292 	sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_ino,
    293 	    IPL_NET, vnet_rx_intr, sc);
    294 	if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
    295 		printf(", can't establish interrupts\n");
    296 		return;
    297 	}
    298 #endif
    299 
    300 	lc = &sc->sc_lc;
    301 	lc->lc_id = ca->ca_id;
    302 	lc->lc_sc = sc;
    303 	lc->lc_reset = vnet_ldc_reset;
    304 	lc->lc_start = vnet_ldc_start;
    305 	lc->lc_rx_data = vio_rx_data;
    306 
    307 #if 0
    308 FIXME openbsd
    309 	timeout_set(&sc->sc_handshake_to, vnet_handshake, sc);
    310 #endif
    311 	sc->sc_peer_state = VIO_DP_STOPPED;
    312 
    313 #if OPENBSD_BUSDMA
    314 	lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VNET_TX_ENTRIES);
    315 	if (lc->lc_txq == NULL) {
    316 		printf(", can't allocate tx queue\n");
    317 		return;
    318 	}
    319 
    320 	lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VNET_RX_ENTRIES);
    321 	if (lc->lc_rxq == NULL) {
    322 		printf(", can't allocate rx queue\n");
    323 		goto free_txqueue;
    324 	}
    325 #else
    326 	lc->lc_txq = ldc_queue_alloc(VNET_TX_ENTRIES);
    327 	if (lc->lc_txq == NULL) {
    328 		printf(", can't allocate tx queue\n");
    329 		return;
    330 	}
    331 
    332 	lc->lc_rxq = ldc_queue_alloc(VNET_RX_ENTRIES);
    333 	if (lc->lc_rxq == NULL) {
    334 		printf(", can't allocate rx queue\n");
    335 		goto free_txqueue;
    336 	}
    337 #endif
    338 
    339 	if (OF_getprop(ca->ca_node, "local-mac-address",
    340 				   sc->sc_macaddr, ETHER_ADDR_LEN) > 0) {
    341 		printf(", address %s", ether_sprintf(sc->sc_macaddr));
    342 	} else {
    343 		printf(", cannot retrieve local mac address\n");
    344 		return;
    345 	}
    346 
    347 	/*
    348 	 * Each interface gets its own pool.
    349 	 */
    350 #if 0
    351 FIXME openbsd
    352 	pool_init(&sc->sc_pool, 2048, 0, IPL_NET, 0, sc->sc_dv.dv_xname, NULL);
    353 #else
    354 	pool_init(&sc->sc_pool, 2048, 0, 0, 0, sc->sc_dv.dv_xname, NULL, IPL_NET);
    355 #endif
    356 
    357 	ifp = &sc->sc_ethercom.ec_if;
    358 	ifp->if_softc = sc;
    359 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    360 	ifp->if_link_state = LINK_STATE_DOWN;
    361 	ifp->if_ioctl = vnet_ioctl;
    362 	ifp->if_start = vnet_start;
    363 	ifp->if_watchdog = vnet_watchdog;
    364 	strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
    365 #if 0
    366 FIXME openbsd
    367 	ifq_set_maxlen(&ifp->if_snd, 31); /* XXX */
    368 #else
    369  IFQ_SET_MAXLEN(&ifp->if_snd, 31); /* XXX */
    370 #endif
    371 
    372 	ifmedia_init(&sc->sc_media, 0, vnet_media_change, vnet_media_status);
    373 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
    374 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
    375 
    376 	int error = if_initialize(ifp);
    377 	if (error != 0) {
    378 		printf(", if_initialize() failed\n");
    379 		return;
    380 	}
    381 	ether_ifattach(ifp, sc->sc_macaddr);
    382 	if_register(ifp);
    383 
    384 	printf("\n");
    385 	return;
    386 free_txqueue:
    387 #if OPENBSD_BUSDMA
    388 	ldc_queue_free(sc->sc_dmatag, lc->lc_txq);
    389 #else
    390 	ldc_queue_free(lc->lc_txq);
    391 #endif
    392 }
    393 
    394 int
    395 vnet_tx_intr(void *arg)
    396 {
    397 	DPRINTF(("%s: entry\n", __func__));
    398 
    399 	struct vnet_softc *sc = arg;
    400 	struct ldc_conn *lc = &sc->sc_lc;
    401 	uint64_t tx_head, tx_tail, tx_state;
    402 
    403 	hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
    404 	if (tx_state != lc->lc_tx_state) {
    405 		switch (tx_state) {
    406 		case LDC_CHANNEL_DOWN:
    407 			DPRINTF(("%s: Tx link down\n", __func__));
    408 			break;
    409 		case LDC_CHANNEL_UP:
    410 			DPRINTF(("%s: Tx link up\n", __func__));
    411 			break;
    412 		case LDC_CHANNEL_RESET:
    413 			DPRINTF(("%s: Tx link reset\n", __func__));
    414 			break;
    415 		}
    416 		lc->lc_tx_state = tx_state;
    417 	}
    418 
    419 	DPRINTF(("%s: exit\n", __func__));
    420 	return (1);
    421 }
    422 
    423 int
    424 vnet_rx_intr(void *arg)
    425 {
    426 	DPRINTF(("%s: entry\n", __func__));
    427 
    428 	struct vnet_softc *sc = arg;
    429 	struct ldc_conn *lc = &sc->sc_lc;
    430 	uint64_t rx_head, rx_tail, rx_state;
    431 	struct ldc_pkt *lp;
    432 	int err;
    433 
    434 	err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state);
    435 	if (err == H_EINVAL)
    436 		return (0);
    437 	if (err != H_EOK) {
    438 		printf("hv_ldc_rx_get_state %d\n", err);
    439 		return (0);
    440 	}
    441 
    442 	if (rx_state != lc->lc_rx_state) {
    443 		switch (rx_state) {
    444 		case LDC_CHANNEL_DOWN:
    445 			DPRINTF(("%s: Rx link down\n", __func__));
    446 			lc->lc_tx_seqid = 0;
    447 			lc->lc_state = 0;
    448 			lc->lc_reset(lc);
    449 			if (rx_head == rx_tail)
    450 				break;
    451 			/* Discard and ack pending I/O. */
    452 			DPRINTF(("setting rx qhead to %lld\n", rx_tail));
    453 			err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
    454 			if (err == H_EOK)
    455 				break;
    456 			printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
    457 			break;
    458 		case LDC_CHANNEL_UP:
    459 			DPRINTF(("%s: Rx link up\n", __func__));
    460 #if 0
    461 FIXME openbsd
    462 			timeout_add_msec(&sc->sc_handshake_to, 500);
    463 #endif
    464 			break;
    465 		case LDC_CHANNEL_RESET:
    466 			DPRINTF(("%s: Rx link reset\n", __func__));
    467 			lc->lc_tx_seqid = 0;
    468 			lc->lc_state = 0;
    469 			lc->lc_reset(lc);
    470 #if 0
    471 FIXME openbsd
    472 			timeout_add_msec(&sc->sc_handshake_to, 500);
    473 #endif
    474 			if (rx_head == rx_tail)
    475 				break;
    476 			/* Discard and ack pending I/O. */
    477 			DPRINTF(("setting rx qhead to %lld\n", rx_tail));
    478 			err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
    479 			if (err == H_EOK)
    480 				break;
    481 			printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
    482 			break;
    483 		}
    484 		lc->lc_rx_state = rx_state;
    485 		return (1);
    486 	}
    487 
    488 	if (rx_head == rx_tail)
    489 		return (0);
    490 
    491 	lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head);
    492 	switch (lp->type) {
    493 	case LDC_CTRL:
    494 		ldc_rx_ctrl(lc, lp);
    495 		break;
    496 
    497 	case LDC_DATA:
    498 		ldc_rx_data(lc, lp);
    499 		break;
    500 
    501 	default:
    502 		DPRINTF(("%0x02/%0x02/%0x02\n", lp->type, lp->stype,
    503 		    lp->ctrl));
    504 		ldc_reset(lc);
    505 		break;
    506 	}
    507 
    508 	if (lc->lc_state == 0)
    509 		return (1);
    510 
    511 	rx_head += sizeof(*lp);
    512 	rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1);
    513 	err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head);
    514 	if (err != H_EOK)
    515 		printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
    516 
    517 	DPRINTF(("%s: exit\n", __func__));
    518 	return (1);
    519 }
    520 
    521 void
    522 vnet_handshake(void *arg)
    523 {
    524 	struct vnet_softc *sc = arg;
    525 
    526 	ldc_send_vers(&sc->sc_lc);
    527 }
    528 
    529 void
    530 vio_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
    531 {
    532 	struct vio_msg *vm = (struct vio_msg *)lp;
    533 
    534 	switch (vm->type) {
    535 	case VIO_TYPE_CTRL:
    536 		if ((lp->env & LDC_FRAG_START) == 0 &&
    537 		    (lp->env & LDC_FRAG_STOP) == 0)
    538 			return;
    539 		vnet_rx_vio_ctrl(lc->lc_sc, vm);
    540 		break;
    541 
    542 	case VIO_TYPE_DATA:
    543 		if((lp->env & LDC_FRAG_START) == 0)
    544 			return;
    545 		vnet_rx_vio_data(lc->lc_sc, vm);
    546 		break;
    547 
    548 	default:
    549 		DPRINTF(("Unhandled packet type 0x%02x\n", vm->type));
    550 		ldc_reset(lc);
    551 		break;
    552 	}
    553 }
    554 
    555 void
    556 vnet_rx_vio_ctrl(struct vnet_softc *sc, struct vio_msg *vm)
    557 {
    558 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
    559 
    560 	switch (tag->stype_env) {
    561 	case VIO_VER_INFO:
    562 		vnet_rx_vio_ver_info(sc, tag);
    563 		break;
    564 	case VIO_ATTR_INFO:
    565 		vnet_rx_vio_attr_info(sc, tag);
    566 		break;
    567 	case VIO_DRING_REG:
    568 		vnet_rx_vio_dring_reg(sc, tag);
    569 		break;
    570 	case VIO_RDX:
    571 		vnet_rx_vio_rdx(sc, tag);
    572 		break;
    573 	default:
    574 		DPRINTF(("CTRL/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
    575 		break;
    576 	}
    577 }
    578 
    579 void
    580 vnet_rx_vio_ver_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
    581 {
    582 	struct vio_ver_info *vi = (struct vio_ver_info *)tag;
    583 
    584 	switch (vi->tag.stype) {
    585 	case VIO_SUBTYPE_INFO:
    586 		DPRINTF(("CTRL/INFO/VER_INFO\n"));
    587 
    588 		/* Make sure we're talking to a virtual network device. */
    589 		if (vi->dev_class != VDEV_NETWORK &&
    590 		    vi->dev_class != VDEV_NETWORK_SWITCH) {
    591 			/* Huh, we're not talking to a network device? */
    592 			printf("Not a network device\n");
    593 			vi->tag.stype = VIO_SUBTYPE_NACK;
    594 			vnet_sendmsg(sc, vi, sizeof(*vi));
    595 			return;
    596 		}
    597 
    598 		if (vi->major != VNET_MAJOR) {
    599 			vi->tag.stype = VIO_SUBTYPE_NACK;
    600 			vi->major = VNET_MAJOR;
    601 			vi->minor = VNET_MINOR;
    602 			vnet_sendmsg(sc, vi, sizeof(*vi));
    603 			return;
    604 		}
    605 
    606 		vi->tag.stype = VIO_SUBTYPE_ACK;
    607 		vi->tag.sid = sc->sc_local_sid;
    608 		vi->minor = VNET_MINOR;
    609 		vnet_sendmsg(sc, vi, sizeof(*vi));
    610 		sc->sc_vio_state |= VIO_RCV_VER_INFO;
    611 		break;
    612 
    613 	case VIO_SUBTYPE_ACK:
    614 		DPRINTF(("CTRL/ACK/VER_INFO\n"));
    615 		if (!ISSET(sc->sc_vio_state, VIO_SND_VER_INFO)) {
    616 			ldc_reset(&sc->sc_lc);
    617 			break;
    618 		}
    619 		sc->sc_vio_state |= VIO_ACK_VER_INFO;
    620 		break;
    621 
    622 	default:
    623 		DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype));
    624 		break;
    625 	}
    626 
    627 	if (ISSET(sc->sc_vio_state, VIO_RCV_VER_INFO) &&
    628 	    ISSET(sc->sc_vio_state, VIO_ACK_VER_INFO))
    629 		vnet_send_attr_info(sc);
    630 }
    631 
    632 void
    633 vnet_rx_vio_attr_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
    634 {
    635 	struct vnet_attr_info *ai = (struct vnet_attr_info *)tag;
    636 
    637 	switch (ai->tag.stype) {
    638 	case VIO_SUBTYPE_INFO:
    639 		DPRINTF(("CTRL/INFO/ATTR_INFO\n"));
    640 		sc->sc_xfer_mode = ai->xfer_mode;
    641 
    642 		ai->tag.stype = VIO_SUBTYPE_ACK;
    643 		ai->tag.sid = sc->sc_local_sid;
    644 		vnet_sendmsg(sc, ai, sizeof(*ai));
    645 		sc->sc_vio_state |= VIO_RCV_ATTR_INFO;
    646 		break;
    647 
    648 	case VIO_SUBTYPE_ACK:
    649 		DPRINTF(("CTRL/ACK/ATTR_INFO\n"));
    650 		if (!ISSET(sc->sc_vio_state, VIO_SND_ATTR_INFO)) {
    651 			ldc_reset(&sc->sc_lc);
    652 			break;
    653 		}
    654 		sc->sc_vio_state |= VIO_ACK_ATTR_INFO;
    655 		break;
    656 
    657 	default:
    658 		DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype));
    659 		break;
    660 	}
    661 
    662 	if (ISSET(sc->sc_vio_state, VIO_RCV_ATTR_INFO) &&
    663 	    ISSET(sc->sc_vio_state, VIO_ACK_ATTR_INFO)) {
    664 		if (sc->sc_xfer_mode == VIO_DRING_MODE)
    665 			vnet_send_dring_reg(sc);
    666 		else
    667 			vio_send_rdx(sc);
    668 	}
    669 }
    670 
    671 void
    672 vnet_rx_vio_dring_reg(struct vnet_softc *sc, struct vio_msg_tag *tag)
    673 {
    674 	struct vio_dring_reg *dr = (struct vio_dring_reg *)tag;
    675 
    676 	switch (dr->tag.stype) {
    677 	case VIO_SUBTYPE_INFO:
    678 		DPRINTF(("CTRL/INFO/DRING_REG\n"));
    679 
    680 		sc->sc_peer_dring_nentries = dr->num_descriptors;
    681 		sc->sc_peer_desc_size = dr->descriptor_size;
    682 		sc->sc_peer_dring_cookie = dr->cookie[0];
    683 
    684 		dr->tag.stype = VIO_SUBTYPE_ACK;
    685 		dr->tag.sid = sc->sc_local_sid;
    686 		vnet_sendmsg(sc, dr, sizeof(*dr));
    687 		sc->sc_vio_state |= VIO_RCV_DRING_REG;
    688 		break;
    689 
    690 	case VIO_SUBTYPE_ACK:
    691 		DPRINTF(("CTRL/ACK/DRING_REG\n"));
    692 		if (!ISSET(sc->sc_vio_state, VIO_SND_DRING_REG)) {
    693 			ldc_reset(&sc->sc_lc);
    694 			break;
    695 		}
    696 
    697 		sc->sc_dring_ident = dr->dring_ident;
    698 		sc->sc_seq_no = 1;
    699 
    700 		sc->sc_vio_state |= VIO_ACK_DRING_REG;
    701 		break;
    702 
    703 	default:
    704 		DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype));
    705 		break;
    706 	}
    707 
    708 	if (ISSET(sc->sc_vio_state, VIO_RCV_DRING_REG) &&
    709 	    ISSET(sc->sc_vio_state, VIO_ACK_DRING_REG))
    710 		vio_send_rdx(sc);
    711 }
    712 
    713 void
    714 vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *tag)
    715 {
    716 #if 0
    717 FIXME openbsd
    718 	struct ifnet *ifp = &sc->sc_ac.ac_if;
    719 #else
    720 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    721 #endif
    722 
    723 	switch(tag->stype) {
    724 	case VIO_SUBTYPE_INFO:
    725 		DPRINTF(("CTRL/INFO/RDX\n"));
    726 
    727 		tag->stype = VIO_SUBTYPE_ACK;
    728 		tag->sid = sc->sc_local_sid;
    729 		vnet_sendmsg(sc, tag, sizeof(*tag));
    730 		sc->sc_vio_state |= VIO_RCV_RDX;
    731 		break;
    732 
    733 	case VIO_SUBTYPE_ACK:
    734 		DPRINTF(("CTRL/ACK/RDX\n"));
    735 		if (!ISSET(sc->sc_vio_state, VIO_SND_RDX)) {
    736 			ldc_reset(&sc->sc_lc);
    737 			break;
    738 		}
    739 		sc->sc_vio_state |= VIO_ACK_RDX;
    740 		break;
    741 
    742 	default:
    743 		DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype));
    744 		break;
    745 	}
    746 
    747 	if (ISSET(sc->sc_vio_state, VIO_RCV_RDX) &&
    748 	    ISSET(sc->sc_vio_state, VIO_ACK_RDX)) {
    749 		/* Link is up! */
    750 		vnet_link_state(sc);
    751 
    752 		/* Configure multicast now that we can. */
    753 		vnet_setmulti(sc, 1);
    754 
    755 #if 0
    756 FIXME openbsd
    757 		KERNEL_LOCK();
    758 #else
    759 	KERNEL_LOCK(1, curlwp);
    760 #endif
    761 #if 0
    762 FIXME openbsd
    763 		ifq_clr_oactive(&ifp->if_snd);
    764 #else
    765 	ifp->if_flags &= ~IFF_OACTIVE;
    766 #endif
    767 		vnet_start(ifp);
    768 #if 0
    769 FIXME openbsd
    770 		KERNEL_UNLOCK();
    771 #else
    772 	KERNEL_UNLOCK_ONE(curlwp);
    773 #endif
    774 	}
    775 }
    776 
    777 void
    778 vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *vm)
    779 {
    780 	struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
    781 
    782 	if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
    783 	    !ISSET(sc->sc_vio_state, VIO_ACK_RDX)) {
    784 		DPRINTF(("Spurious DATA/0x%02x/0x%04x\n", tag->stype,
    785 		    tag->stype_env));
    786 		return;
    787 	}
    788 
    789 	switch(tag->stype_env) {
    790 	case VIO_DESC_DATA:
    791 		vnet_rx_vio_desc_data(sc, tag);
    792 		break;
    793 
    794 	case VIO_DRING_DATA:
    795 		vnet_rx_vio_dring_data(sc, tag);
    796 		break;
    797 
    798 	default:
    799 		DPRINTF(("DATA/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
    800 		break;
    801 	}
    802 }
    803 
    804 void
    805 vnet_rx_vio_desc_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
    806 {
    807 	struct vnet_desc_msg *dm = (struct vnet_desc_msg *)tag;
    808 	struct ldc_conn *lc = &sc->sc_lc;
    809 	struct ldc_map *map = sc->sc_lm;
    810 #if 0
    811 FIXME openbsd
    812 	struct ifnet *ifp = &sc->sc_ac.ac_if;
    813 #else
    814 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    815 #endif
    816 #if 0
    817 FIXME openbsd
    818 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    819 #endif
    820 	struct mbuf *m;
    821 	unsigned char *buf;
    822 	paddr_t pa;
    823 	psize_t nbytes;
    824 	u_int cons;
    825 	int err;
    826 
    827 	switch(tag->stype) {
    828 	case VIO_SUBTYPE_INFO:
    829 		buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
    830 		if (buf == NULL) {
    831 #if 0
    832 FIXME openbsd
    833 			ifp->if_ierrors++;
    834 #else
    835 			if_statinc(ifp, if_ierrors);
    836 #endif
    837 			goto skip;
    838 		}
    839 		nbytes = roundup(dm->nbytes, 8);
    840 
    841 		if (dm->nbytes > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
    842 #if 0
    843 FIXME openbsd
    844 			ifp->if_ierrors++;
    845 #else
    846 			if_statinc(ifp, if_ierrors);
    847 #endif
    848 			goto skip;
    849 		}
    850 
    851 		pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
    852 		err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
    853 		    dm->cookie[0].addr, pa, nbytes, &nbytes);
    854 		if (err != H_EOK) {
    855 			pool_put(&sc->sc_pool, buf);
    856 #if 0
    857 FIXME openbsd
    858 			ifp->if_ierrors++;
    859 #else
    860 			if_statinc(ifp, if_ierrors);
    861 #endif
    862 			goto skip;
    863 		}
    864 
    865 		/* Stupid OBP doesn't align properly. */
    866 #if 0
    867 FIXME openbsd
    868                 m = m_devget(buf, dm->nbytes, ETHER_ALIGN);
    869 #else
    870 		m = m_devget(buf, dm->nbytes, 0, ifp);
    871 #endif
    872 		pool_put(&sc->sc_pool, buf);
    873 		if (m == NULL) {
    874 #if 0
    875 FIXME openbsd
    876 			ifp->if_ierrors++;
    877 #else
    878 			if_statinc(ifp, if_ierrors);
    879 #endif
    880 			goto skip;
    881 		}
    882 
    883 		/* Pass it on. */
    884 #if 0
    885 FIXME openbsd
    886 		ml_enqueue(&ml, m);
    887 		if_input(ifp, &ml);
    888 #else
    889 	if_percpuq_enqueue(ifp->if_percpuq, m);
    890 #endif
    891 	skip:
    892 		dm->tag.stype = VIO_SUBTYPE_ACK;
    893 		dm->tag.sid = sc->sc_local_sid;
    894 		vnet_sendmsg(sc, dm, sizeof(*dm));
    895 		break;
    896 
    897 	case VIO_SUBTYPE_ACK:
    898 		DPRINTF(("DATA/ACK/DESC_DATA\n"));
    899 
    900 		if (dm->desc_handle != sc->sc_tx_cons) {
    901 			printf("out of order\n");
    902 			return;
    903 		}
    904 
    905 		cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
    906 
    907 		map->lm_slot[sc->sc_vsd[cons].vsd_map_idx].entry = 0;
    908 #if 0
    909 FIXME openbsd
    910 		atomic_dec_int(&map->lm_count);
    911 #else
    912 		map->lm_count--;
    913 #endif
    914 
    915 		pool_put(&sc->sc_pool, sc->sc_vsd[cons].vsd_buf);
    916 		sc->sc_vsd[cons].vsd_buf = NULL;
    917 
    918 		sc->sc_tx_cons++;
    919 		break;
    920 
    921 	case VIO_SUBTYPE_NACK:
    922 		DPRINTF(("DATA/NACK/DESC_DATA\n"));
    923 		break;
    924 
    925 	default:
    926 		DPRINTF(("DATA/0x%02x/DESC_DATA\n", tag->stype));
    927 		break;
    928 	}
    929 }
    930 
    931 void
    932 vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
    933 {
    934 	struct vio_dring_msg *dm = (struct vio_dring_msg *)tag;
    935 	struct ldc_conn *lc = &sc->sc_lc;
    936 #if 0
    937 FIXME openbsd
    938 	struct ifnet *ifp = &sc->sc_ac.ac_if;
    939 #else
    940 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    941 #endif
    942 	struct mbuf *m = NULL;
    943 	paddr_t pa;
    944 	psize_t nbytes;
    945 	int err;
    946 
    947 	switch(tag->stype) {
    948 	case VIO_SUBTYPE_INFO:
    949 	{
    950 		struct vnet_desc desc;
    951 		uint64_t cookie;
    952 		paddr_t desc_pa;
    953 		int idx, ack_end_idx = -1;
    954 #if 0
    955 FIXME openbsd
    956 		struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    957 #endif
    958 
    959 		idx = dm->start_idx;
    960 		for (;;) {
    961 			cookie = sc->sc_peer_dring_cookie.addr;
    962 			cookie += idx * sc->sc_peer_desc_size;
    963 			nbytes = sc->sc_peer_desc_size;
    964 			pmap_extract(pmap_kernel(), (vaddr_t)&desc, &desc_pa);
    965 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN, cookie,
    966 			    desc_pa, nbytes, &nbytes);
    967 			if (err != H_EOK) {
    968 				printf("hv_ldc_copy_in %d\n", err);
    969 				break;
    970 			}
    971 
    972 			if (desc.hdr.dstate != VIO_DESC_READY)
    973 				break;
    974 
    975 			if (desc.nbytes > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
    976 #if 0
    977 FIXME openbsd
    978 				ifp->if_ierrors++;
    979 #else
    980 				if_statinc(ifp, if_ierrors);
    981 #endif
    982 				goto skip;
    983 			}
    984 #if 0
    985 FIXME openbsd
    986 			m = MCLGETI(NULL, M_DONTWAIT, NULL, desc.nbytes);
    987 			if (!m)
    988 				break;
    989 #else
    990 			MCLGET(NULL, M_DONTWAIT);
    991 			if ((m->m_flags & M_EXT) == 0)
    992 				break;
    993 #endif
    994 			m->m_len = m->m_pkthdr.len = desc.nbytes;
    995 			nbytes = roundup(desc.nbytes + VNET_ETHER_ALIGN, 8);
    996 
    997 			pmap_extract(pmap_kernel(), (vaddr_t)m->m_data, &pa);
    998 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
    999 			    desc.cookie[0].addr, pa, nbytes, &nbytes);
   1000 			if (err != H_EOK) {
   1001 				m_freem(m);
   1002 				goto skip;
   1003 			}
   1004 			m->m_data += VNET_ETHER_ALIGN;
   1005 
   1006 #if 0
   1007 FIXME openbsd
   1008 			ml_enqueue(&ml, m);
   1009 #else
   1010 			if_percpuq_enqueue(ifp->if_percpuq, m);
   1011 #endif
   1012 
   1013 		skip:
   1014 			desc.hdr.dstate = VIO_DESC_DONE;
   1015 			nbytes = sc->sc_peer_desc_size;
   1016 			err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, cookie,
   1017 			    desc_pa, nbytes, &nbytes);
   1018 			if (err != H_EOK)
   1019 				printf("hv_ldc_copy_out %d\n", err);
   1020 
   1021 			ack_end_idx = idx;
   1022 			if (++idx == sc->sc_peer_dring_nentries)
   1023 				idx = 0;
   1024 		}
   1025 #if 0
   1026 FIXME openbd
   1027 		if_input(ifp, &ml);
   1028 #else
   1029 		printf("vnet_rx_vio_dring_data() ignoring if_input - FIXME\n");
   1030 #endif
   1031 
   1032 		if (ack_end_idx == -1) {
   1033 			dm->tag.stype = VIO_SUBTYPE_NACK;
   1034 		} else {
   1035 			dm->tag.stype = VIO_SUBTYPE_ACK;
   1036 			dm->end_idx = ack_end_idx;
   1037 		}
   1038 		dm->tag.sid = sc->sc_local_sid;
   1039 		dm->proc_state = VIO_DP_STOPPED;
   1040 		vnet_sendmsg(sc, dm, sizeof(*dm));
   1041 		break;
   1042 	}
   1043 
   1044 	case VIO_SUBTYPE_ACK:
   1045 	{
   1046 		struct ldc_map *map = sc->sc_lm;
   1047 		u_int cons, count;
   1048 
   1049 		sc->sc_peer_state = dm->proc_state;
   1050 
   1051 		cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
   1052 		while (sc->sc_vd->vd_desc[cons].hdr.dstate == VIO_DESC_DONE) {
   1053 			map->lm_slot[sc->sc_vsd[cons].vsd_map_idx].entry = 0;
   1054 #if 0
   1055 FIXME openbsd
   1056 			atomic_dec_int(&map->lm_count);
   1057 #else
   1058 			map->lm_count--;
   1059 #endif
   1060 
   1061 			pool_put(&sc->sc_pool, sc->sc_vsd[cons].vsd_buf);
   1062 			sc->sc_vsd[cons].vsd_buf = NULL;
   1063 
   1064 			sc->sc_vd->vd_desc[cons].hdr.dstate = VIO_DESC_FREE;
   1065 			sc->sc_tx_cons++;
   1066 			cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
   1067 		}
   1068 
   1069 		count = sc->sc_tx_prod - sc->sc_tx_cons;
   1070 		if (count > 0 && sc->sc_peer_state != VIO_DP_ACTIVE)
   1071 			vnet_send_dring_data(sc, cons);
   1072 
   1073 #if 0
   1074 FIXME openbsd
   1075 		KERNEL_LOCK();
   1076 #else
   1077 		KERNEL_LOCK(1, curlwp);
   1078 #endif
   1079 		if (count < (sc->sc_vd->vd_nentries - 1))
   1080 #if 0
   1081 FIXME openbsd
   1082 			ifq_clr_oactive(&ifp->if_snd);
   1083 #else
   1084 			ifp->if_flags &= ~IFF_OACTIVE;
   1085 #endif
   1086 		if (count == 0)
   1087 			ifp->if_timer = 0;
   1088 
   1089 		vnet_start(ifp);
   1090 #if 0
   1091 FIXME openbsd
   1092 		KERNEL_UNLOCK();
   1093 #else
   1094 		KERNEL_UNLOCK_ONE(curlwp);
   1095 #endif
   1096 		break;
   1097 	}
   1098 
   1099 	case VIO_SUBTYPE_NACK:
   1100 		DPRINTF(("DATA/NACK/DRING_DATA\n"));
   1101 		sc->sc_peer_state = VIO_DP_STOPPED;
   1102 		break;
   1103 
   1104 	default:
   1105 		DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype));
   1106 		break;
   1107 	}
   1108 }
   1109 
   1110 void
   1111 vnet_ldc_reset(struct ldc_conn *lc)
   1112 {
   1113 	struct vnet_softc *sc = lc->lc_sc;
   1114 	int i;
   1115 #if 0
   1116 FIXME openbsd
   1117 	timeout_del(&sc->sc_handshake_to);
   1118 #endif
   1119 	sc->sc_tx_prod = sc->sc_tx_cons = 0;
   1120 	sc->sc_peer_state = VIO_DP_STOPPED;
   1121 	sc->sc_vio_state = 0;
   1122 	vnet_link_state(sc);
   1123 
   1124 	sc->sc_lm->lm_next = 1;
   1125 	sc->sc_lm->lm_count = 1;
   1126 	for (i = 1; i < sc->sc_lm->lm_nentries; i++)
   1127 		sc->sc_lm->lm_slot[i].entry = 0;
   1128 
   1129 	for (i = 0; i < sc->sc_vd->vd_nentries; i++) {
   1130 		if (sc->sc_vsd[i].vsd_buf) {
   1131 			pool_put(&sc->sc_pool, sc->sc_vsd[i].vsd_buf);
   1132 			sc->sc_vsd[i].vsd_buf = NULL;
   1133 		}
   1134 		sc->sc_vd->vd_desc[i].hdr.dstate = VIO_DESC_FREE;
   1135 	}
   1136 }
   1137 
   1138 void
   1139 vnet_ldc_start(struct ldc_conn *lc)
   1140 {
   1141 	struct vnet_softc *sc = lc->lc_sc;
   1142 #if 0
   1143 FIXME openbsd
   1144 	timeout_del(&sc->sc_handshake_to);
   1145 #endif
   1146 	vnet_send_ver_info(sc, VNET_MAJOR, VNET_MINOR);
   1147 }
   1148 
   1149 void
   1150 vnet_sendmsg(struct vnet_softc *sc, void *msg, size_t len)
   1151 {
   1152 	struct ldc_conn *lc = &sc->sc_lc;
   1153 	int err;
   1154 
   1155 	err = ldc_send_unreliable(lc, msg, len);
   1156 	if (err)
   1157 		printf("%s: ldc_send_unreliable: %d\n", __func__, err);
   1158 }
   1159 
   1160 void
   1161 vnet_send_ver_info(struct vnet_softc *sc, uint16_t major, uint16_t minor)
   1162 {
   1163 	struct vio_ver_info vi;
   1164 
   1165 	bzero(&vi, sizeof(vi));
   1166 	vi.tag.type = VIO_TYPE_CTRL;
   1167 	vi.tag.stype = VIO_SUBTYPE_INFO;
   1168 	vi.tag.stype_env = VIO_VER_INFO;
   1169 	vi.tag.sid = sc->sc_local_sid;
   1170 	vi.major = major;
   1171 	vi.minor = minor;
   1172 	vi.dev_class = VDEV_NETWORK;
   1173 	vnet_sendmsg(sc, &vi, sizeof(vi));
   1174 
   1175 	sc->sc_vio_state |= VIO_SND_VER_INFO;
   1176 }
   1177 
   1178 void
   1179 vnet_send_attr_info(struct vnet_softc *sc)
   1180 {
   1181 	struct vnet_attr_info ai;
   1182 	int i;
   1183 
   1184 	bzero(&ai, sizeof(ai));
   1185 	ai.tag.type = VIO_TYPE_CTRL;
   1186 	ai.tag.stype = VIO_SUBTYPE_INFO;
   1187 	ai.tag.stype_env = VIO_ATTR_INFO;
   1188 	ai.tag.sid = sc->sc_local_sid;
   1189 	ai.xfer_mode = VIO_DRING_MODE;
   1190 	ai.addr_type = VNET_ADDR_ETHERMAC;
   1191 	ai.ack_freq = 0;
   1192 	ai.addr = 0;
   1193 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
   1194 		ai.addr <<= 8;
   1195 		ai.addr |= sc->sc_macaddr[i];
   1196 	}
   1197 	ai.mtu = ETHER_MAX_LEN - ETHER_CRC_LEN;
   1198 	vnet_sendmsg(sc, &ai, sizeof(ai));
   1199 
   1200 	sc->sc_vio_state |= VIO_SND_ATTR_INFO;
   1201 }
   1202 
   1203 void
   1204 vnet_send_dring_reg(struct vnet_softc *sc)
   1205 {
   1206 	struct vio_dring_reg dr;
   1207 
   1208 	bzero(&dr, sizeof(dr));
   1209 	dr.tag.type = VIO_TYPE_CTRL;
   1210 	dr.tag.stype = VIO_SUBTYPE_INFO;
   1211 	dr.tag.stype_env = VIO_DRING_REG;
   1212 	dr.tag.sid = sc->sc_local_sid;
   1213 	dr.dring_ident = 0;
   1214 	dr.num_descriptors = sc->sc_vd->vd_nentries;
   1215 	dr.descriptor_size = sizeof(struct vnet_desc);
   1216 	dr.options = VIO_TX_RING;
   1217 	dr.ncookies = 1;
   1218 	dr.cookie[0].addr = 0;
   1219 	dr.cookie[0].size = PAGE_SIZE;
   1220 	vnet_sendmsg(sc, &dr, sizeof(dr));
   1221 
   1222 	sc->sc_vio_state |= VIO_SND_DRING_REG;
   1223 };
   1224 
   1225 void
   1226 vio_send_rdx(struct vnet_softc *sc)
   1227 {
   1228 	struct vio_msg_tag tag;
   1229 
   1230 	tag.type = VIO_TYPE_CTRL;
   1231 	tag.stype = VIO_SUBTYPE_INFO;
   1232 	tag.stype_env = VIO_RDX;
   1233 	tag.sid = sc->sc_local_sid;
   1234 	vnet_sendmsg(sc, &tag, sizeof(tag));
   1235 
   1236 	sc->sc_vio_state |= VIO_SND_RDX;
   1237 }
   1238 
   1239 void
   1240 vnet_send_dring_data(struct vnet_softc *sc, uint32_t start_idx)
   1241 {
   1242 	struct vio_dring_msg dm;
   1243 	u_int peer_state;
   1244 
   1245 	peer_state = atomic_swap_uint(&sc->sc_peer_state, VIO_DP_ACTIVE);
   1246 	if (peer_state == VIO_DP_ACTIVE)
   1247 		return;
   1248 
   1249 	bzero(&dm, sizeof(dm));
   1250 	dm.tag.type = VIO_TYPE_DATA;
   1251 	dm.tag.stype = VIO_SUBTYPE_INFO;
   1252 	dm.tag.stype_env = VIO_DRING_DATA;
   1253 	dm.tag.sid = sc->sc_local_sid;
   1254 	dm.seq_no = sc->sc_seq_no++;
   1255 	dm.dring_ident = sc->sc_dring_ident;
   1256 	dm.start_idx = start_idx;
   1257 	dm.end_idx = -1;
   1258 	vnet_sendmsg(sc, &dm, sizeof(dm));
   1259 }
   1260 
   1261 void
   1262 vnet_start(struct ifnet *ifp)
   1263 {
   1264 	struct vnet_softc *sc = ifp->if_softc;
   1265 	struct ldc_conn *lc = &sc->sc_lc;
   1266 	struct ldc_map *map = sc->sc_lm;
   1267 	struct mbuf *m;
   1268 	paddr_t pa;
   1269 	unsigned char *buf;
   1270 	uint64_t tx_head, tx_tail, tx_state;
   1271 	u_int start, prod, count;
   1272 	int err;
   1273 
   1274 #if 0
   1275 FIXME openbsd
   1276 	if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
   1277 #else
   1278 	if (!(ifp->if_flags & IFF_RUNNING) || (ifp->if_flags & IFF_OACTIVE))
   1279 #endif
   1280 		return;
   1281 
   1282 #if 0
   1283 FIXME openbsd
   1284 	if (ifq_empty(&ifp->if_snd))
   1285 #else
   1286 	if (IFQ_IS_EMPTY(&ifp->if_snd))
   1287 #endif
   1288 		return;
   1289 
   1290 	/*
   1291 	 * We cannot transmit packets until a VIO connection has been
   1292 	 * established.
   1293 	 */
   1294 	if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
   1295 	    !ISSET(sc->sc_vio_state, VIO_ACK_RDX))
   1296 		return;
   1297 
   1298 	/*
   1299 	 * Make sure there is room in the LDC transmit queue to send a
   1300 	 * DRING_DATA message.
   1301 	 */
   1302 	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
   1303 	if (err != H_EOK)
   1304 		return;
   1305 	tx_tail += sizeof(struct ldc_pkt);
   1306 	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(struct ldc_pkt)) - 1);
   1307 	if (tx_tail == tx_head) {
   1308 #if 0
   1309 FIXME openbsd
   1310 		ifq_set_oactive(&ifp->if_snd);
   1311 #else
   1312 		ifp->if_flags |= IFF_OACTIVE;
   1313 #endif
   1314 		return;
   1315 	}
   1316 
   1317 	if (sc->sc_xfer_mode == VIO_DESC_MODE) {
   1318 		vnet_start_desc(ifp);
   1319 		return;
   1320 	}
   1321 
   1322 	start = prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
   1323 	while (sc->sc_vd->vd_desc[prod].hdr.dstate == VIO_DESC_FREE) {
   1324 		count = sc->sc_tx_prod - sc->sc_tx_cons;
   1325 		if (count >= (sc->sc_vd->vd_nentries - 1) ||
   1326 		    map->lm_count >= map->lm_nentries) {
   1327 #if 0
   1328 FIXME openbsd
   1329 			ifq_set_oactive(&ifp->if_snd);
   1330 #else
   1331 			ifp->if_flags |= IFF_OACTIVE;
   1332 #endif
   1333 			break;
   1334 		}
   1335 
   1336 		buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
   1337 		if (buf == NULL) {
   1338 #if 0
   1339 FIXME openbsd
   1340 			ifq_set_oactive(&ifp->if_snd);
   1341 #else
   1342 			ifp->if_flags |= IFF_OACTIVE;
   1343 #endif
   1344 			break;
   1345 		}
   1346 #if 0
   1347 FIXME openbsd
   1348 		m = ifq_dequeue(&ifp->if_snd);
   1349 #else
   1350 		IFQ_DEQUEUE(&ifp->if_snd, m);
   1351 #endif
   1352 		if (m == NULL) {
   1353 			pool_put(&sc->sc_pool, buf);
   1354 			break;
   1355 		}
   1356 
   1357 		m_copydata(m, 0, m->m_pkthdr.len, buf + VNET_ETHER_ALIGN);
   1358 
   1359 #if NBPFILTER > 0
   1360 		/*
   1361 		 * If BPF is listening on this interface, let it see the
   1362 		 * packet before we commit it to the wire.
   1363 		 */
   1364 		if (ifp->if_bpf)
   1365 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
   1366 #endif
   1367 
   1368 		pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
   1369 		KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
   1370 		while (map->lm_slot[map->lm_next].entry != 0) {
   1371 			map->lm_next++;
   1372 			map->lm_next &= (map->lm_nentries - 1);
   1373 		}
   1374 		map->lm_slot[map->lm_next].entry = (pa & LDC_MTE_RA_MASK);
   1375 		map->lm_slot[map->lm_next].entry |= LDC_MTE_CPR;
   1376 #if 0
   1377 FIXME openbsd
   1378 		atomic_inc_int(&map->lm_count);
   1379 #else
   1380 		map->lm_count++;
   1381 #endif
   1382 #if 0
   1383 FIXME openbsd
   1384 		sc->sc_vd->vd_desc[prod].nbytes = max(m->m_pkthdr.len, 60);
   1385 #else
   1386 		sc->sc_vd->vd_desc[prod].nbytes = MAX(m->m_pkthdr.len, 60);
   1387 #endif
   1388 		sc->sc_vd->vd_desc[prod].ncookies = 1;
   1389 		sc->sc_vd->vd_desc[prod].cookie[0].addr =
   1390 		    map->lm_next << PAGE_SHIFT | (pa & PAGE_MASK);
   1391 		sc->sc_vd->vd_desc[prod].cookie[0].size = 2048;
   1392 		membar_producer();
   1393 		sc->sc_vd->vd_desc[prod].hdr.dstate = VIO_DESC_READY;
   1394 
   1395 		sc->sc_vsd[prod].vsd_map_idx = map->lm_next;
   1396 		sc->sc_vsd[prod].vsd_buf = buf;
   1397 
   1398 		sc->sc_tx_prod++;
   1399 		prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
   1400 
   1401 		m_freem(m);
   1402 	}
   1403 
   1404 	membar_producer();
   1405 
   1406 	if (start != prod && sc->sc_peer_state != VIO_DP_ACTIVE) {
   1407 		vnet_send_dring_data(sc, start);
   1408 		ifp->if_timer = 5;
   1409 	}
   1410 }
   1411 
   1412 void
   1413 vnet_start_desc(struct ifnet *ifp)
   1414 {
   1415 	struct vnet_softc *sc = ifp->if_softc;
   1416 	struct ldc_map *map = sc->sc_lm;
   1417 	struct vnet_desc_msg dm;
   1418 	struct mbuf *m;
   1419 	paddr_t pa;
   1420 	unsigned char *buf;
   1421 	u_int prod, count;
   1422 
   1423 	for (;;) {
   1424 		count = sc->sc_tx_prod - sc->sc_tx_cons;
   1425 		if (count >= (sc->sc_vd->vd_nentries - 1) ||
   1426 		    map->lm_count >= map->lm_nentries) {
   1427 #if 0
   1428 FIXME openbsd
   1429 			ifq_set_oactive(&ifp->if_snd);
   1430 #else
   1431 			ifp->if_flags |= IFF_OACTIVE;
   1432 #endif
   1433 			return;
   1434 		}
   1435 
   1436 		buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
   1437 		if (buf == NULL) {
   1438 #if 0
   1439 FIXME openbsd
   1440 			ifq_set_oactive(&ifp->if_snd);
   1441 #else
   1442 			ifp->if_flags |= IFF_OACTIVE;
   1443 #endif
   1444 			return;
   1445 		}
   1446 
   1447 #if 0
   1448 FIXME openbsd
   1449 		m = ifq_dequeue(&ifp->if_snd);
   1450 #else
   1451 		IFQ_DEQUEUE(&ifp->if_snd, m);
   1452 #endif
   1453 
   1454 		if (m == NULL) {
   1455 			pool_put(&sc->sc_pool, buf);
   1456 			return;
   1457 		}
   1458 
   1459 		m_copydata(m, 0, m->m_pkthdr.len, buf);
   1460 
   1461 #if NBPFILTER > 0
   1462 		/*
   1463 		 * If BPF is listening on this interface, let it see the
   1464 		 * packet before we commit it to the wire.
   1465 		 */
   1466 		if (ifp->if_bpf)
   1467 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
   1468 #endif
   1469 
   1470 		pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
   1471 		KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
   1472 		while (map->lm_slot[map->lm_next].entry != 0) {
   1473 			map->lm_next++;
   1474 			map->lm_next &= (map->lm_nentries - 1);
   1475 		}
   1476 		map->lm_slot[map->lm_next].entry = (pa & LDC_MTE_RA_MASK);
   1477 		map->lm_slot[map->lm_next].entry |= LDC_MTE_CPR;
   1478 #if 0
   1479 FIXME openbsd
   1480 		atomic_inc_int(&map->lm_count);
   1481 #else
   1482 		map->lm_count++;
   1483 #endif
   1484 
   1485 		prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
   1486 		sc->sc_vsd[prod].vsd_map_idx = map->lm_next;
   1487 		sc->sc_vsd[prod].vsd_buf = buf;
   1488 
   1489 		bzero(&dm, sizeof(dm));
   1490 		dm.tag.type = VIO_TYPE_DATA;
   1491 		dm.tag.stype = VIO_SUBTYPE_INFO;
   1492 		dm.tag.stype_env = VIO_DESC_DATA;
   1493 		dm.tag.sid = sc->sc_local_sid;
   1494 		dm.seq_no = sc->sc_seq_no++;
   1495 		dm.desc_handle = sc->sc_tx_prod;
   1496 #if 0
   1497 FIXME openbsd
   1498 		dm.nbytes = max(m->m_pkthdr.len, 60);
   1499 #else
   1500 		dm.nbytes = MAX(m->m_pkthdr.len, 60);
   1501 #endif
   1502 		dm.ncookies = 1;
   1503 		dm.cookie[0].addr =
   1504 			map->lm_next << PAGE_SHIFT | (pa & PAGE_MASK);
   1505 		dm.cookie[0].size = 2048;
   1506 		vnet_sendmsg(sc, &dm, sizeof(dm));
   1507 
   1508 		sc->sc_tx_prod++;
   1509 		sc->sc_tx_prod &= (sc->sc_vd->vd_nentries - 1);
   1510 
   1511 		m_freem(m);
   1512 	}
   1513 }
   1514 
   1515 int
   1516 vnet_ioctl(struct ifnet *ifp, u_long cmd, void* data)
   1517 {
   1518 
   1519 	struct vnet_softc *sc = ifp->if_softc;
   1520 	struct ifreq *ifr = (struct ifreq *)data;
   1521 	int s, error = 0;
   1522 
   1523 	s = splnet();
   1524 
   1525 	switch (cmd) {
   1526 
   1527 		case SIOCSIFADDR:
   1528 			ifp->if_flags |= IFF_UP;
   1529 			/* FALLTHROUGH */
   1530 		case SIOCSIFFLAGS:
   1531 			if (ifp->if_flags & IFF_UP) {
   1532 				if ((ifp->if_flags & IFF_RUNNING) == 0)
   1533 					vnet_init(ifp);
   1534 			} else {
   1535 				if (ifp->if_flags & IFF_RUNNING)
   1536 					vnet_stop(ifp);
   1537 			}
   1538 		break;
   1539 
   1540 		case SIOCGIFMEDIA:
   1541 		case SIOCSIFMEDIA:
   1542 			error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
   1543 			break;
   1544 
   1545 		case SIOCADDMULTI:
   1546 		case SIOCDELMULTI:
   1547 			/*
   1548 			 * XXX Removing all multicast addresses and adding
   1549 			 * most of them back, is somewhat retarded.
   1550 			 */
   1551 			vnet_setmulti(sc, 0);
   1552 			error = ether_ioctl(ifp, cmd, data);
   1553 			vnet_setmulti(sc, 1);
   1554 			if (error == ENETRESET)
   1555 				error = 0;
   1556 			break;
   1557 
   1558 		default:
   1559 			error = ether_ioctl(ifp, cmd, data);
   1560 	}
   1561 
   1562 	splx(s);
   1563 
   1564 	return (error);
   1565 }
   1566 
   1567 void
   1568 vnet_watchdog(struct ifnet *ifp)
   1569 {
   1570 	struct vnet_softc *sc = ifp->if_softc;
   1571 
   1572 	printf("%s: watchdog timeout\n", sc->sc_dv.dv_xname);
   1573 }
   1574 
   1575 int
   1576 vnet_media_change(struct ifnet *ifp)
   1577 {
   1578 	printf("vnet_media_change()\n");
   1579 	return (0);
   1580 }
   1581 
   1582 void
   1583 vnet_media_status(struct ifnet *ifp, struct ifmediareq *imr)
   1584 {
   1585 	imr->ifm_active = IFM_ETHER | IFM_AUTO;
   1586 	imr->ifm_status = IFM_AVALID;
   1587 #if 0
   1588 FIXME openbsd
   1589 	if (LINK_STATE_IS_UP(ifp->if_link_state) &&
   1590 #else
   1591 	if (ifp->if_link_state == LINK_STATE_UP &&
   1592 #endif
   1593 	    ifp->if_flags & IFF_UP)
   1594 		imr->ifm_status |= IFM_ACTIVE;
   1595 }
   1596 
   1597 void
   1598 vnet_link_state(struct vnet_softc *sc)
   1599 {
   1600 #if 0
   1601 FIXME openbsd
   1602 	struct ifnet *ifp = &sc->sc_ac.ac_if;
   1603 #else
   1604 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1605 #endif
   1606 	int link_state = LINK_STATE_DOWN;
   1607 
   1608 #if 0
   1609 FIXME openbsd
   1610 	KERNEL_LOCK();
   1611 #else
   1612 	KERNEL_LOCK(1, curlwp);
   1613 #endif
   1614 	if (ISSET(sc->sc_vio_state, VIO_RCV_RDX) &&
   1615 	    ISSET(sc->sc_vio_state, VIO_ACK_RDX))
   1616 #if 0
   1617 FIXME openbsd
   1618 		link_state = LINK_STATE_FULL_DUPLEX;
   1619 #else
   1620 		link_state = LINK_STATE_UP;
   1621 #endif
   1622 	if (ifp->if_link_state != link_state) {
   1623 #if 0
   1624 FIXME openbsd
   1625 		ifp->if_link_state = link_state;
   1626 		if_link_state_change(ifp);
   1627 #else
   1628 		if_link_state_change(ifp, link_state);
   1629 #endif
   1630 	}
   1631 #if 0
   1632 FIXME openbsd
   1633 	KERNEL_UNLOCK();
   1634 #else
   1635 	KERNEL_UNLOCK_ONE(curlwp);
   1636 #endif
   1637 }
   1638 
   1639 void
   1640 vnet_setmulti(struct vnet_softc *sc, int set)
   1641 {
   1642 	struct ethercom *ec = &sc->sc_ethercom;
   1643 	struct ether_multi *enm;
   1644 	struct ether_multistep step;
   1645 	struct vnet_mcast_info mi;
   1646 	int count = 0;
   1647 
   1648 	if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
   1649 	    !ISSET(sc->sc_vio_state, VIO_ACK_RDX))
   1650 		return;
   1651 
   1652 	bzero(&mi, sizeof(mi));
   1653 	mi.tag.type = VIO_TYPE_CTRL;
   1654 	mi.tag.stype = VIO_SUBTYPE_INFO;
   1655 	mi.tag.stype_env = VNET_MCAST_INFO;
   1656 	mi.tag.sid = sc->sc_local_sid;
   1657 	mi.set = set ? 1 : 0;
   1658 #if 0
   1659 FIXME openbsd
   1660 	KERNEL_LOCK();
   1661 #else
   1662 	KERNEL_LOCK(1, curlwp);
   1663 #endif
   1664 	ETHER_FIRST_MULTI(step, ec, enm);
   1665 	while (enm != NULL) {
   1666 		/* XXX What about multicast ranges? */
   1667 		bcopy(enm->enm_addrlo, mi.mcast_addr[count], ETHER_ADDR_LEN);
   1668 		ETHER_NEXT_MULTI(step, enm);
   1669 
   1670 		count++;
   1671 		if (count < VNET_NUM_MCAST)
   1672 			continue;
   1673 
   1674 		mi.count = VNET_NUM_MCAST;
   1675 		vnet_sendmsg(sc, &mi, sizeof(mi));
   1676 		count = 0;
   1677 	}
   1678 
   1679 	if (count > 0) {
   1680 		mi.count = count;
   1681 		vnet_sendmsg(sc, &mi, sizeof(mi));
   1682 	}
   1683 #if 0
   1684 FIXME openbsd
   1685 	KERNEL_UNLOCK();
   1686 #else
   1687 	KERNEL_UNLOCK_ONE(curlwp);
   1688 #endif
   1689 }
   1690 
   1691 
   1692 void
   1693 vnet_init(struct ifnet *ifp)
   1694 {
   1695 
   1696 	struct vnet_softc *sc = ifp->if_softc;
   1697 	struct ldc_conn *lc = &sc->sc_lc;
   1698 	int err;
   1699 	vaddr_t va;
   1700 	paddr_t pa;
   1701 
   1702 #if OPENBSD_BUSDMA
   1703 	sc->sc_lm = ldc_map_alloc(sc->sc_dmatag, 2048);
   1704 #else
   1705 	sc->sc_lm = ldc_map_alloc(2048);
   1706 #endif
   1707 	if (sc->sc_lm == NULL)
   1708 		return;
   1709 
   1710 #if OPENBSD_BUSDMA
   1711 	err = hv_ldc_set_map_table(lc->lc_id,
   1712 							   sc->sc_lm->lm_map->dm_segs[0].ds_addr, sc->sc_lm->lm_nentries);
   1713 #else
   1714 	va = (vaddr_t)sc->sc_lm->lm_slot;
   1715 	pa = 0;
   1716 	if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
   1717 		panic("pmap_extract failed %lx\n", va);
   1718 	err = hv_ldc_set_map_table(lc->lc_id, pa, 2048);
   1719 #endif
   1720 	if (err != H_EOK) {
   1721 		printf("hv_ldc_set_map_table %d\n", err);
   1722 		return;
   1723 	}
   1724 
   1725 	sc->sc_vd = vnet_dring_alloc(sc->sc_dmatag, VNET_NUM_SOFT_DESC);
   1726 	if (sc->sc_vd == NULL)
   1727 		return;
   1728 	sc->sc_vsd = malloc(VNET_NUM_SOFT_DESC * sizeof(*sc->sc_vsd), M_DEVBUF,
   1729 	    M_NOWAIT|M_ZERO);
   1730 	if (sc->sc_vsd == NULL)
   1731 		return;
   1732 
   1733 	sc->sc_lm->lm_slot[0].entry = sc->sc_vd->vd_map->dm_segs[0].ds_addr;
   1734 	sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK;
   1735 	sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW;
   1736 	sc->sc_lm->lm_next = 1;
   1737 	sc->sc_lm->lm_count = 1;
   1738 
   1739 #if OPENBSD_BUSDMA
   1740 	err = hv_ldc_tx_qconf(lc->lc_id,
   1741 						  lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries);
   1742 #else
   1743 	err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_txq->lq_nentries);
   1744 #endif
   1745 	if (err != H_EOK)
   1746 		printf("hv_ldc_tx_qconf %d\n", err);
   1747 
   1748 #if OPENBSD_BUSDMA
   1749 	err = hv_ldc_rx_qconf(lc->lc_id,
   1750 						  lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries);
   1751 #else
   1752 	err = hv_ldc_rx_qconf(lc->lc_id, pa, lc->lc_rxq->lq_nentries);
   1753 #endif
   1754 	if (err != H_EOK)
   1755 		printf("hv_ldc_rx_qconf %d\n", err);
   1756 
   1757 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_ENABLED);
   1758 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_ENABLED);
   1759 
   1760 	ldc_send_vers(lc);
   1761 
   1762 	ifp->if_flags |= IFF_RUNNING;
   1763 
   1764 }
   1765 
   1766 void
   1767 vnet_stop(struct ifnet *ifp)
   1768 
   1769 {
   1770 	struct vnet_softc *sc = ifp->if_softc;
   1771 	struct ldc_conn *lc = &sc->sc_lc;
   1772 
   1773 	ifp->if_flags &= ~IFF_RUNNING;
   1774 #if 0
   1775 FIXME openbsd
   1776 	ifq_clr_oactive(&ifp->if_snd);
   1777 #else
   1778 	ifp->if_flags &= ~IFF_OACTIVE;
   1779 #endif
   1780 	ifp->if_timer = 0;
   1781 
   1782 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_DISABLED);
   1783 	cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_DISABLED);
   1784 
   1785 #if 0
   1786 FIXME openbsd
   1787 	intr_barrier(sc->sc_tx_ih);
   1788 	intr_barrier(sc->sc_rx_ih);
   1789 #else
   1790 	printf("vnet_stop() intr_barrier() FIXME\n");
   1791 #endif
   1792 
   1793 	hv_ldc_tx_qconf(lc->lc_id, 0, 0);
   1794 	hv_ldc_rx_qconf(lc->lc_id, 0, 0);
   1795 	lc->lc_tx_seqid = 0;
   1796 	lc->lc_state = 0;
   1797 	lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN;
   1798 	vnet_ldc_reset(lc);
   1799 
   1800 #if 0
   1801 FIXME openbsd
   1802 	free(sc->sc_vsd, M_DEVBUF, VNET_NUM_SOFT_DESC * sizeof(*sc->sc_vsd));
   1803 #else
   1804 	free(sc->sc_vsd, M_DEVBUF);
   1805 #endif
   1806 
   1807 	vnet_dring_free(sc->sc_dmatag, sc->sc_vd);
   1808 
   1809 	hv_ldc_set_map_table(lc->lc_id, 0, 0);
   1810 #if OPENBSD_BUSDMA
   1811 	ldc_map_free(sc->sc_dmatag, sc->sc_lm);
   1812 #else
   1813 	ldc_map_free(sc->sc_lm);
   1814 #endif
   1815 }
   1816 
   1817 struct vnet_dring *
   1818 vnet_dring_alloc(bus_dma_tag_t t, int nentries)
   1819 {
   1820 	struct vnet_dring *vd;
   1821 	bus_size_t size;
   1822 	vaddr_t va;
   1823 #if OPENBSD_BUSDMA
   1824 	int nsegs;
   1825 #endif
   1826 	int i;
   1827 
   1828 	vd = kmem_zalloc(sizeof(struct vnet_dring), KM_SLEEP);
   1829 	if (vd == NULL)
   1830 		return NULL;
   1831 
   1832 	size = roundup(nentries * sizeof(struct vnet_desc), PAGE_SIZE);
   1833 
   1834 #if OPENBSD_BUSDMA
   1835 	if (bus_dmamap_create(t, size, 1, size, 0,
   1836 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &vd->vd_map) != 0)
   1837 		return (NULL);
   1838 
   1839 	if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &vd->vd_seg, 1,
   1840 	    &nsegs, BUS_DMA_NOWAIT) != 0)
   1841 		goto destroy;
   1842 
   1843 	if (bus_dmamem_map(t, &vd->vd_seg, 1, size, &va,
   1844 	    BUS_DMA_NOWAIT) != 0)
   1845 		goto free;
   1846 
   1847 	if (bus_dmamap_load(t, vd->vd_map, va, size, NULL,
   1848 	    BUS_DMA_NOWAIT) != 0)
   1849 		goto unmap;
   1850 #else
   1851 	va = (vaddr_t)kmem_zalloc(size, KM_SLEEP);
   1852 #endif
   1853 	vd->vd_desc = (struct vnet_desc *)va;
   1854 	vd->vd_nentries = nentries;
   1855 	bzero(vd->vd_desc, nentries * sizeof(struct vnet_desc));
   1856 	for (i = 0; i < vd->vd_nentries; i++)
   1857 		vd->vd_desc[i].hdr.dstate = VIO_DESC_FREE;
   1858 	return (vd);
   1859 
   1860 #if OPENBSD_BUSDMA
   1861 unmap:
   1862 	bus_dmamem_unmap(t, va, size);
   1863 free:
   1864 	bus_dmamem_free(t, &vd->vd_seg, 1);
   1865 destroy:
   1866 	bus_dmamap_destroy(t, vd->vd_map);
   1867 #endif
   1868 	return (NULL);
   1869 }
   1870 
   1871 void
   1872 vnet_dring_free(bus_dma_tag_t t, struct vnet_dring *vd)
   1873 {
   1874 	bus_size_t size;
   1875 
   1876 	size = vd->vd_nentries * sizeof(struct vnet_desc);
   1877 	size = roundup(size, PAGE_SIZE);
   1878 
   1879 #if OPENBSD_BUSDMA
   1880 	bus_dmamap_unload(t, vd->vd_map);
   1881 	bus_dmamem_unmap(t, (caddr_t)vd->vd_desc, size);
   1882 	bus_dmamem_free(t, &vd->vd_seg, 1);
   1883 	bus_dmamap_destroy(t, vd->vd_map);
   1884 #else
   1885 	kmem_free(vd->vd_desc, size);
   1886 #endif
   1887 	kmem_free(vd, size);
   1888 }
   1889 
   1890