ia64/xen-unstable

view tools/python/xen/lowlevel/xu/xu.c @ 6316:f7dfaa2af90c

merge?
author cl349@firebug.cl.cam.ac.uk
date Sun Aug 21 11:02:00 2005 +0000 (2005-08-21)
parents 1872e09bfba3
children 6721abf6b16d
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/un.h>
17 #include <sys/mman.h>
18 #include <sys/poll.h>
19 #include <sys/sysmacros.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 /* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
50 * to check for errors. */
51 /*
52 static void set_cloexec(int fd)
53 {
54 int flags = fcntl(fd, F_GETFD, 0);
56 if ( flags < 0 )
57 return;
59 flags |= FD_CLOEXEC;
60 fcntl(fd, F_SETFD, flags);
61 }
62 */
63 /*
64 * *********************** XCS INTERFACE ***********************
65 */
67 #include <arpa/inet.h>
68 #include <xcs_proto.h>
70 static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
71 static int xcs_data_fd = -1; /* data connection to the xcs server. */
72 static unsigned long xcs_session_id = 0;
74 static int xcs_ctrl_send(xcs_msg_t *msg);
75 static int xcs_ctrl_read(xcs_msg_t *msg);
76 static int xcs_data_send(xcs_msg_t *msg);
77 static int xcs_data_read(xcs_msg_t *msg);
79 static int xcs_connect(char *path)
80 {
81 struct sockaddr_un addr;
82 int ret, len, flags;
83 xcs_msg_t msg;
85 if (xcs_data_fd != -1) /* already connected */
86 return 0;
88 xcs_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
89 if (xcs_ctrl_fd < 0)
90 {
91 printf("error creating xcs socket!\n");
92 goto fail;
93 }
95 addr.sun_family = AF_UNIX;
96 strcpy(addr.sun_path, path);
97 len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
99 ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr, len);
100 if (ret < 0)
101 {
102 printf("error connecting to xcs(ctrl)! (%d)\n", errno);
103 goto ctrl_fd_fail;
104 }
106 /*set_cloexec(xcs_ctrl_fd);*/
108 msg.type = XCS_CONNECT_CTRL;
109 msg.u.connect.session_id = xcs_session_id;
110 xcs_ctrl_send(&msg);
111 xcs_ctrl_read(&msg); /* TODO: timeout + error! */
113 if (msg.result != XCS_RSLT_OK)
114 {
115 printf("error connecting xcs control channel!\n");
116 goto ctrl_fd_fail;
117 }
118 xcs_session_id = msg.u.connect.session_id;
120 /* now the data connection. */
121 xcs_data_fd = socket(AF_UNIX, SOCK_STREAM, 0);
122 if (xcs_data_fd < 0)
123 {
124 printf("error creating xcs data socket!\n");
125 goto ctrl_fd_fail;
126 }
128 addr.sun_family = AF_UNIX;
129 strcpy(addr.sun_path, path);
130 len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
132 ret = connect(xcs_data_fd, (struct sockaddr *)&addr, len);
133 if (ret < 0)
134 {
135 printf("error connecting to xcs(data)! (%d)\n", errno);
136 goto data_fd_fail;
137 }
139 //set_cloexec(xcs_data_fd);
140 msg.type = XCS_CONNECT_DATA;
141 msg.u.connect.session_id = xcs_session_id;
142 xcs_data_send(&msg);
143 xcs_data_read(&msg); /* TODO: timeout + error! */
145 if (msg.result != XCS_RSLT_OK)
146 {
147 printf("error connecting xcs control channel!\n");
148 goto ctrl_fd_fail;
149 }
151 if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
152 (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
153 {
154 printf("Unable to set non-blocking status on data socket.");
155 goto data_fd_fail;
156 }
158 return 0;
160 data_fd_fail:
161 close(xcs_data_fd);
162 xcs_data_fd = -1;
164 ctrl_fd_fail:
165 close(xcs_ctrl_fd);
166 xcs_ctrl_fd = -1;
168 fail:
169 return -1;
171 }
173 static void xcs_disconnect(void)
174 {
175 close(xcs_data_fd);
176 xcs_data_fd = -1;
177 close(xcs_ctrl_fd);
178 xcs_ctrl_fd = -1;
179 }
181 static int xcs_ctrl_read(xcs_msg_t *msg)
182 {
183 int ret;
185 ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
186 return ret;
187 }
189 static int xcs_ctrl_send(xcs_msg_t *msg)
190 {
191 int ret;
193 ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
194 return ret;
195 }
197 static int xcs_data_read(xcs_msg_t *msg)
198 {
199 int ret;
201 ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
202 return ret;
203 }
205 static int xcs_data_send(xcs_msg_t *msg)
206 {
207 int ret;
209 ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
210 return ret;
211 }
214 typedef struct kme_st {
215 xcs_msg_t msg;
216 struct kme_st *next;
217 } xcs_msg_ent_t;
220 #define XCS_RING_SIZE 64
221 static xcs_msg_ent_t *req_ring[64];
222 static unsigned req_prod = 0;
223 static unsigned req_cons = 0;
225 static xcs_msg_ent_t *rsp_ring[64];
226 static unsigned rsp_prod = 0;
227 static unsigned rsp_cons = 0;
229 #define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
230 #define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE])
231 #define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
232 #define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
233 #define REQ_RING_EMPTY ( req_prod == req_cons )
234 #define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
235 /*
236 * *********************** NOTIFIER ***********************
237 */
239 typedef struct {
240 PyObject_HEAD;
241 int evtchn_fd;
242 } xu_notifier_object;
244 static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
245 {
246 xcs_msg_ent_t *ent;
247 int ret;
249 if ( !PyArg_ParseTuple(args, "") )
250 return NULL;
252 while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
253 {
254 ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
255 ret = xcs_data_read(&ent->msg);
257 if (ret == -1)
258 {
259 free(ent);
260 if ( errno == EINTR )
261 continue;
262 if ( errno == EAGAIN )
263 break;
264 return PyErr_SetFromErrno(PyExc_IOError);
265 }
267 switch (ent->msg.type)
268 {
269 case XCS_REQUEST:
270 REQ_RING_ENT(req_prod) = ent;
271 req_prod++;
272 continue;
274 case XCS_RESPONSE:
275 RSP_RING_ENT(rsp_prod) = ent;
276 rsp_prod++;
277 continue;
279 case XCS_VIRQ:
280 ret = ent->msg.u.control.local_port;
281 free(ent);
282 return PyInt_FromLong(ret);
284 default:
285 /*printf("Throwing away xcs msg type: %u\n", ent->msg.type);*/
286 free(ent);
287 }
288 }
290 if (!REQ_RING_EMPTY)
291 {
292 return PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port);
293 }
295 if (!RSP_RING_EMPTY)
296 {
297 return PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port);
298 }
300 Py_INCREF(Py_None);
301 return Py_None;
302 }
304 static PyObject *xu_notifier_bind_virq(PyObject *self,
305 PyObject *args, PyObject *kwds)
306 {
307 int virq;
308 xcs_msg_t kmsg;
310 static char *kwd_list[] = { "virq", NULL };
311 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
312 return NULL;
314 kmsg.type = XCS_VIRQ_BIND;
315 kmsg.u.virq.virq = virq;
316 xcs_ctrl_send(&kmsg);
317 xcs_ctrl_read(&kmsg);
319 if ( kmsg.result != XCS_RSLT_OK )
320 {
321 Py_INCREF(Py_None);
322 return Py_None;
323 }
325 return PyInt_FromLong(kmsg.u.virq.port);
326 }
328 static PyObject *xu_notifier_virq_send(PyObject *self,
329 PyObject *args, PyObject *kwds)
330 {
331 int port;
332 xcs_msg_t kmsg;
334 static char *kwd_list[] = { "port", NULL };
335 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
336 return NULL;
338 kmsg.type = XCS_VIRQ;
339 kmsg.u.control.local_port = port;
340 xcs_ctrl_send(&kmsg);
341 xcs_ctrl_read(&kmsg);
343 if ( kmsg.result != XCS_RSLT_OK )
344 {
345 Py_INCREF(Py_None);
346 return Py_None;
347 }
349 return PyInt_FromLong(kmsg.u.virq.port);
350 }
352 static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
353 {
354 return PyInt_FromLong(xcs_data_fd);
355 }
357 static PyMethodDef xu_notifier_methods[] = {
358 { "read",
359 (PyCFunction)xu_notifier_read,
360 METH_VARARGS,
361 "Read a @port with pending notifications.\n" },
363 { "bind_virq",
364 (PyCFunction)xu_notifier_bind_virq,
365 METH_VARARGS | METH_KEYWORDS,
366 "Get notifications for a virq.\n"
367 " virq [int]: VIRQ to bind.\n\n" },
369 { "virq_send",
370 (PyCFunction)xu_notifier_virq_send,
371 METH_VARARGS | METH_KEYWORDS,
372 "Fire a virq notification.\n"
373 " port [int]: port that VIRQ is bound to.\n\n" },
375 { "fileno",
376 (PyCFunction)xu_notifier_fileno,
377 METH_VARARGS,
378 "Return the file descriptor for the notification channel.\n" },
380 { NULL, NULL, 0, NULL }
381 };
383 staticforward PyTypeObject xu_notifier_type;
385 /* connect to xcs if we aren't already, and return a dummy object. */
386 static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
387 {
388 xu_notifier_object *xun;
389 int i;
391 if ( !PyArg_ParseTuple(args, "") )
392 return NULL;
394 xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
396 for (i = 0; i < XCS_RING_SIZE; i++)
397 REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
399 (void)xcs_connect(XCS_SUN_PATH);
402 return (PyObject *)xun;
403 }
405 static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
406 {
407 return Py_FindMethod(xu_notifier_methods, obj, name);
408 }
410 static void xu_notifier_dealloc(PyObject *self)
411 {
412 xcs_disconnect();
413 PyObject_Del(self);
414 }
416 static PyTypeObject xu_notifier_type = {
417 PyObject_HEAD_INIT(&PyType_Type)
418 0,
419 "notifier",
420 sizeof(xu_notifier_object),
421 0,
422 xu_notifier_dealloc, /* tp_dealloc */
423 NULL, /* tp_print */
424 xu_notifier_getattr, /* tp_getattr */
425 NULL, /* tp_setattr */
426 NULL, /* tp_compare */
427 NULL, /* tp_repr */
428 NULL, /* tp_as_number */
429 NULL, /* tp_as_sequence */
430 NULL, /* tp_as_mapping */
431 NULL /* tp_hash */
432 };
436 /*
437 * *********************** MESSAGE ***********************
438 */
440 #define TYPE(_x,_y) (((_x)<<8)|(_y))
442 #define P2C(_struct, _field, _ctype) \
443 do { \
444 PyObject *obj; \
445 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
446 { \
447 if ( PyInt_Check(obj) ) \
448 { \
449 ((_struct *)&xum->msg.msg[0])->_field = \
450 (_ctype)PyInt_AsLong(obj); \
451 dict_items_parsed++; \
452 } \
453 else if ( PyLong_Check(obj) ) \
454 { \
455 ((_struct *)&xum->msg.msg[0])->_field = \
456 (_ctype)PyLong_AsUnsignedLongLong(obj); \
457 dict_items_parsed++; \
458 } \
459 } \
460 xum->msg.length = sizeof(_struct); \
461 } while ( 0 )
463 /** Set a char[] field in a struct from a Python string.
464 * Can't do this in P2C because of the typing.
465 */
466 #define P2CSTRING(_struct, _field) \
467 do { \
468 PyObject *obj; \
469 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
470 { \
471 if ( PyString_Check(obj) ) \
472 { \
473 _struct * _cobj = (_struct *)&xum->msg.msg[0]; \
474 int _field_n = sizeof(_cobj->_field); \
475 memset(_cobj->_field, 0, _field_n); \
476 strncpy(_cobj->_field, \
477 PyString_AsString(obj), \
478 _field_n - 1); \
479 dict_items_parsed++; \
480 } \
481 } \
482 xum->msg.length = sizeof(_struct); \
483 } while ( 0 )
485 #define C2P(_struct, _field, _pytype, _ctype) \
486 do { \
487 PyObject *obj = Py ## _pytype ## _From ## _ctype \
488 (((_struct *)&xum->msg.msg[0])->_field); \
489 if ( dict == NULL ) dict = PyDict_New(); \
490 PyDict_SetItemString(dict, #_field, obj); \
491 } while ( 0 )
493 #define PSTR2CHAR(_struct, _field) \
494 do { \
495 PyObject *obj; \
496 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
497 { \
498 if ( PyString_Check(obj) ) \
499 { \
500 char *buffer = PyString_AsString(obj); \
501 \
502 strcpy(((_struct *)&xum->msg.msg[0])->_field, \
503 buffer); \
504 /* Should complain about length - think later */ \
505 dict_items_parsed++; \
506 } \
507 } \
508 xum->msg.length = sizeof(_struct); \
509 } while ( 0 )
511 typedef struct {
512 PyObject_HEAD;
513 control_msg_t msg;
514 } xu_message_object;
516 static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
517 {
518 xu_message_object *xum = (xu_message_object *)self;
519 char *str;
520 int len;
522 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
523 return NULL;
525 if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
526 {
527 PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
528 return NULL;
529 }
531 memcpy(&xum->msg.msg[xum->msg.length], str, len);
532 xum->msg.length += len;
534 Py_INCREF(Py_None);
535 return Py_None;
536 }
538 static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
539 {
540 xu_message_object *xum = (xu_message_object *)self;
541 PyObject *payload;
542 int dict_items_parsed = 0;
544 if ( !PyArg_ParseTuple(args, "O", &payload) )
545 return NULL;
547 if ( !PyDict_Check(payload) )
548 {
549 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
550 return NULL;
551 }
553 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
554 {
555 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
556 P2C(blkif_fe_driver_status_t, max_handle, u32);
557 break;
558 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
559 P2C(netif_fe_driver_status_t, max_handle, u32);
560 break;
561 }
563 if ( dict_items_parsed != PyDict_Size(payload) )
564 {
565 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
566 return NULL;
567 }
569 Py_INCREF(Py_None);
570 return Py_None;
571 }
573 static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
574 {
575 xu_message_object *xum = (xu_message_object *)self;
576 PyObject *dict = NULL;
578 if ( !PyArg_ParseTuple(args, "") )
579 return NULL;
581 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
582 {
583 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
584 C2P(blkif_fe_interface_status_t, handle, Int, Long);
585 C2P(blkif_fe_interface_status_t, status, Int, Long);
586 C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
587 return dict;
588 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
589 C2P(blkif_fe_driver_status_t, status, Int, Long);
590 return dict;
591 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
592 C2P(blkif_fe_interface_connect_t, handle, Int, Long);
593 C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
594 C2P(blkif_fe_interface_connect_t, shmem_ref , Int, Long);
595 return dict;
596 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
597 C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
598 return dict;
599 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
600 C2P(blkif_be_create_t, domid, Int, Long);
601 C2P(blkif_be_create_t, blkif_handle, Int, Long);
602 C2P(blkif_be_create_t, status, Int, Long);
603 return dict;
604 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
605 C2P(blkif_be_destroy_t, domid, Int, Long);
606 C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
607 C2P(blkif_be_destroy_t, status, Int, Long);
608 return dict;
609 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
610 C2P(blkif_be_connect_t, domid, Int, Long);
611 C2P(blkif_be_connect_t, blkif_handle, Int, Long);
612 C2P(blkif_be_connect_t, shmem_frame, Int, Long);
613 C2P(blkif_be_connect_t, shmem_ref, Int, Long);
614 C2P(blkif_be_connect_t, evtchn, Int, Long);
615 C2P(blkif_be_connect_t, status, Int, Long);
616 return dict;
617 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
618 C2P(blkif_be_disconnect_t, domid, Int, Long);
619 C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
620 C2P(blkif_be_disconnect_t, status, Int, Long);
621 return dict;
622 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
623 C2P(blkif_be_vbd_create_t, domid, Int, Long);
624 C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
625 C2P(blkif_be_vbd_create_t, pdevice, Int, Long);
626 C2P(blkif_be_vbd_create_t, dev_handle, Int, Long);
627 C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
628 C2P(blkif_be_vbd_create_t, readonly, Int, Long);
629 C2P(blkif_be_vbd_create_t, status, Int, Long);
630 return dict;
631 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
632 C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
633 C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
634 C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
635 C2P(blkif_be_vbd_destroy_t, status, Int, Long);
636 return dict;
637 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
638 C2P(blkif_be_driver_status_t, status, Int, Long);
639 return dict;
640 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
641 C2P(netif_fe_interface_status_t, handle, Int, Long);
642 C2P(netif_fe_interface_status_t, status, Int, Long);
643 C2P(netif_fe_interface_status_t, evtchn, Int, Long);
644 C2P(netif_fe_interface_status_t, mac[0], Int, Long);
645 C2P(netif_fe_interface_status_t, mac[1], Int, Long);
646 C2P(netif_fe_interface_status_t, mac[2], Int, Long);
647 C2P(netif_fe_interface_status_t, mac[3], Int, Long);
648 C2P(netif_fe_interface_status_t, mac[4], Int, Long);
649 C2P(netif_fe_interface_status_t, mac[5], Int, Long);
650 return dict;
651 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
652 C2P(netif_fe_driver_status_t, status, Int, Long);
653 C2P(netif_fe_driver_status_t, max_handle, Int, Long);
654 return dict;
655 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
656 C2P(netif_fe_interface_connect_t, handle, Int, Long);
657 C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
658 C2P(netif_fe_interface_connect_t, tx_shmem_ref, Int, Long);
659 C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
660 C2P(netif_fe_interface_connect_t, rx_shmem_ref, Int, Long);
661 return dict;
662 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
663 C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
664 return dict;
665 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
666 C2P(netif_be_create_t, domid, Int, Long);
667 C2P(netif_be_create_t, netif_handle, Int, Long);
668 C2P(netif_be_create_t, status, Int, Long);
669 return dict;
670 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
671 C2P(netif_be_destroy_t, domid, Int, Long);
672 C2P(netif_be_destroy_t, netif_handle, Int, Long);
673 C2P(netif_be_destroy_t, status, Int, Long);
674 return dict;
675 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
676 C2P(netif_be_creditlimit_t, domid, Int, Long);
677 C2P(netif_be_creditlimit_t, netif_handle, Int, Long);
678 C2P(netif_be_creditlimit_t, credit_bytes, Int, Long);
679 C2P(netif_be_creditlimit_t, period_usec, Int, Long);
680 C2P(netif_be_creditlimit_t, status, Int, Long);
681 return dict;
682 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
683 C2P(netif_be_connect_t, domid, Int, Long);
684 C2P(netif_be_connect_t, netif_handle, Int, Long);
685 C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
686 C2P(netif_be_connect_t, tx_shmem_ref, Int, Long);
687 C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
688 C2P(netif_be_connect_t, rx_shmem_ref, Int, Long);
689 C2P(netif_be_connect_t, evtchn, Int, Long);
690 C2P(netif_be_connect_t, status, Int, Long);
691 return dict;
692 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
693 C2P(netif_be_disconnect_t, domid, Int, Long);
694 C2P(netif_be_disconnect_t, netif_handle, Int, Long);
695 C2P(netif_be_disconnect_t, status, Int, Long);
696 return dict;
697 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
698 C2P(netif_be_driver_status_t, status, Int, Long);
699 return dict;
700 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
701 C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
702 C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
703 C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
704 C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
705 C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
706 return dict;
707 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
708 C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
709 return dict;
710 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
711 C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
712 return dict;
713 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
714 return dict;
715 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
716 C2P(usbif_be_create_t, domid, Int, Long);
717 C2P(usbif_be_create_t, status, Int, Long);
718 return dict;
719 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
720 C2P(usbif_be_destroy_t, domid, Int, Long);
721 C2P(usbif_be_destroy_t, status, Int, Long);
722 return dict;
723 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
724 C2P(usbif_be_connect_t, domid, Int, Long);
725 C2P(usbif_be_connect_t, shmem_frame, Int, Long);
726 C2P(usbif_be_connect_t, evtchn, Int, Long);
727 C2P(usbif_be_connect_t, bandwidth, Int, Long);
728 C2P(usbif_be_connect_t, status, Int, Long);
729 return dict;
730 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
731 C2P(usbif_be_disconnect_t, domid, Int, Long);
732 C2P(usbif_be_disconnect_t, status, Int, Long);
733 return dict;
734 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
735 C2P(usbif_be_driver_status_changed_t, status, Int, Long);
736 return dict;
737 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
738 C2P(usbif_be_claim_port_t, domid, Int, Long);
739 C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
740 C2P(usbif_be_claim_port_t, status, Int, Long);
741 C2P(usbif_be_claim_port_t, path, String, String);
742 return dict;
743 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
744 C2P(usbif_be_release_port_t, path, String, String);
745 return dict;
746 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
747 C2P(mem_request_t, target, Int, Long);
748 C2P(mem_request_t, status, Int, Long);
749 return dict;
750 case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
751 C2P(vcpu_hotplug_t, vcpu, Int, Long);
752 C2P(vcpu_hotplug_t, status, Int, Long);
753 return dict;
754 case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
755 C2P(vcpu_hotplug_t, vcpu, Int, Long);
756 C2P(vcpu_hotplug_t, status, Int, Long);
757 return dict;
758 }
760 return PyString_FromStringAndSize((char *)xum->msg.msg, xum->msg.length);
761 }
763 static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
764 {
765 xu_message_object *xum = (xu_message_object *)self;
767 if ( !PyArg_ParseTuple(args, "") )
768 return NULL;
770 return Py_BuildValue("{s:i,s:i,s:i}",
771 "type", xum->msg.type,
772 "subtype", xum->msg.subtype,
773 "id", xum->msg.id);
774 }
776 static PyMethodDef xu_message_methods[] = {
777 { "append_payload",
778 (PyCFunction)xu_message_append_payload,
779 METH_VARARGS,
780 "Append @str to the message payload.\n" },
782 { "set_response_fields",
783 (PyCFunction)xu_message_set_response_fields,
784 METH_VARARGS,
785 "Fill in the response fields in a message that was passed to us.\n" },
787 { "get_payload",
788 (PyCFunction)xu_message_get_payload,
789 METH_VARARGS,
790 "Return the message payload in string form.\n" },
792 { "get_header",
793 (PyCFunction)xu_message_get_header,
794 METH_VARARGS,
795 "Returns a dictionary of values for @type, @subtype, and @id.\n" },
797 { NULL, NULL, 0, NULL }
798 };
800 staticforward PyTypeObject xu_message_type;
802 static PyObject *xu_message_new(PyObject *self, PyObject *args)
803 {
804 xu_message_object *xum;
805 int type, subtype, id, dict_items_parsed = 0;
806 PyObject *payload = NULL;
808 if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
809 return NULL;
811 xum = PyObject_New(xu_message_object, &xu_message_type);
813 xum->msg.type = type;
814 xum->msg.subtype = subtype;
815 xum->msg.id = id;
816 xum->msg.length = 0;
818 if ( payload == NULL )
819 return (PyObject *)xum;
821 if ( !PyDict_Check(payload) )
822 {
823 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
824 PyObject_Del((PyObject *)xum);
825 return NULL;
826 }
828 switch ( TYPE(type, subtype) )
829 {
830 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
831 P2C(blkif_fe_interface_status_t, handle, u32);
832 P2C(blkif_fe_interface_status_t, status, u32);
833 P2C(blkif_fe_interface_status_t, evtchn, u16);
834 P2C(blkif_fe_interface_status_t, domid, u16);
835 break;
836 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
837 P2C(blkif_be_create_t, domid, u32);
838 P2C(blkif_be_create_t, blkif_handle, u32);
839 break;
840 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
841 P2C(blkif_be_destroy_t, domid, u32);
842 P2C(blkif_be_destroy_t, blkif_handle, u32);
843 break;
844 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
845 P2C(blkif_be_connect_t, domid, u32);
846 P2C(blkif_be_connect_t, blkif_handle, u32);
847 P2C(blkif_be_connect_t, shmem_frame, unsigned long);
848 P2C(blkif_be_connect_t, shmem_ref, u32);
849 P2C(blkif_be_connect_t, evtchn, u16);
850 break;
851 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
852 P2C(blkif_be_disconnect_t, domid, u32);
853 P2C(blkif_be_disconnect_t, blkif_handle, u32);
854 break;
855 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
856 P2C(blkif_be_vbd_create_t, domid, u32);
857 P2C(blkif_be_vbd_create_t, blkif_handle, u32);
858 P2C(blkif_be_vbd_create_t, pdevice, blkif_pdev_t);
859 P2C(blkif_be_vbd_create_t, dev_handle, u32);
860 P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
861 P2C(blkif_be_vbd_create_t, readonly, u16);
862 break;
863 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
864 P2C(blkif_be_vbd_destroy_t, domid, u32);
865 P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
866 P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
867 break;
868 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
869 P2C(netif_fe_interface_status_t, handle, u32);
870 P2C(netif_fe_interface_status_t, status, u32);
871 P2C(netif_fe_interface_status_t, evtchn, u16);
872 P2C(netif_fe_interface_status_t, domid, u16);
873 P2C(netif_fe_interface_status_t, mac[0], u8);
874 P2C(netif_fe_interface_status_t, mac[1], u8);
875 P2C(netif_fe_interface_status_t, mac[2], u8);
876 P2C(netif_fe_interface_status_t, mac[3], u8);
877 P2C(netif_fe_interface_status_t, mac[4], u8);
878 P2C(netif_fe_interface_status_t, mac[5], u8);
879 break;
880 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
881 P2C(netif_be_create_t, domid, u32);
882 P2C(netif_be_create_t, netif_handle, u32);
883 P2C(netif_be_create_t, mac[0], u8);
884 P2C(netif_be_create_t, mac[1], u8);
885 P2C(netif_be_create_t, mac[2], u8);
886 P2C(netif_be_create_t, mac[3], u8);
887 P2C(netif_be_create_t, mac[4], u8);
888 P2C(netif_be_create_t, mac[5], u8);
889 P2C(netif_be_create_t, be_mac[0], u8);
890 P2C(netif_be_create_t, be_mac[1], u8);
891 P2C(netif_be_create_t, be_mac[2], u8);
892 P2C(netif_be_create_t, be_mac[3], u8);
893 P2C(netif_be_create_t, be_mac[4], u8);
894 P2C(netif_be_create_t, be_mac[5], u8);
895 break;
896 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
897 P2C(netif_be_destroy_t, domid, u32);
898 P2C(netif_be_destroy_t, netif_handle, u32);
899 break;
900 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
901 P2C(netif_be_creditlimit_t, domid, u32);
902 P2C(netif_be_creditlimit_t, netif_handle, u32);
903 P2C(netif_be_creditlimit_t, credit_bytes, u32);
904 P2C(netif_be_creditlimit_t, period_usec, u32);
905 break;
906 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
907 P2C(netif_be_connect_t, domid, u32);
908 P2C(netif_be_connect_t, netif_handle, u32);
909 P2C(netif_be_connect_t, tx_shmem_frame, unsigned long);
910 P2C(netif_be_connect_t, tx_shmem_ref, u32);
911 P2C(netif_be_connect_t, rx_shmem_frame, unsigned long);
912 P2C(netif_be_connect_t, rx_shmem_ref, u32);
913 P2C(netif_be_connect_t, evtchn, u16);
914 break;
915 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
916 P2C(netif_be_disconnect_t, domid, u32);
917 P2C(netif_be_disconnect_t, netif_handle, u32);
918 break;
919 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
920 P2C(netif_fe_driver_status_t, status, u32);
921 P2C(netif_fe_driver_status_t, max_handle, u32);
922 break;
923 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
924 P2C(mem_request_t, target, u32);
925 break;
926 case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
927 P2C(vcpu_hotplug_t, vcpu, u32);
928 P2C(vcpu_hotplug_t, status, u32);
929 break;
930 case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
931 P2C(vcpu_hotplug_t, vcpu, u32);
932 P2C(vcpu_hotplug_t, status, u32);
933 break;
934 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
935 P2C(usbif_fe_interface_status_changed_t, status, u32);
936 P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
937 P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
938 P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
939 P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
940 break;
941 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
942 P2C(usbif_fe_driver_status_changed_t, status, u32);
943 break;
944 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
945 P2C(usbif_fe_interface_connect_t, shmem_frame, unsigned long);
946 break;
947 case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
948 break;
949 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
950 P2C(usbif_be_create_t, domid, domid_t);
951 P2C(usbif_be_create_t, status, u32);
952 break;
953 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
954 P2C(usbif_be_destroy_t, domid, domid_t);
955 P2C(usbif_be_destroy_t, status, u32);
956 break;
957 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
958 P2C(usbif_be_connect_t, domid, domid_t);
959 P2C(usbif_be_connect_t, shmem_frame, unsigned long);
960 P2C(usbif_be_connect_t, evtchn, u32);
961 P2C(usbif_be_connect_t, bandwidth, u32);
962 P2C(usbif_be_connect_t, status, u32);
963 break;
964 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
965 P2C(usbif_be_disconnect_t, domid, domid_t);
966 P2C(usbif_be_disconnect_t, status, u32);
967 break;
968 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
969 P2C(usbif_be_driver_status_changed_t, status, u32);
970 break;
971 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
972 P2C(usbif_be_claim_port_t, domid, domid_t);
973 P2C(usbif_be_claim_port_t, usbif_port, u32);
974 P2C(usbif_be_claim_port_t, status, u32);
975 PSTR2CHAR(usbif_be_claim_port_t, path);
976 printf("dict items parsed = %d", dict_items_parsed);
977 break;
978 case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
979 PSTR2CHAR(usbif_be_release_port_t, path);
980 break;
981 case TYPE(CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ):
982 P2C(shutdown_sysrq_t, key, char);
983 break;
984 }
986 if ( dict_items_parsed != PyDict_Size(payload) )
987 {
988 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
989 PyObject_Del((PyObject *)xum);
990 return NULL;
991 }
993 return (PyObject *)xum;
994 }
996 static PyObject *xu_message_getattr(PyObject *obj, char *name)
997 {
998 xu_message_object *xum;
999 if ( strcmp(name, "MAX_PAYLOAD") == 0 )
1000 return PyInt_FromLong(sizeof(xum->msg.msg));
1001 return Py_FindMethod(xu_message_methods, obj, name);
1004 static void xu_message_dealloc(PyObject *self)
1006 PyObject_Del(self);
1009 static PyTypeObject xu_message_type = {
1010 PyObject_HEAD_INIT(&PyType_Type)
1011 0,
1012 "message",
1013 sizeof(xu_message_object),
1014 0,
1015 xu_message_dealloc, /* tp_dealloc */
1016 NULL, /* tp_print */
1017 xu_message_getattr, /* tp_getattr */
1018 NULL, /* tp_setattr */
1019 NULL, /* tp_compare */
1020 NULL, /* tp_repr */
1021 NULL, /* tp_as_number */
1022 NULL, /* tp_as_sequence */
1023 NULL, /* tp_as_mapping */
1024 NULL /* tp_hash */
1025 };
1029 /*
1030 * *********************** PORT ***********************
1031 */
1033 typedef struct xu_port_object {
1034 PyObject_HEAD;
1035 int xc_handle;
1036 int connected;
1037 u32 remote_dom;
1038 int local_port, remote_port;
1039 struct xu_port_object *fix_next;
1040 } xu_port_object;
1042 static PyObject *port_error;
1044 static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
1046 xu_port_object *xup = (xu_port_object *)self;
1047 xu_message_object *xum;
1048 control_msg_t *cmsg;
1049 unsigned i;
1050 xcs_msg_ent_t *ent = NULL;
1052 for ( i = req_cons; (i != req_prod); i++ ) {
1053 ent = REQ_RING_ENT(i);
1054 if (ent == NULL)
1055 continue;
1056 if (ent->msg.u.control.remote_dom == xup->remote_dom)
1057 break;
1060 if ((ent == NULL) ||
1061 (ent->msg.u.control.remote_dom != xup->remote_dom))
1062 goto none;
1064 cmsg = &ent->msg.u.control.msg;
1065 xum = PyObject_New(xu_message_object, &xu_message_type);
1066 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
1067 if ( xum->msg.length > sizeof(xum->msg.msg) )
1068 xum->msg.length = sizeof(xum->msg.msg);
1069 free(ent);
1071 /* remove the entry from the ring and advance the consumer if possible */
1072 REQ_RING_ENT(i) = NULL;
1073 while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
1074 req_cons++;
1076 return (PyObject *)xum;
1078 none:
1079 Py_INCREF(Py_None);
1080 return Py_None;
1084 static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
1086 xu_port_object *xup = (xu_port_object *)self;
1087 xu_message_object *xum;
1088 xcs_msg_t kmsg;
1090 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
1091 return NULL;
1093 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
1095 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
1096 return NULL;
1099 kmsg.type = XCS_REQUEST;
1100 kmsg.u.control.remote_dom = xup->remote_dom;
1101 memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
1102 xcs_data_send(&kmsg);
1104 Py_INCREF(Py_None);
1105 return Py_None;
1108 static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
1110 xu_port_object *xup = (xu_port_object *)self;
1111 xu_message_object *xum;
1112 control_msg_t *cmsg;
1113 unsigned i;
1114 xcs_msg_ent_t *ent = NULL;
1116 for ( i = rsp_cons; (i != rsp_prod); i++ ) {
1117 ent = RSP_RING_ENT(i);
1118 if (ent == NULL)
1119 continue;
1120 if (ent->msg.u.control.remote_dom == xup->remote_dom)
1121 break;
1124 if ((ent == NULL) ||
1125 (ent->msg.u.control.remote_dom != xup->remote_dom))
1126 goto none;
1128 cmsg = &ent->msg.u.control.msg;
1129 xum = PyObject_New(xu_message_object, &xu_message_type);
1130 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
1131 if ( xum->msg.length > sizeof(xum->msg.msg) )
1132 xum->msg.length = sizeof(xum->msg.msg);
1133 free(ent);
1135 /* remove the entry from the ring and advance the consumer if possible */
1136 RSP_RING_ENT(i) = NULL;
1137 while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
1138 rsp_cons++;
1140 return (PyObject *)xum;
1142 none:
1143 Py_INCREF(Py_None);
1144 return Py_None;
1148 static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
1150 xu_port_object *xup = (xu_port_object *)self;
1151 xu_message_object *xum;
1152 xcs_msg_t kmsg;
1154 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
1155 return NULL;
1157 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
1159 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
1160 return NULL;
1163 kmsg.type = XCS_RESPONSE;
1164 kmsg.u.control.remote_dom = xup->remote_dom;
1165 memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
1166 xcs_data_send(&kmsg);
1168 Py_INCREF(Py_None);
1169 return Py_None;
1172 static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
1174 xu_port_object *xup = (xu_port_object *)self;
1175 xcs_msg_ent_t *ent;
1176 int found = 0;
1177 unsigned i;
1179 if ( !PyArg_ParseTuple(args, "") )
1180 return NULL;
1182 for ( i = req_cons; (i != req_prod); i++ ) {
1183 ent = REQ_RING_ENT(i);
1184 if (ent == NULL)
1185 continue;
1186 if (ent->msg.u.control.remote_dom == xup->remote_dom) {
1187 found = 1;
1188 break;
1192 return PyInt_FromLong(found);
1195 static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
1197 xu_port_object *xup = (xu_port_object *)self;
1198 xcs_msg_ent_t *ent;
1199 int found = 0;
1200 unsigned i;
1202 if ( !PyArg_ParseTuple(args, "") )
1203 return NULL;
1205 for ( i = rsp_cons; (i != rsp_prod); i++ ) {
1206 ent = RSP_RING_ENT(i);
1207 if (ent == NULL)
1208 continue;
1209 if (ent->msg.u.control.remote_dom == xup->remote_dom) {
1210 found = 1;
1211 break;
1215 return PyInt_FromLong(found);
1218 static void _xu_port_close(xu_port_object *xup )
1220 if ( xup->connected && xup->remote_dom != 0 )
1222 xcs_msg_t kmsg;
1223 kmsg.type = XCS_CIF_FREE_CC;
1224 kmsg.u.interface.dom = xup->remote_dom;
1225 kmsg.u.interface.local_port = xup->local_port;
1226 kmsg.u.interface.remote_port = xup->remote_port;
1227 xcs_ctrl_send(&kmsg);
1228 xcs_ctrl_read(&kmsg);
1229 xup->connected = 0;
1233 static PyObject *xu_port_close(PyObject *self, PyObject *args)
1235 xu_port_object *xup = (xu_port_object *)self;
1237 _xu_port_close(xup);
1239 Py_INCREF(Py_None);
1240 return Py_None;
1243 static PyObject *xu_port_register(PyObject *self, PyObject *args,
1244 PyObject *kwds)
1246 int type;
1247 xcs_msg_t msg;
1248 xu_port_object *xup = (xu_port_object *)self;
1249 static char *kwd_list[] = { "type", NULL };
1251 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
1252 &type) )
1253 return NULL;
1255 if (!xup->connected)
1257 return PyInt_FromLong(0);
1260 msg.type = XCS_MSG_BIND;
1261 msg.u.bind.port = xup->local_port;
1262 msg.u.bind.type = type;
1263 xcs_ctrl_send(&msg);
1264 xcs_ctrl_read(&msg);
1266 if (msg.result != XCS_RSLT_OK)
1268 return PyInt_FromLong(0);
1271 return PyInt_FromLong(1);
1274 static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
1275 PyObject *kwds)
1277 int type;
1278 xcs_msg_t msg;
1279 xu_port_object *xup = (xu_port_object *)self;
1280 static char *kwd_list[] = { "type", NULL };
1282 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
1283 &type) )
1284 return NULL;
1286 if (!xup->connected)
1288 return PyInt_FromLong(0);
1291 msg.type = XCS_MSG_UNBIND;
1292 msg.u.bind.port = xup->local_port;
1293 msg.u.bind.type = type;
1294 xcs_ctrl_send(&msg);
1295 xcs_ctrl_read(&msg);
1297 if (msg.result != XCS_RSLT_OK)
1299 return PyInt_FromLong(0);
1302 return PyInt_FromLong(1);
1305 static PyMethodDef xu_port_methods[] = {
1307 { "read_request",
1308 (PyCFunction)xu_port_read_request,
1309 METH_VARARGS,
1310 "Read a request message from the control interface.\n" },
1312 { "write_request",
1313 (PyCFunction)xu_port_write_request,
1314 METH_VARARGS,
1315 "Write a request message to the control interface.\n" },
1317 { "read_response",
1318 (PyCFunction)xu_port_read_response,
1319 METH_VARARGS,
1320 "Read a response message from the control interface.\n" },
1322 { "write_response",
1323 (PyCFunction)xu_port_write_response,
1324 METH_VARARGS,
1325 "Write a response message to the control interface.\n" },
1327 { "request_to_read",
1328 (PyCFunction)xu_port_request_to_read,
1329 METH_VARARGS,
1330 "Returns TRUE if there is a request message to read.\n" },
1333 { "response_to_read",
1334 (PyCFunction)xu_port_response_to_read,
1335 METH_VARARGS,
1336 "Returns TRUE if there is a response message to read.\n" },
1338 { "register",
1339 (PyCFunction)xu_port_register,
1340 METH_VARARGS | METH_KEYWORDS,
1341 "Register to receive a type of message on this channel.\n" },
1343 { "deregister",
1344 (PyCFunction)xu_port_deregister,
1345 METH_VARARGS | METH_KEYWORDS,
1346 "Stop receiving a type of message on this port.\n" },
1348 { "close",
1349 (PyCFunction)xu_port_close,
1350 METH_VARARGS,
1351 "Close the port.\n" },
1353 { NULL, NULL, 0, NULL }
1354 };
1356 staticforward PyTypeObject xu_port_type;
1358 static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
1360 xu_port_object *xup;
1361 u32 dom;
1362 int port1 = 0, port2 = 0;
1363 xcs_msg_t kmsg;
1365 static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
1367 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
1368 &dom, &port1, &port2) )
1369 return NULL;
1371 xup = PyObject_New(xu_port_object, &xu_port_type);
1373 xup->connected = 0;
1374 xup->remote_dom = dom;
1376 kmsg.type = XCS_CIF_NEW_CC;
1377 kmsg.u.interface.dom = xup->remote_dom;
1378 kmsg.u.interface.local_port = port1;
1379 kmsg.u.interface.remote_port = port2;
1380 xcs_ctrl_send(&kmsg);
1381 xcs_ctrl_read(&kmsg);
1383 if ( kmsg.result != XCS_RSLT_OK )
1384 goto fail1;
1386 xup->local_port = kmsg.u.interface.local_port;
1387 xup->remote_port = kmsg.u.interface.remote_port;
1388 xup->connected = 1;
1390 return (PyObject *)xup;
1392 fail1:
1393 PyObject_Del((PyObject *)xup);
1394 PyErr_SetString(PyExc_ValueError, "cannot create port");
1395 return NULL;
1398 static PyObject *xu_port_getattr(PyObject *obj, char *name)
1400 xu_port_object *xup = (xu_port_object *)obj;
1402 if ( strcmp(name, "local_port") == 0 )
1404 return PyInt_FromLong(xup->connected ? xup->local_port : -1);
1406 if ( strcmp(name, "remote_port") == 0 )
1408 return PyInt_FromLong(xup->connected ? xup->remote_port : -1);
1410 if ( strcmp(name, "remote_dom") == 0 )
1412 return PyInt_FromLong(xup->remote_dom);
1414 if ( strcmp(name, "connected") == 0 )
1416 return PyInt_FromLong(xup->connected);
1418 return Py_FindMethod(xu_port_methods, obj, name);
1421 static void xu_port_dealloc(PyObject *self)
1423 xu_port_object *xup = (xu_port_object *)self;
1425 _xu_port_close(xup);
1427 PyObject_Del(self);
1430 static PyTypeObject xu_port_type = {
1431 PyObject_HEAD_INIT(&PyType_Type)
1432 0,
1433 "port",
1434 sizeof(xu_port_object),
1435 0,
1436 xu_port_dealloc, /* tp_dealloc */
1437 NULL, /* tp_print */
1438 xu_port_getattr, /* tp_getattr */
1439 NULL, /* tp_setattr */
1440 NULL, /* tp_compare */
1441 NULL, /* tp_repr */
1442 NULL, /* tp_as_number */
1443 NULL, /* tp_as_sequence */
1444 NULL, /* tp_as_mapping */
1445 NULL /* tp_hash */
1446 };
1450 /*
1451 * *********************** BUFFER ***********************
1452 */
1454 #define BUFSZ 65536
1455 #define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
1456 typedef unsigned int BUF_IDX;
1458 typedef struct {
1459 PyObject_HEAD;
1460 char *buf;
1461 unsigned int prod, cons;
1462 } xu_buffer_object;
1464 static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
1466 PyObject *str1, *str2;
1467 int len1, len2, c = MASK_BUF_IDX(xub->cons);
1469 len1 = xub->prod - xub->cons;
1470 if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
1471 len1 = BUFSZ - c;
1472 if ( len1 > max ) /* clip to specified maximum */
1473 len1 = max;
1474 if ( len1 < 0 ) /* sanity */
1475 len1 = 0;
1477 if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
1478 return NULL;
1480 if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
1482 len2 = max - len1;
1483 if ( len2 > MASK_BUF_IDX(xub->prod) )
1484 len2 = MASK_BUF_IDX(xub->prod);
1485 if ( len2 > 0 )
1487 str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
1488 if ( str2 == NULL )
1489 return NULL;
1490 PyString_ConcatAndDel(&str1, str2);
1491 if ( str1 == NULL )
1492 return NULL;
1496 return str1;
1499 static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
1501 xu_buffer_object *xub = (xu_buffer_object *)self;
1502 int max = 1024;
1504 if ( !PyArg_ParseTuple(args, "|i", &max) )
1505 return NULL;
1507 return __xu_buffer_peek(xub, max);
1510 static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
1512 xu_buffer_object *xub = (xu_buffer_object *)self;
1513 PyObject *str;
1514 int max = 1024;
1516 if ( !PyArg_ParseTuple(args, "|i", &max) )
1517 return NULL;
1519 if ( (str = __xu_buffer_peek(xub, max)) != NULL )
1520 xub->cons += PyString_Size(str);
1522 return str;
1525 static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
1527 xu_buffer_object *xub = (xu_buffer_object *)self;
1528 int max, len;
1530 if ( !PyArg_ParseTuple(args, "i", &max) )
1531 return NULL;
1533 len = xub->prod - xub->cons;
1534 if ( len > max )
1535 len = max;
1536 if ( len < 0 )
1537 len = 0;
1539 xub->cons += len;
1541 return PyInt_FromLong(len);
1544 static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
1546 xu_buffer_object *xub = (xu_buffer_object *)self;
1547 char *str;
1548 int len, len1, len2;
1550 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
1551 return NULL;
1553 len1 = len;
1554 if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1555 len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
1556 if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
1557 len1 = BUFSZ - (xub->prod - xub->cons);
1559 if ( len1 == 0 )
1560 return PyInt_FromLong(0);
1562 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
1563 xub->prod += len1;
1565 if ( len1 < len )
1567 len2 = len - len1;
1568 if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1569 len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
1570 if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
1571 len2 = BUFSZ - (xub->prod - xub->cons);
1572 if ( len2 != 0 )
1574 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
1575 xub->prod += len2;
1576 return PyInt_FromLong(len1 + len2);
1580 return PyInt_FromLong(len1);
1583 static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
1585 xu_buffer_object *xub = (xu_buffer_object *)self;
1587 if ( !PyArg_ParseTuple(args, "") )
1588 return NULL;
1590 if ( xub->cons == xub->prod )
1591 return PyInt_FromLong(1);
1593 return PyInt_FromLong(0);
1596 static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
1598 xu_buffer_object *xub = (xu_buffer_object *)self;
1600 if ( !PyArg_ParseTuple(args, "") )
1601 return NULL;
1603 if ( (xub->prod - xub->cons) == BUFSZ )
1604 return PyInt_FromLong(1);
1606 return PyInt_FromLong(0);
1609 static PyObject *xu_buffer_size(PyObject *self, PyObject *args)
1611 xu_buffer_object *xub = (xu_buffer_object *)self;
1613 if ( !PyArg_ParseTuple(args, "") )
1614 return NULL;
1616 return PyInt_FromLong(xub->prod - xub->cons);
1619 static PyObject *xu_buffer_space(PyObject *self, PyObject *args)
1621 xu_buffer_object *xub = (xu_buffer_object *)self;
1623 if ( !PyArg_ParseTuple(args, "") )
1624 return NULL;
1626 return PyInt_FromLong(BUFSZ - (xub->prod - xub->cons));
1629 static PyMethodDef xu_buffer_methods[] = {
1630 { "peek",
1631 (PyCFunction)xu_buffer_peek,
1632 METH_VARARGS,
1633 "Peek up to @max bytes from the buffer. Returns a string.\n" },
1635 { "read",
1636 (PyCFunction)xu_buffer_read,
1637 METH_VARARGS,
1638 "Read up to @max bytes from the buffer. Returns a string.\n" },
1640 { "discard",
1641 (PyCFunction)xu_buffer_discard,
1642 METH_VARARGS,
1643 "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
1645 { "write",
1646 (PyCFunction)xu_buffer_write,
1647 METH_VARARGS,
1648 "Write @string into buffer. Return number of bytes written.\n" },
1650 { "empty",
1651 (PyCFunction)xu_buffer_empty,
1652 METH_VARARGS,
1653 "Return TRUE if the buffer is empty.\n" },
1655 { "full",
1656 (PyCFunction)xu_buffer_full,
1657 METH_VARARGS,
1658 "Return TRUE if the buffer is full.\n" },
1660 { "size",
1661 (PyCFunction)xu_buffer_size,
1662 METH_VARARGS,
1663 "Return number of bytes in the buffer.\n" },
1665 { "space",
1666 (PyCFunction)xu_buffer_space,
1667 METH_VARARGS,
1668 "Return space left in the buffer.\n" },
1670 { NULL, NULL, 0, NULL }
1671 };
1673 staticforward PyTypeObject xu_buffer_type;
1675 static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
1677 xu_buffer_object *xub;
1679 if ( !PyArg_ParseTuple(args, "") )
1680 return NULL;
1682 xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
1684 if ( (xub->buf = malloc(BUFSZ)) == NULL )
1686 PyObject_Del((PyObject *)xub);
1687 return NULL;
1690 xub->prod = xub->cons = 0;
1692 return (PyObject *)xub;
1695 static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
1697 return Py_FindMethod(xu_buffer_methods, obj, name);
1700 static void xu_buffer_dealloc(PyObject *self)
1702 xu_buffer_object *xub = (xu_buffer_object *)self;
1703 free(xub->buf);
1704 PyObject_Del(self);
1707 static PyTypeObject xu_buffer_type = {
1708 PyObject_HEAD_INIT(&PyType_Type)
1709 0,
1710 "buffer",
1711 sizeof(xu_buffer_object),
1712 0,
1713 xu_buffer_dealloc, /* tp_dealloc */
1714 NULL, /* tp_print */
1715 xu_buffer_getattr, /* tp_getattr */
1716 NULL, /* tp_setattr */
1717 NULL, /* tp_compare */
1718 NULL, /* tp_repr */
1719 NULL, /* tp_as_number */
1720 NULL, /* tp_as_sequence */
1721 NULL, /* tp_as_mapping */
1722 NULL /* tp_hash */
1723 };
1727 /*
1728 * *********************** MODULE WRAPPER ***********************
1729 */
1731 static void handle_child_death(int dummy)
1733 while ( waitpid(-1, NULL, WNOHANG) > 0 )
1734 continue;
1737 static PyObject *xu_autoreap(PyObject *self, PyObject *args)
1739 struct sigaction sa;
1741 if ( !PyArg_ParseTuple(args, "") )
1742 return NULL;
1744 memset(&sa, 0, sizeof(sa));
1745 sa.sa_handler = handle_child_death;
1746 sigemptyset(&sa.sa_mask);
1747 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
1748 (void)sigaction(SIGCHLD, &sa, NULL);
1750 Py_INCREF(Py_None);
1751 return Py_None;
1754 static PyMethodDef xu_methods[] = {
1755 { "notifier", xu_notifier_new, METH_VARARGS,
1756 "Create a new notifier." },
1757 { "message", xu_message_new, METH_VARARGS,
1758 "Create a new communications message." },
1759 { "port", (PyCFunction)xu_port_new, METH_VARARGS | METH_KEYWORDS,
1760 "Create a new communications port." },
1761 { "buffer", xu_buffer_new, METH_VARARGS,
1762 "Create a new ring buffer." },
1763 { "autoreap", xu_autoreap, METH_VARARGS,
1764 "Ensure that zombie children are automatically reaped by the OS." },
1765 { NULL, NULL, 0, NULL }
1766 };
1768 PyMODINIT_FUNC initxu(void)
1770 PyObject *m, *d;
1772 m = Py_InitModule(XENPKG, xu_methods);
1774 d = PyModule_GetDict(m);
1775 port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
1776 PyDict_SetItemString(d, "PortError", port_error);
1778 /* KAF: This ensures that we get debug output in a timely manner. */
1779 setbuf(stdout, NULL);
1780 setbuf(stderr, NULL);