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