xref: /netbsd-src/sys/arch/xen/xen/if_xennet_xenbus.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*      $NetBSD: if_xennet_xenbus.c,v 1.22 2007/12/03 15:34:30 ad Exp $      */
2 
3 /*
4  * Copyright (c) 2006 Manuel Bouyer.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Manuel Bouyer.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /*
34  * Copyright (c) 2004 Christian Limpach.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *      This product includes software developed by Christian Limpach.
48  * 4. The name of the author may not be used to endorse or promote products
49  *    derived from this software without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
53  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
54  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
55  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62 
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.22 2007/12/03 15:34:30 ad Exp $");
65 
66 #include "opt_xen.h"
67 #include "opt_nfs_boot.h"
68 #include "rnd.h"
69 #include "bpfilter.h"
70 
71 #include <sys/param.h>
72 #include <sys/device.h>
73 #include <sys/conf.h>
74 #include <sys/kernel.h>
75 #include <sys/proc.h>
76 #include <sys/systm.h>
77 #include <sys/intr.h>
78 #if NRND > 0
79 #include <sys/rnd.h>
80 #endif
81 
82 #include <net/if.h>
83 #include <net/if_dl.h>
84 #include <net/if_ether.h>
85 #if NBPFILTER > 0
86 #include <net/bpf.h>
87 #include <net/bpfdesc.h>
88 #endif
89 
90 #if defined(NFS_BOOT_BOOTSTATIC)
91 #include <sys/fstypes.h>
92 #include <sys/mount.h>
93 #include <sys/statvfs.h>
94 #include <netinet/in.h>
95 #include <nfs/rpcv2.h>
96 #include <nfs/nfsproto.h>
97 #include <nfs/nfs.h>
98 #include <nfs/nfsmount.h>
99 #include <nfs/nfsdiskless.h>
100 #include <xen/if_xennetvar.h>
101 #endif /* defined(NFS_BOOT_BOOTSTATIC) */
102 
103 #include <xen/xennet_checksum.h>
104 
105 #include <uvm/uvm.h>
106 
107 #include <xen/xen3-public/io/ring.h>
108 
109 #include <xen/granttables.h>
110 #include <xen/xenbus.h>
111 #include "locators.h"
112 
113 #undef XENNET_DEBUG_DUMP
114 #undef XENNET_DEBUG
115 #ifdef XENNET_DEBUG
116 #define XEDB_FOLLOW     0x01
117 #define XEDB_INIT       0x02
118 #define XEDB_EVENT      0x04
119 #define XEDB_MBUF       0x08
120 #define XEDB_MEM        0x10
121 int xennet_debug = 0xff;
122 #define DPRINTF(x) if (xennet_debug) printf x;
123 #define DPRINTFN(n,x) if (xennet_debug & (n)) printf x;
124 #else
125 #define DPRINTF(x)
126 #define DPRINTFN(n,x)
127 #endif
128 
129 #define GRANT_INVALID_REF -1 /* entry is free */
130 #define GRANT_STACK_REF   -2 /* entry owned by the network stack */
131 
132 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
133 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
134 
135 struct xennet_txreq {
136 	SLIST_ENTRY(xennet_txreq) txreq_next;
137 	uint16_t txreq_id; /* ID passed to backed */
138 	grant_ref_t txreq_gntref; /* grant ref of this request */
139 	struct mbuf *txreq_m; /* mbuf being transmitted */
140 };
141 
142 struct xennet_rxreq {
143 	SLIST_ENTRY(xennet_rxreq) rxreq_next;
144 	uint16_t rxreq_id; /* ID passed to backed */
145 	grant_ref_t rxreq_gntref; /* grant ref of this request */
146 /* va/pa for this receive buf. ma will be provided by backend */
147 	paddr_t rxreq_pa;
148 	vaddr_t rxreq_va;
149 	struct xennet_xenbus_softc *rxreq_sc; /* pointer to our interface */
150 };
151 
152 struct xennet_xenbus_softc {
153 	struct device sc_dev;
154 	struct ethercom sc_ethercom;
155 	uint8_t sc_enaddr[6];
156 	struct xenbus_device *sc_xbusd;
157 
158 	netif_tx_front_ring_t sc_tx_ring;
159 	netif_rx_front_ring_t sc_rx_ring;
160 
161 	unsigned int sc_evtchn;
162 	void *sc_softintr;
163 
164 	grant_ref_t sc_tx_ring_gntref;
165 	grant_ref_t sc_rx_ring_gntref;
166 
167 	struct xennet_txreq sc_txreqs[NET_TX_RING_SIZE];
168 	struct xennet_rxreq sc_rxreqs[NET_RX_RING_SIZE];
169 	SLIST_HEAD(,xennet_txreq) sc_txreq_head; /* list of free TX requests */
170 	SLIST_HEAD(,xennet_rxreq) sc_rxreq_head; /* list of free RX requests */
171 	int sc_free_rxreql; /* number of free receive request struct */
172 
173 	int sc_backend_status; /* our status with backend */
174 #define BEST_CLOSED		0
175 #define BEST_DISCONNECTED	1
176 #define BEST_CONNECTED		2
177 #if NRND > 0
178 	rndsource_element_t     sc_rnd_source;
179 #endif
180 };
181 #define SC_NLIVEREQ(sc) ((sc)->sc_rx_ring.req_prod_pvt - \
182 			    (sc)->sc_rx_ring.sring->rsp_prod)
183 
184 /* too big to be on stack */
185 static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
186 static paddr_t xennet_pages[NET_RX_RING_SIZE];
187 
188 static int  xennet_xenbus_match(struct device *, struct cfdata *, void *);
189 static void xennet_xenbus_attach(struct device *, struct device *, void *);
190 static int  xennet_xenbus_detach(struct device *, int);
191 static void xennet_backend_changed(void *, XenbusState);
192 
193 static int  xennet_xenbus_resume(void *);
194 static void xennet_alloc_rx_buffer(struct xennet_xenbus_softc *);
195 static void xennet_free_rx_buffer(struct xennet_xenbus_softc *);
196 static void xennet_tx_complete(struct xennet_xenbus_softc *);
197 static void xennet_rx_mbuf_free(struct mbuf *, void *, size_t, void *);
198 static int  xennet_handler(void *);
199 #ifdef XENNET_DEBUG_DUMP
200 static void xennet_hex_dump(const unsigned char *, size_t, const char *, int);
201 #endif
202 
203 static int  xennet_init(struct ifnet *);
204 static void xennet_stop(struct ifnet *, int);
205 static void xennet_reset(struct xennet_xenbus_softc *);
206 static void xennet_softstart(void *);
207 static void xennet_start(struct ifnet *);
208 static int  xennet_ioctl(struct ifnet *, u_long, void *);
209 static void xennet_watchdog(struct ifnet *);
210 
211 CFATTACH_DECL(xennet_xenbus, sizeof(struct xennet_xenbus_softc),
212    xennet_xenbus_match, xennet_xenbus_attach, xennet_xenbus_detach, NULL);
213 
214 static int
215 xennet_xenbus_match(struct device *parent, struct cfdata *match, void *aux)
216 {
217 	struct xenbusdev_attach_args *xa = aux;
218 
219 	if (strcmp(xa->xa_type, "vif") != 0)
220 		return 0;
221 
222 	if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT &&
223 	    match->cf_loc[XENBUSCF_ID] != xa->xa_id)
224 		return 0;
225 
226 	return 1;
227 }
228 
229 static void
230 xennet_xenbus_attach(struct device *parent, struct device *self, void *aux)
231 {
232 	struct xennet_xenbus_softc *sc = (void *)self;
233 	struct xenbusdev_attach_args *xa = aux;
234 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
235 	int err;
236 	RING_IDX i;
237 	char *val, *e, *p;
238 	int s;
239 	extern int ifqmaxlen; /* XXX */
240 #ifdef XENNET_DEBUG
241 	char **dir;
242 	int dir_n = 0;
243 	char id_str[20];
244 #endif
245 
246 	aprint_normal(": Xen Virtual Network Interface\n");
247 #ifdef XENNET_DEBUG
248 	printf("path: %s\n", xa->xa_xbusd->xbusd_path);
249 	snprintf(id_str, sizeof(id_str), "%d", xa->xa_id);
250 	err = xenbus_directory(NULL, "device/vif", id_str, &dir_n, &dir);
251 	if (err) {
252 		printf("%s: xenbus_directory err %d\n",
253 		    sc->sc_dev.dv_xname, err);
254 	} else {
255 		printf("%s/\n", xa->xa_xbusd->xbusd_path);
256 		for (i = 0; i < dir_n; i++) {
257 			printf("\t/%s", dir[i]);
258 			err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, dir[i],
259 			    NULL, &val);
260 			if (err) {
261 				printf("%s: xenbus_read err %d\n",
262 		    		sc->sc_dev.dv_xname, err);
263 			} else {
264 				printf(" = %s\n", val);
265 				free(val, M_DEVBUF);
266 			}
267 		}
268 	}
269 #endif /* XENNET_DEBUG */
270 	sc->sc_xbusd = xa->xa_xbusd;
271 	sc->sc_xbusd->xbusd_otherend_changed = xennet_backend_changed;
272 
273 	/* initialize free RX and RX request lists */
274 	SLIST_INIT(&sc->sc_txreq_head);
275 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
276 		sc->sc_txreqs[i].txreq_id = i;
277 		SLIST_INSERT_HEAD(&sc->sc_txreq_head, &sc->sc_txreqs[i],
278 		    txreq_next);
279 	}
280 	SLIST_INIT(&sc->sc_rxreq_head);
281 	s = splvm();
282 	for (i = 0; i < NET_RX_RING_SIZE; i++) {
283 		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
284 		rxreq->rxreq_id = i;
285 		rxreq->rxreq_sc = sc;
286 		rxreq->rxreq_va = uvm_km_alloc(kernel_map,
287 		    PAGE_SIZE, PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_ZERO);
288 		if (rxreq->rxreq_va == 0)
289 			break;
290 		if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va,
291 		    &rxreq->rxreq_pa))
292 			panic("xennet: no pa for mapped va ?");
293 		rxreq->rxreq_gntref = GRANT_INVALID_REF;
294 		SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next);
295 	}
296 	splx(s);
297 	sc->sc_free_rxreql = i;
298 	if (sc->sc_free_rxreql == 0) {
299 		aprint_error("%s: failed to allocate rx memory\n",
300 		    sc->sc_dev.dv_xname);
301 		return;
302 	}
303 
304 	/* read mac address */
305 	err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, "mac", NULL, &val);
306 	if (err) {
307 		aprint_error("%s: can't read mac address, err %d\n",
308 		    sc->sc_dev.dv_xname, err);
309 		return;
310 	}
311 	/* read mac address */
312 	for (i = 0, p = val; i < 6; i++) {
313 		sc->sc_enaddr[i] = strtoul(p, &e, 16);
314 		if ((e[0] == '\0' && i != 5) && e[0] != ':') {
315 			aprint_error("%s: %s is not a valid mac address\n",
316 			    sc->sc_dev.dv_xname, val);
317 			free(val, M_DEVBUF);
318 			return;
319 		}
320 		p = &e[1];
321 	}
322 	free(val, M_DEVBUF);
323 	aprint_normal("%s: MAC address %s\n", sc->sc_dev.dv_xname,
324 	    ether_sprintf(sc->sc_enaddr));
325 	/* Initialize ifnet structure and attach interface */
326 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
327 	ifp->if_softc = sc;
328 	ifp->if_start = xennet_start;
329 	ifp->if_ioctl = xennet_ioctl;
330 	ifp->if_watchdog = xennet_watchdog;
331 	ifp->if_init = xennet_init;
332 	ifp->if_stop = xennet_stop;
333 	ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
334 	ifp->if_timer = 0;
335 	ifp->if_snd.ifq_maxlen = max(ifqmaxlen, NET_TX_RING_SIZE * 2);
336 	ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx;
337 	IFQ_SET_READY(&ifp->if_snd);
338 	if_attach(ifp);
339 	ether_ifattach(ifp, sc->sc_enaddr);
340 	sc->sc_softintr = softint_establish(SOFTINT_NET, xennet_softstart, sc);
341 	if (sc->sc_softintr == NULL)
342 		panic(" xennet: can't establish soft interrupt");
343 
344 	/* initialise shared structures and tell backend that we are ready */
345 	xennet_xenbus_resume(sc);
346 }
347 
348 static int
349 xennet_xenbus_detach(struct device *self, int flags)
350 {
351 	struct xennet_xenbus_softc *sc = (void *)self;
352 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
353 	int s0, s1;
354 	RING_IDX i;
355 
356 	DPRINTF(("%s: xennet_xenbus_detach\n", sc->sc_dev.dv_xname));
357 	s0 = splnet();
358 	xennet_stop(ifp, 1);
359 	/* wait for pending TX to complete, and collect pending RX packets */
360 	xennet_handler(sc);
361 	while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) {
362 		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_detach", hz/2);
363 		xennet_handler(sc);
364 	}
365 	xennet_free_rx_buffer(sc);
366 
367 	s1 = splvm();
368 	for (i = 0; i < NET_RX_RING_SIZE; i++) {
369 		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
370 		uvm_km_free(kernel_map, rxreq->rxreq_va, PAGE_SIZE,
371 		    UVM_KMF_WIRED);
372 	}
373 	splx(s1);
374 
375 	ether_ifdetach(ifp);
376 	if_detach(ifp);
377 	while (xengnt_status(sc->sc_tx_ring_gntref)) {
378 		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_txref", hz/2);
379 	}
380 	xengnt_revoke_access(sc->sc_tx_ring_gntref);
381 	uvm_km_free(kernel_map, (vaddr_t)sc->sc_tx_ring.sring, PAGE_SIZE,
382 	    UVM_KMF_WIRED);
383 	while (xengnt_status(sc->sc_rx_ring_gntref)) {
384 		tsleep(xennet_xenbus_detach, PRIBIO, "xnet_rxref", hz/2);
385 	}
386 	xengnt_revoke_access(sc->sc_rx_ring_gntref);
387 	uvm_km_free(kernel_map, (vaddr_t)sc->sc_rx_ring.sring, PAGE_SIZE,
388 	    UVM_KMF_WIRED);
389 	softint_disestablish(sc->sc_softintr);
390 	event_remove_handler(sc->sc_evtchn, &xennet_handler, sc);
391 	splx(s0);
392 	DPRINTF(("%s: xennet_xenbus_detach done\n", sc->sc_dev.dv_xname));
393 	return 0;
394 }
395 
396 static int
397 xennet_xenbus_resume(void *p)
398 {
399 	struct xennet_xenbus_softc *sc = p;
400 	struct xenbus_transaction *xbt;
401 	int error;
402 	netif_tx_sring_t *tx_ring;
403 	netif_rx_sring_t *rx_ring;
404 	paddr_t ma;
405 	const char *errmsg;
406 
407 	sc->sc_tx_ring_gntref = GRANT_INVALID_REF;
408 	sc->sc_rx_ring_gntref = GRANT_INVALID_REF;
409 
410 
411 	/* setup device: alloc event channel and shared rings */
412 	tx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
413 	     UVM_KMF_WIRED | UVM_KMF_ZERO);
414 	rx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
415 	    UVM_KMF_WIRED | UVM_KMF_ZERO);
416 	if (tx_ring == NULL || rx_ring == NULL)
417 		panic("xennet_xenbus_resume: can't alloc rings");
418 
419 	SHARED_RING_INIT(tx_ring);
420 	FRONT_RING_INIT(&sc->sc_tx_ring, tx_ring, PAGE_SIZE);
421 	SHARED_RING_INIT(rx_ring);
422 	FRONT_RING_INIT(&sc->sc_rx_ring, rx_ring, PAGE_SIZE);
423 
424 	(void)pmap_extract_ma(pmap_kernel(), (vaddr_t)tx_ring, &ma);
425 	error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_tx_ring_gntref);
426 	if (error)
427 		return error;
428 	(void)pmap_extract_ma(pmap_kernel(), (vaddr_t)rx_ring, &ma);
429 	error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_rx_ring_gntref);
430 	if (error)
431 		return error;
432 	error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn);
433 	if (error)
434 		return error;
435 	aprint_verbose("%s: using event channel %d\n",
436 	    sc->sc_dev.dv_xname, sc->sc_evtchn);
437 	event_set_handler(sc->sc_evtchn, &xennet_handler, sc,
438 	    IPL_NET, sc->sc_dev.dv_xname);
439 
440 again:
441 	xbt = xenbus_transaction_start();
442 	if (xbt == NULL)
443 		return ENOMEM;
444 	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
445 	    "tx-ring-ref","%u", sc->sc_tx_ring_gntref);
446 	if (error) {
447 		errmsg = "writing tx ring-ref";
448 		goto abort_transaction;
449 	}
450 	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
451 	    "rx-ring-ref","%u", sc->sc_rx_ring_gntref);
452 	if (error) {
453 		errmsg = "writing rx ring-ref";
454 		goto abort_transaction;
455 	}
456 	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
457 	    "event-channel", "%u", sc->sc_evtchn);
458 	if (error) {
459 		errmsg = "writing event channel";
460 		goto abort_transaction;
461 	}
462 	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
463 	    "state", "%d", XenbusStateConnected);
464 	if (error) {
465 		errmsg = "writing frontend XenbusStateConnected";
466 		goto abort_transaction;
467 	}
468 	error = xenbus_transaction_end(xbt, 0);
469 	if (error == EAGAIN)
470 		goto again;
471 	if (error) {
472 		xenbus_dev_fatal(sc->sc_xbusd, error, "completing transaction");
473 		return -1;
474 	}
475 	xennet_alloc_rx_buffer(sc);
476 	sc->sc_backend_status = BEST_CONNECTED;
477 	return 0;
478 
479 abort_transaction:
480 	xenbus_transaction_end(xbt, 1);
481 	xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg);
482 	return error;
483 }
484 
485 static void xennet_backend_changed(void *arg, XenbusState new_state)
486 {
487 	struct xennet_xenbus_softc *sc = arg;
488 	DPRINTF(("%s: new backend state %d\n", sc->sc_dev.dv_xname, new_state));
489 
490 	switch (new_state) {
491 	case XenbusStateInitialising:
492 	case XenbusStateInitWait:
493 	case XenbusStateInitialised:
494 		break;
495 	case XenbusStateClosing:
496 		sc->sc_backend_status = BEST_CLOSED;
497 		xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed);
498 		break;
499 	case XenbusStateConnected:
500 		break;
501 	case XenbusStateUnknown:
502 	default:
503 		panic("bad backend state %d", new_state);
504 	}
505 }
506 
507 static void
508 xennet_alloc_rx_buffer(struct xennet_xenbus_softc *sc)
509 {
510 	RING_IDX req_prod = sc->sc_rx_ring.req_prod_pvt;
511 	RING_IDX i;
512 	struct xennet_rxreq *req;
513 	struct xen_memory_reservation reservation;
514 	int s1, s2;
515 	paddr_t pfn;
516 
517 	s1 = splnet();
518 	for (i = 0; sc->sc_free_rxreql != 0; i++) {
519 		req  = SLIST_FIRST(&sc->sc_rxreq_head);
520 		KASSERT(req != NULL);
521 		KASSERT(req == &sc->sc_rxreqs[req->rxreq_id]);
522 		RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->id =
523 		    req->rxreq_id;
524 		if (xengnt_grant_transfer(sc->sc_xbusd->xbusd_otherend_id,
525 		    &req->rxreq_gntref) != 0) {
526 			break;
527 		}
528 		RING_GET_REQUEST(&sc->sc_rx_ring, req_prod + i)->gref =
529 		    req->rxreq_gntref;
530 
531 		SLIST_REMOVE_HEAD(&sc->sc_rxreq_head, rxreq_next);
532 		sc->sc_free_rxreql--;
533 
534 		/* unmap the page */
535 		MULTI_update_va_mapping(&rx_mcl[i], req->rxreq_va, 0, 0);
536 		/*
537 		 * Remove this page from pseudo phys map before
538 		 * passing back to Xen.
539 		 */
540 		pfn = (req->rxreq_pa - XPMAP_OFFSET) >> PAGE_SHIFT;
541 		xennet_pages[i] = xpmap_phys_to_machine_mapping[pfn];
542 		xpmap_phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
543 	}
544 	if (i == 0) {
545 		splx(s1);
546 		return;
547 	}
548 	/* also make sure to flush all TLB entries */
549 	rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
550 	/*
551 	 * We may have allocated buffers which have entries
552 	 * outstanding in the page update queue -- make sure we flush
553 	 * those first!
554 	 */
555 	s2 = splvm();
556 	xpq_flush_queue();
557 	splx(s2);
558 	/* now decrease reservation */
559 	reservation.extent_start = xennet_pages;
560 	reservation.nr_extents = i;
561 	reservation.extent_order = 0;
562 	reservation.address_bits = 0;
563 	reservation.domid = DOMID_SELF;
564 	rx_mcl[i].op = __HYPERVISOR_memory_op;
565 	rx_mcl[i].args[0] = XENMEM_decrease_reservation;
566 	rx_mcl[i].args[1] = (unsigned long)&reservation;
567 	HYPERVISOR_multicall(rx_mcl, i+1);
568 	if (__predict_false(rx_mcl[i].result != i)) {
569 		panic("xennet_alloc_rx_buffer: XENMEM_decrease_reservation");
570 	}
571 	sc->sc_rx_ring.req_prod_pvt = req_prod + i;
572 	RING_PUSH_REQUESTS(&sc->sc_rx_ring);
573 
574 	splx(s1);
575 	return;
576 }
577 
578 static void
579 xennet_free_rx_buffer(struct xennet_xenbus_softc *sc)
580 {
581 	paddr_t ma, pa;
582 	vaddr_t va;
583 	RING_IDX i;
584 	mmu_update_t mmu[1];
585 	multicall_entry_t mcl[2];
586 
587 	int s = splbio();
588 
589 	DPRINTF(("%s: xennet_free_rx_buffer\n", sc->sc_dev.dv_xname));
590 	/* get back memory from RX ring */
591 	for (i = 0; i < NET_RX_RING_SIZE; i++) {
592 		struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i];
593 
594 		/*
595 		 * if the buffer is in transit in the network stack, wait for
596 		 * the network stack to free it.
597 		 */
598 		while ((volatile grant_ref_t)rxreq->rxreq_gntref ==
599 		    GRANT_STACK_REF)
600 			tsleep(xennet_xenbus_detach, PRIBIO, "xnet_free", hz/2);
601 
602 		if (rxreq->rxreq_gntref != GRANT_INVALID_REF) {
603 			/*
604 			 * this req is still granted. Get back the page or
605 			 * allocate a new one, and remap it.
606 			 */
607 			SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq,
608 			    rxreq_next);
609 			sc->sc_free_rxreql++;
610 			ma = xengnt_revoke_transfer(rxreq->rxreq_gntref);
611 			rxreq->rxreq_gntref = GRANT_INVALID_REF;
612 			if (ma == 0) {
613 				struct xen_memory_reservation xenres;
614 				/*
615 				 * transfer not complete, we lost the page.
616 				 * Get one from hypervisor
617 				 */
618 				xenres.extent_start = &ma;
619 				xenres.nr_extents = 1;
620 				xenres.extent_order = 0;
621 				xenres.address_bits = 31;
622 				xenres.domid = DOMID_SELF;
623 				if (HYPERVISOR_memory_op(
624 				    XENMEM_increase_reservation, &xenres) < 0) {
625 					panic("xennet_free_rx_buffer: "
626 					    "can't get memory back");
627 				}
628 				KASSERT(ma != 0);
629 			}
630 			pa = rxreq->rxreq_pa;
631 			va = rxreq->rxreq_va;
632 			/* remap the page */
633 			mmu[0].ptr = (ma << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
634 			mmu[0].val = ((pa - XPMAP_OFFSET) >> PAGE_SHIFT);
635 			MULTI_update_va_mapping(&mcl[0], va,
636 			    (ma << PAGE_SHIFT) | PG_V | PG_KW,
637 			    UVMF_TLB_FLUSH|UVMF_ALL);
638 			xpmap_phys_to_machine_mapping[
639 			    (pa - XPMAP_OFFSET) >> PAGE_SHIFT] = ma;
640 			mcl[1].op = __HYPERVISOR_mmu_update;
641 			mcl[1].args[0] = (unsigned long)mmu;
642 			mcl[1].args[1] = 1;
643 			mcl[1].args[2] = 0;
644 			mcl[1].args[3] = DOMID_SELF;
645 			HYPERVISOR_multicall(mcl, 2);
646 		}
647 
648 	}
649 	splx(s);
650 	DPRINTF(("%s: xennet_free_rx_buffer done\n", sc->sc_dev.dv_xname));
651 }
652 
653 static void
654 xennet_rx_mbuf_free(struct mbuf *m, void *buf, size_t size, void *arg)
655 {
656 	struct xennet_rxreq *req = arg;
657 	struct xennet_xenbus_softc *sc = req->rxreq_sc;
658 
659 	int s = splnet();
660 
661 	SLIST_INSERT_HEAD(&sc->sc_rxreq_head, req, rxreq_next);
662 	sc->sc_free_rxreql++;
663 
664 	req->rxreq_gntref = GRANT_INVALID_REF;
665 	if (sc->sc_free_rxreql >= SC_NLIVEREQ(sc) &&
666 	    __predict_true(sc->sc_backend_status == BEST_CONNECTED)) {
667 		xennet_alloc_rx_buffer(sc);
668 	}
669 
670 	if (m)
671 		pool_cache_put(mb_cache, m);
672 	splx(s);
673 }
674 
675 
676 static void
677 xennet_tx_complete(struct xennet_xenbus_softc *sc)
678 {
679 	struct xennet_txreq *req;
680 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
681 	RING_IDX resp_prod, i;
682 
683 	DPRINTFN(XEDB_EVENT, ("xennet_tx_complete prod %d cons %d\n",
684 	    sc->sc_tx_ring.sring->rsp_prod, sc->sc_tx_ring.rsp_cons));
685 
686 again:
687 	resp_prod = sc->sc_tx_ring.sring->rsp_prod;
688 	x86_lfence();
689 	for (i = sc->sc_tx_ring.rsp_cons; i != resp_prod; i++) {
690 		req = &sc->sc_txreqs[RING_GET_RESPONSE(&sc->sc_tx_ring, i)->id];
691 		KASSERT(req->txreq_id ==
692 		    RING_GET_RESPONSE(&sc->sc_tx_ring, i)->id);
693 		if (__predict_false(xengnt_status(req->txreq_gntref))) {
694 			printf("%s: grant still used by backend\n",
695 			    sc->sc_dev.dv_xname);
696 			sc->sc_tx_ring.rsp_cons = i;
697 			goto end;
698 		}
699 		if (__predict_false(
700 		    RING_GET_RESPONSE(&sc->sc_tx_ring, i)->status !=
701 		    NETIF_RSP_OKAY))
702 			ifp->if_oerrors++;
703 		else
704 			ifp->if_opackets++;
705 		xengnt_revoke_access(req->txreq_gntref);
706 		m_freem(req->txreq_m);
707 		SLIST_INSERT_HEAD(&sc->sc_txreq_head, req, txreq_next);
708 	}
709 	sc->sc_tx_ring.rsp_cons = resp_prod;
710 	/* set new event and check fopr race with rsp_cons update */
711 	sc->sc_tx_ring.sring->rsp_event =
712 	    resp_prod + ((sc->sc_tx_ring.sring->req_prod - resp_prod) >> 1) + 1;
713 	ifp->if_timer = 0;
714 	x86_sfence();
715 	if (resp_prod != sc->sc_tx_ring.sring->rsp_prod)
716 		goto again;
717 end:
718 	if (ifp->if_flags & IFF_OACTIVE) {
719 		ifp->if_flags &= ~IFF_OACTIVE;
720 		xennet_softstart(sc);
721 	}
722 }
723 
724 static int
725 xennet_handler(void *arg)
726 {
727 	struct xennet_xenbus_softc *sc = arg;
728 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
729 	RING_IDX resp_prod, i;
730 	struct xennet_rxreq *req;
731 	paddr_t ma, pa;
732 	vaddr_t va;
733 	mmu_update_t mmu[1];
734 	multicall_entry_t mcl[2];
735 	struct mbuf *m;
736 	void *pktp;
737 	int more_to_do;
738 
739 	if (sc->sc_backend_status != BEST_CONNECTED)
740 		return 1;
741 
742 	xennet_tx_complete(sc);
743 
744 again:
745 	DPRINTFN(XEDB_EVENT, ("xennet_handler prod %d cons %d\n",
746 	    sc->sc_rx_ring.sring->rsp_prod, sc->sc_rx_ring.rsp_cons));
747 
748 	resp_prod = sc->sc_rx_ring.sring->rsp_prod;
749 	x86_lfence(); /* ensure we see replies up to resp_prod */
750 	for (i = sc->sc_rx_ring.rsp_cons; i != resp_prod; i++) {
751 		netif_rx_response_t *rx = RING_GET_RESPONSE(&sc->sc_rx_ring, i);
752 		req = &sc->sc_rxreqs[rx->id];
753 		KASSERT(req->rxreq_gntref != GRANT_INVALID_REF);
754 		KASSERT(req->rxreq_id == rx->id);
755 		ma = xengnt_revoke_transfer(req->rxreq_gntref);
756 		if (ma == 0) {
757 			DPRINTFN(XEDB_EVENT, ("xennet_handler ma == 0\n"));
758 			/*
759 			 * the remote could't send us a packet.
760 			 * we can't free this rxreq as no page will be mapped
761 			 * here. Instead give it back immediatly to backend.
762 			 */
763 			ifp->if_ierrors++;
764 			RING_GET_REQUEST(&sc->sc_rx_ring,
765 			    sc->sc_rx_ring.req_prod_pvt)->id = req->rxreq_id;
766 			RING_GET_REQUEST(&sc->sc_rx_ring,
767 			    sc->sc_rx_ring.req_prod_pvt)->gref =
768 				req->rxreq_gntref;
769 			sc->sc_rx_ring.req_prod_pvt++;
770 			RING_PUSH_REQUESTS(&sc->sc_rx_ring);
771 			continue;
772 		}
773 		req->rxreq_gntref = GRANT_INVALID_REF;
774 
775 		pa = req->rxreq_pa;
776 		va = req->rxreq_va;
777 		/* remap the page */
778 		mmu[0].ptr = (ma << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
779 		mmu[0].val = ((pa - XPMAP_OFFSET) >> PAGE_SHIFT);
780 		MULTI_update_va_mapping(&mcl[0], va,
781 		    (ma << PAGE_SHIFT) | PG_V | PG_KW, UVMF_TLB_FLUSH|UVMF_ALL);
782 		xpmap_phys_to_machine_mapping[
783 		    (pa - XPMAP_OFFSET) >> PAGE_SHIFT] = ma;
784 		mcl[1].op = __HYPERVISOR_mmu_update;
785 		mcl[1].args[0] = (unsigned long)mmu;
786 		mcl[1].args[1] = 1;
787 		mcl[1].args[2] = 0;
788 		mcl[1].args[3] = DOMID_SELF;
789 		HYPERVISOR_multicall(mcl, 2);
790 		pktp = (void *)(va + rx->offset);
791 #ifdef XENNET_DEBUG_DUMP
792 		xennet_hex_dump(pktp, rx->status, "r", rx->id);
793 #endif
794 		if ((ifp->if_flags & IFF_PROMISC) == 0) {
795 			struct ether_header *eh = pktp;
796 			if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 &&
797 			    memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
798 			    ETHER_ADDR_LEN) != 0) {
799 				DPRINTFN(XEDB_EVENT,
800 				    ("xennet_handler bad dest\n"));
801 				/* packet not for us */
802 				xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE,
803 				    req);
804 				continue;
805 			}
806 		}
807 		MGETHDR(m, M_DONTWAIT, MT_DATA);
808 		if (__predict_false(m == NULL)) {
809 			printf("xennet: rx no mbuf\n");
810 			ifp->if_ierrors++;
811 			xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req);
812 			continue;
813 		}
814 		MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
815 
816 		m->m_pkthdr.rcvif = ifp;
817 		if (__predict_true(sc->sc_rx_ring.req_prod_pvt !=
818 		    sc->sc_rx_ring.sring->rsp_prod)) {
819 			m->m_len = m->m_pkthdr.len = rx->status;
820 			MEXTADD(m, pktp, rx->status,
821 			    M_DEVBUF, xennet_rx_mbuf_free, req);
822 			m->m_flags |= M_EXT_RW; /* we own the buffer */
823 			req->rxreq_gntref = GRANT_STACK_REF;
824 		} else {
825 			/*
826 			 * This was our last receive buffer, allocate
827 			 * memory, copy data and push the receive
828 			 * buffer back to the hypervisor.
829 			 */
830 			m->m_len = min(MHLEN, rx->status);
831 			m->m_pkthdr.len = 0;
832 			m_copyback(m, 0, rx->status, pktp);
833 			xennet_rx_mbuf_free(NULL, (void *)va, PAGE_SIZE, req);
834 			if (m->m_pkthdr.len < rx->status) {
835 				/* out of memory, just drop packets */
836 				ifp->if_ierrors++;
837 				m_freem(m);
838 				continue;
839 			}
840 		}
841 		if ((rx->flags & NETRXF_csum_blank) != 0) {
842 			xennet_checksum_fill(&m);
843 			if (m == NULL) {
844 				ifp->if_ierrors++;
845 				continue;
846 			}
847 		}
848 #if NBPFILTER > 0
849 		/*
850 		 * Pass packet to bpf if there is a listener.
851 		 */
852 		if (ifp->if_bpf)
853 			bpf_mtap(ifp->if_bpf, m);
854 #endif
855 
856 		ifp->if_ipackets++;
857 
858 		/* Pass the packet up. */
859 		(*ifp->if_input)(ifp, m);
860 	}
861 	x86_lfence();
862 	sc->sc_rx_ring.rsp_cons = i;
863 	RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_rx_ring, more_to_do);
864 	if (more_to_do)
865 		goto again;
866 	return 1;
867 }
868 
869 /*
870  * Called at splnet.
871  */
872 void
873 xennet_start(struct ifnet *ifp)
874 {
875 	struct xennet_xenbus_softc *sc = ifp->if_softc;
876 
877 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_start()\n", sc->sc_dev.dv_xname));
878 
879 #if NRND > 0
880 	rnd_add_uint32(&sc->sc_rnd_source, sc->sc_tx_ring.req_prod_pvt);
881 #endif
882 
883 	xennet_tx_complete(sc);
884 
885 	if (__predict_false(
886 	    (ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING))
887 		return;
888 
889 	/*
890 	 * The Xen communication channel is much more efficient if we can
891 	 * schedule batch of packets for domain0. To achieve this, we
892 	 * schedule a soft interrupt, and just return. This way, the network
893 	 * stack will enqueue all pending mbufs in the interface's send queue
894 	 * before it is processed by xennet_softstart().
895 	 */
896 	softint_schedule(sc->sc_softintr);
897 	return;
898 }
899 
900 /*
901  * called at splsoftnet
902  */
903 void
904 xennet_softstart(void *arg)
905 {
906 	struct xennet_xenbus_softc *sc = arg;
907 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
908 	struct mbuf *m, *new_m;
909 	netif_tx_request_t *txreq;
910 	RING_IDX req_prod;
911 	paddr_t pa, pa2;
912 	struct xennet_txreq *req;
913 	int notify;
914 	int do_notify = 0;
915 	int s;
916 
917 	s = splnet();
918 	if (__predict_false(
919 	    (ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)) {
920 		splx(s);
921 		return;
922 	}
923 
924 	req_prod = sc->sc_tx_ring.req_prod_pvt;
925 	while (/*CONSTCOND*/1) {
926 		uint16_t txflags;
927 
928 		req = SLIST_FIRST(&sc->sc_txreq_head);
929 		if (__predict_false(req == NULL)) {
930 			ifp->if_flags |= IFF_OACTIVE;
931 			break;
932 		}
933 		IFQ_POLL(&ifp->if_snd, m);
934 		if (m == NULL)
935 			break;
936 
937 		switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) {
938 		case M_EXT|M_EXT_CLUSTER:
939 			KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID);
940 			pa = m->m_ext.ext_paddr +
941 				(m->m_data - m->m_ext.ext_buf);
942 			break;
943 		case 0:
944 			KASSERT(m->m_paddr != M_PADDR_INVALID);
945 			pa = m->m_paddr + M_BUFOFFSET(m) +
946 				(m->m_data - M_BUFADDR(m));
947 			break;
948 		default:
949 			if (__predict_false(
950 			    !pmap_extract(pmap_kernel(), (vaddr_t)m->m_data,
951 			    &pa))) {
952 				panic("xennet_start: no pa");
953 			}
954 			break;
955 		}
956 
957 		if ((m->m_pkthdr.csum_flags &
958 		    (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) {
959 			txflags = NETTXF_csum_blank;
960 		} else {
961 			txflags = 0;
962 		}
963 
964 		if (m->m_pkthdr.len != m->m_len ||
965 		    (pa ^ (pa + m->m_pkthdr.len - 1)) & PG_FRAME) {
966 
967 			MGETHDR(new_m, M_DONTWAIT, MT_DATA);
968 			if (__predict_false(new_m == NULL)) {
969 				printf("xennet: no mbuf\n");
970 				break;
971 			}
972 			if (m->m_pkthdr.len > MHLEN) {
973 				MCLGET(new_m, M_DONTWAIT);
974 				if (__predict_false(
975 				    (new_m->m_flags & M_EXT) == 0)) {
976 					DPRINTF(("xennet: no mbuf cluster\n"));
977 					m_freem(new_m);
978 					break;
979 				}
980 			}
981 
982 			m_copydata(m, 0, m->m_pkthdr.len, mtod(new_m, void *));
983 			new_m->m_len = new_m->m_pkthdr.len = m->m_pkthdr.len;
984 
985 			if ((new_m->m_flags & M_EXT) != 0) {
986 				pa = new_m->m_ext.ext_paddr;
987 				KASSERT(new_m->m_data == new_m->m_ext.ext_buf);
988 				KASSERT(pa != M_PADDR_INVALID);
989 			} else {
990 				pa = new_m->m_paddr;
991 				KASSERT(pa != M_PADDR_INVALID);
992 				KASSERT(new_m->m_data == M_BUFADDR(new_m));
993 				pa += M_BUFOFFSET(new_m);
994 			}
995 			if (__predict_false(xengnt_grant_access(
996 			    sc->sc_xbusd->xbusd_otherend_id,
997 			    xpmap_ptom_masked(pa),
998 			    GNTMAP_readonly, &req->txreq_gntref) != 0)) {
999 				m_freem(new_m);
1000 				ifp->if_flags |= IFF_OACTIVE;
1001 				break;
1002 			}
1003 			/* we will be able to send new_m */
1004 			IFQ_DEQUEUE(&ifp->if_snd, m);
1005 			m_freem(m);
1006 			m = new_m;
1007 		} else {
1008 			if (__predict_false(xengnt_grant_access(
1009 			    sc->sc_xbusd->xbusd_otherend_id,
1010 			    xpmap_ptom_masked(pa),
1011 			    GNTMAP_readonly, &req->txreq_gntref) != 0)) {
1012 				ifp->if_flags |= IFF_OACTIVE;
1013 				break;
1014 			}
1015 			/* we will be able to send m */
1016 			IFQ_DEQUEUE(&ifp->if_snd, m);
1017 		}
1018 		MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner);
1019 
1020 		KASSERT(((pa ^ (pa + m->m_pkthdr.len -  1)) & PG_FRAME) == 0);
1021 
1022 		SLIST_REMOVE_HEAD(&sc->sc_txreq_head, txreq_next);
1023 		req->txreq_m = m;
1024 
1025 		DPRINTFN(XEDB_MBUF, ("xennet_start id %d, "
1026 		    "mbuf %p, buf %p/%p/%p, size %d\n",
1027 		    req->txreq_id, m, mtod(m, void *), (void *)pa,
1028 		    (void *)xpmap_ptom_masked(pa), m->m_pkthdr.len));
1029 		pmap_extract_ma(pmap_kernel(), mtod(m, vaddr_t), &pa2);
1030 		DPRINTFN(XEDB_MBUF, ("xennet_start pa %p ma %p/%p\n",
1031 		    (void *)pa, (void *)xpmap_ptom_masked(pa), (void *)pa2));
1032 #ifdef XENNET_DEBUG_DUMP
1033 		xennet_hex_dump(mtod(m, u_char *), m->m_pkthdr.len, "s", req->txreq_id);
1034 #endif
1035 
1036 		txreq = RING_GET_REQUEST(&sc->sc_tx_ring, req_prod);
1037 		txreq->id = req->txreq_id;
1038 		txreq->gref = req->txreq_gntref;
1039 		txreq->offset = pa & ~PG_FRAME;
1040 		txreq->size = m->m_pkthdr.len;
1041 		txreq->flags = txflags;
1042 
1043 		req_prod++;
1044 		sc->sc_tx_ring.req_prod_pvt = req_prod;
1045 		RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_tx_ring, notify);
1046 		if (notify)
1047 			do_notify = 1;
1048 
1049 #ifdef XENNET_DEBUG
1050 		DPRINTFN(XEDB_MEM, ("packet addr %p/%p, physical %p/%p, "
1051 		    "m_paddr %p, len %d/%d\n", M_BUFADDR(m), mtod(m, void *),
1052 		    (void *)*kvtopte(mtod(m, vaddr_t)),
1053 		    (void *)xpmap_mtop(*kvtopte(mtod(m, vaddr_t))),
1054 		    (void *)m->m_paddr, m->m_pkthdr.len, m->m_len));
1055 		DPRINTFN(XEDB_MEM, ("id %d gref %d offset %d size %d flags %d"
1056 		    " prod %d\n",
1057 		    txreq->id, txreq->gref, txreq->offset, txreq->size,
1058 		    txreq->flags, req_prod));
1059 #endif
1060 
1061 #if NBPFILTER > 0
1062 		/*
1063 		 * Pass packet to bpf if there is a listener.
1064 		 */
1065 		if (ifp->if_bpf) {
1066 			bpf_mtap(ifp->if_bpf, m);
1067 		}
1068 #endif
1069 	}
1070 
1071 	x86_lfence();
1072 	if (do_notify) {
1073 		hypervisor_notify_via_evtchn(sc->sc_evtchn);
1074 		ifp->if_timer = 5;
1075 	}
1076 	splx(s);
1077 
1078 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_start() done\n",
1079 	    sc->sc_dev.dv_xname));
1080 }
1081 
1082 int
1083 xennet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1084 {
1085 #ifdef XENNET_DEBUG
1086 	struct xennet_xenbus_softc *sc = ifp->if_softc;
1087 #endif
1088 	int s, error = 0;
1089 
1090 	s = splnet();
1091 
1092 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_ioctl()\n", sc->sc_dev.dv_xname));
1093 	error = ether_ioctl(ifp, cmd, data);
1094 	if (error == ENETRESET)
1095 		error = 0;
1096 	splx(s);
1097 
1098 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_ioctl() returning %d\n",
1099 	    sc->sc_dev.dv_xname, error));
1100 
1101 	return error;
1102 }
1103 
1104 void
1105 xennet_watchdog(struct ifnet *ifp)
1106 {
1107 	struct xennet_xenbus_softc *sc = ifp->if_softc;
1108 
1109 	printf("%s: xennet_watchdog\n", sc->sc_dev.dv_xname);
1110 }
1111 
1112 int
1113 xennet_init(struct ifnet *ifp)
1114 {
1115 	struct xennet_xenbus_softc *sc = ifp->if_softc;
1116 	int s = splnet();
1117 
1118 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_init()\n", sc->sc_dev.dv_xname));
1119 
1120 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
1121 		sc->sc_rx_ring.sring->rsp_event =
1122 		    sc->sc_rx_ring.rsp_cons + 1;
1123 		hypervisor_enable_event(sc->sc_evtchn);
1124 		hypervisor_notify_via_evtchn(sc->sc_evtchn);
1125 		xennet_reset(sc);
1126 	}
1127 	ifp->if_flags |= IFF_RUNNING;
1128 	ifp->if_flags &= ~IFF_OACTIVE;
1129 	ifp->if_timer = 0;
1130 	splx(s);
1131 	return 0;
1132 }
1133 
1134 void
1135 xennet_stop(struct ifnet *ifp, int disable)
1136 {
1137 	struct xennet_xenbus_softc *sc = ifp->if_softc;
1138 	int s = splnet();
1139 
1140 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1141 	hypervisor_mask_event(sc->sc_evtchn);
1142 	xennet_reset(sc);
1143 	splx(s);
1144 }
1145 
1146 void
1147 xennet_reset(struct xennet_xenbus_softc *sc)
1148 {
1149 
1150 	DPRINTFN(XEDB_FOLLOW, ("%s: xennet_reset()\n", sc->sc_dev.dv_xname));
1151 }
1152 
1153 #if defined(NFS_BOOT_BOOTSTATIC)
1154 int
1155 xennet_bootstatic_callback(struct nfs_diskless *nd)
1156 {
1157 #if 0
1158 	struct ifnet *ifp = nd->nd_ifp;
1159 	struct xennet_xenbus_softc *sc =
1160 	    (struct xennet_xenbus_softc *)ifp->if_softc;
1161 #endif
1162 	union xen_cmdline_parseinfo xcp;
1163 	struct sockaddr_in *sin;
1164 
1165 	memset(&xcp, 0, sizeof(xcp.xcp_netinfo));
1166 	xcp.xcp_netinfo.xi_ifno = /* XXX sc->sc_ifno */ 0;
1167 	xcp.xcp_netinfo.xi_root = nd->nd_root.ndm_host;
1168 	xen_parse_cmdline(XEN_PARSE_NETINFO, &xcp);
1169 
1170 	nd->nd_myip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[0]);
1171 	nd->nd_gwip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[2]);
1172 	nd->nd_mask.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[3]);
1173 
1174 	sin = (struct sockaddr_in *) &nd->nd_root.ndm_saddr;
1175 	memset((void *)sin, 0, sizeof(*sin));
1176 	sin->sin_len = sizeof(*sin);
1177 	sin->sin_family = AF_INET;
1178 	sin->sin_addr.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[1]);
1179 	if (nd->nd_myip.s_addr == 0)
1180 		return NFS_BOOTSTATIC_NOSTATIC;
1181 	else
1182 		return (NFS_BOOTSTATIC_HAS_MYIP|NFS_BOOTSTATIC_HAS_GWIP|
1183 		    NFS_BOOTSTATIC_HAS_MASK|NFS_BOOTSTATIC_HAS_SERVADDR|
1184 		    NFS_BOOTSTATIC_HAS_SERVER);
1185 }
1186 #endif /* defined(NFS_BOOT_BOOTSTATIC) */
1187 
1188 #ifdef XENNET_DEBUG_DUMP
1189 #define XCHR(x) hexdigits[(x) & 0xf]
1190 static void
1191 xennet_hex_dump(const unsigned char *pkt, size_t len, const char *type, int id)
1192 {
1193 	size_t i, j;
1194 
1195 	printf("pkt %p len %d/%x type %s id %d\n", pkt, len, len, type, id);
1196 	printf("00000000  ");
1197 	for(i=0; i<len; i++) {
1198 		printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i]));
1199 		if ((i+1) % 16 == 8)
1200 			printf(" ");
1201 		if ((i+1) % 16 == 0) {
1202 			printf(" %c", '|');
1203 			for(j=0; j<16; j++)
1204 				printf("%c", pkt[i-15+j]>=32 &&
1205 				    pkt[i-15+j]<127?pkt[i-15+j]:'.');
1206 			printf("%c\n%c%c%c%c%c%c%c%c  ", '|',
1207 			    XCHR((i+1)>>28), XCHR((i+1)>>24),
1208 			    XCHR((i+1)>>20), XCHR((i+1)>>16),
1209 			    XCHR((i+1)>>12), XCHR((i+1)>>8),
1210 			    XCHR((i+1)>>4), XCHR(i+1));
1211 		}
1212 	}
1213 	printf("\n");
1214 }
1215 #undef XCHR
1216 #endif
1217