debuggers.hg

view tools/python/xen/lowlevel/xu/xu.c @ 3598:de9af8f0cdf1

bitkeeper revision 1.1159.231.7 (41f913d39TdyKRddqjGU3m60tTUoUQ)

Remove excessive debug messages from xend/xcs interface code.
author akw27@labyrinth.cl.cam.ac.uk
date Thu Jan 27 16:16:19 2005 +0000 (2005-01-27)
parents 3ced9b0f4dab
children 25f3f22927e9 30ee9c427a5b
line source
1 /******************************************************************************
2 * utils.c
3 *
4 * Copyright (c) 2004, K A Fraser
5 */
7 #include <Python.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <sys/stat.h>
15 #include <sys/socket.h>
16 #include <sys/mman.h>
17 #include <sys/poll.h>
18 #include <sys/sysmacros.h>
19 #include <netinet/in.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <xc.h>
26 #include <xen/xen.h>
27 #include <xen/io/domain_controller.h>
28 #include <xen/linux/privcmd.h>
30 #define XENPKG "xen.lowlevel.xu"
32 /* Needed for Python versions earlier than 2.3. */
33 #ifndef PyMODINIT_FUNC
34 #define PyMODINIT_FUNC DL_EXPORT(void)
35 #endif
37 /* NB. The following should be kept in sync with the kernel's evtchn driver. */
38 #define EVTCHN_DEV_NAME "/dev/xen/evtchn"
39 #define EVTCHN_DEV_MAJOR 10
40 #define EVTCHN_DEV_MINOR 201
41 /* /dev/xen/evtchn ioctls: */
42 /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
43 #define EVTCHN_RESET _IO('E', 1)
44 /* EVTCHN_BIND: Bind to teh specified event-channel port. */
45 #define EVTCHN_BIND _IO('E', 2)
46 /* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
47 #define EVTCHN_UNBIND _IO('E', 3)
49 /* Size of a machine page frame. */
50 #define PAGE_SIZE 4096
52 #if defined(__i386__)
53 #define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
54 #define wmb() __asm__ __volatile__ ( "" : : : "memory" )
55 #else
56 #error "Define barriers"
57 #endif
60 /* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
61 * to check for errors. */
62 /*
63 static void set_cloexec(int fd)
64 {
65 int flags = fcntl(fd, F_GETFD, 0);
67 if ( flags < 0 )
68 return;
70 flags |= FD_CLOEXEC;
71 fcntl(fd, F_SETFD, flags);
72 }
73 */
74 /*
75 * *********************** XCS INTERFACE ***********************
76 */
78 #include <arpa/inet.h>
79 #include <xcs_proto.h>
81 static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
82 static int xcs_data_fd = -1; /* data connection to the xcs server. */
83 static u32 xcs_session_id = 0;
85 static int xcs_ctrl_send(xcs_msg_t *msg);
86 static int xcs_ctrl_read(xcs_msg_t *msg);
87 static int xcs_data_send(xcs_msg_t *msg);
88 static int xcs_data_read(xcs_msg_t *msg);
90 static int xcs_connect(char *ip, short port)
91 {
92 struct sockaddr_in addr;
93 int ret, flags;
94 xcs_msg_t msg;
96 if (xcs_data_fd != -1) /* already connected */
97 return 0;
99 xcs_ctrl_fd = socket(AF_INET, SOCK_STREAM, 0);
100 if (xcs_ctrl_fd < 0)
101 {
102 printf("error creating xcs socket!\n");
103 goto fail;
104 }
106 addr.sin_family = AF_INET;
107 addr.sin_port = htons(port);
108 addr.sin_addr.s_addr = inet_addr(ip);
109 memset(&(addr.sin_zero), '\0', 8);
111 ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr,
112 sizeof(struct sockaddr));
113 if (ret < 0)
114 {
115 printf("error connecting to xcs(ctrl)! (%d)\n", errno);
116 goto ctrl_fd_fail;
117 }
119 //set_cloexec(xcs_ctrl_fd);
121 msg.type = XCS_CONNECT_CTRL;
122 msg.u.connect.session_id = xcs_session_id;
123 xcs_ctrl_send(&msg);
124 xcs_ctrl_read(&msg); /* TODO: timeout + error! */
126 if (msg.result != XCS_RSLT_OK)
127 {
128 printf("error connecting xcs control channel!\n");
129 goto ctrl_fd_fail;
130 }
131 xcs_session_id = msg.u.connect.session_id;
133 /* now the data connection. */
134 xcs_data_fd = socket(AF_INET, SOCK_STREAM, 0);
135 if (xcs_data_fd < 0)
136 {
137 printf("error creating xcs data socket!\n");
138 goto ctrl_fd_fail;
139 }
141 addr.sin_family = AF_INET;
142 addr.sin_port = htons(port);
143 addr.sin_addr.s_addr = inet_addr(ip);
144 memset(&(addr.sin_zero), '\0', 8);
146 ret = connect(xcs_data_fd, (struct sockaddr *)&addr,
147 sizeof(struct sockaddr));
148 if (ret < 0)
149 {
150 printf("error connecting to xcs(data)! (%d)\n", errno);
151 goto data_fd_fail;
152 }
154 //set_cloexec(xcs_data_fd);
155 msg.type = XCS_CONNECT_DATA;
156 msg.u.connect.session_id = xcs_session_id;
157 xcs_data_send(&msg);
158 xcs_data_read(&msg); /* TODO: timeout + error! */
160 if (msg.result != XCS_RSLT_OK)
161 {
162 printf("error connecting xcs control channel!\n");
163 goto ctrl_fd_fail;
164 }
166 if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
167 (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
168 {
169 printf("Unable to set non-blocking status on data socket.");
170 goto data_fd_fail;
171 }
173 return 0;
175 data_fd_fail:
176 close(xcs_data_fd);
177 xcs_data_fd = -1;
179 ctrl_fd_fail:
180 close(xcs_ctrl_fd);
181 xcs_ctrl_fd = -1;
183 fail:
184 return -1;
186 }
188 static void xcs_disconnect(void)
189 {
190 close(xcs_data_fd);
191 xcs_data_fd = -1;
192 close(xcs_ctrl_fd);
193 xcs_ctrl_fd = -1;
194 }
196 static int xcs_ctrl_read(xcs_msg_t *msg)
197 {
198 int ret;
200 ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
201 return ret;
202 }
204 static int xcs_ctrl_send(xcs_msg_t *msg)
205 {
206 int ret;
208 ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
209 return ret;
210 }
212 static int xcs_data_read(xcs_msg_t *msg)
213 {
214 int ret;
216 ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
217 return ret;
218 }
220 static int xcs_data_send(xcs_msg_t *msg)
221 {
222 int ret;
224 ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
225 return ret;
226 }
229 typedef struct kme_st {
230 xcs_msg_t msg;
231 struct kme_st *next;
232 } xcs_msg_ent_t;
235 #define XCS_RING_SIZE 64
236 static xcs_msg_ent_t *req_ring[64];
237 static unsigned req_prod = 0;
238 static unsigned req_cons = 0;
240 static xcs_msg_ent_t *rsp_ring[64];
241 static unsigned rsp_prod = 0;
242 static unsigned rsp_cons = 0;
244 #define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
245 #define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE])
246 #define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
247 #define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
248 #define REQ_RING_EMPTY ( req_prod == req_cons )
249 #define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
250 /*
251 * *********************** NOTIFIER ***********************
252 */
254 typedef struct {
255 PyObject_HEAD;
256 int evtchn_fd;
257 } xu_notifier_object;
259 static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
260 {
261 xcs_msg_ent_t *ent;
262 int ret;
264 if ( !PyArg_ParseTuple(args, "") )
265 return NULL;
267 while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
268 {
269 ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
270 ret = xcs_data_read(&ent->msg);
272 if (ret == -1)
273 {
274 free(ent);
275 if ( errno == EINTR )
276 continue;
277 if ( errno == EAGAIN )
278 break;
279 return PyErr_SetFromErrno(PyExc_IOError);
280 }
282 switch (ent->msg.type)
283 {
284 case XCS_REQUEST:
285 REQ_RING_ENT(req_prod) = ent;
286 req_prod++;
287 continue;
289 case XCS_RESPONSE:
290 RSP_RING_ENT(rsp_prod) = ent;
291 rsp_prod++;
292 continue;
294 case XCS_VIRQ:
295 ret = ent->msg.u.control.local_port;
296 free(ent);
297 return PyInt_FromLong(ret);
299 default:
300 /*printf("Throwing away xcs msg type: %u\n", ent->msg.type);*/
301 free(ent);
302 }
303 }
305 if (!REQ_RING_EMPTY)
306 {
307 return PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port);
308 }
310 if (!RSP_RING_EMPTY)
311 {
312 return PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port);
313 }
315 Py_INCREF(Py_None);
316 return Py_None;
317 }
319 /* this is now a NOOP */
320 static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
321 {
322 Py_INCREF(Py_None);
323 return Py_None;
324 }
326 /* this is now a NOOP */
327 static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
328 {
329 Py_INCREF(Py_None);
330 return Py_None;
331 }
333 static PyObject *xu_notifier_bind_virq(PyObject *self,
334 PyObject *args, PyObject *kwds)
335 {
336 int virq;
337 xcs_msg_t kmsg;
339 static char *kwd_list[] = { "virq", NULL };
340 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
341 return NULL;
343 kmsg.type = XCS_VIRQ_BIND;
344 kmsg.u.virq.virq = virq;
345 xcs_ctrl_send(&kmsg);
346 xcs_ctrl_read(&kmsg);
348 if ( kmsg.result != XCS_RSLT_OK )
349 {
350 Py_INCREF(Py_None);
351 return Py_None;
352 }
354 return PyInt_FromLong(kmsg.u.virq.port);
355 }
357 static PyObject *xu_notifier_virq_send(PyObject *self,
358 PyObject *args, PyObject *kwds)
359 {
360 int port;
361 xcs_msg_t kmsg;
363 static char *kwd_list[] = { "port", NULL };
364 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
365 return NULL;
367 kmsg.type = XCS_VIRQ;
368 kmsg.u.control.local_port = port;
369 xcs_ctrl_send(&kmsg);
370 xcs_ctrl_read(&kmsg);
372 if ( kmsg.result != XCS_RSLT_OK )
373 {
374 Py_INCREF(Py_None);
375 return Py_None;
376 }
378 return PyInt_FromLong(kmsg.u.virq.port);
379 }
381 /* this is now a NOOP */
382 static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
383 {
384 Py_INCREF(Py_None);
385 return Py_None;
386 }
388 static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
389 {
390 return PyInt_FromLong(xcs_data_fd);
391 }
393 static PyMethodDef xu_notifier_methods[] = {
394 { "read",
395 (PyCFunction)xu_notifier_read,
396 METH_VARARGS,
397 "Read a @port with pending notifications.\n" },
399 { "unmask",
400 (PyCFunction)xu_notifier_unmask,
401 METH_VARARGS,
402 "Unmask notifications for a @port.\n" },
404 { "bind",
405 (PyCFunction)xu_notifier_bind,
406 METH_VARARGS,
407 "Get notifications for a @port.\n" },
409 { "unbind",
410 (PyCFunction)xu_notifier_unbind,
411 METH_VARARGS,
412 "No longer get notifications for a @port.\n" },
414 { "bind_virq",
415 (PyCFunction)xu_notifier_bind_virq,
416 METH_VARARGS | METH_KEYWORDS,
417 "Get notifications for a virq.\n"
418 " virq [int]: VIRQ to bind.\n\n" },
420 { "virq_send",
421 (PyCFunction)xu_notifier_virq_send,
422 METH_VARARGS | METH_KEYWORDS,
423 "Fire a virq notification.\n"
424 " port [int]: port that VIRQ is bound to.\n\n" },
426 { "fileno",
427 (PyCFunction)xu_notifier_fileno,
428 METH_VARARGS,
429 "Return the file descriptor for the notification channel.\n" },
431 { NULL, NULL, 0, NULL }
432 };
434 staticforward PyTypeObject xu_notifier_type;
436 /* connect to xcs if we aren't already, and return a dummy object. */
437 static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
438 {
439 xu_notifier_object *xun;
440 int i;
442 if ( !PyArg_ParseTuple(args, "") )
443 return NULL;
445 xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
447 for (i = 0; i < XCS_RING_SIZE; i++)
448 REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
450 (void)xcs_connect("127.0.0.1", XCS_TCP_PORT);
453 return (PyObject *)xun;
454 }
456 static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
457 {
458 return Py_FindMethod(xu_notifier_methods, obj, name);
459 }
461 static void xu_notifier_dealloc(PyObject *self)
462 {
463 xcs_disconnect();
464 PyObject_Del(self);
465 }
467 static PyTypeObject xu_notifier_type = {
468 PyObject_HEAD_INIT(&PyType_Type)
469 0,
470 "notifier",
471 sizeof(xu_notifier_object),
472 0,
473 xu_notifier_dealloc, /* tp_dealloc */
474 NULL, /* tp_print */
475 xu_notifier_getattr, /* tp_getattr */
476 NULL, /* tp_setattr */
477 NULL, /* tp_compare */
478 NULL, /* tp_repr */
479 NULL, /* tp_as_number */
480 NULL, /* tp_as_sequence */
481 NULL, /* tp_as_mapping */
482 NULL /* tp_hash */
483 };
487 /*
488 * *********************** MESSAGE ***********************
489 */
491 #define TYPE(_x,_y) (((_x)<<8)|(_y))
492 #define P2C(_struct, _field, _ctype) \
493 do { \
494 PyObject *obj; \
495 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
496 { \
497 if ( PyInt_Check(obj) ) \
498 { \
499 ((_struct *)&xum->msg.msg[0])->_field = \
500 (_ctype)PyInt_AsLong(obj); \
501 dict_items_parsed++; \
502 } \
503 else if ( PyLong_Check(obj) ) \
504 { \
505 ((_struct *)&xum->msg.msg[0])->_field = \
506 (_ctype)PyLong_AsUnsignedLongLong(obj); \
507 dict_items_parsed++; \
508 } \
509 } \
510 xum->msg.length = sizeof(_struct); \
511 } while ( 0 )
512 #define C2P(_struct, _field, _pytype, _ctype) \
513 do { \
514 PyObject *obj = Py ## _pytype ## _From ## _ctype \
515 (((_struct *)&xum->msg.msg[0])->_field); \
516 if ( dict == NULL ) dict = PyDict_New(); \
517 PyDict_SetItemString(dict, #_field, obj); \
518 } while ( 0 )
520 #define PSTR2CHAR(_struct, _field) \
521 do { \
522 PyObject *obj; \
523 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
524 { \
525 if ( PyString_Check(obj) ) \
526 { \
527 char *buffer = PyString_AsString(obj); \
528 \
529 strcpy(((_struct *)&xum->msg.msg[0])->_field, \
530 buffer); \
531 /* Should complain about length - think later */ \
532 dict_items_parsed++; \
533 } \
534 } \
535 xum->msg.length = sizeof(_struct); \
536 } while ( 0 )
538 typedef struct {
539 PyObject_HEAD;
540 control_msg_t msg;
541 } xu_message_object;
543 static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
544 {
545 xu_message_object *xum = (xu_message_object *)self;
546 char *str;
547 int len;
549 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
550 return NULL;
552 if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
553 {
554 PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
555 return NULL;
556 }
558 memcpy(&xum->msg.msg[xum->msg.length], str, len);
559 xum->msg.length += len;
561 Py_INCREF(Py_None);
562 return Py_None;
563 }
565 static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
566 {
567 xu_message_object *xum = (xu_message_object *)self;
568 PyObject *payload;
569 int dict_items_parsed = 0;
571 if ( !PyArg_ParseTuple(args, "O", &payload) )
572 return NULL;
574 if ( !PyDict_Check(payload) )
575 {
576 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
577 return NULL;
578 }
580 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
581 {
582 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
583 P2C(blkif_fe_driver_status_t, max_handle, u32);
584 break;
585 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
586 P2C(netif_fe_driver_status_t, max_handle, u32);
587 break;
588 }
590 if ( dict_items_parsed != PyDict_Size(payload) )
591 {
592 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
593 return NULL;
594 }
596 Py_INCREF(Py_None);
597 return Py_None;
598 }
600 static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
601 {
602 xu_message_object *xum = (xu_message_object *)self;
603 PyObject *dict = NULL;
605 if ( !PyArg_ParseTuple(args, "") )
606 return NULL;
608 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
609 {
610 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
611 C2P(blkif_fe_interface_status_t, handle, Int, Long);
612 C2P(blkif_fe_interface_status_t, status, Int, Long);
613 C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
614 return dict;
615 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
616 C2P(blkif_fe_driver_status_t, status, Int, Long);
617 return dict;
618 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
619 C2P(blkif_fe_interface_connect_t, handle, Int, Long);
620 C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
621 return dict;
622 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
623 C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
624 return dict;
625 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
626 C2P(blkif_be_create_t, domid, Int, Long);
627 C2P(blkif_be_create_t, blkif_handle, Int, Long);
628 C2P(blkif_be_create_t, status, Int, Long);
629 return dict;
630 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
631 C2P(blkif_be_destroy_t, domid, Int, Long);
632 C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
633 C2P(blkif_be_destroy_t, status, Int, Long);
634 return dict;
635 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
636 C2P(blkif_be_connect_t, domid, Int, Long);
637 C2P(blkif_be_connect_t, blkif_handle, Int, Long);
638 C2P(blkif_be_connect_t, shmem_frame, Int, Long);
639 C2P(blkif_be_connect_t, evtchn, Int, Long);
640 C2P(blkif_be_connect_t, status, Int, Long);
641 return dict;
642 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
643 C2P(blkif_be_disconnect_t, domid, Int, Long);
644 C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
645 C2P(blkif_be_disconnect_t, status, Int, Long);
646 return dict;
647 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
648 C2P(blkif_be_vbd_create_t, domid, Int, Long);
649 C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
650 C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
651 C2P(blkif_be_vbd_create_t, readonly, Int, Long);
652 C2P(blkif_be_vbd_create_t, status, Int, Long);
653 return dict;
654 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
655 C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
656 C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
657 C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
658 C2P(blkif_be_vbd_destroy_t, status, Int, Long);
659 return dict;
660 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
661 C2P(blkif_be_vbd_grow_t, domid, Int, Long);
662 C2P(blkif_be_vbd_grow_t, blkif_handle, Int, Long);
663 C2P(blkif_be_vbd_grow_t, vdevice, Int, Long);
664 C2P(blkif_be_vbd_grow_t, extent.sector_start,
665 Long, UnsignedLongLong);
666 C2P(blkif_be_vbd_grow_t, extent.sector_length,
667 Long, UnsignedLongLong);
668 C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
669 C2P(blkif_be_vbd_grow_t, status, Int, Long);
670 return dict;
671 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
672 C2P(blkif_be_vbd_shrink_t, domid, Int, Long);
673 C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
674 C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long);
675 C2P(blkif_be_vbd_shrink_t, status, Int, Long);
676 return dict;
677 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
678 C2P(blkif_be_driver_status_t, status, Int, Long);
679 return dict;
680 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
681 C2P(netif_fe_interface_status_t, handle, Int, Long);
682 C2P(netif_fe_interface_status_t, status, Int, Long);
683 C2P(netif_fe_interface_status_t, evtchn, Int, Long);
684 C2P(netif_fe_interface_status_t, mac[0], Int, Long);
685 C2P(netif_fe_interface_status_t, mac[1], Int, Long);
686 C2P(netif_fe_interface_status_t, mac[2], Int, Long);
687 C2P(netif_fe_interface_status_t, mac[3], Int, Long);
688 C2P(netif_fe_interface_status_t, mac[4], Int, Long);
689 C2P(netif_fe_interface_status_t, mac[5], Int, Long);
690 return dict;
691 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
692 C2P(netif_fe_driver_status_t, status, Int, Long);
693 C2P(netif_fe_driver_status_t, max_handle, Int, Long);
694 return dict;
695 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
696 C2P(netif_fe_interface_connect_t, handle, Int, Long);
697 C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
698 C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
699 return dict;
700 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
701 C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
702 return dict;
703 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
704 C2P(netif_be_create_t, domid, Int, Long);
705 C2P(netif_be_create_t, netif_handle, Int, Long);
706 C2P(netif_be_create_t, status, Int, Long);
707 return dict;
708 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
709 C2P(netif_be_destroy_t, domid, Int, Long);
710 C2P(netif_be_destroy_t, netif_handle, Int, Long);
711 C2P(netif_be_destroy_t, status, Int, Long);
712 return dict;
713 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
714 C2P(netif_be_connect_t, domid, Int, Long);
715 C2P(netif_be_connect_t, netif_handle, Int, Long);
716 C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
717 C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
718 C2P(netif_be_connect_t, evtchn, Int, Long);
719 C2P(netif_be_connect_t, status, Int, Long);
720 return dict;
721 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
722 C2P(netif_be_disconnect_t, domid, Int, Long);
723 C2P(netif_be_disconnect_t, netif_handle, Int, Long);
724 C2P(netif_be_disconnect_t, status, Int, Long);
725 return dict;
726 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
727 C2P(netif_be_driver_status_t, status, Int, Long);
728 return dict;
729 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
730 C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
731 C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
732 C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
733 C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
734 C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
735 return dict;
736 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
737 C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
738 return dict;
739 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
740 C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
741 return dict;
742 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
743 return dict;
744 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
745 C2P(usbif_be_create_t, domid, Int, Long);
746 C2P(usbif_be_create_t, status, Int, Long);
747 return dict;
748 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
749 C2P(usbif_be_destroy_t, domid, Int, Long);
750 C2P(usbif_be_destroy_t, status, Int, Long);
751 return dict;
752 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
753 C2P(usbif_be_connect_t, domid, Int, Long);
754 C2P(usbif_be_connect_t, shmem_frame, Int, Long);
755 C2P(usbif_be_connect_t, evtchn, Int, Long);
756 C2P(usbif_be_connect_t, bandwidth, Int, Long);
757 C2P(usbif_be_connect_t, status, Int, Long);
758 return dict;
759 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
760 C2P(usbif_be_disconnect_t, domid, Int, Long);
761 C2P(usbif_be_disconnect_t, status, Int, Long);
762 return dict;
763 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
764 C2P(usbif_be_driver_status_changed_t, status, Int, Long);
765 return dict;
766 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
767 C2P(usbif_be_claim_port_t, domid, Int, Long);
768 C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
769 C2P(usbif_be_claim_port_t, status, Int, Long);
770 C2P(usbif_be_claim_port_t, path, String, String);
771 return dict;
772 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
773 C2P(usbif_be_release_port_t, path, String, String);
774 return dict;
775 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
776 C2P(mem_request_t, target, Int, Long);
777 C2P(mem_request_t, status, Int, Long);
778 return dict;
779 }
781 return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
782 }
784 static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
785 {
786 xu_message_object *xum = (xu_message_object *)self;
788 if ( !PyArg_ParseTuple(args, "") )
789 return NULL;
791 return Py_BuildValue("{s:i,s:i,s:i}",
792 "type", xum->msg.type,
793 "subtype", xum->msg.subtype,
794 "id", xum->msg.id);
795 }
797 static PyMethodDef xu_message_methods[] = {
798 { "append_payload",
799 (PyCFunction)xu_message_append_payload,
800 METH_VARARGS,
801 "Append @str to the message payload.\n" },
803 { "set_response_fields",
804 (PyCFunction)xu_message_set_response_fields,
805 METH_VARARGS,
806 "Fill in the response fields in a message that was passed to us.\n" },
808 { "get_payload",
809 (PyCFunction)xu_message_get_payload,
810 METH_VARARGS,
811 "Return the message payload in string form.\n" },
813 { "get_header",
814 (PyCFunction)xu_message_get_header,
815 METH_VARARGS,
816 "Returns a dictionary of values for @type, @subtype, and @id.\n" },
818 { NULL, NULL, 0, NULL }
819 };
821 staticforward PyTypeObject xu_message_type;
823 static PyObject *xu_message_new(PyObject *self, PyObject *args)
824 {
825 xu_message_object *xum;
826 int type, subtype, id, dict_items_parsed = 0;
827 PyObject *payload = NULL;
829 if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
830 return NULL;
832 xum = PyObject_New(xu_message_object, &xu_message_type);
834 xum->msg.type = type;
835 xum->msg.subtype = subtype;
836 xum->msg.id = id;
837 xum->msg.length = 0;
839 if ( payload == NULL )
840 return (PyObject *)xum;
842 if ( !PyDict_Check(payload) )
843 {
844 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
845 PyObject_Del((PyObject *)xum);
846 return NULL;
847 }
849 switch ( TYPE(type, subtype) )
850 {
851 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
852 P2C(blkif_fe_interface_status_t, handle, u32);
853 P2C(blkif_fe_interface_status_t, status, u32);
854 P2C(blkif_fe_interface_status_t, evtchn, u16);
855 P2C(blkif_fe_interface_status_t, domid, u16);
856 break;
857 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
858 P2C(blkif_be_create_t, domid, u32);
859 P2C(blkif_be_create_t, blkif_handle, u32);
860 break;
861 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
862 P2C(blkif_be_destroy_t, domid, u32);
863 P2C(blkif_be_destroy_t, blkif_handle, u32);
864 break;
865 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
866 P2C(blkif_be_connect_t, domid, u32);
867 P2C(blkif_be_connect_t, blkif_handle, u32);
868 P2C(blkif_be_connect_t, shmem_frame, memory_t);
869 P2C(blkif_be_connect_t, evtchn, u16);
870 break;
871 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
872 P2C(blkif_be_disconnect_t, domid, u32);
873 P2C(blkif_be_disconnect_t, blkif_handle, u32);
874 break;
875 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
876 P2C(blkif_be_vbd_create_t, domid, u32);
877 P2C(blkif_be_vbd_create_t, blkif_handle, u32);
878 P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
879 P2C(blkif_be_vbd_create_t, readonly, u16);
880 break;
881 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
882 P2C(blkif_be_vbd_destroy_t, domid, u32);
883 P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
884 P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
885 break;
886 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
887 P2C(blkif_be_vbd_grow_t, domid, u32);
888 P2C(blkif_be_vbd_grow_t, blkif_handle, u32);
889 P2C(blkif_be_vbd_grow_t, vdevice, blkif_vdev_t);
890 P2C(blkif_be_vbd_grow_t, extent.sector_start, blkif_sector_t);
891 P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
892 P2C(blkif_be_vbd_grow_t, extent.device, blkif_pdev_t);
893 break;
894 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
895 P2C(blkif_be_vbd_shrink_t, domid, u32);
896 P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
897 P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t);
898 break;
899 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
900 P2C(netif_fe_interface_status_t, handle, u32);
901 P2C(netif_fe_interface_status_t, status, u32);
902 P2C(netif_fe_interface_status_t, evtchn, u16);
903 P2C(netif_fe_interface_status_t, domid, u16);
904 P2C(netif_fe_interface_status_t, mac[0], u8);
905 P2C(netif_fe_interface_status_t, mac[1], u8);
906 P2C(netif_fe_interface_status_t, mac[2], u8);
907 P2C(netif_fe_interface_status_t, mac[3], u8);
908 P2C(netif_fe_interface_status_t, mac[4], u8);
909 P2C(netif_fe_interface_status_t, mac[5], u8);
910 break;
911 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
912 P2C(netif_be_create_t, domid, u32);
913 P2C(netif_be_create_t, netif_handle, u32);
914 P2C(netif_be_create_t, mac[0], u8);
915 P2C(netif_be_create_t, mac[1], u8);
916 P2C(netif_be_create_t, mac[2], u8);
917 P2C(netif_be_create_t, mac[3], u8);
918 P2C(netif_be_create_t, mac[4], u8);
919 P2C(netif_be_create_t, mac[5], u8);
920 break;
921 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
922 P2C(netif_be_destroy_t, domid, u32);
923 P2C(netif_be_destroy_t, netif_handle, u32);
924 break;
925 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
926 P2C(netif_be_connect_t, domid, u32);
927 P2C(netif_be_connect_t, netif_handle, u32);
928 P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
929 P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
930 P2C(netif_be_connect_t, evtchn, u16);
931 break;
932 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
933 P2C(netif_be_disconnect_t, domid, u32);
934 P2C(netif_be_disconnect_t, netif_handle, u32);
935 break;
936 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
937 P2C(netif_fe_driver_status_t, status, u32);
938 P2C(netif_fe_driver_status_t, max_handle, u32);
939 break;
940 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
941 P2C(mem_request_t, target, u32);
942 P2C(mem_request_t, status, u32);
943 break;
944 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
945 P2C(usbif_fe_interface_status_changed_t, status, u32);
946 P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
947 P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
948 P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
949 P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
950 break;
951 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
952 P2C(usbif_fe_driver_status_changed_t, status, u32);
953 break;
954 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
955 P2C(usbif_fe_interface_connect_t, shmem_frame, memory_t);
956 break;
957 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
958 break;
959 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
960 P2C(usbif_be_create_t, domid, domid_t);
961 P2C(usbif_be_create_t, status, u32);
962 break;
963 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
964 P2C(usbif_be_destroy_t, domid, domid_t);
965 P2C(usbif_be_destroy_t, status, u32);
966 break;
967 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
968 P2C(usbif_be_connect_t, domid, domid_t);
969 P2C(usbif_be_connect_t, shmem_frame, memory_t);
970 P2C(usbif_be_connect_t, evtchn, u32);
971 P2C(usbif_be_connect_t, bandwidth, u32);
972 P2C(usbif_be_connect_t, status, u32);
973 break;
974 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
975 P2C(usbif_be_disconnect_t, domid, domid_t);
976 P2C(usbif_be_disconnect_t, status, u32);
977 break;
978 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
979 P2C(usbif_be_driver_status_changed_t, status, u32);
980 break;
981 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
982 P2C(usbif_be_claim_port_t, domid, domid_t);
983 P2C(usbif_be_claim_port_t, usbif_port, u32);
984 P2C(usbif_be_claim_port_t, status, u32);
985 PSTR2CHAR(usbif_be_claim_port_t, path);
986 printf("dict items parsed = %d", dict_items_parsed);
987 break;
988 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
989 PSTR2CHAR(usbif_be_release_port_t, path);
990 break;
991 }
993 if ( dict_items_parsed != PyDict_Size(payload) )
994 {
995 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
996 PyObject_Del((PyObject *)xum);
997 return NULL;
998 }
1000 return (PyObject *)xum;
1003 static PyObject *xu_message_getattr(PyObject *obj, char *name)
1005 xu_message_object *xum;
1006 if ( strcmp(name, "MAX_PAYLOAD") == 0 )
1007 return PyInt_FromLong(sizeof(xum->msg.msg));
1008 return Py_FindMethod(xu_message_methods, obj, name);
1011 static void xu_message_dealloc(PyObject *self)
1013 PyObject_Del(self);
1016 static PyTypeObject xu_message_type = {
1017 PyObject_HEAD_INIT(&PyType_Type)
1018 0,
1019 "message",
1020 sizeof(xu_message_object),
1021 0,
1022 xu_message_dealloc, /* tp_dealloc */
1023 NULL, /* tp_print */
1024 xu_message_getattr, /* tp_getattr */
1025 NULL, /* tp_setattr */
1026 NULL, /* tp_compare */
1027 NULL, /* tp_repr */
1028 NULL, /* tp_as_number */
1029 NULL, /* tp_as_sequence */
1030 NULL, /* tp_as_mapping */
1031 NULL /* tp_hash */
1032 };
1036 /*
1037 * *********************** PORT ***********************
1038 */
1040 typedef struct xu_port_object {
1041 PyObject_HEAD;
1042 int xc_handle;
1043 int connected;
1044 u32 remote_dom;
1045 int local_port, remote_port;
1046 struct xu_port_object *fix_next;
1047 } xu_port_object;
1049 static PyObject *port_error;
1051 /* now a NOOP */
1052 static PyObject *xu_port_notify(PyObject *self, PyObject *args)
1054 Py_INCREF(Py_None);
1055 return Py_None;
1058 static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
1060 xu_port_object *xup = (xu_port_object *)self;
1061 xu_message_object *xum;
1062 control_msg_t *cmsg;
1063 unsigned i;
1064 xcs_msg_ent_t *ent = NULL;
1066 for ( i = req_cons; (i != req_prod); i++ ) {
1067 ent = REQ_RING_ENT(i);
1068 if (ent == NULL)
1069 continue;
1070 if (ent->msg.u.control.remote_dom == xup->remote_dom)
1071 break;
1074 if ((ent == NULL) ||
1075 (ent->msg.u.control.remote_dom != xup->remote_dom))
1076 goto none;
1078 cmsg = &ent->msg.u.control.msg;
1079 xum = PyObject_New(xu_message_object, &xu_message_type);
1080 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
1081 if ( xum->msg.length > sizeof(xum->msg.msg) )
1082 xum->msg.length = sizeof(xum->msg.msg);
1083 free(ent);
1085 /* remove the entry from the ring and advance the consumer if possible */
1086 REQ_RING_ENT(i) = NULL;
1087 while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
1088 req_cons++;
1090 return (PyObject *)xum;
1092 none:
1093 Py_INCREF(Py_None);
1094 return Py_None;
1098 static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
1100 xu_port_object *xup = (xu_port_object *)self;
1101 xu_message_object *xum;
1102 xcs_msg_t kmsg;
1104 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
1105 return NULL;
1107 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
1109 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
1110 return NULL;
1113 kmsg.type = XCS_REQUEST;
1114 kmsg.u.control.remote_dom = xup->remote_dom;
1115 memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
1116 xcs_data_send(&kmsg);
1118 Py_INCREF(Py_None);
1119 return Py_None;
1122 static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
1124 xu_port_object *xup = (xu_port_object *)self;
1125 xu_message_object *xum;
1126 control_msg_t *cmsg;
1127 unsigned i;
1128 xcs_msg_ent_t *ent = NULL;
1130 for ( i = rsp_cons; (i != rsp_prod); i++ ) {
1131 ent = RSP_RING_ENT(i);
1132 if (ent == NULL)
1133 continue;
1134 if (ent->msg.u.control.remote_dom == xup->remote_dom)
1135 break;
1138 if ((ent == NULL) ||
1139 (ent->msg.u.control.remote_dom != xup->remote_dom))
1140 goto none;
1142 cmsg = &ent->msg.u.control.msg;
1143 xum = PyObject_New(xu_message_object, &xu_message_type);
1144 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
1145 if ( xum->msg.length > sizeof(xum->msg.msg) )
1146 xum->msg.length = sizeof(xum->msg.msg);
1147 free(ent);
1149 /* remove the entry from the ring and advance the consumer if possible */
1150 RSP_RING_ENT(i) = NULL;
1151 while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
1152 rsp_cons++;
1154 return (PyObject *)xum;
1156 none:
1157 Py_INCREF(Py_None);
1158 return Py_None;
1162 static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
1164 xu_port_object *xup = (xu_port_object *)self;
1165 xu_message_object *xum;
1166 xcs_msg_t kmsg;
1168 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
1169 return NULL;
1171 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
1173 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
1174 return NULL;
1177 kmsg.type = XCS_RESPONSE;
1178 kmsg.u.control.remote_dom = xup->remote_dom;
1179 memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
1180 xcs_data_send(&kmsg);
1182 Py_INCREF(Py_None);
1183 return Py_None;
1186 static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
1188 xu_port_object *xup = (xu_port_object *)self;
1189 xcs_msg_ent_t *ent;
1190 int found = 0;
1191 unsigned i;
1193 if ( !PyArg_ParseTuple(args, "") )
1194 return NULL;
1196 for ( i = req_cons; (i != req_prod); i++ ) {
1197 ent = REQ_RING_ENT(i);
1198 if (ent == NULL)
1199 continue;
1200 if (ent->msg.u.control.remote_dom == xup->remote_dom) {
1201 found = 1;
1202 break;
1206 return PyInt_FromLong(found);
1209 static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
1211 if ( !PyArg_ParseTuple(args, "") )
1212 return NULL;
1214 return PyInt_FromLong(1);
1217 static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
1219 xu_port_object *xup = (xu_port_object *)self;
1220 xcs_msg_ent_t *ent;
1221 int found = 0;
1222 unsigned i;
1224 if ( !PyArg_ParseTuple(args, "") )
1225 return NULL;
1227 for ( i = rsp_cons; (i != rsp_prod); i++ ) {
1228 ent = RSP_RING_ENT(i);
1229 if (ent == NULL)
1230 continue;
1231 if (ent->msg.u.control.remote_dom == xup->remote_dom) {
1232 found = 1;
1233 break;
1237 return PyInt_FromLong(found);
1240 static PyObject *xu_port_space_to_write_response(
1241 PyObject *self, PyObject *args)
1243 if ( !PyArg_ParseTuple(args, "") )
1244 return NULL;
1246 return PyInt_FromLong(1);
1249 /* NOOP */
1250 static PyObject *xu_port_connect(PyObject *self, PyObject *args)
1252 Py_INCREF(Py_None);
1253 return Py_None;
1256 /* NOOP */
1257 static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
1259 Py_INCREF(Py_None);
1260 return Py_None;
1263 static PyObject *xu_port_register(PyObject *self, PyObject *args,
1264 PyObject *kwds)
1266 int type;
1267 xcs_msg_t msg;
1268 xu_port_object *xup = (xu_port_object *)self;
1269 static char *kwd_list[] = { "type", NULL };
1271 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
1272 &type) )
1273 return NULL;
1275 msg.type = XCS_MSG_BIND;
1276 msg.u.bind.port = xup->local_port;
1277 msg.u.bind.type = type;
1278 xcs_ctrl_send(&msg);
1279 xcs_ctrl_read(&msg);
1281 if (msg.result != XCS_RSLT_OK)
1283 return PyInt_FromLong(0);
1286 return PyInt_FromLong(1);
1289 static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
1290 PyObject *kwds)
1292 int type;
1293 xcs_msg_t msg;
1294 xu_port_object *xup = (xu_port_object *)self;
1295 static char *kwd_list[] = { "type", NULL };
1297 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
1298 &type) )
1299 return NULL;
1301 msg.type = XCS_MSG_UNBIND;
1302 msg.u.bind.port = xup->local_port;
1303 msg.u.bind.type = type;
1304 xcs_ctrl_send(&msg);
1305 xcs_ctrl_read(&msg);
1307 if (msg.result != XCS_RSLT_OK)
1309 return PyInt_FromLong(0);
1312 return PyInt_FromLong(1);
1315 static PyMethodDef xu_port_methods[] = {
1316 { "notify",
1317 (PyCFunction)xu_port_notify,
1318 METH_VARARGS,
1319 "Send a notification to the remote end.\n" },
1321 { "read_request",
1322 (PyCFunction)xu_port_read_request,
1323 METH_VARARGS,
1324 "Read a request message from the control interface.\n" },
1326 { "write_request",
1327 (PyCFunction)xu_port_write_request,
1328 METH_VARARGS,
1329 "Write a request message to the control interface.\n" },
1331 { "read_response",
1332 (PyCFunction)xu_port_read_response,
1333 METH_VARARGS,
1334 "Read a response message from the control interface.\n" },
1336 { "write_response",
1337 (PyCFunction)xu_port_write_response,
1338 METH_VARARGS,
1339 "Write a response message to the control interface.\n" },
1341 { "request_to_read",
1342 (PyCFunction)xu_port_request_to_read,
1343 METH_VARARGS,
1344 "Returns TRUE if there is a request message to read.\n" },
1346 { "space_to_write_request",
1347 (PyCFunction)xu_port_space_to_write_request,
1348 METH_VARARGS,
1349 "Returns TRUE if there is space to write a request message.\n" },
1351 { "response_to_read",
1352 (PyCFunction)xu_port_response_to_read,
1353 METH_VARARGS,
1354 "Returns TRUE if there is a response message to read.\n" },
1356 { "space_to_write_response",
1357 (PyCFunction)xu_port_space_to_write_response,
1358 METH_VARARGS,
1359 "Returns TRUE if there is space to write a response message.\n" },
1361 { "register",
1362 (PyCFunction)xu_port_register,
1363 METH_VARARGS | METH_KEYWORDS,
1364 "Register to receive a type of message on this channel.\n" },
1366 { "deregister",
1367 (PyCFunction)xu_port_deregister,
1368 METH_VARARGS | METH_KEYWORDS,
1369 "Stop receiving a type of message on this port.\n" },
1371 { "connect",
1372 (PyCFunction)xu_port_connect,
1373 METH_VARARGS,
1374 "Synchronously connect to remote domain.\n" },
1376 { "disconnect",
1377 (PyCFunction)xu_port_disconnect,
1378 METH_VARARGS,
1379 "Synchronously disconnect from remote domain.\n" },
1381 { NULL, NULL, 0, NULL }
1382 };
1384 staticforward PyTypeObject xu_port_type;
1386 static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
1388 xu_port_object *xup;
1389 u32 dom;
1390 int port1 = 0, port2 = 0;
1391 xcs_msg_t kmsg;
1393 static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
1395 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
1396 &dom, &port1, &port2) )
1397 return NULL;
1399 xup = PyObject_New(xu_port_object, &xu_port_type);
1401 xup->connected = 0;
1402 xup->remote_dom = dom;
1404 kmsg.type = XCS_CIF_NEW_CC;
1405 kmsg.u.interface.dom = xup->remote_dom;
1406 kmsg.u.interface.local_port = port1;
1407 kmsg.u.interface.remote_port = port2;
1408 xcs_ctrl_send(&kmsg);
1409 xcs_ctrl_read(&kmsg);
1411 if ( kmsg.result != XCS_RSLT_OK )
1412 goto fail1;
1414 xup->local_port = kmsg.u.interface.local_port;
1415 xup->remote_port = kmsg.u.interface.remote_port;
1416 xup->connected = 1;
1418 return (PyObject *)xup;
1420 fail1:
1421 PyObject_Del((PyObject *)xup);
1422 return NULL;
1425 static PyObject *xu_port_getattr(PyObject *obj, char *name)
1427 xu_port_object *xup = (xu_port_object *)obj;
1428 if ( strcmp(name, "local_port") == 0 )
1429 return PyInt_FromLong(xup->local_port);
1430 if ( strcmp(name, "remote_port") == 0 )
1431 return PyInt_FromLong(xup->remote_port);
1432 if ( strcmp(name, "remote_dom") == 0 )
1433 return PyInt_FromLong(xup->remote_dom);
1434 return Py_FindMethod(xu_port_methods, obj, name);
1437 static void xu_port_dealloc(PyObject *self)
1440 xu_port_object *xup = (xu_port_object *)self;
1441 xcs_msg_t kmsg;
1443 if ( xup->remote_dom != 0 )
1445 kmsg.type = XCS_CIF_FREE_CC;
1446 kmsg.u.interface.dom = xup->remote_dom;
1447 kmsg.u.interface.local_port = xup->local_port;
1448 kmsg.u.interface.remote_port = xup->remote_port;
1449 xcs_ctrl_send(&kmsg);
1450 xcs_ctrl_read(&kmsg);
1453 PyObject_Del(self);
1456 static PyTypeObject xu_port_type = {
1457 PyObject_HEAD_INIT(&PyType_Type)
1458 0,
1459 "port",
1460 sizeof(xu_port_object),
1461 0,
1462 xu_port_dealloc, /* tp_dealloc */
1463 NULL, /* tp_print */
1464 xu_port_getattr, /* tp_getattr */
1465 NULL, /* tp_setattr */
1466 NULL, /* tp_compare */
1467 NULL, /* tp_repr */
1468 NULL, /* tp_as_number */
1469 NULL, /* tp_as_sequence */
1470 NULL, /* tp_as_mapping */
1471 NULL /* tp_hash */
1472 };
1476 /*
1477 * *********************** BUFFER ***********************
1478 */
1480 #define BUFSZ 65536
1481 #define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
1482 typedef unsigned int BUF_IDX;
1484 typedef struct {
1485 PyObject_HEAD;
1486 char *buf;
1487 unsigned int prod, cons;
1488 } xu_buffer_object;
1490 static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
1492 PyObject *str1, *str2;
1493 int len1, len2, c = MASK_BUF_IDX(xub->cons);
1495 len1 = xub->prod - xub->cons;
1496 if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
1497 len1 = BUFSZ - c;
1498 if ( len1 > max ) /* clip to specified maximum */
1499 len1 = max;
1500 if ( len1 < 0 ) /* sanity */
1501 len1 = 0;
1503 if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
1504 return NULL;
1506 if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
1508 len2 = max - len1;
1509 if ( len2 > MASK_BUF_IDX(xub->prod) )
1510 len2 = MASK_BUF_IDX(xub->prod);
1511 if ( len2 > 0 )
1513 str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
1514 if ( str2 == NULL )
1515 return NULL;
1516 PyString_ConcatAndDel(&str1, str2);
1517 if ( str1 == NULL )
1518 return NULL;
1522 return str1;
1525 static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
1527 xu_buffer_object *xub = (xu_buffer_object *)self;
1528 int max = 1024;
1530 if ( !PyArg_ParseTuple(args, "|i", &max) )
1531 return NULL;
1533 return __xu_buffer_peek(xub, max);
1536 static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
1538 xu_buffer_object *xub = (xu_buffer_object *)self;
1539 PyObject *str;
1540 int max = 1024;
1542 if ( !PyArg_ParseTuple(args, "|i", &max) )
1543 return NULL;
1545 if ( (str = __xu_buffer_peek(xub, max)) != NULL )
1546 xub->cons += PyString_Size(str);
1548 return str;
1551 static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
1553 xu_buffer_object *xub = (xu_buffer_object *)self;
1554 int max, len;
1556 if ( !PyArg_ParseTuple(args, "i", &max) )
1557 return NULL;
1559 len = xub->prod - xub->cons;
1560 if ( len > max )
1561 len = max;
1562 if ( len < 0 )
1563 len = 0;
1565 xub->cons += len;
1567 return PyInt_FromLong(len);
1570 static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
1572 xu_buffer_object *xub = (xu_buffer_object *)self;
1573 char *str;
1574 int len, len1, len2;
1576 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
1577 return NULL;
1579 len1 = len;
1580 if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1581 len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
1582 if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
1583 len1 = BUFSZ - (xub->prod - xub->cons);
1585 if ( len1 == 0 )
1586 return PyInt_FromLong(0);
1588 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
1589 xub->prod += len1;
1591 if ( len1 < len )
1593 len2 = len - len1;
1594 if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1595 len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
1596 if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
1597 len2 = BUFSZ - (xub->prod - xub->cons);
1598 if ( len2 != 0 )
1600 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
1601 xub->prod += len2;
1602 return PyInt_FromLong(len1 + len2);
1606 return PyInt_FromLong(len1);
1609 static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
1611 xu_buffer_object *xub = (xu_buffer_object *)self;
1613 if ( !PyArg_ParseTuple(args, "") )
1614 return NULL;
1616 if ( xub->cons == xub->prod )
1617 return PyInt_FromLong(1);
1619 return PyInt_FromLong(0);
1622 static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
1624 xu_buffer_object *xub = (xu_buffer_object *)self;
1626 if ( !PyArg_ParseTuple(args, "") )
1627 return NULL;
1629 if ( (xub->prod - xub->cons) == BUFSZ )
1630 return PyInt_FromLong(1);
1632 return PyInt_FromLong(0);
1635 static PyMethodDef xu_buffer_methods[] = {
1636 { "peek",
1637 (PyCFunction)xu_buffer_peek,
1638 METH_VARARGS,
1639 "Peek up to @max bytes from the buffer. Returns a string.\n" },
1641 { "read",
1642 (PyCFunction)xu_buffer_read,
1643 METH_VARARGS,
1644 "Read up to @max bytes from the buffer. Returns a string.\n" },
1646 { "discard",
1647 (PyCFunction)xu_buffer_discard,
1648 METH_VARARGS,
1649 "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
1651 { "write",
1652 (PyCFunction)xu_buffer_write,
1653 METH_VARARGS,
1654 "Write @string into buffer. Return number of bytes written.\n" },
1656 { "empty",
1657 (PyCFunction)xu_buffer_empty,
1658 METH_VARARGS,
1659 "Return TRUE if the buffer is empty.\n" },
1661 { "full",
1662 (PyCFunction)xu_buffer_full,
1663 METH_VARARGS,
1664 "Return TRUE if the buffer is full.\n" },
1666 { NULL, NULL, 0, NULL }
1667 };
1669 staticforward PyTypeObject xu_buffer_type;
1671 static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
1673 xu_buffer_object *xub;
1675 if ( !PyArg_ParseTuple(args, "") )
1676 return NULL;
1678 xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
1680 if ( (xub->buf = malloc(BUFSZ)) == NULL )
1682 PyObject_Del((PyObject *)xub);
1683 return NULL;
1686 xub->prod = xub->cons = 0;
1688 return (PyObject *)xub;
1691 static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
1693 return Py_FindMethod(xu_buffer_methods, obj, name);
1696 static void xu_buffer_dealloc(PyObject *self)
1698 xu_buffer_object *xub = (xu_buffer_object *)self;
1699 free(xub->buf);
1700 PyObject_Del(self);
1703 static PyTypeObject xu_buffer_type = {
1704 PyObject_HEAD_INIT(&PyType_Type)
1705 0,
1706 "buffer",
1707 sizeof(xu_buffer_object),
1708 0,
1709 xu_buffer_dealloc, /* tp_dealloc */
1710 NULL, /* tp_print */
1711 xu_buffer_getattr, /* tp_getattr */
1712 NULL, /* tp_setattr */
1713 NULL, /* tp_compare */
1714 NULL, /* tp_repr */
1715 NULL, /* tp_as_number */
1716 NULL, /* tp_as_sequence */
1717 NULL, /* tp_as_mapping */
1718 NULL /* tp_hash */
1719 };
1723 /*
1724 * *********************** MODULE WRAPPER ***********************
1725 */
1727 static void handle_child_death(int dummy)
1729 while ( waitpid(-1, NULL, WNOHANG) > 0 )
1730 continue;
1733 static PyObject *xu_autoreap(PyObject *self, PyObject *args)
1735 struct sigaction sa;
1737 if ( !PyArg_ParseTuple(args, "") )
1738 return NULL;
1740 memset(&sa, 0, sizeof(sa));
1741 sa.sa_handler = handle_child_death;
1742 sigemptyset(&sa.sa_mask);
1743 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
1744 (void)sigaction(SIGCHLD, &sa, NULL);
1746 Py_INCREF(Py_None);
1747 return Py_None;
1750 static PyMethodDef xu_methods[] = {
1751 { "notifier", xu_notifier_new, METH_VARARGS,
1752 "Create a new notifier." },
1753 { "message", xu_message_new, METH_VARARGS,
1754 "Create a new communications message." },
1755 { "port", (PyCFunction)xu_port_new, METH_VARARGS | METH_KEYWORDS,
1756 "Create a new communications port." },
1757 { "buffer", xu_buffer_new, METH_VARARGS,
1758 "Create a new ring buffer." },
1759 { "autoreap", xu_autoreap, METH_VARARGS,
1760 "Ensure that zombie children are automatically reaped by the OS." },
1761 { NULL, NULL, 0, NULL }
1762 };
1764 PyMODINIT_FUNC initxu(void)
1766 PyObject *m, *d;
1768 m = Py_InitModule(XENPKG, xu_methods);
1770 d = PyModule_GetDict(m);
1771 port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
1772 PyDict_SetItemString(d, "PortError", port_error);
1774 /* KAF: This ensures that we get debug output in a timely manner. */
1775 setbuf(stdout, NULL);
1776 setbuf(stderr, NULL);