|
|
1.1 root 1: /*
2: * Copyright (C) 2006-2009, 2011 Free Software Foundation
3: *
4: * This program is free software ; you can redistribute it and/or modify
5: * it under the terms of the GNU General Public License as published by
6: * the Free Software Foundation ; either version 2 of the License, or
7: * (at your option) any later version.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY ; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with the program ; if not, write to the Free Software
16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include <sys/types.h>
20: #include <mach/mig_errors.h>
21: #include <kern/kalloc.h>
22: #include <ipc/ipc_port.h>
23: #include <ipc/ipc_space.h>
24: #include <vm/vm_kern.h>
25: #include <device/device_types.h>
26: #include <device/device_port.h>
27: #include <device/if_hdr.h>
28: #include <device/if_ether.h>
29: #include <device/net_io.h>
30: #include <device/device_reply.user.h>
31: #include <device/device_emul.h>
1.1.1.4 ! root 32: #include <device/ds_routines.h>
1.1 root 33: #include <intel/pmap.h>
34: #include <xen/public/io/netif.h>
35: #include <xen/public/memory.h>
36: #include <string.h>
37: #include <util/atoi.h>
38: #include "evt.h"
39: #include "store.h"
40: #include "net.h"
41: #include "grant.h"
42: #include "ring.h"
43: #include "time.h"
44: #include "xen.h"
45:
46: /* Hypervisor part */
47:
48: #define ADDRESS_SIZE 6
49: #define WINDOW __RING_SIZE((netif_rx_sring_t*)0, PAGE_SIZE)
50:
51: /* Are we paranoid enough to not leak anything to backend? */
52: static const int paranoia = 0;
53:
54: struct net_data {
55: struct device device;
56: struct ifnet ifnet;
57: int open_count;
58: char *backend;
59: domid_t domid;
60: char *vif;
61: u_char address[ADDRESS_SIZE];
62: int handle;
63: ipc_port_t port;
64: netif_tx_front_ring_t tx;
65: netif_rx_front_ring_t rx;
66: void *rx_buf[WINDOW];
67: grant_ref_t rx_buf_gnt[WINDOW];
68: unsigned long rx_buf_pfn[WINDOW];
69: int rx_copy;
70: evtchn_port_t evt;
71: simple_lock_data_t lock;
72: simple_lock_data_t pushlock;
73: };
74:
75: static int n_vifs;
76: static struct net_data *vif_data;
77:
78: struct device_emulation_ops hyp_net_emulation_ops;
79:
80: int hextoi(char *cp, int *nump)
81: {
82: int number;
83: char *original;
84: char c;
85:
86: original = cp;
87: for (number = 0, c = *cp | 0x20; (('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')); c = *(++cp)) {
88: number *= 16;
89: if (c <= '9')
90: number += c - '0';
91: else
92: number += c - 'a' + 10;
93: }
94: if (original == cp)
95: *nump = -1;
96: else
97: *nump = number;
98: return(cp - original);
99: }
100:
101: static void enqueue_rx_buf(struct net_data *nd, int number) {
102: unsigned reqn = nd->rx.req_prod_pvt++;
103: netif_rx_request_t *req = RING_GET_REQUEST(&nd->rx, reqn);
104: grant_ref_t gref;
105:
106: assert(number < WINDOW);
107:
108: req->id = number;
109: if (nd->rx_copy) {
110: /* Let domD write the data */
111: gref = hyp_grant_give(nd->domid, nd->rx_buf_pfn[number], 0);
112: } else {
113: /* Accept pages from domD */
114: gref = hyp_grant_accept_transfer(nd->domid, nd->rx_buf_pfn[number]);
115: /* give back page */
116: hyp_free_page(nd->rx_buf_pfn[number], nd->rx_buf[number]);
117: }
118:
119: req->gref = nd->rx_buf_gnt[number] = gref;
120: }
121:
122: static int recompute_checksum(void *data, int len) {
1.1.1.3 root 123: uint16_t *header16 = data;
124: uint8_t *header8 = data;
1.1 root 125: unsigned length, i;
1.1.1.3 root 126: uint32_t checksum = 0;
1.1 root 127:
128: /* IPv4 header length */
129: length = (header8[0] & 0xf) * 4;
130: if (length < 20)
131: /* Too small for an IP header16 */
132: return -1;
133: if (length > len)
134: /* Does not fit in the ethernet frame */
135: return -1;
136:
137: /* Compute IP header checksum */
138: header16[5] = 0;
139: for (i = 0; i < length/2; i++)
140: checksum += ntohs(header16[i]);
141:
142: while (checksum >> 16)
143: checksum = (checksum & 0xffff) + (checksum >> 16);
144:
145: header16[5] = htons(~checksum);
146:
147: if (header8[9] == 6) {
148: /* Need to fix TCP checksum as well */
1.1.1.3 root 149: uint16_t *tcp_header16 = header16 + length/2;
150: uint8_t *tcp_header8 = header8 + length;
1.1 root 151: unsigned tcp_length = ntohs(header16[1]) - length;
152:
153: /* Pseudo IP header */
154: checksum = ntohs(header16[6]) + ntohs(header16[7]) +
155: ntohs(header16[8]) + ntohs(header16[9]) +
156: header8[9] + tcp_length;
157:
158: tcp_header16[8] = 0;
159: for (i = 0; i < tcp_length / 2; i++)
160: checksum += ntohs(tcp_header16[i]);
161: if (tcp_length & 1)
162: checksum += tcp_header8[tcp_length-1] << 8;
163:
164: while (checksum >> 16)
165: checksum = (checksum & 0xffff) + (checksum >> 16);
166:
167: tcp_header16[8] = htons(~checksum);
168: } else if (header8[9] == 17) {
169: /* Drop any bogus checksum */
1.1.1.3 root 170: uint16_t *udp_header16 = header16 + length/2;
1.1 root 171: udp_header16[3] = 0;
172: }
173:
174: return 0;
175: }
176:
177: static void hyp_net_intr(int unit) {
178: ipc_kmsg_t kmsg;
179: struct ether_header *eh;
180: struct packet_header *ph;
181: netif_rx_response_t *rx_rsp;
182: netif_tx_response_t *tx_rsp;
183: void *data;
184: int len, more;
185: struct net_data *nd = &vif_data[unit];
186:
187: simple_lock(&nd->lock);
188: if ((nd->rx.sring->rsp_prod - nd->rx.rsp_cons) >= (WINDOW*3)/4)
189: printf("window %ld a bit small!\n", WINDOW);
190:
191: more = RING_HAS_UNCONSUMED_RESPONSES(&nd->rx);
192: while (more) {
193: rmb(); /* make sure we see responses */
194: rx_rsp = RING_GET_RESPONSE(&nd->rx, nd->rx.rsp_cons++);
195:
196: unsigned number = rx_rsp->id;
197: assert(number < WINDOW);
198: if (nd->rx_copy) {
199: hyp_grant_takeback(nd->rx_buf_gnt[number]);
200: } else {
201: unsigned long mfn = hyp_grant_finish_transfer(nd->rx_buf_gnt[number]);
202: #ifdef MACH_PSEUDO_PHYS
203: mfn_list[nd->rx_buf_pfn[number]] = mfn;
204: #endif /* MACH_PSEUDO_PHYS */
205: pmap_map_mfn(nd->rx_buf[number], mfn);
206: }
207:
208: kmsg = net_kmsg_get();
209: if (!kmsg)
210: /* gasp! Drop */
211: goto drop;
212:
213: if (rx_rsp->status <= 0)
214: switch (rx_rsp->status) {
215: case NETIF_RSP_DROPPED:
216: printf("Packet dropped\n");
217: goto drop_kmsg;
218: case NETIF_RSP_ERROR:
219: printf("Packet error\n");
220: goto drop_kmsg;
221: case 0:
222: printf("nul packet\n");
223: goto drop_kmsg;
224: default:
225: printf("Unknown error %d\n", rx_rsp->status);
226: goto drop_kmsg;
227: }
228:
229: data = nd->rx_buf[number] + rx_rsp->offset;
230: len = rx_rsp->status;
231:
232: if (rx_rsp->flags & NETRXF_csum_blank) {
233: struct ether_header *ether = data;
234:
235: if (!(rx_rsp->flags & NETRXF_data_validated)) {
236: printf("packet with no checksum and not validated, dropping it\n");
237: goto drop_kmsg;
238: }
239:
240: /* TODO: rather tell pfinet to ignore checksums */
241:
242: if (ntohs(ether->ether_type) != 0x0800) {
243: printf("packet with no checksum and not IPv4, dropping it\n");
244: goto drop_kmsg;
245: }
246:
247: if (recompute_checksum(data + sizeof(*ether), len - sizeof(*ether)))
248: goto drop_kmsg;
249: }
250:
251: eh = (void*) (net_kmsg(kmsg)->header);
252: ph = (void*) (net_kmsg(kmsg)->packet);
253: memcpy(eh, data, sizeof (struct ether_header));
254: memcpy(ph + 1, data + sizeof (struct ether_header), len - sizeof(struct ether_header));
255: RING_FINAL_CHECK_FOR_RESPONSES(&nd->rx, more);
256: enqueue_rx_buf(nd, number);
257: ph->type = eh->ether_type;
258: ph->length = len - sizeof(struct ether_header) + sizeof (struct packet_header);
259:
260: net_kmsg(kmsg)->sent = FALSE; /* Mark packet as received. */
261:
262: net_packet(&nd->ifnet, kmsg, ph->length, ethernet_priority(kmsg));
263: continue;
264:
265: drop_kmsg:
266: net_kmsg_put(kmsg);
267: drop:
268: RING_FINAL_CHECK_FOR_RESPONSES(&nd->rx, more);
269: enqueue_rx_buf(nd, number);
270: }
271:
272: /* commit new requests */
273: int notify;
274: wmb(); /* make sure it sees requests */
275: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&nd->rx, notify);
276: if (notify)
277: hyp_event_channel_send(nd->evt);
278:
279: /* Now the tx side */
280: more = RING_HAS_UNCONSUMED_RESPONSES(&nd->tx);
281: spl_t s = splsched ();
282: while (more) {
283: rmb(); /* make sure we see responses */
284: tx_rsp = RING_GET_RESPONSE(&nd->tx, nd->tx.rsp_cons++);
285: switch (tx_rsp->status) {
286: case NETIF_RSP_DROPPED:
287: printf("Packet dropped\n");
288: break;
289: case NETIF_RSP_ERROR:
290: printf("Packet error\n");
291: break;
292: case NETIF_RSP_OKAY:
293: break;
294: default:
295: printf("Unknown error %d\n", tx_rsp->status);
296: break;
297: }
298: thread_wakeup((event_t) hyp_grant_address(tx_rsp->id));
299: thread_wakeup_one(nd);
300: RING_FINAL_CHECK_FOR_RESPONSES(&nd->tx, more);
301: }
302: splx(s);
303:
304: simple_unlock(&nd->lock);
305: }
306:
307: #define VIF_PATH "device/vif"
308: void hyp_net_init(void) {
309: char **vifs, **vif;
310: char *c;
311: int i;
312: int n;
313: int grant;
314: char port_name[10];
315: domid_t domid;
316: evtchn_port_t evt;
317: hyp_store_transaction_t t;
318: vm_offset_t addr;
319: struct net_data *nd;
320: struct ifnet *ifp;
321: netif_tx_sring_t *tx_ring;
322: netif_rx_sring_t *rx_ring;
323:
324: vifs = hyp_store_ls(0, 1, VIF_PATH);
325: if (!vifs) {
326: printf("eth: No net device (%s). Hoping you don't need any\n", hyp_store_error);
327: n_vifs = 0;
328: return;
329: }
330:
331: n = 0;
332: for (vif = vifs; *vif; vif++)
333: n++;
334:
335: vif_data = (void*) kalloc(n * sizeof(*vif_data));
336: if (!vif_data) {
337: printf("eth: No memory room for VIF\n");
338: n_vifs = 0;
339: return;
340: }
341: n_vifs = n;
342:
343: for (n = 0; n < n_vifs; n++) {
344: nd = &vif_data[n];
345: mach_atoi((u_char *) vifs[n], &nd->handle);
346: if (nd->handle == MACH_ATOI_DEFAULT)
347: continue;
348:
349: nd->open_count = -2;
350: nd->vif = vifs[n];
351:
352: /* Get domain id of frontend driver. */
353: i = hyp_store_read_int(0, 5, VIF_PATH, "/", vifs[n], "/", "backend-id");
354: if (i == -1)
355: panic("eth: couldn't read frontend domid of VIF %s (%s)",vifs[n], hyp_store_error);
356: nd->domid = domid = i;
357:
358: do {
359: t = hyp_store_transaction_start();
360:
361: /* Get a page for tx_ring */
362: if ((addr = vm_page_grab_phys_addr()) == -1)
363: panic("eth: couldn't allocate space for store tx_ring");
364: tx_ring = (void*) phystokv(addr);
365: SHARED_RING_INIT(tx_ring);
366: FRONT_RING_INIT(&nd->tx, tx_ring, PAGE_SIZE);
367: grant = hyp_grant_give(domid, atop(addr), 0);
368:
369: /* and give it to backend. */
370: i = sprintf(port_name, "%d", grant);
371: c = hyp_store_write(t, port_name, 5, VIF_PATH, "/", vifs[n], "/", "tx-ring-ref");
372: if (!c)
373: panic("eth: couldn't store tx_ring reference for VIF %s (%s)", vifs[n], hyp_store_error);
374: kfree((vm_offset_t) c, strlen(c)+1);
375:
376: /* Get a page for rx_ring */
377: if ((addr = vm_page_grab_phys_addr()) == -1)
378: panic("eth: couldn't allocate space for store tx_ring");
379: rx_ring = (void*) phystokv(addr);
380: SHARED_RING_INIT(rx_ring);
381: FRONT_RING_INIT(&nd->rx, rx_ring, PAGE_SIZE);
382: grant = hyp_grant_give(domid, atop(addr), 0);
383:
384: /* and give it to backend. */
385: i = sprintf(port_name, "%d", grant);
386: c = hyp_store_write(t, port_name, 5, VIF_PATH, "/", vifs[n], "/", "rx-ring-ref");
387: if (!c)
388: panic("eth: couldn't store rx_ring reference for VIF %s (%s)", vifs[n], hyp_store_error);
389: kfree((vm_offset_t) c, strlen(c)+1);
390:
391: /* tell we need csums. */
392: c = hyp_store_write(t, "1", 5, VIF_PATH, "/", vifs[n], "/", "feature-no-csum-offload");
393: if (!c)
394: panic("eth: couldn't store feature-no-csum-offload reference for VIF %s (%s)", vifs[n], hyp_store_error);
395: kfree((vm_offset_t) c, strlen(c)+1);
396:
397: /* Allocate an event channel and give it to backend. */
398: nd->evt = evt = hyp_event_channel_alloc(domid);
1.1.1.3 root 399: i = sprintf(port_name, "%u", evt);
1.1 root 400: c = hyp_store_write(t, port_name, 5, VIF_PATH, "/", vifs[n], "/", "event-channel");
401: if (!c)
402: panic("eth: couldn't store event channel for VIF %s (%s)", vifs[n], hyp_store_error);
403: kfree((vm_offset_t) c, strlen(c)+1);
404: c = hyp_store_write(t, hyp_store_state_initialized, 5, VIF_PATH, "/", vifs[n], "/", "state");
405: if (!c)
406: panic("eth: couldn't store state for VIF %s (%s)", vifs[n], hyp_store_error);
407: kfree((vm_offset_t) c, strlen(c)+1);
408: } while ((!hyp_store_transaction_stop(t)));
409: /* TODO randomly wait? */
410:
411: c = hyp_store_read(0, 5, VIF_PATH, "/", vifs[n], "/", "backend");
412: if (!c)
413: panic("eth: couldn't get path to VIF %s backend (%s)", vifs[n], hyp_store_error);
414: nd->backend = c;
415:
416: while(1) {
417: i = hyp_store_read_int(0, 3, nd->backend, "/", "state");
418: if (i == MACH_ATOI_DEFAULT)
419: panic("can't read state from %s", nd->backend);
420: if (i == XenbusStateInitWait)
421: break;
422: hyp_yield();
423: }
424:
425: c = hyp_store_read(0, 3, nd->backend, "/", "mac");
426: if (!c)
427: panic("eth: couldn't get VIF %s's mac (%s)", vifs[n], hyp_store_error);
428:
429: for (i=0; ; i++) {
430: int val;
431: hextoi(&c[3*i], &val);
432: if (val == -1)
433: panic("eth: couldn't understand %dth number of VIF %s's mac %s", i, vifs[n], c);
434: nd->address[i] = val;
435: if (i==ADDRESS_SIZE-1)
436: break;
437: if (c[3*i+2] != ':')
438: panic("eth: couldn't understand %dth separator of VIF %s's mac %s", i, vifs[n], c);
439: }
440: kfree((vm_offset_t) c, strlen(c)+1);
441:
442: printf("eth%d: dom%d's VIF %s ", n, domid, vifs[n]);
443: for (i=0; ; i++) {
444: printf("%02x", nd->address[i]);
445: if (i==ADDRESS_SIZE-1)
446: break;
447: printf(":");
448: }
449: printf("\n");
450:
451: nd->rx_copy = hyp_store_read_int(0, 3, nd->backend, "/", "feature-rx-copy");
452: if (nd->rx_copy == 1) {
453: c = hyp_store_write(0, "1", 5, VIF_PATH, "/", vifs[n], "/", "request-rx-copy");
454: if (!c)
455: panic("eth: couldn't request rx copy feature for VIF %s (%s)", vifs[n], hyp_store_error);
456: } else
457: nd->rx_copy = 0;
458:
459: c = hyp_store_write(0, hyp_store_state_connected, 5, VIF_PATH, "/", nd->vif, "/", "state");
460: if (!c)
461: panic("couldn't store state for eth%d (%s)", nd - vif_data, hyp_store_error);
462: kfree((vm_offset_t) c, strlen(c)+1);
463:
464: while(1) {
465: i = hyp_store_read_int(0, 3, nd->backend, "/", "state");
466: if (i == MACH_ATOI_DEFAULT)
467: panic("can't read state from %s", nd->backend);
468: if (i == XenbusStateConnected)
469: break;
470: hyp_yield();
471: }
472:
473: /* Get a page for packet reception */
474: for (i= 0; i<WINDOW; i++) {
475: if ((addr = vm_page_grab_phys_addr()) == -1)
476: panic("eth: couldn't allocate space for store tx_ring");
477: nd->rx_buf[i] = (void*)phystokv(addr);
478: nd->rx_buf_pfn[i] = atop(addr);
479: if (!nd->rx_copy) {
480: if (hyp_do_update_va_mapping(kvtolin(nd->rx_buf[i]), 0, UVMF_INVLPG|UVMF_ALL))
481: panic("eth: couldn't clear rx kv buf %d at %p", i, addr);
482: }
483: /* and enqueue it to backend. */
484: enqueue_rx_buf(nd, i);
485: }
486: int notify;
487: wmb(); /* make sure it sees requests */
488: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&nd->rx, notify);
489: if (notify)
490: hyp_event_channel_send(nd->evt);
491:
492:
493: nd->open_count = -1;
494: nd->device.emul_ops = &hyp_net_emulation_ops;
495: nd->device.emul_data = nd;
496: simple_lock_init(&nd->lock);
497: simple_lock_init(&nd->pushlock);
498:
499: ifp = &nd->ifnet;
500: ifp->if_unit = n;
501: ifp->if_flags = IFF_UP | IFF_RUNNING;
502: ifp->if_header_size = 14;
503: ifp->if_header_format = HDR_ETHERNET;
504: /* Set to the maximum that we can handle in device_write. */
505: ifp->if_mtu = PAGE_SIZE - ifp->if_header_size;
506: ifp->if_address_size = ADDRESS_SIZE;
507: ifp->if_address = (void*) nd->address;
508: if_init_queues (ifp);
509:
510: /* Now we can start receiving */
511: hyp_evt_handler(evt, hyp_net_intr, n, SPL6);
512: }
513: }
514:
515: static ipc_port_t
516: dev_to_port(void *d)
517: {
518: struct net_data *b = d;
519: if (!d)
520: return IP_NULL;
521: return ipc_port_make_send(b->port);
522: }
523:
524: static int
525: device_close(void *devp)
526: {
527: struct net_data *nd = devp;
528: if (--nd->open_count < 0)
529: panic("too many closes on eth%d", nd - vif_data);
530: printf("close, eth%d count %d\n",nd-vif_data,nd->open_count);
531: if (nd->open_count)
532: return 0;
533: ipc_kobject_set(nd->port, IKO_NULL, IKOT_NONE);
534: ipc_port_dealloc_kernel(nd->port);
535: return 0;
536: }
537:
538: static io_return_t
539: device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
540: dev_mode_t mode, char *name, device_t *devp /* out */)
541: {
1.1.1.3 root 542: int i, n;
1.1 root 543: ipc_port_t port, notify;
544: struct net_data *nd;
545:
546: if (name[0] != 'e' || name[1] != 't' || name[2] != 'h' || name[3] < '0' || name[3] > '9')
547: return D_NO_SUCH_DEVICE;
548: i = mach_atoi((u_char *) &name[3], &n);
549: if (n == MACH_ATOI_DEFAULT)
550: return D_NO_SUCH_DEVICE;
551: if (name[3 + i])
552: return D_NO_SUCH_DEVICE;
553: if (n >= n_vifs)
554: return D_NO_SUCH_DEVICE;
555: nd = &vif_data[n];
556: if (nd->open_count == -2)
557: /* couldn't be initialized */
558: return D_NO_SUCH_DEVICE;
559:
560: if (nd->open_count >= 0) {
561: *devp = &nd->device ;
562: nd->open_count++ ;
563: printf("re-open, eth%d count %d\n",nd-vif_data,nd->open_count);
564: return D_SUCCESS;
565: }
566:
567: nd->open_count = 1;
568: printf("eth%d count %d\n",nd-vif_data,nd->open_count);
569:
570: port = ipc_port_alloc_kernel();
571: if (port == IP_NULL) {
1.1.1.2 root 572: device_close (nd);
573: return KERN_RESOURCE_SHORTAGE;
1.1 root 574: }
575: nd->port = port;
576:
577: *devp = &nd->device;
578:
579: ipc_kobject_set (port, (ipc_kobject_t) &nd->device, IKOT_DEVICE);
580:
581: notify = ipc_port_make_sonce (nd->port);
582: ip_lock (nd->port);
583: ipc_port_nsrequest (nd->port, 1, notify, ¬ify);
584: assert (notify == IP_NULL);
585:
586: if (IP_VALID (reply_port))
587: ds_device_open_reply (reply_port, reply_port_type, D_SUCCESS, dev_to_port(nd));
588: else
589: device_close(nd);
590: return MIG_NO_REPLY;
591: }
592:
593: static io_return_t
594: device_write(void *d, ipc_port_t reply_port,
595: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
596: recnum_t bn, io_buf_ptr_t data, unsigned int count,
597: int *bytes_written)
598: {
599: vm_map_copy_t copy = (vm_map_copy_t) data;
600: grant_ref_t gref;
601: struct net_data *nd = d;
602: struct ifnet *ifp = &nd->ifnet;
603: netif_tx_request_t *req;
604: unsigned reqn;
1.1.1.4 ! root 605: vm_offset_t buffer;
! 606: char *map_data;
! 607: vm_offset_t map_addr;
! 608: vm_size_t map_size;
! 609: kern_return_t kr;
1.1 root 610:
611: /* The maximum that we can handle. */
612: assert(ifp->if_header_size + ifp->if_mtu <= PAGE_SIZE);
613:
614: if (count < ifp->if_header_size ||
615: count > ifp->if_header_size + ifp->if_mtu)
616: return D_INVALID_SIZE;
617:
618: assert(copy->type == VM_MAP_COPY_PAGE_LIST);
619:
620: assert(copy->cpy_npages <= 2);
621: assert(copy->cpy_npages >= 1);
622:
1.1.1.4 ! root 623: kr = kmem_alloc(device_io_map, &buffer, count);
1.1 root 624:
1.1.1.4 ! root 625: if (kr != KERN_SUCCESS)
! 626: return kr;
! 627:
! 628: kr = kmem_io_map_copyout(device_io_map, (vm_offset_t *)&map_data,
! 629: &map_addr, &map_size, copy, count);
! 630:
! 631: if (kr != KERN_SUCCESS) {
! 632: kmem_free(device_io_map, buffer, count);
! 633: return kr;
! 634: }
1.1 root 635:
1.1.1.4 ! root 636: memcpy((void *)buffer, map_data, count);
! 637: kmem_io_map_deallocate(device_io_map, map_addr, map_size);
1.1 root 638:
639: /* allocate a request */
640: spl_t spl = splimp();
641: while (1) {
642: simple_lock(&nd->lock);
643: if (!RING_FULL(&nd->tx))
644: break;
645: thread_sleep(nd, &nd->lock, FALSE);
646: }
647: mb();
648: reqn = nd->tx.req_prod_pvt++;;
649: simple_lock(&nd->pushlock);
650: simple_unlock(&nd->lock);
651: (void) splx(spl);
652:
653: req = RING_GET_REQUEST(&nd->tx, reqn);
1.1.1.4 ! root 654: req->gref = gref = hyp_grant_give(nd->domid, atop(kvtophys(buffer)), 1);
! 655: req->offset = 0;
1.1 root 656: req->flags = 0;
657: req->id = gref;
658: req->size = count;
659:
660: assert_wait(hyp_grant_address(gref), FALSE);
661:
662: int notify;
663: wmb(); /* make sure it sees requests */
664: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&nd->tx, notify);
665: if (notify)
666: hyp_event_channel_send(nd->evt);
667: simple_unlock(&nd->pushlock);
668:
669: thread_block(NULL);
670:
671: hyp_grant_takeback(gref);
672:
673: /* Send packet to filters. */
674: {
675: struct packet_header *packet;
676: struct ether_header *header;
677: ipc_kmsg_t kmsg;
678:
679: kmsg = net_kmsg_get ();
680:
681: if (kmsg != IKM_NULL)
682: {
683: /* Suitable for Ethernet only. */
684: header = (struct ether_header *) (net_kmsg (kmsg)->header);
685: packet = (struct packet_header *) (net_kmsg (kmsg)->packet);
1.1.1.4 ! root 686: memcpy (header, (void*)buffer, sizeof (struct ether_header));
1.1 root 687:
688: /* packet is prefixed with a struct packet_header,
689: see include/device/net_status.h. */
1.1.1.4 ! root 690: memcpy (packet + 1, (void*)buffer + sizeof (struct ether_header),
1.1 root 691: count - sizeof (struct ether_header));
692: packet->length = count - sizeof (struct ether_header)
693: + sizeof (struct packet_header);
694: packet->type = header->ether_type;
695: net_kmsg (kmsg)->sent = TRUE; /* Mark packet as sent. */
696: spl_t s = splimp ();
697: net_packet (&nd->ifnet, kmsg, packet->length,
698: ethernet_priority (kmsg));
699: splx (s);
700: }
701: }
702:
1.1.1.4 ! root 703: kmem_free(device_io_map, buffer, count);
1.1 root 704:
705: vm_map_copy_discard (copy);
706:
707: *bytes_written = count;
708:
709: if (IP_VALID(reply_port))
710: ds_device_write_reply (reply_port, reply_port_type, 0, count);
711:
712: return MIG_NO_REPLY;
713: }
714:
715: static io_return_t
716: device_get_status(void *d, dev_flavor_t flavor, dev_status_t status,
717: mach_msg_type_number_t *status_count)
718: {
719: struct net_data *nd = d;
720:
721: return net_getstat (&nd->ifnet, flavor, status, status_count);
722: }
723:
724: static io_return_t
725: device_set_status(void *d, dev_flavor_t flavor, dev_status_t status,
726: mach_msg_type_number_t count)
727: {
728: struct net_data *nd = d;
729:
730: switch (flavor)
731: {
732: default:
733: printf("TODO: net_%s(%p, 0x%x)\n", __func__, nd, flavor);
734: return D_INVALID_OPERATION;
735: }
736: return D_SUCCESS;
737: }
738:
739: static io_return_t
740: device_set_filter(void *d, ipc_port_t port, int priority,
741: filter_t * filter, unsigned filter_count)
742: {
743: struct net_data *nd = d;
744:
745: if (!nd)
746: return D_NO_SUCH_DEVICE;
747:
748: return net_set_filter (&nd->ifnet, port, priority, filter, filter_count);
749: }
750:
751: struct device_emulation_ops hyp_net_emulation_ops = {
752: NULL, /* dereference */
753: NULL, /* deallocate */
754: dev_to_port,
755: device_open,
756: device_close,
757: device_write,
758: NULL, /* write_inband */
759: NULL,
760: NULL, /* read_inband */
761: device_set_status, /* set_status */
762: device_get_status,
763: device_set_filter, /* set_filter */
764: NULL, /* map */
765: NULL, /* no_senders */
766: NULL, /* write_trap */
767: NULL, /* writev_trap */
768: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.