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