direct-io.hg

changeset 3504:bb56e77896e7

bitkeeper revision 1.1159.1.536 (41f4cb97IRNBhG4wvbvEsMQ2SPTXCg)

Merge tempest.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into tempest.cl.cam.ac.uk:/local/scratch/smh22/xen-unstable.bk
author smh22@tempest.cl.cam.ac.uk
date Mon Jan 24 10:19:03 2005 +0000 (2005-01-24)
parents 12e84ce22ce3 10d4d8627af0
children d8ba911dce48
files .rootkeys docs/src/user.tex linux-2.4.29-xen-sparse/arch/xen/Makefile linux-2.4.29-xen-sparse/arch/xen/config.in linux-2.4.29-xen-sparse/arch/xen/defconfig-xen0 linux-2.4.29-xen-sparse/arch/xen/defconfig-xenU linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/Makefile linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/Makefile linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/common.h linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/control.c linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/interface.c linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/main.c linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/Makefile linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/main.c linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/xhci.h linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/usbif.h linux-2.6.10-xen-sparse/arch/xen/Kconfig linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig tools/python/xen/lowlevel/xu/xu.c tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvUsbif.py tools/python/xen/xend/server/messages.py tools/python/xen/xend/server/usbif.py tools/python/xen/xm/create.py tools/xcs/xcs.c xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/memory.c xen/common/Makefile xen/common/dom0_ops.c xen/common/domain.c xen/common/elf.c xen/common/keyhandler.c xen/common/schedule.c xen/common/softirq.c xen/drivers/char/console.c xen/drivers/char/serial.c xen/include/asm-x86/mm.h xen/include/public/arch-x86_32.h xen/include/public/arch-x86_64.h xen/include/public/io/domain_controller.h xen/include/public/xen.h xen/include/xen/domain.h xen/include/xen/grant_table.h xen/include/xen/slab.h
line diff
     1.1 --- a/.rootkeys	Fri Jan 21 13:52:28 2005 +0000
     1.2 +++ b/.rootkeys	Mon Jan 24 10:19:03 2005 +0000
     1.3 @@ -63,6 +63,16 @@ 40420a6ebRqDjufoN1WSJvolEW2Wjw linux-2.4
     1.4  4083dc16-Kd5y9psK_yk161sme5j5Q linux-2.4.29-xen-sparse/arch/xen/drivers/netif/Makefile
     1.5  4083dc16UmHXxS9g_UFVnkUpN-oP2Q linux-2.4.29-xen-sparse/arch/xen/drivers/netif/backend/Makefile
     1.6  405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.29-xen-sparse/arch/xen/drivers/netif/frontend/Makefile
     1.7 +41ee5e8b_2rt-qHzbDXtIoBzOli0EA linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/Makefile
     1.8 +41ee5e8bUhF4tH7OoJaVbUxdXqneVw linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/Makefile
     1.9 +41ee5e8bYDQkjRVKnFn5uFyy0KreCw linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/common.h
    1.10 +41ee5e8bt7xeBUJqG5XJS-ofukdsgA linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/control.c
    1.11 +41ee5e8bSs3BGC7yegM_ek2Tn0Ahvw linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/interface.c
    1.12 +41ee5e8bglvqKvZSY5uJ5JGQejEwyQ linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/main.c
    1.13 +41ee5e8bSPpxzhGO6TrY20TegW3cZg linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/Makefile
    1.14 +41ee5e8ckZ9xVNvu9NHIZDK7JqApmQ linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/main.c
    1.15 +41ee5e8ck9scpGirfqEZRARbGDyTXA linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/xhci.h
    1.16 +41ee5e8c6mLxIx82KPsbpt_uts_vSA linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/usbif.h
    1.17  3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.29-xen-sparse/arch/xen/kernel/Makefile
    1.18  3e5a4e65_hqfuxtGG8IUy6wRM86Ecg linux-2.4.29-xen-sparse/arch/xen/kernel/entry.S
    1.19  3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg linux-2.4.29-xen-sparse/arch/xen/kernel/head.S
    1.20 @@ -680,6 +690,7 @@ 40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/pyt
    1.21  40c9c4694eu5759Dehr4Uhakei0EMg tools/python/xen/xend/server/SrvNode.py
    1.22  40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
    1.23  40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
    1.24 +41ee5e8cFlODpYxhBMZqo9ZgGtcHbg tools/python/xen/xend/server/SrvUsbif.py
    1.25  40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
    1.26  4108f181GtRoD1U9TBuJXMfBbGJwdQ tools/python/xen/xend/server/SrvXendLog.py
    1.27  40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
    1.28 @@ -691,6 +702,7 @@ 40d83983OXjt-y3HjSCcuoPp9rzvmw tools/pyt
    1.29  40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py
    1.30  40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
    1.31  40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py
    1.32 +41ee5e8dq9NtihbL4nWKjuSLOhXPUg tools/python/xen/xend/server/usbif.py
    1.33  40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
    1.34  4189125cL90jKSOcBJ3Vx4nWGiXXvA tools/python/xen/xend/util.py
    1.35  40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
     2.1 --- a/docs/src/user.tex	Fri Jan 21 13:52:28 2005 +0000
     2.2 +++ b/docs/src/user.tex	Mon Jan 24 10:19:03 2005 +0000
     2.3 @@ -1770,7 +1770,7 @@ editing \path{grub.conf}.
     2.4   possibilities are `bvt' (default), `atropos' and `rrobin'. 
     2.5   For more information see Section~\ref{s:sched}. 
     2.6  
     2.7 -\item [pci\_dom0\_hide=(xx.xx.x)(yy.yy.y)\ldots ] 
     2.8 +\item [physdev\_dom0\_hide=(xx:xx.x)(yy:yy.y)\ldots ]
     2.9  Hide selected PCI devices from domain 0 (for instance, to stop it
    2.10  taking ownership of them so that they can be driven by another
    2.11  domain).  Device IDs should be given in hex format.  Bridge devices do
     3.1 --- a/linux-2.4.29-xen-sparse/arch/xen/Makefile	Fri Jan 21 13:52:28 2005 +0000
     3.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/Makefile	Mon Jan 24 10:19:03 2005 +0000
     3.3 @@ -61,6 +61,7 @@ SUBDIRS += arch/xen/drivers/console
     3.4  SUBDIRS += arch/xen/drivers/evtchn
     3.5  SUBDIRS += arch/xen/drivers/blkif
     3.6  SUBDIRS += arch/xen/drivers/netif
     3.7 +SUBDIRS += arch/xen/drivers/usbif
     3.8  SUBDIRS += arch/xen/drivers/balloon
     3.9  ifdef CONFIG_XEN_PRIVILEGED_GUEST
    3.10  SUBDIRS += arch/xen/drivers/dom0 
    3.11 @@ -71,6 +72,7 @@ CORE_FILES += arch/xen/drivers/evtchn/dr
    3.12  CORE_FILES += arch/xen/drivers/console/drv.o
    3.13  DRIVERS += arch/xen/drivers/blkif/drv.o
    3.14  DRIVERS += arch/xen/drivers/netif/drv.o
    3.15 +DRIVERS += arch/xen/drivers/usbif/drv.o
    3.16  ifdef CONFIG_XEN_PRIVILEGED_GUEST
    3.17  CORE_FILES += arch/xen/drivers/dom0/drv.o
    3.18  endif
     4.1 --- a/linux-2.4.29-xen-sparse/arch/xen/config.in	Fri Jan 21 13:52:28 2005 +0000
     4.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/config.in	Mon Jan 24 10:19:03 2005 +0000
     4.3 @@ -16,14 +16,18 @@ mainmenu_option next_comment
     4.4  comment 'Xen'
     4.5  bool 'Support for privileged operations (domain 0)' CONFIG_XEN_PRIVILEGED_GUEST
     4.6  bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS
     4.7 +if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
     4.8 +    bool 'USB-device backend driver' CONFIG_XEN_USB_BACKEND
     4.9 +fi
    4.10  bool 'Scrub memory before freeing it to Xen' CONFIG_XEN_SCRUB_PAGES
    4.11  bool 'Network-device frontend driver' CONFIG_XEN_NETDEV_FRONTEND
    4.12  bool 'Block-device frontend driver' CONFIG_XEN_BLKDEV_FRONTEND
    4.13 +bool 'USB-device frontend driver' CONFIG_XEN_USB_FRONTEND
    4.14  endmenu
    4.15  # The IBM S/390 patch needs this.
    4.16  define_bool CONFIG_NO_IDLE_HZ y
    4.17  
    4.18 -if [ "$CONFIG_XEN_PHYSDEV_ACCESS" == "y" ]; then
    4.19 +if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
    4.20     define_bool CONFIG_FOREIGN_PAGES y
    4.21  else
    4.22     define_bool CONFIG_FOREIGN_PAGES n
    4.23 @@ -262,7 +266,7 @@ fi
    4.24  
    4.25  source drivers/char/Config.in
    4.26  
    4.27 -if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
    4.28 +if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" -o "$CONFIG_XEN_USB_FRONTEND" = "y" ]; then
    4.29     source drivers/media/Config.in
    4.30  fi
    4.31  
    4.32 @@ -295,9 +299,16 @@ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" 
    4.33        source drivers/sound/Config.in
    4.34     fi
    4.35     endmenu
    4.36 +fi
    4.37  
    4.38 +if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" -o "$CONFIG_XEN_USB_FRONTEND" = "y" ]; then
    4.39 +   if [ "$CONFIG_XEN_USB_FRONTEND" = "y" -o "$CONFIG_XEN_USB_BACKEND" = "y" ]; then
    4.40 +       define_bool CONFIG_USB y
    4.41 +   fi
    4.42     source drivers/usb/Config.in
    4.43 +fi
    4.44  
    4.45 +if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
    4.46     source net/bluetooth/Config.in
    4.47  fi
    4.48  
     5.1 --- a/linux-2.4.29-xen-sparse/arch/xen/defconfig-xen0	Fri Jan 21 13:52:28 2005 +0000
     5.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/defconfig-xen0	Mon Jan 24 10:19:03 2005 +0000
     5.3 @@ -12,9 +12,11 @@ CONFIG_UID16=y
     5.4  #
     5.5  CONFIG_XEN_PRIVILEGED_GUEST=y
     5.6  CONFIG_XEN_PHYSDEV_ACCESS=y
     5.7 +# CONFIG_XEN_USB_BACKEND is not set
     5.8  CONFIG_XEN_SCRUB_PAGES=y
     5.9  CONFIG_XEN_NETDEV_FRONTEND=y
    5.10  CONFIG_XEN_BLKDEV_FRONTEND=y
    5.11 +# CONFIG_XEN_USB_FRONTEND is not set
    5.12  CONFIG_NO_IDLE_HZ=y
    5.13  CONFIG_FOREIGN_PAGES=y
    5.14  
     6.1 --- a/linux-2.4.29-xen-sparse/arch/xen/defconfig-xenU	Fri Jan 21 13:52:28 2005 +0000
     6.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/defconfig-xenU	Mon Jan 24 10:19:03 2005 +0000
     6.3 @@ -15,6 +15,7 @@ CONFIG_UID16=y
     6.4  CONFIG_XEN_SCRUB_PAGES=y
     6.5  CONFIG_XEN_NETDEV_FRONTEND=y
     6.6  CONFIG_XEN_BLKDEV_FRONTEND=y
     6.7 +# CONFIG_XEN_USB_FRONTEND is not set
     6.8  CONFIG_NO_IDLE_HZ=y
     6.9  # CONFIG_FOREIGN_PAGES is not set
    6.10  CONFIG_NETDEVICES=y
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/Makefile	Mon Jan 24 10:19:03 2005 +0000
     7.3 @@ -0,0 +1,10 @@
     7.4 +
     7.5 +O_TARGET := drv.o
     7.6 +
     7.7 +subdir-$(CONFIG_XEN_USB_FRONTEND) += frontend
     7.8 +obj-$(CONFIG_XEN_USB_FRONTEND) += frontend/drv.o
     7.9 +
    7.10 +subdir-$(CONFIG_XEN_USB_BACKEND) += backend
    7.11 +obj-$(CONFIG_XEN_USB_BACKEND)    += backend/drv.o
    7.12 +
    7.13 +include $(TOPDIR)/Rules.make
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/Makefile	Mon Jan 24 10:19:03 2005 +0000
     8.3 @@ -0,0 +1,3 @@
     8.4 +O_TARGET := drv.o
     8.5 +obj-y := main.o interface.o control.o # vrh.o don't think I need this!
     8.6 +include $(TOPDIR)/Rules.make
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/common.h	Mon Jan 24 10:19:03 2005 +0000
     9.3 @@ -0,0 +1,87 @@
     9.4 +
     9.5 +#ifndef __USBIF__BACKEND__COMMON_H__
     9.6 +#define __USBIF__BACKEND__COMMON_H__
     9.7 +
     9.8 +#include <linux/config.h>
     9.9 +#include <linux/version.h>
    9.10 +#include <linux/module.h>
    9.11 +#include <linux/rbtree.h>
    9.12 +#include <linux/interrupt.h>
    9.13 +#include <linux/slab.h>
    9.14 +#include <linux/blkdev.h>
    9.15 +#include <asm/io.h>
    9.16 +#include <asm/setup.h>
    9.17 +#include <asm/pgalloc.h>
    9.18 +#include <asm-xen/ctrl_if.h>
    9.19 +#include <asm-xen/hypervisor.h>
    9.20 +
    9.21 +#include "../usbif.h"
    9.22 +
    9.23 +#if 0
    9.24 +#define ASSERT(_p) \
    9.25 +    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
    9.26 +    __LINE__, __FILE__); *(int*)0=0; }
    9.27 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
    9.28 +                           __FILE__ , __LINE__ , ## _a )
    9.29 +#else
    9.30 +#define ASSERT(_p) ((void)0)
    9.31 +#define DPRINTK(_f, _a...) ((void)0)
    9.32 +#endif
    9.33 +
    9.34 +typedef struct usbif_priv_st usbif_priv_t;
    9.35 +
    9.36 +struct usbif_priv_st {
    9.37 +    /* Unique identifier for this interface. */
    9.38 +    domid_t          domid;
    9.39 +    unsigned int     handle;
    9.40 +    /* Physical parameters of the comms window. */
    9.41 +    unsigned long    shmem_frame;
    9.42 +    unsigned int     evtchn;
    9.43 +    int              irq;
    9.44 +    /* Comms information. */
    9.45 +    usbif_t      *usb_ring_base; /* ioremap()'ed ptr to shmem_frame. */
    9.46 +    USBIF_RING_IDX     usb_req_cons;  /* Request consumer. */
    9.47 +    USBIF_RING_IDX     usb_resp_prod; /* Private version of resp. producer. */
    9.48 +    /* Private fields. */
    9.49 +    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
    9.50 +    /*
    9.51 +     * DISCONNECT response is deferred until pending requests are ack'ed.
    9.52 +     * We therefore need to store the id from the original request.
    9.53 +     */
    9.54 +    u8                   disconnect_rspid;
    9.55 +    usbif_priv_t *hash_next;
    9.56 +    struct list_head     usbif_list;
    9.57 +    spinlock_t           usb_ring_lock;
    9.58 +    atomic_t             refcnt;
    9.59 +    atomic_t             work_scheduled;
    9.60 +
    9.61 +    struct work_struct work;
    9.62 +};
    9.63 +
    9.64 +void usbif_create(usbif_be_create_t *create);
    9.65 +void usbif_destroy(usbif_be_destroy_t *destroy);
    9.66 +void usbif_connect(usbif_be_connect_t *connect);
    9.67 +int  usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id);
    9.68 +void usbif_disconnect_complete(usbif_priv_t *up);
    9.69 +
    9.70 +void usbif_release_port(usbif_be_release_port_t *msg);
    9.71 +int usbif_claim_port(usbif_be_claim_port_t *msg);
    9.72 +void usbif_release_ports(usbif_priv_t *up);
    9.73 +
    9.74 +usbif_priv_t *usbif_find(domid_t domid);
    9.75 +#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
    9.76 +#define usbif_put(_b)                             \
    9.77 +    do {                                          \
    9.78 +        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
    9.79 +            usbif_disconnect_complete(_b);        \
    9.80 +    } while (0)
    9.81 +
    9.82 +
    9.83 +void usbif_interface_init(void);
    9.84 +void usbif_ctrlif_init(void);
    9.85 +
    9.86 +void usbif_deschedule(usbif_priv_t *usbif);
    9.87 +
    9.88 +irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs);
    9.89 +
    9.90 +#endif /* __USBIF__BACKEND__COMMON_H__ */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/control.c	Mon Jan 24 10:19:03 2005 +0000
    10.3 @@ -0,0 +1,77 @@
    10.4 +/******************************************************************************
    10.5 + * arch/xen/drivers/usbif/backend/control.c
    10.6 + * 
    10.7 + * Routines for interfacing with the control plane.
    10.8 + * 
    10.9 + * Copyright (c) 2004, Keir Fraser
   10.10 + */
   10.11 +
   10.12 +#include "common.h"
   10.13 +
   10.14 +static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
   10.15 +{
   10.16 +    DPRINTK("Received usbif backend message, subtype=%d\n", msg->subtype);
   10.17 +    
   10.18 +    switch ( msg->subtype )
   10.19 +    {
   10.20 +    case CMSG_USBIF_BE_CREATE:
   10.21 +        if ( msg->length != sizeof(usbif_be_create_t) )
   10.22 +            goto parse_error;
   10.23 +        usbif_create((usbif_be_create_t *)&msg->msg[0]);
   10.24 +        break;        
   10.25 +    case CMSG_USBIF_BE_DESTROY:
   10.26 +        if ( msg->length != sizeof(usbif_be_destroy_t) )
   10.27 +            goto parse_error;
   10.28 +        usbif_destroy((usbif_be_destroy_t *)&msg->msg[0]);
   10.29 +        break;        
   10.30 +    case CMSG_USBIF_BE_CONNECT:
   10.31 +        if ( msg->length != sizeof(usbif_be_connect_t) )
   10.32 +            goto parse_error;
   10.33 +        usbif_connect((usbif_be_connect_t *)&msg->msg[0]);
   10.34 +        break;        
   10.35 +    case CMSG_USBIF_BE_DISCONNECT:
   10.36 +        if ( msg->length != sizeof(usbif_be_disconnect_t) )
   10.37 +            goto parse_error;
   10.38 +        if ( !usbif_disconnect((usbif_be_disconnect_t *)&msg->msg[0],msg->id) )
   10.39 +            return; /* Sending the response is deferred until later. */
   10.40 +        break;        
   10.41 +    case CMSG_USBIF_BE_CLAIM_PORT:
   10.42 +        if ( msg->length != sizeof(usbif_be_claim_port_t) )
   10.43 +            goto parse_error;
   10.44 +	usbif_claim_port((usbif_be_claim_port_t *)&msg->msg[0]);
   10.45 +        break;
   10.46 +    case CMSG_USBIF_BE_RELEASE_PORT:
   10.47 +        if ( msg->length != sizeof(usbif_be_release_port_t) )
   10.48 +            goto parse_error;
   10.49 +        usbif_release_port((usbif_be_release_port_t *)&msg->msg[0]);
   10.50 +        break;
   10.51 +    default:
   10.52 +        goto parse_error;
   10.53 +    }
   10.54 +
   10.55 +    ctrl_if_send_response(msg);
   10.56 +    return;
   10.57 +
   10.58 + parse_error:
   10.59 +    DPRINTK("Parse error while reading message subtype %d, len %d\n",
   10.60 +            msg->subtype, msg->length);
   10.61 +    msg->length = 0;
   10.62 +    ctrl_if_send_response(msg);
   10.63 +}
   10.64 +
   10.65 +void usbif_ctrlif_init(void)
   10.66 +{
   10.67 +    ctrl_msg_t                       cmsg;
   10.68 +    usbif_be_driver_status_changed_t st;
   10.69 +
   10.70 +    (void)ctrl_if_register_receiver(CMSG_USBIF_BE, usbif_ctrlif_rx, 
   10.71 +                                    CALLBACK_IN_BLOCKING_CONTEXT);
   10.72 +
   10.73 +    /* Send a driver-UP notification to the domain controller. */
   10.74 +    cmsg.type      = CMSG_USBIF_BE;
   10.75 +    cmsg.subtype   = CMSG_USBIF_BE_DRIVER_STATUS_CHANGED;
   10.76 +    cmsg.length    = sizeof(usbif_be_driver_status_changed_t);
   10.77 +    st.status      = USBIF_DRIVER_STATUS_UP;
   10.78 +    memcpy(cmsg.msg, &st, sizeof(st));
   10.79 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   10.80 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/interface.c	Mon Jan 24 10:19:03 2005 +0000
    11.3 @@ -0,0 +1,248 @@
    11.4 +/******************************************************************************
    11.5 + * arch/xen/drivers/usbif/backend/interface.c
    11.6 + * 
    11.7 + * USB device interface management.
    11.8 + * 
    11.9 + * by Mark Williamson, Copyright (c) 2004
   11.10 + */
   11.11 +
   11.12 +
   11.13 +/******************************************************************************
   11.14 + * arch/xen/drivers/blkif/backend/interface.c
   11.15 + * 
   11.16 + * Block-device interface management.
   11.17 + * 
   11.18 + * Copyright (c) 2004, Keir Fraser
   11.19 + */
   11.20 +
   11.21 +#include "common.h"
   11.22 +
   11.23 +#define USBIF_HASHSZ 1024
   11.24 +#define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1))
   11.25 +
   11.26 +static kmem_cache_t      *usbif_priv_cachep;
   11.27 +static usbif_priv_t      *usbif_priv_hash[USBIF_HASHSZ];
   11.28 +
   11.29 +usbif_priv_t *usbif_find(domid_t domid)
   11.30 +{
   11.31 +    usbif_priv_t *up = usbif_priv_hash[USBIF_HASH(domid)];
   11.32 +    while ( (up != NULL ) && ( up->domid != domid ) )
   11.33 +        up = up->hash_next;
   11.34 +    return up;
   11.35 +}
   11.36 +
   11.37 +static void __usbif_disconnect_complete(void *arg)
   11.38 +{
   11.39 +    usbif_priv_t         *usbif = (usbif_priv_t *)arg;
   11.40 +    ctrl_msg_t            cmsg;
   11.41 +    usbif_be_disconnect_t disc;
   11.42 +
   11.43 +    /*
   11.44 +     * These can't be done in usbif_disconnect() because at that point there
   11.45 +     * may be outstanding requests at the device whose asynchronous responses
   11.46 +     * must still be notified to the remote driver.
   11.47 +     */
   11.48 +    unbind_evtchn_from_irq(usbif->evtchn);
   11.49 +    vfree(usbif->usb_ring_base);
   11.50 +
   11.51 +    /* Construct the deferred response message. */
   11.52 +    cmsg.type         = CMSG_USBIF_BE;
   11.53 +    cmsg.subtype      = CMSG_USBIF_BE_DISCONNECT;
   11.54 +    cmsg.id           = usbif->disconnect_rspid;
   11.55 +    cmsg.length       = sizeof(usbif_be_disconnect_t);
   11.56 +    disc.domid        = usbif->domid;
   11.57 +    disc.status       = USBIF_BE_STATUS_OKAY;
   11.58 +    memcpy(cmsg.msg, &disc, sizeof(disc));
   11.59 +
   11.60 +    /*
   11.61 +     * Make sure message is constructed /before/ status change, because
   11.62 +     * after the status change the 'usbif' structure could be deallocated at
   11.63 +     * any time. Also make sure we send the response /after/ status change,
   11.64 +     * as otherwise a subsequent CONNECT request could spuriously fail if
   11.65 +     * another CPU doesn't see the status change yet.
   11.66 +     */
   11.67 +    mb();
   11.68 +    if ( usbif->status != DISCONNECTING )
   11.69 +        BUG();
   11.70 +    usbif->status = DISCONNECTED;
   11.71 +    mb();
   11.72 +
   11.73 +    /* Send the successful response. */
   11.74 +    ctrl_if_send_response(&cmsg);
   11.75 +}
   11.76 +
   11.77 +void usbif_disconnect_complete(usbif_priv_t *up)
   11.78 +{
   11.79 +    INIT_WORK(&up->work, __usbif_disconnect_complete, (void *)up);
   11.80 +    schedule_work(&up->work);
   11.81 +}
   11.82 +
   11.83 +void usbif_create(usbif_be_create_t *create)
   11.84 +{
   11.85 +    domid_t       domid  = create->domid;
   11.86 +    usbif_priv_t **pup, *up;
   11.87 +
   11.88 +    if ( (up = kmem_cache_alloc(usbif_priv_cachep, GFP_KERNEL)) == NULL )
   11.89 +    {
   11.90 +        DPRINTK("Could not create usbif: out of memory\n");
   11.91 +        create->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
   11.92 +        return;
   11.93 +    }
   11.94 +
   11.95 +    memset(up, 0, sizeof(*up));
   11.96 +    up->domid  = domid;
   11.97 +    up->status = DISCONNECTED;
   11.98 +    spin_lock_init(&up->usb_ring_lock);
   11.99 +    atomic_set(&up->refcnt, 0);
  11.100 +
  11.101 +    pup = &usbif_priv_hash[USBIF_HASH(domid)];
  11.102 +    while ( *pup != NULL )
  11.103 +    {
  11.104 +        if ( (*pup)->domid == domid )
  11.105 +        {
  11.106 +            create->status = USBIF_BE_STATUS_INTERFACE_EXISTS;
  11.107 +            kmem_cache_free(usbif_priv_cachep, up);
  11.108 +            return;
  11.109 +        }
  11.110 +        pup = &(*pup)->hash_next;
  11.111 +    }
  11.112 +
  11.113 +    up->hash_next = *pup;
  11.114 +    *pup = up;
  11.115 +
  11.116 +    create->status = USBIF_BE_STATUS_OKAY;
  11.117 +}
  11.118 +
  11.119 +void usbif_destroy(usbif_be_destroy_t *destroy)
  11.120 +{
  11.121 +    domid_t       domid  = destroy->domid;
  11.122 +    usbif_priv_t  **pup, *up;
  11.123 +
  11.124 +    pup = &usbif_priv_hash[USBIF_HASH(domid)];
  11.125 +    while ( (up = *pup) != NULL )
  11.126 +    {
  11.127 +        if ( up->domid == domid )
  11.128 +        {
  11.129 +            if ( up->status != DISCONNECTED )
  11.130 +                goto still_connected;
  11.131 +            goto destroy;
  11.132 +        }
  11.133 +        pup = &up->hash_next;
  11.134 +    }
  11.135 +
  11.136 +    destroy->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.137 +    return;
  11.138 +
  11.139 + still_connected:
  11.140 +    destroy->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
  11.141 +    return;
  11.142 +
  11.143 + destroy:
  11.144 +    *pup = up->hash_next;
  11.145 +    usbif_release_ports(up);
  11.146 +    kmem_cache_free(usbif_priv_cachep, up);
  11.147 +    destroy->status = USBIF_BE_STATUS_OKAY;
  11.148 +}
  11.149 +
  11.150 +void usbif_connect(usbif_be_connect_t *connect)
  11.151 +{
  11.152 +    domid_t       domid  = connect->domid;
  11.153 +    unsigned int  evtchn = connect->evtchn;
  11.154 +    unsigned long shmem_frame = connect->shmem_frame;
  11.155 +    struct vm_struct *vma;
  11.156 +    pgprot_t      prot;
  11.157 +    int           error;
  11.158 +    usbif_priv_t *up;
  11.159 +
  11.160 +    up = usbif_find(domid);
  11.161 +    if ( unlikely(up == NULL) )
  11.162 +    {
  11.163 +        DPRINTK("usbif_connect attempted for non-existent usbif (%u)\n", 
  11.164 +                connect->domid); 
  11.165 +        connect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.166 +        return;
  11.167 +    }
  11.168 +
  11.169 +    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
  11.170 +    {
  11.171 +        connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
  11.172 +        return;
  11.173 +    }
  11.174 +
  11.175 +    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
  11.176 +    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
  11.177 +                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
  11.178 +                                    prot, domid);
  11.179 +    if ( error != 0 )
  11.180 +    {
  11.181 +        if ( error == -ENOMEM )
  11.182 +            connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
  11.183 +        else if ( error == -EFAULT )
  11.184 +            connect->status = USBIF_BE_STATUS_MAPPING_ERROR;
  11.185 +        else
  11.186 +            connect->status = USBIF_BE_STATUS_ERROR;
  11.187 +        vfree(vma->addr);
  11.188 +        return;
  11.189 +    }
  11.190 +
  11.191 +    if ( up->status != DISCONNECTED )
  11.192 +    {
  11.193 +        connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
  11.194 +        vfree(vma->addr);
  11.195 +        return;
  11.196 +    }
  11.197 +
  11.198 +    up->evtchn        = evtchn;
  11.199 +    up->irq           = bind_evtchn_to_irq(evtchn);
  11.200 +    up->shmem_frame   = shmem_frame;
  11.201 +    up->usb_ring_base = (usbif_t *)vma->addr;
  11.202 +    up->status        = CONNECTED;
  11.203 +    usbif_get(up);
  11.204 +
  11.205 +    request_irq(up->irq, usbif_be_int, 0, "usbif-backend", up);
  11.206 +
  11.207 +    connect->status = USBIF_BE_STATUS_OKAY;
  11.208 +}
  11.209 +
  11.210 +/* Remove URBs for this interface before destroying it. */
  11.211 +void usbif_deschedule(usbif_priv_t *up)
  11.212 +{
  11.213 +    remove_from_usbif_list(up);
  11.214 +}
  11.215 +
  11.216 +int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id)
  11.217 +{
  11.218 +    domid_t       domid  = disconnect->domid;
  11.219 +    usbif_priv_t *up;
  11.220 +
  11.221 +    up = usbif_find(domid);
  11.222 +    if ( unlikely(up == NULL) )
  11.223 +    {
  11.224 +        DPRINTK("usbif_disconnect attempted for non-existent usbif"
  11.225 +                " (%u)\n", disconnect->domid); 
  11.226 +        disconnect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  11.227 +        return 1; /* Caller will send response error message. */
  11.228 +    }
  11.229 +
  11.230 +    if ( up->status == CONNECTED )
  11.231 +    {
  11.232 +        up->status = DISCONNECTING;
  11.233 +        up->disconnect_rspid = rsp_id;
  11.234 +        wmb(); /* Let other CPUs see the status change. */
  11.235 +        free_irq(up->irq, up);
  11.236 +	usbif_deschedule(up);
  11.237 +        usbif_put(up);
  11.238 +        return 0; /* Caller should not send response message. */
  11.239 +    }
  11.240 +
  11.241 +    disconnect->status = USBIF_BE_STATUS_OKAY;
  11.242 +    return 1;
  11.243 +}
  11.244 +
  11.245 +void __init usbif_interface_init(void)
  11.246 +{
  11.247 +    usbif_priv_cachep = kmem_cache_create("usbif_priv_cache",
  11.248 +					  sizeof(usbif_priv_t), 
  11.249 +					  0, 0, NULL, NULL);
  11.250 +    memset(usbif_priv_hash, 0, sizeof(usbif_priv_hash));
  11.251 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/main.c	Mon Jan 24 10:19:03 2005 +0000
    12.3 @@ -0,0 +1,1011 @@
    12.4 +/******************************************************************************
    12.5 + * arch/xen/drivers/usbif/backend/main.c
    12.6 + * 
    12.7 + * Backend for the Xen virtual USB driver - provides an abstraction of a
    12.8 + * USB host controller to the corresponding frontend driver.
    12.9 + *
   12.10 + * by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge
   12.11 + *
   12.12 + * Based on arch/xen/drivers/blkif/backend/main.c
   12.13 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
   12.14 + */
   12.15 +
   12.16 +#include "common.h"
   12.17 +
   12.18 +
   12.19 +#include <linux/list.h>
   12.20 +#include <linux/usb.h>
   12.21 +#include <linux/spinlock.h>
   12.22 +#include <linux/module.h>
   12.23 +#include <linux/tqueue.h>
   12.24 +
   12.25 +/*
   12.26 + * This is rather arbitrary.
   12.27 + */
   12.28 +#define MAX_PENDING_REQS 4
   12.29 +#define BATCH_PER_DOMAIN 1
   12.30 +
   12.31 +static unsigned long mmap_vstart;
   12.32 +
   12.33 +/* Needs to be sufficiently large that we can map the (large) buffers
   12.34 + * the USB mass storage driver wants. */
   12.35 +#define MMAP_PAGES_PER_REQUEST \
   12.36 +    (128)
   12.37 +#define MMAP_PAGES             \
   12.38 +    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
   12.39 +
   12.40 +#define MMAP_VADDR(_req,_seg)                        \
   12.41 +    (mmap_vstart +                                   \
   12.42 +     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
   12.43 +     ((_seg) * PAGE_SIZE))
   12.44 +
   12.45 +#define MIN(x,y) ( ( x < y ) ? x : y )
   12.46 +
   12.47 +static spinlock_t owned_ports_lock;
   12.48 +LIST_HEAD(owned_ports);
   12.49 +
   12.50 +/* A list of these structures is used to track ownership of physical USB
   12.51 + * ports. */
   12.52 +typedef struct 
   12.53 +{
   12.54 +    usbif_priv_t     *usbif_priv;
   12.55 +    char             path[16];
   12.56 +    int               guest_port;
   12.57 +    int enabled;
   12.58 +    struct list_head  list;
   12.59 +    unsigned long guest_address; /* The USB device address that has been
   12.60 +                                  * assigned by the guest. */
   12.61 +    int               dev_present; /* Is there a device present? */
   12.62 +    struct usb_device * dev;
   12.63 +    unsigned long ifaces;  /* What interfaces are present on this device? */
   12.64 +} owned_port_t;
   12.65 +
   12.66 +
   12.67 +/*
   12.68 + * Each outstanding request that we've passed to the lower device layers has a
   12.69 + * 'pending_req' allocated to it.  The request is complete, the specified
   12.70 + * domain has a response queued for it, with the saved 'id' passed back.
   12.71 + */
   12.72 +typedef struct {
   12.73 +    usbif_priv_t       *usbif_priv;
   12.74 +    usbif_iso_t        *iso_sched;
   12.75 +    unsigned long      id;
   12.76 +    int                nr_pages;
   12.77 +    unsigned short     operation;
   12.78 +    int                status;
   12.79 +} pending_req_t;
   12.80 +
   12.81 +/*
   12.82 + * We can't allocate pending_req's in order, since they may complete out of 
   12.83 + * order. We therefore maintain an allocation ring. This ring also indicates 
   12.84 + * when enough work has been passed down -- at that point the allocation ring 
   12.85 + * will be empty.
   12.86 + */
   12.87 +static pending_req_t pending_reqs[MAX_PENDING_REQS];
   12.88 +static unsigned char pending_ring[MAX_PENDING_REQS];
   12.89 +static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
   12.90 +
   12.91 +/* NB. We use a different index type to differentiate from shared blk rings. */
   12.92 +typedef unsigned int PEND_RING_IDX;
   12.93 +#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
   12.94 +static PEND_RING_IDX pending_prod, pending_cons;
   12.95 +#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
   12.96 +
   12.97 +static int do_usb_io_op(usbif_priv_t *usbif, int max_to_do);
   12.98 +static void make_response(usbif_priv_t *usbif, unsigned long id, 
   12.99 +                          unsigned short op, int st, int inband,
  12.100 +			  unsigned long actual_length);
  12.101 +static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long port);
  12.102 +static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req);    
  12.103 +static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid);
  12.104 +static owned_port_t *usbif_find_port(char *);
  12.105 +
  12.106 +
  12.107 +void dump_port(owned_port_t *p)
  12.108 +{
  12.109 +    printk("owned_port_t @ %p\n", p);
  12.110 +    printk("  usbif_priv @ %p\n", p->usbif_priv);
  12.111 +    printk("  path: %s\n", p->path);
  12.112 +    printk("  guest_port: %d\n", p->guest_port);
  12.113 +    printk("  guest_address: %ld\n", p->guest_address);
  12.114 +    printk("  dev_present: %d\n", p->dev_present);
  12.115 +    printk("  dev @ %p\n", p->dev);
  12.116 +    printk("  ifaces: 0x%lx\n", p->ifaces);
  12.117 +}
  12.118 +
  12.119 +
  12.120 +
  12.121 +static void fast_flush_area(int idx, int nr_pages)
  12.122 +{
  12.123 +    multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
  12.124 +    int               i;
  12.125 +
  12.126 +    for ( i = 0; i < nr_pages; i++ )
  12.127 +    {
  12.128 +        mcl[i].op = __HYPERVISOR_update_va_mapping;
  12.129 +        mcl[i].args[0] = MMAP_VADDR(idx, i) >> PAGE_SHIFT;
  12.130 +        mcl[i].args[1] = 0;
  12.131 +        mcl[i].args[2] = 0;
  12.132 +    }
  12.133 +
  12.134 +    mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB;
  12.135 +    if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
  12.136 +        BUG();
  12.137 +}
  12.138 +
  12.139 +
  12.140 +/******************************************************************
  12.141 + * USB INTERFACE SCHEDULER LIST MAINTENANCE
  12.142 + */
  12.143 +
  12.144 +static struct list_head usbio_schedule_list;
  12.145 +static spinlock_t usbio_schedule_list_lock;
  12.146 +
  12.147 +static int __on_usbif_list(usbif_priv_t *up)
  12.148 +{
  12.149 +    return up->usbif_list.next != NULL;
  12.150 +}
  12.151 +
  12.152 +void remove_from_usbif_list(usbif_priv_t *up)
  12.153 +{
  12.154 +    unsigned long flags;
  12.155 +    if ( !__on_usbif_list(up) ) return;
  12.156 +    spin_lock_irqsave(&usbio_schedule_list_lock, flags);
  12.157 +    if ( __on_usbif_list(up) )
  12.158 +    {
  12.159 +        list_del(&up->usbif_list);
  12.160 +        up->usbif_list.next = NULL;
  12.161 +        usbif_put(up);
  12.162 +    }
  12.163 +    spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
  12.164 +}
  12.165 +
  12.166 +static void add_to_usbif_list_tail(usbif_priv_t *up)
  12.167 +{
  12.168 +    unsigned long flags;
  12.169 +    if ( __on_usbif_list(up) ) return;
  12.170 +    spin_lock_irqsave(&usbio_schedule_list_lock, flags);
  12.171 +    if ( !__on_usbif_list(up) && (up->status == CONNECTED) )
  12.172 +    {
  12.173 +        list_add_tail(&up->usbif_list, &usbio_schedule_list);
  12.174 +        usbif_get(up);
  12.175 +    }
  12.176 +    spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
  12.177 +}
  12.178 +
  12.179 +
  12.180 +/******************************************************************
  12.181 + * COMPLETION CALLBACK -- Called as urb->complete()
  12.182 + */
  12.183 +
  12.184 +static void maybe_trigger_usbio_schedule(void);
  12.185 +
  12.186 +static void __end_usb_io_op(struct urb *purb)
  12.187 +{
  12.188 +    unsigned long flags;
  12.189 +    pending_req_t *pending_req;
  12.190 +    int pending_idx;
  12.191 +
  12.192 +    pending_req = purb->context;
  12.193 +
  12.194 +/*     printk("Completed for id = %p to 0x%lx - 0x%lx\n", pending_req->id, */
  12.195 +/*            virt_to_machine(purb->transfer_buffer), */
  12.196 +/*            virt_to_machine(purb->transfer_buffer) */
  12.197 +/*            + pending_req->nr_pages * PAGE_SIZE); */
  12.198 +
  12.199 +    pending_idx = pending_req - pending_reqs;
  12.200 +
  12.201 +    ASSERT(purb->actual_length <= purb->transfer_buffer_length);
  12.202 +    ASSERT(purb->actual_length <= pending_req->nr_pages * PAGE_SIZE);
  12.203 +    
  12.204 +    /* An error fails the entire request. */
  12.205 +    if ( purb->status )
  12.206 +    {
  12.207 +        printk("URB @ %p failed. Status %d\n", purb, purb->status);
  12.208 +    }
  12.209 +
  12.210 +    if ( usb_pipetype(purb->pipe) == 0 )
  12.211 +    {
  12.212 +        int i;
  12.213 +        usbif_iso_t *sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, pending_req->nr_pages - 1);
  12.214 +
  12.215 +        ASSERT(sched == pending_req->sched);
  12.216 +
  12.217 +	//	printk("writing back schedule at %p\n", sched);
  12.218 +
  12.219 +        /* If we're dealing with an iso pipe, we need to copy back the schedule. */
  12.220 +        for ( i = 0; i < purb->number_of_packets; i++ )
  12.221 +        {
  12.222 +            sched[i].length = purb->iso_frame_desc[i].actual_length;
  12.223 +            ASSERT(sched[i].buffer_offset ==
  12.224 +                   purb->iso_frame_desc[i].offset);
  12.225 +            sched[i].status = purb->iso_frame_desc[i].status;
  12.226 +        }
  12.227 +    }
  12.228 +    
  12.229 +    //    printk("Flushing %d pages\n", pending_req->nr_pages);
  12.230 +    fast_flush_area(pending_req - pending_reqs, pending_req->nr_pages);
  12.231 +
  12.232 +    kfree(purb->setup_packet);
  12.233 +
  12.234 +    spin_lock_irqsave(&pending_req->usbif_priv->usb_ring_lock, flags);
  12.235 +    make_response(pending_req->usbif_priv, pending_req->id,
  12.236 +		  pending_req->operation, pending_req->status, 0, purb->actual_length);
  12.237 +    spin_unlock_irqrestore(&pending_req->usbif_priv->usb_ring_lock, flags);
  12.238 +    usbif_put(pending_req->usbif_priv);
  12.239 +
  12.240 +    usb_free_urb(purb);
  12.241 +
  12.242 +    /* Free the pending request. */
  12.243 +    spin_lock_irqsave(&pend_prod_lock, flags);
  12.244 +    pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
  12.245 +    spin_unlock_irqrestore(&pend_prod_lock, flags);
  12.246 +
  12.247 +    rmb();
  12.248 +
  12.249 +    /* Check for anything still waiting in the rings, having freed a request... */
  12.250 +    maybe_trigger_usbio_schedule();
  12.251 +}
  12.252 +
  12.253 +/******************************************************************
  12.254 + * SCHEDULER FUNCTIONS
  12.255 + */
  12.256 +
  12.257 +static DECLARE_WAIT_QUEUE_HEAD(usbio_schedule_wait);
  12.258 +
  12.259 +static int usbio_schedule(void *arg)
  12.260 +{
  12.261 +    DECLARE_WAITQUEUE(wq, current);
  12.262 +
  12.263 +    usbif_priv_t          *up;
  12.264 +    struct list_head *ent;
  12.265 +
  12.266 +    daemonize();
  12.267 +
  12.268 +    for ( ; ; )
  12.269 +    {
  12.270 +        /* Wait for work to do. */
  12.271 +        add_wait_queue(&usbio_schedule_wait, &wq);
  12.272 +        set_current_state(TASK_INTERRUPTIBLE);
  12.273 +        if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || 
  12.274 +             list_empty(&usbio_schedule_list) )
  12.275 +            schedule();
  12.276 +        __set_current_state(TASK_RUNNING);
  12.277 +        remove_wait_queue(&usbio_schedule_wait, &wq);
  12.278 +
  12.279 +        /* Queue up a batch of requests. */
  12.280 +        while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
  12.281 +                !list_empty(&usbio_schedule_list) )
  12.282 +        {
  12.283 +            ent = usbio_schedule_list.next;
  12.284 +            up = list_entry(ent, usbif_priv_t, usbif_list);
  12.285 +            usbif_get(up);
  12.286 +            remove_from_usbif_list(up);
  12.287 +            if ( do_usb_io_op(up, BATCH_PER_DOMAIN) )
  12.288 +                add_to_usbif_list_tail(up);
  12.289 +            usbif_put(up);
  12.290 +        }
  12.291 +    }
  12.292 +}
  12.293 +
  12.294 +static void maybe_trigger_usbio_schedule(void)
  12.295 +{
  12.296 +    /*
  12.297 +     * Needed so that two processes, who together make the following predicate
  12.298 +     * true, don't both read stale values and evaluate the predicate
  12.299 +     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
  12.300 +     */
  12.301 +    smp_mb();
  12.302 +
  12.303 +    if ( !list_empty(&usbio_schedule_list) )
  12.304 +        wake_up(&usbio_schedule_wait);
  12.305 +}
  12.306 +
  12.307 +
  12.308 +/******************************************************************************
  12.309 + * NOTIFICATION FROM GUEST OS.
  12.310 + */
  12.311 +
  12.312 +irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs)
  12.313 +{
  12.314 +    usbif_priv_t *up = dev_id;
  12.315 +
  12.316 +    smp_mb();
  12.317 +
  12.318 +    add_to_usbif_list_tail(up); 
  12.319 +
  12.320 +    /* Will in fact /always/ trigger an io schedule in this case. */
  12.321 +    maybe_trigger_usbio_schedule();
  12.322 +
  12.323 +    return IRQ_HANDLED;
  12.324 +}
  12.325 +
  12.326 +
  12.327 +
  12.328 +/******************************************************************
  12.329 + * DOWNWARD CALLS -- These interface with the usb-device layer proper.
  12.330 + */
  12.331 +
  12.332 +static int do_usb_io_op(usbif_priv_t *up, int max_to_do)
  12.333 +{
  12.334 +    usbif_t *usb_ring = up->usb_ring_base;
  12.335 +    usbif_request_t *req;
  12.336 +    USBIF_RING_IDX i, rp;
  12.337 +    int more_to_do = 0;
  12.338 +    unsigned long flags;
  12.339 +
  12.340 +    spin_lock_irqsave(&up->usb_ring_lock, flags);
  12.341 +
  12.342 +    rp = usb_ring->req_prod;
  12.343 +    rmb(); /* Ensure we see queued requests up to 'rp'. */
  12.344 +    
  12.345 +    /* Take items off the comms ring, taking care not to overflow. */
  12.346 +    for ( i = up->usb_req_cons; 
  12.347 +          (i != rp) && ((i-up->usb_resp_prod) != USBIF_RING_SIZE);
  12.348 +          i++ )
  12.349 +    {
  12.350 +        if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
  12.351 +        {
  12.352 +            more_to_do = 1;
  12.353 +            break;
  12.354 +        }
  12.355 +
  12.356 +        req = &usb_ring->ring[MASK_USBIF_IDX(i)].req;
  12.357 +        
  12.358 +        switch ( req->operation )
  12.359 +        {
  12.360 +        case USBIF_OP_PROBE:
  12.361 +            dispatch_usb_probe(up, req->id, req->port);
  12.362 +            break;
  12.363 +
  12.364 +        case USBIF_OP_IO:
  12.365 +	  /* Assemble an appropriate URB. */
  12.366 +	  dispatch_usb_io(up, req);
  12.367 +          break;
  12.368 +
  12.369 +	case USBIF_OP_RESET:
  12.370 +	  dispatch_usb_reset(up, req->port);
  12.371 +          break;
  12.372 +
  12.373 +        default:
  12.374 +            DPRINTK("error: unknown USB io operation [%d]\n",
  12.375 +                    req->operation);
  12.376 +            make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  12.377 +            break;
  12.378 +        }
  12.379 +    }
  12.380 +
  12.381 +    up->usb_req_cons = i;
  12.382 +
  12.383 +    spin_unlock_irqrestore(&up->usb_ring_lock, flags);
  12.384 +
  12.385 +    return more_to_do;
  12.386 +}
  12.387 +
  12.388 +static owned_port_t *find_guest_port(usbif_priv_t *up, int port)
  12.389 +{
  12.390 +    unsigned long flags;
  12.391 +    struct list_head *l;
  12.392 +
  12.393 +    spin_lock_irqsave(&owned_ports_lock, flags);
  12.394 +    list_for_each(l, &owned_ports)
  12.395 +    {
  12.396 +        owned_port_t *p = list_entry(l, owned_port_t, list);
  12.397 +        if(p->usbif_priv == up && p->guest_port == port)
  12.398 +        {
  12.399 +            spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.400 +            return p;
  12.401 +        }
  12.402 +    }
  12.403 +    spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.404 +
  12.405 +    return NULL;
  12.406 +}
  12.407 +
  12.408 +static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid)
  12.409 +{
  12.410 +    owned_port_t *port = find_guest_port(up, portid);
  12.411 +    int ret = 0;
  12.412 +
  12.413 +
  12.414 +    /* Allowing the guest to actually reset the device causes more problems
  12.415 +     * than it's worth.  We just fake it out in software but we will do a real
  12.416 +     * reset when the interface is destroyed. */
  12.417 +
  12.418 +#if 0
  12.419 +    printk("Reset port %d\n", portid);
  12.420 +
  12.421 +    dump_port(port);
  12.422 +#endif
  12.423 +
  12.424 +    port->guest_address = 0;
  12.425 +    /* If there's an attached device then the port is now enabled. */
  12.426 +    if ( port->dev_present )
  12.427 +        port->enabled = 1;
  12.428 +    else
  12.429 +        port->enabled = 0;
  12.430 +
  12.431 +    make_response(up, 0, USBIF_OP_RESET, ret, 0, 0);
  12.432 +}
  12.433 +
  12.434 +static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long portid)
  12.435 +{
  12.436 +    owned_port_t *port = find_guest_port(up, portid);
  12.437 +    int ret;
  12.438 + 
  12.439 +    if ( port != NULL )
  12.440 +        ret = port->dev_present;
  12.441 +    else
  12.442 +    {
  12.443 +        ret = -EINVAL;
  12.444 +        printk("dispatch_usb_probe(): invalid port probe request (port %ld)\n",
  12.445 +	       portid);
  12.446 +    }
  12.447 +
  12.448 +    /* Probe result is sent back in-band.  Probes don't have an associated id
  12.449 +     * right now... */
  12.450 +    make_response(up, id, USBIF_OP_PROBE, ret, portid, 0);
  12.451 +}
  12.452 +
  12.453 +owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req);
  12.454 +
  12.455 +static void dump_request(usbif_request_t *req)
  12.456 +{    
  12.457 +    printk("id = 0x%lx\n", req->id);
  12.458 +    
  12.459 +	printk("devnum %d\n", req->devnum);
  12.460 +	printk("endpoint 0x%x\n", req->endpoint);
  12.461 +	printk("direction %d\n", req->direction);
  12.462 +	printk("speed %d\n", req->speed);
  12.463 +        printk("pipe_type 0x%x\n", req->pipe_type);
  12.464 +        printk("transfer_buffer 0x%lx\n", req->transfer_buffer);
  12.465 +        printk("length 0x%lx\n", req->length);
  12.466 +        printk("transfer_flags 0x%lx\n", req->transfer_flags);
  12.467 +        printk("setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
  12.468 +               req->setup[0], req->setup[1], req->setup[2], req->setup[3],
  12.469 +               req->setup[4], req->setup[5], req->setup[6], req->setup[7]);
  12.470 +        printk("iso_schedule = 0x%lx\n", req->iso_schedule);
  12.471 +        printk("num_iso %ld\n", req->num_iso);
  12.472 +}
  12.473 +
  12.474 +void dump_urb(struct urb *urb)
  12.475 +{
  12.476 +    printk("dumping urb @ %p\n", urb);
  12.477 +
  12.478 +#define DUMP_URB_FIELD(name, format) printk("  " # name " " format "\n", urb-> name)
  12.479 +    
  12.480 +    DUMP_URB_FIELD(pipe, "0x%x");
  12.481 +    DUMP_URB_FIELD(status, "%d");
  12.482 +    DUMP_URB_FIELD(transfer_flags, "0x%x");    
  12.483 +    DUMP_URB_FIELD(transfer_buffer, "%p");
  12.484 +    DUMP_URB_FIELD(transfer_buffer_length, "%d");
  12.485 +    DUMP_URB_FIELD(actual_length, "%d");
  12.486 +}
  12.487 +
  12.488 +
  12.489 +static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
  12.490 +{
  12.491 +    unsigned long buffer_mach;
  12.492 +    int i = 0, offset = 0,
  12.493 +        pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
  12.494 +    pending_req_t *pending_req;
  12.495 +    unsigned long  remap_prot;
  12.496 +    multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
  12.497 +    struct urb *purb = NULL;
  12.498 +    owned_port_t *port;
  12.499 +    unsigned char *setup;    
  12.500 +
  12.501 +//    dump_request(req);
  12.502 +
  12.503 +    if ( NR_PENDING_REQS == MAX_PENDING_REQS )
  12.504 +    {
  12.505 +        printk("usbback: Max requests already queued.  Now giving up!\n");
  12.506 +        
  12.507 +        return;
  12.508 +    }
  12.509 +
  12.510 +    port = find_port_for_request(up, req);
  12.511 +
  12.512 +    if(port == NULL)
  12.513 +    {
  12.514 +	printk("No such device! (%d)\n", req->devnum);
  12.515 +	dump_request(req);
  12.516 +
  12.517 +        make_response(up, req->id, req->operation, -ENODEV, 0, 0);
  12.518 +	return;
  12.519 +    }
  12.520 +
  12.521 +    setup = kmalloc(8, GFP_ATOMIC | GFP_NOIO);
  12.522 +
  12.523 +    if ( setup == NULL )
  12.524 +        goto no_mem;
  12.525 +   
  12.526 +    /* Copy request out for safety. */
  12.527 +    memcpy(setup, req->setup, 8);
  12.528 +
  12.529 +    if( setup[0] == 0x0 && setup[1] == 0x5)
  12.530 +    {
  12.531 +        /* To virtualise the USB address space, we need to intercept
  12.532 +         * set_address messages and emulate.  From the USB specification:
  12.533 +         * bmRequestType = 0x0;
  12.534 +         * Brequest = SET_ADDRESS (i.e. 0x5)
  12.535 +         * wValue = device address
  12.536 +         * wIndex = 0
  12.537 +         * wLength = 0
  12.538 +         * data = None
  12.539 +         */
  12.540 +        /* Store into the guest transfer buffer using cpu_to_le16 */
  12.541 +        port->guest_address = le16_to_cpu(*(u16 *)(setup + 2));
  12.542 +        /* Make a successful response.  That was easy! */
  12.543 +
  12.544 +        make_response(up, req->id, req->operation, 0, 0, 0);
  12.545 +
  12.546 +	kfree(setup);
  12.547 +        return;
  12.548 +    }
  12.549 +    else if ( setup[0] == 0x0 && setup[1] == 0x9 )
  12.550 +    {
  12.551 +        /* The host kernel needs to know what device configuration is in use
  12.552 +         * because various error checks get confused otherwise.  We just do
  12.553 +         * configuration settings here, under controlled conditions.
  12.554 +         */
  12.555 +        usb_set_configuration(port->dev, setup[2]);
  12.556 +
  12.557 +        make_response(up, req->id, req->operation, 0, 0, 0);
  12.558 +
  12.559 +        kfree(setup);
  12.560 +        return;
  12.561 +    }
  12.562 +
  12.563 +    else if ( setup[0] == 0x1 && setup[1] == 0xB )
  12.564 +    {
  12.565 +        /* The host kernel needs to know what device interface is in use
  12.566 +         * because various error checks get confused otherwise.  We just do
  12.567 +         * configuration settings here, under controlled conditions.
  12.568 +         */
  12.569 +        usb_set_interface(port->dev, (setup[4] | setup[5] << 8),
  12.570 +                          (setup[2] | setup[3] << 8) );
  12.571 +
  12.572 +        make_response(up, req->id, req->operation, 0, 0, 0);
  12.573 +
  12.574 +        kfree(setup);
  12.575 +        return;
  12.576 +    }
  12.577 +
  12.578 +    if ( ( req->transfer_buffer - (req->transfer_buffer & PAGE_MASK)
  12.579 +	   + req->length )
  12.580 +	 > MMAP_PAGES_PER_REQUEST * PAGE_SIZE )
  12.581 +    {
  12.582 +        printk("usbback: request of %d bytes too large, failing it\n", req->length);
  12.583 +        make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  12.584 +        kfree(setup);
  12.585 +        return;
  12.586 +    }
  12.587 +    
  12.588 +    buffer_mach = req->transfer_buffer;
  12.589 +
  12.590 +    if( buffer_mach == 0 )
  12.591 +	goto no_remap;
  12.592 +
  12.593 +    ASSERT((req->length >> PAGE_SHIFT) <= MMAP_PAGES_PER_REQUEST);
  12.594 +    ASSERT(buffer_mach);
  12.595 +
  12.596 +    /* Always map writeable for now. */
  12.597 +    remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
  12.598 +
  12.599 +    for ( i = 0, offset = 0; offset < req->length;
  12.600 +          i++, offset += PAGE_SIZE )
  12.601 +    {
  12.602 +      //        printk("length = %d, offset = %d, looping!\n", req->length, offset);
  12.603 +        
  12.604 +	mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
  12.605 +	mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
  12.606 +        mcl[i].args[1] = ((buffer_mach & PAGE_MASK) + offset) | remap_prot;
  12.607 +        mcl[i].args[2] = 0;
  12.608 +        mcl[i].args[3] = up->domid;
  12.609 +        
  12.610 +        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
  12.611 +            FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT);
  12.612 +	//	printk("i = %d\n", i);
  12.613 +
  12.614 +        ASSERT(virt_to_machine(MMAP_VADDR(pending_idx, i))
  12.615 +               == buffer_mach + i << PAGE_SHIFT);
  12.616 +    }
  12.617 +
  12.618 +    if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */
  12.619 +    {
  12.620 +      //      printk("for iso, i = %d\n", i);
  12.621 +        /* Map in ISO schedule, if necessary. */
  12.622 +        mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
  12.623 +        mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
  12.624 +        mcl[i].args[1] = (req->iso_schedule & PAGE_MASK) | remap_prot;
  12.625 +        mcl[i].args[2] = 0;
  12.626 +        mcl[i].args[3] = up->domid;
  12.627 +
  12.628 +        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
  12.629 +            FOREIGN_FRAME(req->iso_schedule >> PAGE_SHIFT);
  12.630 +    
  12.631 +        //    printk("Mapped iso at %p\n", MMAP_VADDR(pending_idx, i));
  12.632 +        i++;
  12.633 +    }
  12.634 +
  12.635 +    //    printk("Well we got this far!\n");
  12.636 +
  12.637 +    if ( unlikely(HYPERVISOR_multicall(mcl, i) != 0) )
  12.638 +        BUG();
  12.639 +    
  12.640 +    {
  12.641 +        int j;
  12.642 +        for ( j = 0; j < i; j++ )
  12.643 +        {
  12.644 +            if ( unlikely(mcl[j].args[5] != 0) )
  12.645 +            {
  12.646 +                printk("invalid buffer %d -- could not remap it\n", j);
  12.647 +                fast_flush_area(pending_idx, i);
  12.648 +		printk("sending invalid descriptor\n");
  12.649 +                goto bad_descriptor;
  12.650 +            }
  12.651 +	}
  12.652 +    }
  12.653 +    
  12.654 + no_remap:
  12.655 +
  12.656 +    ASSERT(i <= MMAP_PAGES_PER_REQUEST);
  12.657 +    ASSERT(i * PAGE_SIZE >= req->length);
  12.658 +
  12.659 +    /* We have to do this because some things might complete out of order. */
  12.660 +    pending_req = &pending_reqs[pending_idx];
  12.661 +    pending_req->usbif_priv= up;
  12.662 +    pending_req->id        = req->id;
  12.663 +    pending_req->operation = req->operation;
  12.664 +    pending_req->nr_pages  = i;
  12.665 +
  12.666 +
  12.667 +
  12.668 +    pending_cons++;
  12.669 +
  12.670 +    usbif_get(up);
  12.671 +    
  12.672 +    /* Fill out an actual request for the USB layer. */
  12.673 +    purb = usb_alloc_urb(req->num_iso);
  12.674 +
  12.675 +    if ( purb == NULL )
  12.676 +        goto no_mem;
  12.677 +
  12.678 +    purb->dev = port->dev;
  12.679 +    purb->context = pending_req;
  12.680 +    purb->transfer_buffer = (void *)MMAP_VADDR(pending_idx, 0) + (buffer_mach & ~PAGE_MASK);
  12.681 +    if(buffer_mach == 0)
  12.682 +      purb->transfer_buffer = NULL;
  12.683 +    purb->complete = __end_usb_io_op;
  12.684 +    purb->transfer_buffer_length = req->length;
  12.685 +    purb->transfer_flags = req->transfer_flags;
  12.686 +
  12.687 +/*     if ( req->transfer_flags != 0 ) */
  12.688 +/*       dump_request(req); */
  12.689 +
  12.690 +    purb->pipe = 0;
  12.691 +    purb->pipe |= req->direction << 7;
  12.692 +    purb->pipe |= port->dev->devnum << 8;
  12.693 +    purb->pipe |= req->speed << 26;
  12.694 +    purb->pipe |= req->pipe_type << 30;
  12.695 +    purb->pipe |= req->endpoint << 15;
  12.696 +
  12.697 +    purb->number_of_packets = req->num_iso;
  12.698 +
  12.699 +    /* Make sure there's always some kind of timeout. */
  12.700 +    purb->timeout = ( req->timeout > 0 ) ?  (req->timeout * HZ) / 1000
  12.701 +                    :  1000;
  12.702 +
  12.703 +    purb->setup_packet = setup;
  12.704 +
  12.705 +    if ( req->pipe_type == 0 ) /* ISO */
  12.706 +    {
  12.707 +        int j;
  12.708 +        usbif_iso_t *iso_sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, i - 1);
  12.709 +
  12.710 +	//	printk("Reading iso sched at %p\n", iso_sched);
  12.711 +
  12.712 +        /* If we're dealing with an iso pipe, we need to copy in a schedule. */
  12.713 +        for ( j = 0; j < req->num_iso; j++ )
  12.714 +        {
  12.715 +            purb->iso_frame_desc[j].length = iso_sched[j].length;
  12.716 +            purb->iso_frame_desc[j].offset = iso_sched[j].buffer_offset;
  12.717 +            iso_sched[j].status = 0;
  12.718 +        }
  12.719 +        pending_req->iso_sched = iso_sched;
  12.720 +    }
  12.721 +
  12.722 +    {
  12.723 +      int ret;
  12.724 +      ret = usb_submit_urb(purb);
  12.725 +
  12.726 +      //      dump_urb(purb);
  12.727 +
  12.728 +      if ( ret != 0 )
  12.729 +          goto bad_descriptor; /* XXX free pending here! */
  12.730 +    }
  12.731 +    
  12.732 +    return;
  12.733 +
  12.734 + bad_descriptor:
  12.735 +    kfree ( setup );
  12.736 +    if ( purb != NULL )
  12.737 +        usb_free_urb(purb);
  12.738 +    make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  12.739 +    return;
  12.740 +    
  12.741 + no_mem:
  12.742 +    if ( setup != NULL )
  12.743 +        kfree(setup);
  12.744 +    make_response(up, req->id, req->operation, -ENOMEM, 0, 0);
  12.745 +    return;
  12.746 +} 
  12.747 +
  12.748 +
  12.749 +
  12.750 +/******************************************************************
  12.751 + * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
  12.752 + */
  12.753 +
  12.754 +
  12.755 +static void make_response(usbif_priv_t *up, unsigned long id,
  12.756 +                          unsigned short op, int st, int inband,
  12.757 +			  unsigned long length)
  12.758 +{
  12.759 +    usbif_response_t *resp;
  12.760 +    unsigned long     flags;
  12.761 +
  12.762 +#if 0
  12.763 +    printk("usbback: Sending response:\n");
  12.764 +    printk("         id = 0x%x\n", id);
  12.765 +    printk("         op = %d\n", op);
  12.766 +    printk("         status = %d\n", st);
  12.767 +    printk("         data = %d\n", inband);
  12.768 +    printk("         length = %d\n", length);
  12.769 +#endif
  12.770 +
  12.771 +    /* Place on the response ring for the relevant domain. */ 
  12.772 +    spin_lock_irqsave(&up->usb_ring_lock, flags);
  12.773 +    resp = &up->usb_ring_base->
  12.774 +        ring[MASK_USBIF_IDX(up->usb_resp_prod)].resp;
  12.775 +    resp->id        = id;
  12.776 +    resp->operation = op;
  12.777 +    resp->status    = st;
  12.778 +    resp->data      = inband;
  12.779 +    resp->length = length;
  12.780 +    wmb(); /* Ensure other side can see the response fields. */
  12.781 +    up->usb_ring_base->resp_prod = ++up->usb_resp_prod;
  12.782 +    spin_unlock_irqrestore(&up->usb_ring_lock, flags);
  12.783 +
  12.784 +    /* Kick the relevant domain. */
  12.785 +    notify_via_evtchn(up->evtchn);
  12.786 +}
  12.787 +
  12.788 +/**
  12.789 + * usbif_claim_port - claim devices on a port on behalf of guest
  12.790 + *
  12.791 + * Once completed, this will ensure that any device attached to that
  12.792 + * port is claimed by this driver for use by the guest.
  12.793 + */
  12.794 +int usbif_claim_port(usbif_be_claim_port_t *msg)
  12.795 +{
  12.796 +    owned_port_t *o_p;
  12.797 +    
  12.798 +    /* Sanity... */
  12.799 +    if ( usbif_find_port(msg->path) != NULL )
  12.800 +    {
  12.801 +        printk("usbback: Attempted to claim USB port "
  12.802 +               "we already own!\n");
  12.803 +        return -EINVAL;
  12.804 +    }
  12.805 +
  12.806 +    spin_lock_irq(&owned_ports_lock);
  12.807 +    
  12.808 +    /* No need for a slab cache - this should be infrequent. */
  12.809 +    o_p = kmalloc(sizeof(owned_port_t), GFP_KERNEL);
  12.810 +
  12.811 +    o_p->enabled = 0;
  12.812 +    o_p->usbif_priv = usbif_find(msg->domid);
  12.813 +    o_p->guest_port = msg->usbif_port;
  12.814 +    o_p->dev_present = 0;
  12.815 +    o_p->guest_address = 0; /* Default address. */
  12.816 +
  12.817 +    strcpy(o_p->path, msg->path);
  12.818 +
  12.819 +    list_add(&o_p->list, &owned_ports);
  12.820 +
  12.821 +    printk("usbback: Claimed USB port (%s) for %d.%d\n", o_p->path,
  12.822 +	   msg->domid, msg->usbif_port);
  12.823 +
  12.824 +    spin_unlock_irq(&owned_ports_lock);
  12.825 +
  12.826 +    /* Force a reprobe for unclaimed devices. */
  12.827 +    usb_scan_devices();
  12.828 +
  12.829 +    return 0;
  12.830 +}
  12.831 +
  12.832 +owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req)
  12.833 +{
  12.834 +    unsigned long flags;
  12.835 +    struct list_head *port;
  12.836 +
  12.837 +    /* I'm assuming this is not called from IRQ context - correct?  I think
  12.838 +     * it's probably only called in response to control messages or plug events
  12.839 +     * in the USB hub kernel thread, so should be OK. */
  12.840 +    spin_lock_irqsave(&owned_ports_lock, flags);
  12.841 +    list_for_each(port, &owned_ports)
  12.842 +    {
  12.843 +        owned_port_t *p = list_entry(port, owned_port_t, list);
  12.844 +        if(p->usbif_priv == up && p->guest_address == req->devnum && p->enabled )
  12.845 +	  {
  12.846 +#if 0
  12.847 +              printk("Found port for devnum %d\n", req->devnum);
  12.848 +
  12.849 +              dump_port(p);
  12.850 +#endif
  12.851 +              return p;
  12.852 +	  }
  12.853 +    }
  12.854 +    spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.855 +
  12.856 +    return NULL;    
  12.857 +}
  12.858 +
  12.859 +owned_port_t *usbif_find_port(char *path)
  12.860 +{
  12.861 +    struct list_head *port;
  12.862 +    unsigned long flags;
  12.863 +
  12.864 +    spin_lock_irqsave(&owned_ports_lock, flags);
  12.865 +    list_for_each(port, &owned_ports)
  12.866 +    {
  12.867 +        owned_port_t *p = list_entry(port, owned_port_t, list);
  12.868 +        if(!strcmp(path, p->path))
  12.869 +        {
  12.870 +            spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.871 +            return p;
  12.872 +        }
  12.873 +    }
  12.874 +    spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.875 +
  12.876 +    return NULL;
  12.877 +}
  12.878 +
  12.879 +
  12.880 +static void *probe(struct usb_device *dev, unsigned iface,
  12.881 +	    const struct usb_device_id *id)
  12.882 +{
  12.883 +    owned_port_t *p;
  12.884 +
  12.885 +    /* We don't care what the device is - if we own the port, we want it.  We
  12.886 +     * don't deal with device-specifics in this driver, so we don't care what
  12.887 +     * the device actually is ;-) */
  12.888 +    if ( ( p = usbif_find_port(dev->devpath) ) != NULL )
  12.889 +    {
  12.890 +        printk("usbback: claimed device attached to owned port\n");
  12.891 +
  12.892 +        p->dev_present = 1;
  12.893 +        p->dev = dev;
  12.894 +        set_bit(iface, &p->ifaces);
  12.895 +        
  12.896 +        return p->usbif_priv;
  12.897 +    }
  12.898 +    else
  12.899 +        printk("usbback: hotplug for non-owned port (%s), ignoring\n", dev->devpath);
  12.900 +   
  12.901 +
  12.902 +    return NULL;
  12.903 +}
  12.904 +
  12.905 +static void disconnect(struct usb_device *dev, void *usbif)
  12.906 +{
  12.907 +    /* Note the device is removed so we can tell the guest when it probes. */
  12.908 +    owned_port_t *port = usbif_find_port(dev->devpath);
  12.909 +    port->dev_present = 0;
  12.910 +    port->dev = NULL;
  12.911 +    port->ifaces = 0;
  12.912 +}
  12.913 +
  12.914 +
  12.915 +struct usb_driver driver =
  12.916 +{
  12.917 +    .owner      = THIS_MODULE,
  12.918 +    .name       = "Xen USB Backend",
  12.919 +    .probe      = probe,
  12.920 +    .disconnect = disconnect,
  12.921 +    .id_table   = NULL,
  12.922 +};
  12.923 +
  12.924 +/* __usbif_release_port - internal mechanics for releasing a port */
  12.925 +void __usbif_release_port(owned_port_t *p)
  12.926 +{
  12.927 +    int i;
  12.928 +
  12.929 +    for ( i = 0; p->ifaces != 0; i++)
  12.930 +        if ( p->ifaces & 1 << i )
  12.931 +        {
  12.932 +            usb_driver_release_interface(&driver, usb_ifnum_to_if(p->dev, i));
  12.933 +            clear_bit(i, &p->ifaces);
  12.934 +        }
  12.935 +    list_del(&p->list);
  12.936 +
  12.937 +    /* Reset the real device.  We don't simulate disconnect / probe for other
  12.938 +     * drivers in this kernel because we assume the device is completely under
  12.939 +     * the control of ourselves (i.e. the guest!).  This should ensure that the
  12.940 +     * device is in a sane state for the next customer ;-) */
  12.941 +/*     if ( p->dev != NULL) */
  12.942 +/*         usb_reset_device(p->dev); */
  12.943 +
  12.944 +    kfree(p);
  12.945 +}
  12.946 +
  12.947 +
  12.948 +/**
  12.949 + * usbif_release_port - stop claiming devices on a port on behalf of guest
  12.950 + */
  12.951 +void usbif_release_port(usbif_be_release_port_t *msg)
  12.952 +{
  12.953 +    owned_port_t *p;
  12.954 +
  12.955 +    spin_lock_irq(&owned_ports_lock);
  12.956 +    p = usbif_find_port(msg->path);
  12.957 +    __usbif_release_port(p);
  12.958 +    spin_unlock_irq(&owned_ports_lock);
  12.959 +}
  12.960 +
  12.961 +void usbif_release_ports(usbif_priv_t *up)
  12.962 +{
  12.963 +    struct list_head *port, *tmp;
  12.964 +    unsigned long flags;
  12.965 +    
  12.966 +    spin_lock_irqsave(&owned_ports_lock, flags);
  12.967 +    list_for_each_safe(port, tmp, &owned_ports)
  12.968 +    {
  12.969 +        owned_port_t *p = list_entry(port, owned_port_t, list);
  12.970 +        if ( p->usbif_priv == up )
  12.971 +            __usbif_release_port(p);
  12.972 +    }
  12.973 +    spin_unlock_irqrestore(&owned_ports_lock, flags);
  12.974 +}
  12.975 +
  12.976 +static int __init usbif_init(void)
  12.977 +{
  12.978 +    int i;
  12.979 +
  12.980 +    if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
  12.981 +         !(xen_start_info.flags & SIF_USB_BE_DOMAIN) )
  12.982 +        return 0;
  12.983 +    
  12.984 +    INIT_LIST_HEAD(&owned_ports);
  12.985 +
  12.986 +    usb_register(&driver);
  12.987 +
  12.988 +    usbif_interface_init();
  12.989 +
  12.990 +    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
  12.991 +        BUG();
  12.992 +
  12.993 +    pending_cons = 0;
  12.994 +    pending_prod = MAX_PENDING_REQS;
  12.995 +    memset(pending_reqs, 0, sizeof(pending_reqs));
  12.996 +    for ( i = 0; i < MAX_PENDING_REQS; i++ )
  12.997 +        pending_ring[i] = i;
  12.998 +
  12.999 +    spin_lock_init(&usbio_schedule_list_lock);
 12.1000 +    INIT_LIST_HEAD(&usbio_schedule_list);
 12.1001 +
 12.1002 +    if ( kernel_thread(usbio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
 12.1003 +        BUG();
 12.1004 +    
 12.1005 +    usbif_ctrlif_init();
 12.1006 +
 12.1007 +    spin_lock_init(&owned_ports_lock);
 12.1008 +
 12.1009 +    printk("Xen USB Backend Initialised");
 12.1010 +
 12.1011 +    return 0;
 12.1012 +}
 12.1013 +
 12.1014 +__initcall(usbif_init);
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/Makefile	Mon Jan 24 10:19:03 2005 +0000
    13.3 @@ -0,0 +1,3 @@
    13.4 +O_TARGET := drv.o
    13.5 +obj-y := main.o
    13.6 +include $(TOPDIR)/Rules.make
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/main.c	Mon Jan 24 10:19:03 2005 +0000
    14.3 @@ -0,0 +1,1720 @@
    14.4 +/*
    14.5 + * Xen Virtual USB Frontend Driver 
    14.6 + *
    14.7 + * This file contains the first version of the Xen virtual USB hub
    14.8 + * that I've managed not to delete by mistake (3rd time lucky!).
    14.9 + *
   14.10 + * Based on Linux's uhci.c, original copyright notices are displayed
   14.11 + * below.  Portions also (c) 2004 Intel Research Cambridge
   14.12 + * and (c) 2004 Mark Williamson
   14.13 + *
   14.14 + * Contact <mark.williamson@cl.cam.ac.uk> or
   14.15 + * <xen-devel@lists.sourceforge.net> regarding this code.
   14.16 + *
   14.17 + * Still to be (maybe) implemented:
   14.18 + * - multiple port
   14.19 + * - multiple interfaces
   14.20 + * - migration / backend restart support?
   14.21 + * - unloading support
   14.22 + *
   14.23 + * Differences to a normal host controller:
   14.24 + * - the backend does most of the mucky stuff so we don't have to do various
   14.25 + *   things that are necessary for a normal host controller (e.g. FSBR).
   14.26 + * - we don't have any hardware, so status registers are simulated in software.
   14.27 + */
   14.28 +
   14.29 +/*
   14.30 + * Universal Host Controller Interface driver for USB.
   14.31 + *
   14.32 + * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
   14.33 + *
   14.34 + * (C) Copyright 1999 Linus Torvalds
   14.35 + * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
   14.36 + * (C) Copyright 1999 Randy Dunlap
   14.37 + * (C) Copyright 1999 Georg Acher, acher@in.tum.de
   14.38 + * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
   14.39 + * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
   14.40 + * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
   14.41 + * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
   14.42 + *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
   14.43 + * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
   14.44 + *
   14.45 + * Intel documents this fairly well, and as far as I know there
   14.46 + * are no royalties or anything like that, but even so there are
   14.47 + * people who decided that they want to do the same thing in a
   14.48 + * completely different way.
   14.49 + *
   14.50 + * WARNING! The USB documentation is downright evil. Most of it
   14.51 + * is just crap, written by a committee. You're better off ignoring
   14.52 + * most of it, the important stuff is:
   14.53 + *  - the low-level protocol (fairly simple but lots of small details)
   14.54 + *  - working around the horridness of the rest
   14.55 + */
   14.56 +
   14.57 +#include <linux/config.h>
   14.58 +#include <linux/module.h>
   14.59 +#include <linux/kernel.h>
   14.60 +#include <linux/init.h>
   14.61 +#include <linux/delay.h>
   14.62 +#include <linux/ioport.h>
   14.63 +#include <linux/sched.h>
   14.64 +#include <linux/slab.h>
   14.65 +#include <linux/smp_lock.h>
   14.66 +#include <linux/errno.h>
   14.67 +#include <linux/unistd.h>
   14.68 +#include <linux/interrupt.h>
   14.69 +#include <linux/spinlock.h>
   14.70 +#ifdef CONFIG_USB_DEBUG
   14.71 +#define DEBUG
   14.72 +#else
   14.73 +#undef DEBUG
   14.74 +#endif
   14.75 +#include <linux/usb.h>
   14.76 +
   14.77 +#include <asm/uaccess.h>
   14.78 +#include <asm/irq.h>
   14.79 +#include <asm/system.h>
   14.80 +
   14.81 +#include "xhci.h"
   14.82 +
   14.83 +#include <linux/pm.h>
   14.84 +
   14.85 +#include "../../../../../drivers/usb/hcd.h"
   14.86 +
   14.87 +#include "../usbif.h"
   14.88 +#include <asm/ctrl_if.h>
   14.89 +#include <asm/xen-public/io/domain_controller.h>
   14.90 +
   14.91 +/*
   14.92 + * Version Information
   14.93 + */
   14.94 +#define DRIVER_VERSION "v1.0"
   14.95 +#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, Mark Williamson"
   14.96 +#define DRIVER_DESC "Xen Virtual USB Host Controller Interface driver"
   14.97 +
   14.98 +/*
   14.99 + * debug = 0, no debugging messages
  14.100 + * debug = 1, dump failed URB's except for stalls
  14.101 + * debug = 2, dump all failed URB's (including stalls)
  14.102 + */
  14.103 +#ifdef DEBUG
  14.104 +static int debug = 1;
  14.105 +#else
  14.106 +static int debug = 0;
  14.107 +#endif
  14.108 +MODULE_PARM(debug, "i");
  14.109 +MODULE_PARM_DESC(debug, "Debug level");
  14.110 +static char *errbuf;
  14.111 +#define ERRBUF_LEN    (PAGE_SIZE * 8)
  14.112 +
  14.113 +static kmem_cache_t *xhci_up_cachep;	/* urb_priv */
  14.114 +
  14.115 +static int rh_submit_urb(struct urb *urb);
  14.116 +static int rh_unlink_urb(struct urb *urb);
  14.117 +//static int xhci_get_current_frame_number(struct usb_device *dev);
  14.118 +static int xhci_unlink_urb(struct urb *urb);
  14.119 +static void xhci_unlink_generic(struct urb *urb);
  14.120 +static void xhci_call_completion(struct urb *urb);
  14.121 +static void xhci_drain_ring(void);
  14.122 +
  14.123 +#define MAX_URB_LOOP	2048		/* Maximum number of linked URB's */
  14.124 +
  14.125 +struct xhci *xhci;
  14.126 +
  14.127 +enum { USBIF_STATE_CONNECTED = 2,
  14.128 +       USBIF_STATE_DISCONNECTED = 1,
  14.129 +       USBIF_STATE_CLOSED =0
  14.130 +};
  14.131 +
  14.132 +static int awaiting_reset = 0;
  14.133 +
  14.134 +/**
  14.135 + * xhci_construct_isoc - add isochronous information to a request
  14.136 + */
  14.137 +int xhci_construct_isoc(usbif_request_t *req, struct urb *urb)
  14.138 +{
  14.139 +        usbif_iso_t *schedule;
  14.140 +        int i;
  14.141 +        struct urb_priv *urb_priv = urb->hcpriv;
  14.142 +        
  14.143 +        req->num_iso = urb->number_of_packets;
  14.144 +        schedule = (usbif_iso_t *)__get_free_page(GFP_KERNEL);
  14.145 +
  14.146 +        if ( schedule == NULL )
  14.147 +            return -ENOMEM;
  14.148 +
  14.149 +        for ( i = 0; i < req->num_iso; i++ )
  14.150 +        {
  14.151 +                schedule[i].buffer_offset = urb->iso_frame_desc[i].offset;
  14.152 +                schedule[i].length = urb->iso_frame_desc[i].length;
  14.153 +        }
  14.154 +
  14.155 +        urb_priv->schedule = schedule;
  14.156 +	req->iso_schedule = virt_to_machine(schedule);
  14.157 +
  14.158 +        return 0;
  14.159 +}
  14.160 +
  14.161 +#define USBIF_RING_FULL ((xhci->usbif->req_prod - xhci->usb_resp_cons) == USBIF_RING_SIZE)
  14.162 +
  14.163 +static void dump_urb(struct urb *urb)
  14.164 +{
  14.165 +        printk("dumping urb @ %p\n", urb);
  14.166 +        
  14.167 +        printk("hcpriv = %p\n", urb->hcpriv);
  14.168 +        printk("next = %p\n", urb->next);
  14.169 +        printk("dev = %p\n", urb->dev);
  14.170 +        printk("pipe = 0x%lx\n", urb->pipe);
  14.171 +        printk("status = %d\n", urb->status);
  14.172 +        printk("transfer_flags = 0x%lx\n", urb->transfer_flags);
  14.173 +        printk("transfer_buffer = %p\n", urb->transfer_buffer);
  14.174 +        printk("transfer_buffer_length = %d\n", urb->transfer_buffer_length);
  14.175 +        printk("actual_length = %d\n", urb->actual_length);
  14.176 +        printk("bandwidth = %d\n", urb->bandwidth);
  14.177 +        printk("setup_packet = %p\n", urb->setup_packet);
  14.178 +	if ( urb->setup_packet != NULL )
  14.179 +	          printk("setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
  14.180 +               urb->setup_packet[0], urb->setup_packet[1], urb->setup_packet[2], urb->setup_packet[3],
  14.181 +               urb->setup_packet[4], urb->setup_packet[5], urb->setup_packet[6], urb->setup_packet[7]);
  14.182 +        printk("complete = %p\n", urb->complete);
  14.183 +        printk("interval = %d\n", urb->interval);
  14.184 +        
  14.185 +}
  14.186 +
  14.187 +
  14.188 +static int
  14.189 +xhci_queue_req(struct urb *urb)
  14.190 +{
  14.191 +        usbif_request_t *req;
  14.192 +        usbif_t *usbif = xhci->usbif;
  14.193 +
  14.194 +#if 0
  14.195 +        printk("usbif = %p, req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons = %d\n",
  14.196 +               usbif, usbif->req_prod, virt_to_machine(&usbif->req_prod),
  14.197 +               usbif->resp_prod, xhci->usb_resp_cons);
  14.198 +#endif
  14.199 +        
  14.200 +
  14.201 +/* 	printk("Usbif_priv %p, want IO at 0x%lx\n", urb->hcpriv, virt_to_machine(urb->transfer_buffer)); */
  14.202 +
  14.203 +        if ( USBIF_RING_FULL )
  14.204 +        {
  14.205 +                printk("xhci_queue_req(): USB ring full, not queuing request\n");
  14.206 +                return -ENOBUFS;
  14.207 +        }
  14.208 +
  14.209 +        /* Stick something in the shared communications ring. */
  14.210 +        req = &usbif->ring[MASK_USBIF_IDX(usbif->req_prod)].req;
  14.211 +
  14.212 +        req->operation       = USBIF_OP_IO;
  14.213 +        req->port            = 0; /* We don't care what the port is. */
  14.214 +        req->id              = (unsigned long) urb->hcpriv;
  14.215 +        req->transfer_buffer = virt_to_machine(urb->transfer_buffer);
  14.216 +	req->devnum          = usb_pipedevice(urb->pipe);
  14.217 +        req->direction       = usb_pipein(urb->pipe);
  14.218 +	req->speed           = usb_pipeslow(urb->pipe);
  14.219 +        req->pipe_type       = usb_pipetype(urb->pipe);
  14.220 +        req->length          = urb->transfer_buffer_length;
  14.221 +        req->transfer_flags  = urb->transfer_flags;
  14.222 +	req->endpoint        = usb_pipeendpoint(urb->pipe);
  14.223 +	req->speed           = usb_pipeslow(urb->pipe);
  14.224 +	req->timeout         = urb->timeout * (1000 / HZ);
  14.225 +
  14.226 +        if ( usb_pipetype(urb->pipe) == 0 ) /* ISO */
  14.227 +        {
  14.228 +            int ret = xhci_construct_isoc(req, urb);
  14.229 +            if ( ret != 0 )
  14.230 +                return ret;
  14.231 +        }
  14.232 +
  14.233 +	if(urb->setup_packet != NULL)
  14.234 +                memcpy(req->setup, urb->setup_packet, 8);
  14.235 +        else
  14.236 +                memset(req->setup, 0, 8);
  14.237 +        
  14.238 +        wmb();
  14.239 +
  14.240 +        usbif->req_prod++;
  14.241 +
  14.242 +	notify_via_evtchn(xhci->evtchn);
  14.243 +
  14.244 +	//	dump_urb(urb);
  14.245 +
  14.246 +        return -EINPROGRESS;
  14.247 +}
  14.248 +
  14.249 +static inline usbif_request_t *
  14.250 +xhci_queue_probe(usbif_vdev_t port)
  14.251 +{
  14.252 +        usbif_request_t *req;
  14.253 +        usbif_t *usbif = xhci->usbif;
  14.254 +
  14.255 +#if 0
  14.256 +	printk("queuing probe: req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons = %d\n",
  14.257 +	       usbif->req_prod, virt_to_machine(&usbif->req_prod),
  14.258 +	       usbif->resp_prod, xhci->usb_resp_cons);
  14.259 +#endif
  14.260 +        
  14.261 +        if ( USBIF_RING_FULL )
  14.262 +        {
  14.263 +                printk("xhci_queue_probe(): USB ring full, not queuing request\n");
  14.264 +                return NULL;
  14.265 +        }
  14.266 +
  14.267 +        /* Stick something in the shared communications ring. */
  14.268 +        req = &usbif->ring[MASK_USBIF_IDX(usbif->req_prod)].req;
  14.269 +
  14.270 +        req->operation       = USBIF_OP_PROBE;
  14.271 +        req->port            = port;
  14.272 +        req->id              = 0;
  14.273 +        req->transfer_buffer = 0;
  14.274 +	req->devnum          = 0;
  14.275 +        req->direction       = 0;
  14.276 +	req->speed           = 0;
  14.277 +        req->pipe_type       = 0;
  14.278 +        req->length          = 0;
  14.279 +        req->transfer_flags  = 0;
  14.280 +	req->endpoint        = 0;
  14.281 +	req->speed           = 0;
  14.282 +
  14.283 +        wmb();
  14.284 +
  14.285 +        usbif->req_prod++;
  14.286 +
  14.287 +	notify_via_evtchn(xhci->evtchn);
  14.288 +
  14.289 +        return req;
  14.290 +}
  14.291 +
  14.292 +static int
  14.293 +xhci_port_reset(usbif_vdev_t port)
  14.294 +{
  14.295 +        usbif_request_t *req;
  14.296 +        usbif_t *usbif = xhci->usbif;
  14.297 +
  14.298 +        /* We only reset one port at a time, so we only need one variable per
  14.299 +         * hub. */
  14.300 +        awaiting_reset = 1;
  14.301 +        
  14.302 +        /* Stick something in the shared communications ring. */
  14.303 +        req = &usbif->ring[MASK_USBIF_IDX(usbif->req_prod)].req;
  14.304 +
  14.305 +        req->operation       = USBIF_OP_RESET;
  14.306 +        req->port            = port;
  14.307 +        
  14.308 +        wmb();
  14.309 +
  14.310 +        usbif->req_prod++;
  14.311 +
  14.312 +	notify_via_evtchn(xhci->evtchn);
  14.313 +
  14.314 +        while ( awaiting_reset > 0 )
  14.315 +        {
  14.316 +                mdelay(1);
  14.317 +                xhci_drain_ring();
  14.318 +        }
  14.319 +
  14.320 +        return awaiting_reset;
  14.321 +}
  14.322 +
  14.323 +static void xhci_show_resp(usbif_response_t *r)
  14.324 +{
  14.325 +        printk("id=0x%lx, op=0x%x, data=0x%x, status=0x%x, length=0x%lx\n",
  14.326 +               r->id, r->operation, r->data, r->status, r->length);
  14.327 +}
  14.328 +
  14.329 +
  14.330 +/*
  14.331 + * Only the USB core should call xhci_alloc_dev and xhci_free_dev
  14.332 + */
  14.333 +static int xhci_alloc_dev(struct usb_device *dev)
  14.334 +{
  14.335 +	return 0;
  14.336 +}
  14.337 +
  14.338 +static int xhci_free_dev(struct usb_device *dev)
  14.339 +{
  14.340 +	return 0;
  14.341 +}
  14.342 +
  14.343 +static inline void xhci_add_complete(struct urb *urb)
  14.344 +{
  14.345 +	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
  14.346 +	unsigned long flags;
  14.347 +
  14.348 +	spin_lock_irqsave(&xhci->complete_list_lock, flags);
  14.349 +	list_add_tail(&urbp->complete_list, &xhci->complete_list);
  14.350 +	spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
  14.351 +}
  14.352 +
  14.353 +/* When this returns, the owner of the URB may free its
  14.354 + * storage.
  14.355 + *
  14.356 + * We spin and wait for the URB to complete before returning.
  14.357 + */
  14.358 +static void xhci_delete_urb(struct urb *urb)
  14.359 +{
  14.360 +        struct urb_priv *urbp;
  14.361 +
  14.362 +	urbp = urb->hcpriv;
  14.363 +
  14.364 +        /* If there's no urb_priv structure for this URB then it can't have
  14.365 +         * been submitted at all. */
  14.366 +	if ( urbp == NULL )
  14.367 +		return;
  14.368 +
  14.369 +	/* For now we just spin until the URB completes.  It shouldn't take too
  14.370 +         * long and we don't expect to have to do this very often. */
  14.371 +	while ( urb->status == -EINPROGRESS )
  14.372 +        {
  14.373 +            xhci_drain_ring();
  14.374 +            mdelay(1);
  14.375 +        }
  14.376 +
  14.377 +	/* Now we know that further transfers to the buffer won't
  14.378 +	 * occur, so we can safely return. */
  14.379 +}
  14.380 +
  14.381 +static struct urb_priv *xhci_alloc_urb_priv(struct urb *urb)
  14.382 +{
  14.383 +	struct urb_priv *urbp;
  14.384 +
  14.385 +	urbp = kmem_cache_alloc(xhci_up_cachep, SLAB_ATOMIC);
  14.386 +	if (!urbp) {
  14.387 +		err("xhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
  14.388 +		return NULL;
  14.389 +	}
  14.390 +
  14.391 +	memset((void *)urbp, 0, sizeof(*urbp));
  14.392 +
  14.393 +	urbp->inserttime = jiffies;
  14.394 +	urbp->urb = urb;
  14.395 +	urbp->dev = urb->dev;
  14.396 +	
  14.397 +	INIT_LIST_HEAD(&urbp->complete_list);
  14.398 +
  14.399 +	urb->hcpriv = urbp;
  14.400 +
  14.401 +	return urbp;
  14.402 +}
  14.403 +
  14.404 +/*
  14.405 + * MUST be called with urb->lock acquired
  14.406 + */
  14.407 +/* When is this called?  Do we need to stop the transfer (as we
  14.408 + * currently do)? */
  14.409 +static void xhci_destroy_urb_priv(struct urb *urb)
  14.410 +{
  14.411 +    struct urb_priv *urbp;
  14.412 +    
  14.413 +    urbp = (struct urb_priv *)urb->hcpriv;
  14.414 +    if (!urbp)
  14.415 +        return;
  14.416 +
  14.417 +    if (!list_empty(&urb->urb_list))
  14.418 +        warn("xhci_destroy_urb_priv: urb %p still on xhci->urb_list or xhci->remove_list", urb);
  14.419 +    
  14.420 +    if (!list_empty(&urbp->complete_list))
  14.421 +        warn("xhci_destroy_urb_priv: urb %p still on xhci->complete_list", urb);
  14.422 +    
  14.423 +    kmem_cache_free(xhci_up_cachep, urb->hcpriv);
  14.424 +
  14.425 +    urb->hcpriv = NULL;
  14.426 +}
  14.427 +
  14.428 +/**
  14.429 + * Try to find URBs in progress on the same pipe to the same device.
  14.430 + *
  14.431 + * MUST be called with xhci->urb_list_lock acquired
  14.432 + */
  14.433 +static struct urb *xhci_find_urb_ep(struct xhci *xhci, struct urb *urb)
  14.434 +{
  14.435 +	struct list_head *tmp, *head;
  14.436 +
  14.437 +	/* We don't match Isoc transfers since they are special */
  14.438 +	if (usb_pipeisoc(urb->pipe))
  14.439 +		return NULL;
  14.440 +
  14.441 +	head = &xhci->urb_list;
  14.442 +	tmp = head->next;
  14.443 +	while (tmp != head) {
  14.444 +		struct urb *u = list_entry(tmp, struct urb, urb_list);
  14.445 +
  14.446 +		tmp = tmp->next;
  14.447 +
  14.448 +		if (u->dev == urb->dev && u->pipe == urb->pipe &&
  14.449 +		    u->status == -EINPROGRESS)
  14.450 +			return u;
  14.451 +	}
  14.452 +
  14.453 +	return NULL;
  14.454 +}
  14.455 +
  14.456 +static int xhci_submit_urb(struct urb *urb)
  14.457 +{
  14.458 +	int ret = -EINVAL;
  14.459 +	unsigned long flags;
  14.460 +	struct urb *eurb;
  14.461 +	int bustime;
  14.462 +
  14.463 +#if 0
  14.464 +        printk("submitting urb @ %p for dev @ %p, devnum = %d path %s\n",
  14.465 +               urb, urb->dev, urb->dev->devnum, urb->dev->devpath);
  14.466 +#endif
  14.467 +
  14.468 +	if (!urb)
  14.469 +		return -EINVAL;
  14.470 +
  14.471 +	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
  14.472 +		warn("xhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
  14.473 +		return -ENODEV;
  14.474 +	}
  14.475 +
  14.476 +        if ( urb->dev->devpath == NULL )
  14.477 +        {
  14.478 +                printk("BARF!\n");
  14.479 +                BUG();
  14.480 +        }
  14.481 +        
  14.482 +        
  14.483 +
  14.484 +	usb_inc_dev_use(urb->dev);
  14.485 +
  14.486 +	spin_lock_irqsave(&xhci->urb_list_lock, flags);
  14.487 +	spin_lock(&urb->lock);
  14.488 +
  14.489 +	if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
  14.490 +	    urb->status == -ECONNABORTED) {
  14.491 +		dbg("xhci_submit_urb: urb not available to submit (status = %d)", urb->status);
  14.492 +		/* Since we can have problems on the out path */
  14.493 +		spin_unlock(&urb->lock);
  14.494 +		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.495 +		usb_dec_dev_use(urb->dev);
  14.496 +
  14.497 +		return ret;
  14.498 +	}
  14.499 +
  14.500 +	INIT_LIST_HEAD(&urb->urb_list);
  14.501 +	if (!xhci_alloc_urb_priv(urb)) {
  14.502 +		ret = -ENOMEM;
  14.503 +
  14.504 +		goto out;
  14.505 +	}
  14.506 +
  14.507 +        ( (struct urb_priv *)urb->hcpriv )->in_progress = 1;
  14.508 +
  14.509 +	eurb = xhci_find_urb_ep(xhci, urb);
  14.510 +	if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
  14.511 +		ret = -ENXIO;
  14.512 +
  14.513 +		goto out;
  14.514 +	}
  14.515 +
  14.516 +	/* Short circuit the virtual root hub */
  14.517 +	if (urb->dev == xhci->rh.dev) {
  14.518 +		ret = rh_submit_urb(urb);
  14.519 +
  14.520 +		goto out;
  14.521 +	}
  14.522 +
  14.523 +	if ( usb_pipedevice(urb->pipe) == 1 )
  14.524 +	  printk("dev = %p, dev->path = %s, rh.dev = %p, rh.dev.devnum = %d rh.dev->path = %s!\n",
  14.525 +		 urb->dev, urb->dev->devpath, xhci->rh.dev, xhci->rh.dev->devnum, xhci->rh.dev->devpath);
  14.526 +
  14.527 +	switch (usb_pipetype(urb->pipe)) {
  14.528 +	case PIPE_CONTROL:
  14.529 +		ret = xhci_queue_req(urb);
  14.530 +		break;
  14.531 +	case PIPE_INTERRUPT:
  14.532 +		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
  14.533 +			bustime = usb_check_bandwidth(urb->dev, urb);
  14.534 +			if (bustime < 0)
  14.535 +				ret = bustime;
  14.536 +			else {
  14.537 +				ret = xhci_queue_req(urb);
  14.538 +				if (ret == -EINPROGRESS)
  14.539 +					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
  14.540 +			}
  14.541 +		} else		/* bandwidth is already set */
  14.542 +			ret = xhci_queue_req(urb);
  14.543 +		break;
  14.544 +	case PIPE_BULK:
  14.545 +		ret = xhci_queue_req(urb);
  14.546 +		break;
  14.547 +	case PIPE_ISOCHRONOUS:
  14.548 +		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
  14.549 +			if (urb->number_of_packets <= 0) {
  14.550 +				ret = -EINVAL;
  14.551 +				break;
  14.552 +			}
  14.553 +			bustime = usb_check_bandwidth(urb->dev, urb);
  14.554 +			if (bustime < 0) {
  14.555 +				ret = bustime;
  14.556 +				break;
  14.557 +			}
  14.558 +
  14.559 +			ret = xhci_queue_req(urb);
  14.560 +			if (ret == -EINPROGRESS)
  14.561 +				usb_claim_bandwidth(urb->dev, urb, bustime, 1);
  14.562 +		} else		/* bandwidth is already set */
  14.563 +			ret = xhci_queue_req(urb);
  14.564 +		break;
  14.565 +	}
  14.566 +
  14.567 +out:
  14.568 +	urb->status = ret;
  14.569 +
  14.570 +	if (ret == -EINPROGRESS) {
  14.571 +		/* We use _tail to make find_urb_ep more efficient */
  14.572 +		list_add_tail(&urb->urb_list, &xhci->urb_list);
  14.573 +
  14.574 +		spin_unlock(&urb->lock);
  14.575 +		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.576 +
  14.577 +		return 0;
  14.578 +	}
  14.579 +
  14.580 +	xhci_unlink_generic(urb);
  14.581 +
  14.582 +	spin_unlock(&urb->lock);
  14.583 +	spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.584 +
  14.585 +	/* Only call completion if it was successful */
  14.586 +	if (!ret)
  14.587 +		xhci_call_completion(urb);
  14.588 +
  14.589 +	return ret;
  14.590 +}
  14.591 +
  14.592 +/*
  14.593 + * Return the result of a transfer
  14.594 + *
  14.595 + * MUST be called with urb_list_lock acquired
  14.596 + */
  14.597 +static void xhci_transfer_result(struct xhci *xhci, struct urb *urb)
  14.598 +{
  14.599 +	int ret = 0;
  14.600 +	unsigned long flags;
  14.601 +	struct urb_priv *urbp;
  14.602 +
  14.603 +	/* The root hub is special */
  14.604 +	if (urb->dev == xhci->rh.dev)
  14.605 +		return;
  14.606 +
  14.607 +	spin_lock_irqsave(&urb->lock, flags);
  14.608 +
  14.609 +	urbp = (struct urb_priv *)urb->hcpriv;
  14.610 +
  14.611 +        if ( ( (struct urb_priv *)urb->hcpriv )->in_progress )
  14.612 +                ret = -EINPROGRESS;
  14.613 +
  14.614 +        if (urb->actual_length < urb->transfer_buffer_length) {
  14.615 +                if (urb->transfer_flags & USB_DISABLE_SPD) {
  14.616 +                        ret = -EREMOTEIO;
  14.617 +                }
  14.618 +        }
  14.619 +
  14.620 +	if (urb->status == -EPIPE)
  14.621 +        {
  14.622 +                ret = urb->status;
  14.623 +		/* endpoint has stalled - mark it halted */
  14.624 +		usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe),
  14.625 +                                  usb_pipeout(urb->pipe));
  14.626 +        }
  14.627 +
  14.628 +	if ((debug == 1 && ret != 0 && ret != -EPIPE) ||
  14.629 +            (ret != 0 && debug > 1)) {
  14.630 +		/* Some debugging code */
  14.631 +		dbg("xhci_result_interrupt/bulk() failed with status %x",
  14.632 +			status);
  14.633 +	}
  14.634 +
  14.635 +	if (ret == -EINPROGRESS)
  14.636 +		goto out;
  14.637 +
  14.638 +	switch (usb_pipetype(urb->pipe)) {
  14.639 +	case PIPE_CONTROL:
  14.640 +	case PIPE_BULK:
  14.641 +	case PIPE_ISOCHRONOUS:
  14.642 +		/* Release bandwidth for Interrupt or Isoc. transfers */
  14.643 +		/* Spinlock needed ? */
  14.644 +		if (urb->bandwidth)
  14.645 +			usb_release_bandwidth(urb->dev, urb, 1);
  14.646 +		xhci_unlink_generic(urb);
  14.647 +		break;
  14.648 +	case PIPE_INTERRUPT:
  14.649 +		/* Interrupts are an exception */
  14.650 +		if (urb->interval)
  14.651 +			goto out_complete;
  14.652 +
  14.653 +		/* Release bandwidth for Interrupt or Isoc. transfers */
  14.654 +		/* Spinlock needed ? */
  14.655 +		if (urb->bandwidth)
  14.656 +			usb_release_bandwidth(urb->dev, urb, 0);
  14.657 +		xhci_unlink_generic(urb);
  14.658 +		break;
  14.659 +	default:
  14.660 +		info("xhci_transfer_result: unknown pipe type %d for urb %p\n",
  14.661 +			usb_pipetype(urb->pipe), urb);
  14.662 +	}
  14.663 +
  14.664 +	/* Remove it from xhci->urb_list */
  14.665 +	list_del_init(&urb->urb_list);
  14.666 +
  14.667 +out_complete:
  14.668 +	xhci_add_complete(urb);
  14.669 +
  14.670 +out:
  14.671 +	spin_unlock_irqrestore(&urb->lock, flags);
  14.672 +}
  14.673 +
  14.674 +/*
  14.675 + * MUST be called with urb->lock acquired
  14.676 + */
  14.677 +static void xhci_unlink_generic(struct urb *urb)
  14.678 +{
  14.679 +	struct urb_priv *urbp = urb->hcpriv;
  14.680 +
  14.681 +	/* We can get called when urbp allocation fails, so check */
  14.682 +	if (!urbp)
  14.683 +		return;
  14.684 +
  14.685 +        /* ??? This function is now so minimal it doesn't do much.  Do we really
  14.686 +         * need it? */
  14.687 +
  14.688 +	xhci_delete_urb(urb);
  14.689 +}
  14.690 +
  14.691 +static int xhci_unlink_urb(struct urb *urb)
  14.692 +{
  14.693 +	unsigned long flags;
  14.694 +	struct urb_priv *urbp = urb->hcpriv;
  14.695 +
  14.696 +	if (!urb)
  14.697 +		return -EINVAL;
  14.698 +
  14.699 +	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
  14.700 +		return -ENODEV;
  14.701 +
  14.702 +	spin_lock_irqsave(&xhci->urb_list_lock, flags);
  14.703 +	spin_lock(&urb->lock);
  14.704 +
  14.705 +	/* Release bandwidth for Interrupt or Isoc. transfers */
  14.706 +	/* Spinlock needed ? */
  14.707 +	if (urb->bandwidth) {
  14.708 +		switch (usb_pipetype(urb->pipe)) {
  14.709 +		case PIPE_INTERRUPT:
  14.710 +			usb_release_bandwidth(urb->dev, urb, 0);
  14.711 +			break;
  14.712 +		case PIPE_ISOCHRONOUS:
  14.713 +			usb_release_bandwidth(urb->dev, urb, 1);
  14.714 +			break;
  14.715 +		default:
  14.716 +			break;
  14.717 +		}
  14.718 +	}
  14.719 +
  14.720 +	if (urb->status != -EINPROGRESS) {
  14.721 +		spin_unlock(&urb->lock);
  14.722 +		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.723 +		return 0;
  14.724 +	}
  14.725 +
  14.726 +	list_del_init(&urb->urb_list);
  14.727 +
  14.728 +	xhci_unlink_generic(urb);
  14.729 +
  14.730 +	/* Short circuit the virtual root hub */
  14.731 +	if (urb->dev == xhci->rh.dev) {
  14.732 +		rh_unlink_urb(urb);
  14.733 +
  14.734 +		spin_unlock(&urb->lock);
  14.735 +		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.736 +
  14.737 +		xhci_call_completion(urb);
  14.738 +	} else {
  14.739 +		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
  14.740 +			urbp->status = urb->status = -ECONNABORTED;
  14.741 +
  14.742 +			spin_lock(&xhci->urb_remove_list_lock);
  14.743 +
  14.744 +			list_add(&urb->urb_list, &xhci->urb_remove_list);
  14.745 +
  14.746 +			spin_unlock(&xhci->urb_remove_list_lock);
  14.747 +
  14.748 +			spin_unlock(&urb->lock);
  14.749 +			spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.750 +
  14.751 +		} else {
  14.752 +			urb->status = -ENOENT;
  14.753 +
  14.754 +			spin_unlock(&urb->lock);
  14.755 +			spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.756 +
  14.757 +			if (in_interrupt()) {	/* wait at least 1 frame */
  14.758 +				static int errorcount = 10;
  14.759 +
  14.760 +				if (errorcount--)
  14.761 +					dbg("xhci_unlink_urb called from interrupt for urb %p", urb);
  14.762 +				udelay(1000);
  14.763 +			} else
  14.764 +				schedule_timeout(1+1*HZ/1000); 
  14.765 +
  14.766 +			xhci_call_completion(urb);
  14.767 +		}
  14.768 +	}
  14.769 +
  14.770 +	return 0;
  14.771 +}
  14.772 +
  14.773 +
  14.774 +struct usb_operations xhci_device_operations = {
  14.775 +	.allocate = xhci_alloc_dev,
  14.776 +	.deallocate = xhci_free_dev,
  14.777 +        /* It doesn't look like any drivers actually care what the frame number
  14.778 +	 * is at the moment!  If necessary, we could approximate the current
  14.779 +	 * frame nubmer by passing it from the backend in response messages. */
  14.780 +	.get_frame_number = NULL,
  14.781 +	.submit_urb = xhci_submit_urb,
  14.782 +	.unlink_urb = xhci_unlink_urb
  14.783 +};
  14.784 +
  14.785 +/* Virtual Root Hub */
  14.786 +
  14.787 +static __u8 root_hub_dev_des[] =
  14.788 +{
  14.789 + 	0x12,			/*  __u8  bLength; */
  14.790 +	0x01,			/*  __u8  bDescriptorType; Device */
  14.791 +	0x00,			/*  __u16 bcdUSB; v1.0 */
  14.792 +	0x01,
  14.793 +	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
  14.794 +	0x00,			/*  __u8  bDeviceSubClass; */
  14.795 +	0x00,			/*  __u8  bDeviceProtocol; */
  14.796 +	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
  14.797 +	0x00,			/*  __u16 idVendor; */
  14.798 +	0x00,
  14.799 +	0x00,			/*  __u16 idProduct; */
  14.800 +	0x00,
  14.801 +	0x00,			/*  __u16 bcdDevice; */
  14.802 +	0x00,
  14.803 +	0x00,			/*  __u8  iManufacturer; */
  14.804 +	0x02,			/*  __u8  iProduct; */
  14.805 +	0x01,			/*  __u8  iSerialNumber; */
  14.806 +	0x01			/*  __u8  bNumConfigurations; */
  14.807 +};
  14.808 +
  14.809 +
  14.810 +/* Configuration descriptor */
  14.811 +static __u8 root_hub_config_des[] =
  14.812 +{
  14.813 +	0x09,			/*  __u8  bLength; */
  14.814 +	0x02,			/*  __u8  bDescriptorType; Configuration */
  14.815 +	0x19,			/*  __u16 wTotalLength; */
  14.816 +	0x00,
  14.817 +	0x01,			/*  __u8  bNumInterfaces; */
  14.818 +	0x01,			/*  __u8  bConfigurationValue; */
  14.819 +	0x00,			/*  __u8  iConfiguration; */
  14.820 +	0x40,			/*  __u8  bmAttributes;
  14.821 +					Bit 7: Bus-powered, 6: Self-powered,
  14.822 +					Bit 5 Remote-wakeup, 4..0: resvd */
  14.823 +	0x00,			/*  __u8  MaxPower; */
  14.824 +
  14.825 +	/* interface */
  14.826 +	0x09,			/*  __u8  if_bLength; */
  14.827 +	0x04,			/*  __u8  if_bDescriptorType; Interface */
  14.828 +	0x00,			/*  __u8  if_bInterfaceNumber; */
  14.829 +	0x00,			/*  __u8  if_bAlternateSetting; */
  14.830 +	0x01,			/*  __u8  if_bNumEndpoints; */
  14.831 +	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
  14.832 +	0x00,			/*  __u8  if_bInterfaceSubClass; */
  14.833 +	0x00,			/*  __u8  if_bInterfaceProtocol; */
  14.834 +	0x00,			/*  __u8  if_iInterface; */
  14.835 +
  14.836 +	/* endpoint */
  14.837 +	0x07,			/*  __u8  ep_bLength; */
  14.838 +	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
  14.839 +	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
  14.840 +	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
  14.841 +	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
  14.842 +	0x00,
  14.843 +	0xff			/*  __u8  ep_bInterval; 255 ms */
  14.844 +};
  14.845 +
  14.846 +static __u8 root_hub_hub_des[] =
  14.847 +{
  14.848 +	0x09,			/*  __u8  bLength; */
  14.849 +	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
  14.850 +	0x02,			/*  __u8  bNbrPorts; */
  14.851 +	0x00,			/* __u16  wHubCharacteristics; */
  14.852 +	0x00,
  14.853 +	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
  14.854 +	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
  14.855 +	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
  14.856 +	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
  14.857 +};
  14.858 +
  14.859 +/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
  14.860 +static int rh_send_irq(struct urb *urb)
  14.861 +{
  14.862 +	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
  14.863 +        xhci_port_t *ports = xhci->rh.ports;
  14.864 +	unsigned long flags;
  14.865 +	int i, len = 1;
  14.866 +	__u16 data = 0;
  14.867 +
  14.868 +	spin_lock_irqsave(&urb->lock, flags);
  14.869 +	for (i = 0; i < xhci->rh.numports; i++) {
  14.870 +                /* MAW: No idea what the old code was doing here or why it worked.
  14.871 +		 * This implementation sets a bit if anything at all has changed on the 
  14.872 +		 * port, as per USB spec 11.12 */
  14.873 +		data |= (ports[i].cs_chg || ports[i].pe_chg )
  14.874 +                        ? (1 << (i + 1))
  14.875 +                        : 0;
  14.876 +
  14.877 +		len = (i + 1) / 8 + 1;
  14.878 +	}
  14.879 +
  14.880 +	*(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
  14.881 +	urb->actual_length = len;
  14.882 +	urbp->status = 0;
  14.883 +
  14.884 +	spin_unlock_irqrestore(&urb->lock, flags);
  14.885 +
  14.886 +	if ((data > 0) && (xhci->rh.send != 0)) {
  14.887 +		dbg("root-hub INT complete: data: %x", data);
  14.888 +		xhci_call_completion(urb);
  14.889 +	}
  14.890 +
  14.891 +	return 0;
  14.892 +}
  14.893 +
  14.894 +/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
  14.895 +static int rh_init_int_timer(struct urb *urb);
  14.896 +
  14.897 +static void rh_int_timer_do(unsigned long ptr)
  14.898 +{
  14.899 +	struct urb *urb = (struct urb *)ptr;
  14.900 +	struct list_head list, *tmp, *head;
  14.901 +	unsigned long flags;
  14.902 +	int i;
  14.903 +
  14.904 +	for ( i = 0; i < xhci->rh.numports; i++)
  14.905 +                xhci_queue_probe(i);
  14.906 +
  14.907 +	if (xhci->rh.send)
  14.908 +		rh_send_irq(urb);
  14.909 +
  14.910 +	INIT_LIST_HEAD(&list);
  14.911 +
  14.912 +	spin_lock_irqsave(&xhci->urb_list_lock, flags);
  14.913 +	head = &xhci->urb_list;
  14.914 +	tmp = head->next;
  14.915 +	while (tmp != head) {
  14.916 +		struct urb *u = list_entry(tmp, struct urb, urb_list);
  14.917 +		struct urb_priv *up = (struct urb_priv *)u->hcpriv;
  14.918 +
  14.919 +		tmp = tmp->next;
  14.920 +
  14.921 +		spin_lock(&u->lock);
  14.922 +
  14.923 +		/* Check if the URB timed out */
  14.924 +		if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
  14.925 +			list_del(&u->urb_list);
  14.926 +			list_add_tail(&u->urb_list, &list);
  14.927 +		}
  14.928 +
  14.929 +		spin_unlock(&u->lock);
  14.930 +	}
  14.931 +	spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  14.932 +
  14.933 +	head = &list;
  14.934 +	tmp = head->next;
  14.935 +	while (tmp != head) {
  14.936 +		struct urb *u = list_entry(tmp, struct urb, urb_list);
  14.937 +
  14.938 +		tmp = tmp->next;
  14.939 +
  14.940 +		u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
  14.941 +		xhci_unlink_urb(u);
  14.942 +	}
  14.943 +
  14.944 +	rh_init_int_timer(urb);
  14.945 +}
  14.946 +
  14.947 +/* Root Hub INTs are polled by this timer */
  14.948 +static int rh_init_int_timer(struct urb *urb)
  14.949 +{
  14.950 +	xhci->rh.interval = urb->interval;
  14.951 +	init_timer(&xhci->rh.rh_int_timer);
  14.952 +	xhci->rh.rh_int_timer.function = rh_int_timer_do;
  14.953 +	xhci->rh.rh_int_timer.data = (unsigned long)urb;
  14.954 +	xhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
  14.955 +	add_timer(&xhci->rh.rh_int_timer);
  14.956 +
  14.957 +	return 0;
  14.958 +}
  14.959 +
  14.960 +#define OK(x)			len = (x); break
  14.961 +
  14.962 +/* Root Hub Control Pipe */
  14.963 +static int rh_submit_urb(struct urb *urb)
  14.964 +{
  14.965 +	unsigned int pipe = urb->pipe;
  14.966 +	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet;
  14.967 +	void *data = urb->transfer_buffer;
  14.968 +	int leni = urb->transfer_buffer_length;
  14.969 +	int len = 0;
  14.970 +	xhci_port_t *status;
  14.971 +	int stat = 0;
  14.972 +	int i;
  14.973 +	int retstatus;
  14.974 +        unsigned long flags;
  14.975 +        
  14.976 +	__u16 cstatus;
  14.977 +	__u16 bmRType_bReq;
  14.978 +	__u16 wValue;
  14.979 +	__u16 wIndex;
  14.980 +	__u16 wLength;
  14.981 +
  14.982 +	if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
  14.983 +		xhci->rh.urb = urb;
  14.984 +		xhci->rh.send = 1;
  14.985 +		xhci->rh.interval = urb->interval;
  14.986 +		rh_init_int_timer(urb);
  14.987 +
  14.988 +		return -EINPROGRESS;
  14.989 +	}
  14.990 +
  14.991 +	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
  14.992 +	wValue = le16_to_cpu(cmd->wValue);
  14.993 +	wIndex = le16_to_cpu(cmd->wIndex);
  14.994 +	wLength = le16_to_cpu(cmd->wLength);
  14.995 +
  14.996 +	for (i = 0; i < 8; i++)
  14.997 +		xhci->rh.c_p_r[i] = 0;
  14.998 +
  14.999 +        status = &xhci->rh.ports[wIndex - 1];
 14.1000 +
 14.1001 +        spin_lock_irqsave(&xhci->rh.port_state_lock, flags);
 14.1002 +
 14.1003 +	switch (bmRType_bReq) {
 14.1004 +		/* Request Destination:
 14.1005 +		   without flags: Device,
 14.1006 +		   RH_INTERFACE: interface,
 14.1007 +		   RH_ENDPOINT: endpoint,
 14.1008 +		   RH_CLASS means HUB here,
 14.1009 +		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
 14.1010 +		*/
 14.1011 +
 14.1012 +	case RH_GET_STATUS:
 14.1013 +		*(__u16 *)data = cpu_to_le16(1);
 14.1014 +		OK(2);
 14.1015 +	case RH_GET_STATUS | RH_INTERFACE:
 14.1016 +		*(__u16 *)data = cpu_to_le16(0);
 14.1017 +		OK(2);
 14.1018 +	case RH_GET_STATUS | RH_ENDPOINT:
 14.1019 +		*(__u16 *)data = cpu_to_le16(0);
 14.1020 +		OK(2);
 14.1021 +	case RH_GET_STATUS | RH_CLASS:
 14.1022 +		*(__u32 *)data = cpu_to_le32(0);
 14.1023 +		OK(4);		/* hub power */
 14.1024 +	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
 14.1025 +		cstatus = (status->cs_chg) |
 14.1026 +			(status->pe_chg << 1) |
 14.1027 +			(xhci->rh.c_p_r[wIndex - 1] << 4);
 14.1028 +		retstatus = (status->ccs) |
 14.1029 +			(status->pe << 1) |
 14.1030 +			(status->susp << 2) |
 14.1031 +			(status->pr << 8) |
 14.1032 +			(1 << 8) |      /* power on */
 14.1033 +			(status->lsda << 9);
 14.1034 +		*(__u16 *)data = cpu_to_le16(retstatus);
 14.1035 +		*(__u16 *)(data + 2) = cpu_to_le16(cstatus);
 14.1036 +		OK(4);
 14.1037 +	case RH_CLEAR_FEATURE | RH_ENDPOINT:
 14.1038 +		switch (wValue) {
 14.1039 +		case RH_ENDPOINT_STALL:
 14.1040 +			OK(0);
 14.1041 +		}
 14.1042 +		break;
 14.1043 +	case RH_CLEAR_FEATURE | RH_CLASS:
 14.1044 +		switch (wValue) {
 14.1045 +		case RH_C_HUB_OVER_CURRENT:
 14.1046 +			OK(0);	/* hub power over current */
 14.1047 +		}
 14.1048 +		break;
 14.1049 +	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
 14.1050 +		switch (wValue) {
 14.1051 +		case RH_PORT_ENABLE:
 14.1052 +                        status->pe     = 0;
 14.1053 +			OK(0);
 14.1054 +		case RH_PORT_SUSPEND:
 14.1055 +                        status->susp   = 0;
 14.1056 +			OK(0);
 14.1057 +		case RH_PORT_POWER:
 14.1058 +			OK(0);	/* port power */
 14.1059 +		case RH_C_PORT_CONNECTION:
 14.1060 +                        status->cs_chg = 0;
 14.1061 +			OK(0);
 14.1062 +		case RH_C_PORT_ENABLE:
 14.1063 +                        status->pe_chg = 0;
 14.1064 +			OK(0);
 14.1065 +		case RH_C_PORT_SUSPEND:
 14.1066 +			/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
 14.1067 +			OK(0);
 14.1068 +		case RH_C_PORT_OVER_CURRENT:
 14.1069 +			OK(0);	/* port power over current */
 14.1070 +		case RH_C_PORT_RESET:
 14.1071 +			xhci->rh.c_p_r[wIndex - 1] = 0;
 14.1072 +			OK(0);
 14.1073 +		}
 14.1074 +		break;
 14.1075 +	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
 14.1076 +		switch (wValue) {
 14.1077 +		case RH_PORT_SUSPEND:
 14.1078 +                        status->susp = 1;	
 14.1079 +			OK(0);
 14.1080 +		case RH_PORT_RESET:
 14.1081 +                {
 14.1082 +                        int ret;
 14.1083 +                        xhci->rh.c_p_r[wIndex - 1] = 1;
 14.1084 +                        status->pr = 0;
 14.1085 +                        status->pe = 1;
 14.1086 +                        ret = xhci_port_reset(wIndex - 1);
 14.1087 +                        /* XXX MAW: should probably cancel queued transfers during reset... *\/ */
 14.1088 +                        if ( ret == 0 ) { OK(0); }
 14.1089 +                        else { return ret; }
 14.1090 +                }
 14.1091 +                break;
 14.1092 +		case RH_PORT_POWER:
 14.1093 +			OK(0); /* port power ** */
 14.1094 +		case RH_PORT_ENABLE:
 14.1095 +                        status->pe = 1;
 14.1096 +			OK(0);
 14.1097 +		}
 14.1098 +		break;
 14.1099 +	case RH_SET_ADDRESS:
 14.1100 +	  printk("setting root hub device to %d\n", wValue);
 14.1101 +		xhci->rh.devnum = wValue;
 14.1102 +		OK(0);
 14.1103 +	case RH_GET_DESCRIPTOR:
 14.1104 +		switch ((wValue & 0xff00) >> 8) {
 14.1105 +		case 0x01:	/* device descriptor */
 14.1106 +			len = min_t(unsigned int, leni,
 14.1107 +				  min_t(unsigned int,
 14.1108 +				      sizeof(root_hub_dev_des), wLength));
 14.1109 +			memcpy(data, root_hub_dev_des, len);
 14.1110 +			OK(len);
 14.1111 +		case 0x02:	/* configuration descriptor */
 14.1112 +			len = min_t(unsigned int, leni,
 14.1113 +				  min_t(unsigned int,
 14.1114 +				      sizeof(root_hub_config_des), wLength));
 14.1115 +			memcpy (data, root_hub_config_des, len);
 14.1116 +			OK(len);
 14.1117 +		case 0x03:	/* string descriptors */
 14.1118 +			len = usb_root_hub_string (wValue & 0xff,
 14.1119 +				0, "XHCI-alt",
 14.1120 +				data, wLength);
 14.1121 +			if (len > 0) {
 14.1122 +				OK(min_t(int, leni, len));
 14.1123 +			} else 
 14.1124 +				stat = -EPIPE;
 14.1125 +		}
 14.1126 +		break;
 14.1127 +	case RH_GET_DESCRIPTOR | RH_CLASS:
 14.1128 +		root_hub_hub_des[2] = xhci->rh.numports;
 14.1129 +		len = min_t(unsigned int, leni,
 14.1130 +			  min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
 14.1131 +		memcpy(data, root_hub_hub_des, len);
 14.1132 +		OK(len);
 14.1133 +	case RH_GET_CONFIGURATION:
 14.1134 +		*(__u8 *)data = 0x01;
 14.1135 +		OK(1);
 14.1136 +	case RH_SET_CONFIGURATION:
 14.1137 +		OK(0);
 14.1138 +	case RH_GET_INTERFACE | RH_INTERFACE:
 14.1139 +		*(__u8 *)data = 0x00;
 14.1140 +		OK(1);
 14.1141 +	case RH_SET_INTERFACE | RH_INTERFACE:
 14.1142 +		OK(0);
 14.1143 +	default:
 14.1144 +		stat = -EPIPE;
 14.1145 +	}
 14.1146 +
 14.1147 +        spin_unlock_irqrestore(&xhci->rh.port_state_lock, flags);
 14.1148 +
 14.1149 +	urb->actual_length = len;
 14.1150 +
 14.1151 +	return stat;
 14.1152 +}
 14.1153 +
 14.1154 +/*
 14.1155 + * MUST be called with urb->lock acquired
 14.1156 + */
 14.1157 +static int rh_unlink_urb(struct urb *urb)
 14.1158 +{
 14.1159 +	if (xhci->rh.urb == urb) {
 14.1160 +		urb->status = -ENOENT;
 14.1161 +		xhci->rh.send = 0;
 14.1162 +		xhci->rh.urb = NULL;
 14.1163 +		del_timer(&xhci->rh.rh_int_timer);
 14.1164 +	}
 14.1165 +	return 0;
 14.1166 +}
 14.1167 +
 14.1168 +static void xhci_call_completion(struct urb *urb)
 14.1169 +{
 14.1170 +	struct urb_priv *urbp;
 14.1171 +	struct usb_device *dev = urb->dev;
 14.1172 +	int is_ring = 0, killed, resubmit_interrupt, status;
 14.1173 +	struct urb *nurb;
 14.1174 +	unsigned long flags;
 14.1175 +
 14.1176 +	spin_lock_irqsave(&urb->lock, flags);
 14.1177 +
 14.1178 +	urbp = (struct urb_priv *)urb->hcpriv;
 14.1179 +	if (!urbp || !urb->dev) {
 14.1180 +		spin_unlock_irqrestore(&urb->lock, flags);
 14.1181 +		return;
 14.1182 +	}
 14.1183 +
 14.1184 +	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
 14.1185 +			urb->status == -ECONNRESET);
 14.1186 +	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
 14.1187 +			urb->interval);
 14.1188 +
 14.1189 +	nurb = urb->next;
 14.1190 +	if (nurb && !killed) {
 14.1191 +		int count = 0;
 14.1192 +
 14.1193 +		while (nurb && nurb != urb && count < MAX_URB_LOOP) {
 14.1194 +			if (nurb->status == -ENOENT ||
 14.1195 +			    nurb->status == -ECONNABORTED ||
 14.1196 +			    nurb->status == -ECONNRESET) {
 14.1197 +				killed = 1;
 14.1198 +				break;
 14.1199 +			}
 14.1200 +
 14.1201 +			nurb = nurb->next;
 14.1202 +			count++;
 14.1203 +		}
 14.1204 +
 14.1205 +		if (count == MAX_URB_LOOP)
 14.1206 +			err("xhci_call_completion: too many linked URB's, loop? (first loop)");
 14.1207 +
 14.1208 +		/* Check to see if chain is a ring */
 14.1209 +		is_ring = (nurb == urb);
 14.1210 +	}
 14.1211 +
 14.1212 +	status = urbp->status;
 14.1213 +	if (!resubmit_interrupt || killed)
 14.1214 +		/* We don't need urb_priv anymore */
 14.1215 +		xhci_destroy_urb_priv(urb);
 14.1216 +
 14.1217 +	if (!killed)
 14.1218 +		urb->status = status;
 14.1219 +
 14.1220 +	spin_unlock_irqrestore(&urb->lock, flags);
 14.1221 +
 14.1222 +	if (urb->complete)
 14.1223 +		urb->complete(urb);
 14.1224 +
 14.1225 +	if (resubmit_interrupt)
 14.1226 +		/* Recheck the status. The completion handler may have */
 14.1227 +		/*  unlinked the resubmitting interrupt URB */
 14.1228 +		killed = (urb->status == -ENOENT ||
 14.1229 +			  urb->status == -ECONNABORTED ||
 14.1230 +			  urb->status == -ECONNRESET);
 14.1231 +
 14.1232 +	if (resubmit_interrupt && !killed) {
 14.1233 +                if ( urb->dev != xhci->rh.dev )
 14.1234 +                        xhci_queue_req(urb); /* XXX What if this fails? */
 14.1235 +                /* Don't need to resubmit URBs for the virtual root dev. */
 14.1236 +	} else {
 14.1237 +		if (is_ring && !killed) {
 14.1238 +			urb->dev = dev;
 14.1239 +			xhci_submit_urb(urb);
 14.1240 +		} else {
 14.1241 +			/* We decrement the usage count after we're done */
 14.1242 +			/*  with everything */
 14.1243 +			usb_dec_dev_use(dev);
 14.1244 +		}
 14.1245 +	}
 14.1246 +}
 14.1247 +
 14.1248 +static void xhci_finish_completion(void)
 14.1249 +{
 14.1250 +	struct list_head *tmp, *head;
 14.1251 +	unsigned long flags;
 14.1252 +
 14.1253 +	spin_lock_irqsave(&xhci->complete_list_lock, flags);
 14.1254 +	head = &xhci->complete_list;
 14.1255 +	tmp = head->next;
 14.1256 +	while (tmp != head) {
 14.1257 +		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
 14.1258 +		struct urb *urb = urbp->urb;
 14.1259 +
 14.1260 +		list_del_init(&urbp->complete_list);
 14.1261 +		spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
 14.1262 +
 14.1263 +		xhci_call_completion(urb);
 14.1264 +
 14.1265 +		spin_lock_irqsave(&xhci->complete_list_lock, flags);
 14.1266 +		head = &xhci->complete_list;
 14.1267 +		tmp = head->next;
 14.1268 +	}
 14.1269 +	spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
 14.1270 +}
 14.1271 +
 14.1272 +void receive_usb_reset(usbif_response_t *resp)
 14.1273 +{
 14.1274 +    awaiting_reset = resp->status;
 14.1275 +    rmb();
 14.1276 +    
 14.1277 +}
 14.1278 +
 14.1279 +void receive_usb_probe(usbif_response_t *resp)
 14.1280 +{
 14.1281 +    spin_lock(&xhci->rh.port_state_lock);
 14.1282 +
 14.1283 +    if ( resp->status > 0 )
 14.1284 +    {
 14.1285 +        if ( resp->status == 1 )
 14.1286 +        {
 14.1287 +/* 	  printk("hey hey, there's a device on port %d\n", resp->data); */
 14.1288 +
 14.1289 +            /* If theres a device there and there wasn't one before there must
 14.1290 +             * have been a connection status change. */
 14.1291 +            if( xhci->rh.ports[resp->data].cs == 0 )
 14.1292 +	    {
 14.1293 +                xhci->rh.ports[resp->data].cs = 1;
 14.1294 +                xhci->rh.ports[resp->data].ccs = 1;
 14.1295 +                xhci->rh.ports[resp->data].cs_chg = 1;
 14.1296 +/* 		printk("Look at device on port %d that wasn't there before\n", resp->data); */
 14.1297 +	    }
 14.1298 +        }
 14.1299 +        else
 14.1300 +            printk("receive_usb_probe(): unexpected status %d for port %d\n",
 14.1301 +                   resp->status, resp->data);
 14.1302 +    }
 14.1303 +    else if ( resp->status < 0)
 14.1304 +        printk("receive_usb_probe(): got error status %d\n", resp->status);
 14.1305 +
 14.1306 +    spin_unlock(&xhci->rh.port_state_lock);
 14.1307 +}
 14.1308 +
 14.1309 +void receive_usb_io(usbif_response_t *resp)
 14.1310 +{
 14.1311 +        struct urb_priv *urbp = (struct urb_priv *)resp->id;
 14.1312 +        struct urb *urb = urbp->urb;
 14.1313 +
 14.1314 +        urb->actual_length = resp->length;
 14.1315 +	urb->status = resp->status;
 14.1316 +	urbp->status = resp->status;
 14.1317 +        urbp->in_progress = 0;
 14.1318 +
 14.1319 +        if( usb_pipetype(urb->pipe) == 0 ) /* ISO */
 14.1320 +        {
 14.1321 +                int i;
 14.1322 +              
 14.1323 +                /* Copy ISO schedule results back in. */
 14.1324 +
 14.1325 +                for ( i = 0; i < urb->number_of_packets; i++ )
 14.1326 +                {
 14.1327 +                        urb->iso_frame_desc[i].status
 14.1328 +			  = urbp->schedule[i].status;
 14.1329 +                        urb->iso_frame_desc[i].actual_length
 14.1330 +                                = urbp->schedule[i].length;
 14.1331 +                }
 14.1332 +                free_page((unsigned long)urbp->schedule);
 14.1333 +        }
 14.1334 +}
 14.1335 +
 14.1336 +static void xhci_drain_ring(void)
 14.1337 +{
 14.1338 +	struct list_head *tmp, *head;
 14.1339 +	usbif_t *usb_ring = xhci->usbif;
 14.1340 +	usbif_response_t *resp;
 14.1341 +        USBIF_RING_IDX i, rp;
 14.1342 +
 14.1343 +        /* Walk the ring here to get responses, updating URBs to show what
 14.1344 +         * completed. */
 14.1345 +        
 14.1346 +        rp = usb_ring->resp_prod;
 14.1347 +        rmb(); /* Ensure we see queued requests up to 'rp'. */
 14.1348 +
 14.1349 +        /* Take items off the comms ring, taking care not to overflow. */
 14.1350 +        for ( i = xhci->usb_resp_cons; 
 14.1351 +              (i != rp) && ((i-usb_ring->req_prod) != USBIF_RING_SIZE);
 14.1352 +              i++ )
 14.1353 +        {
 14.1354 +            resp = &usb_ring->ring[MASK_USBIF_IDX(i)].resp;
 14.1355 +            
 14.1356 +            /* May need to deal with batching and with putting a ceiling on
 14.1357 +               the number dispatched for performance and anti-dos reasons */
 14.1358 +
 14.1359 +#if 0
 14.1360 +            printk("usbfront: Processing response:\n");
 14.1361 +            printk("          id = 0x%x\n", resp->id);
 14.1362 +            printk("          op = %d\n", resp->operation);
 14.1363 +            printk("          status = %d\n", resp->status);
 14.1364 +            printk("          length = %d\n", resp->length);
 14.1365 +#endif            
 14.1366 +
 14.1367 +            switch ( resp->operation )
 14.1368 +            {
 14.1369 +            case USBIF_OP_PROBE:
 14.1370 +                receive_usb_probe(resp);
 14.1371 +                break;
 14.1372 +                
 14.1373 +            case USBIF_OP_IO:
 14.1374 +                receive_usb_io(resp);
 14.1375 +                break;
 14.1376 +
 14.1377 +            case USBIF_OP_RESET:
 14.1378 +                receive_usb_reset(resp);
 14.1379 +                break;
 14.1380 +
 14.1381 +            default:
 14.1382 +                printk("error: unknown USB io operation response [%d]\n",
 14.1383 +                       usb_ring->ring[i].req.operation);
 14.1384 +                break;
 14.1385 +            }
 14.1386 +        }
 14.1387 +
 14.1388 +        xhci->usb_resp_cons = i;
 14.1389 +
 14.1390 +	/* Walk the list of pending URB's to see which ones completed and do
 14.1391 +         * callbacks, etc. */
 14.1392 +	spin_lock(&xhci->urb_list_lock);
 14.1393 +	head = &xhci->urb_list;
 14.1394 +	tmp = head->next;
 14.1395 +	while (tmp != head) {
 14.1396 +                
 14.1397 +		struct urb *urb = list_entry(tmp, struct urb, urb_list);
 14.1398 +
 14.1399 +		tmp = tmp->next;
 14.1400 +
 14.1401 +		/* Checks the status and does all of the magic necessary */
 14.1402 +		xhci_transfer_result(xhci, urb);
 14.1403 +	}
 14.1404 +	spin_unlock(&xhci->urb_list_lock);
 14.1405 +
 14.1406 +	xhci_finish_completion();
 14.1407 +}
 14.1408 +
 14.1409 +
 14.1410 +static void xhci_interrupt(int irq, void *__xhci, struct pt_regs *regs)
 14.1411 +{
 14.1412 +        xhci_drain_ring();
 14.1413 +}
 14.1414 +
 14.1415 +static void free_xhci(struct xhci *xhci)
 14.1416 +{
 14.1417 +	kfree(xhci);
 14.1418 +}
 14.1419 +
 14.1420 +/* /\* */
 14.1421 +/*  * De-allocate all resources.. */
 14.1422 +/*  *\/ */
 14.1423 +/* static void release_xhci(struct xhci *xhci) */
 14.1424 +/* { */
 14.1425 +/* 	if (xhci->irq >= 0) { */
 14.1426 +/* 		free_irq(xhci->irq, xhci); */
 14.1427 +/* 		xhci->irq = -1; */
 14.1428 +/* 	} */
 14.1429 +
 14.1430 +/*         /\* Get the ring back from the backend domain.  Then free it.  Hmmmm. */
 14.1431 +/*          * Lets ignore this for now - not particularly useful. *\/ */
 14.1432 +
 14.1433 +/* 	free_xhci(xhci); */
 14.1434 +/* } */
 14.1435 +
 14.1436 +/**
 14.1437 + * Initialise a new virtual root hub for a new USB device channel.
 14.1438 + */
 14.1439 +static int alloc_xhci(void)
 14.1440 +{
 14.1441 +	int retval;
 14.1442 +	struct usb_bus *bus;
 14.1443 +
 14.1444 +	retval = -EBUSY;
 14.1445 +
 14.1446 +	xhci = kmalloc(sizeof(*xhci), GFP_KERNEL);
 14.1447 +	if (!xhci) {
 14.1448 +		err("couldn't allocate xhci structure");
 14.1449 +		retval = -ENOMEM;
 14.1450 +		goto err_alloc_xhci;
 14.1451 +	}
 14.1452 +
 14.1453 +	/* Reset here so we don't get any interrupts from an old setup */
 14.1454 +	/*  or broken setup */
 14.1455 +	//	reset_hc(xhci);
 14.1456 +
 14.1457 +
 14.1458 +	xhci->state = USBIF_STATE_CLOSED;
 14.1459 +	xhci->is_suspended = 0;
 14.1460 +
 14.1461 +	spin_lock_init(&xhci->urb_remove_list_lock);
 14.1462 +	INIT_LIST_HEAD(&xhci->urb_remove_list);
 14.1463 +
 14.1464 +	spin_lock_init(&xhci->urb_list_lock);
 14.1465 +	INIT_LIST_HEAD(&xhci->urb_list);
 14.1466 +
 14.1467 +	spin_lock_init(&xhci->complete_list_lock);
 14.1468 +	INIT_LIST_HEAD(&xhci->complete_list);
 14.1469 +
 14.1470 +	spin_lock_init(&xhci->frame_list_lock);
 14.1471 +
 14.1472 +	/* We need exactly one page (per XHCI specs), how convenient */
 14.1473 +	/* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
 14.1474 +#if PAGE_SIZE < (4 * 1024)
 14.1475 +#error PAGE_SIZE is not atleast 4k
 14.1476 +#endif
 14.1477 +	bus = usb_alloc_bus(&xhci_device_operations);
 14.1478 +	if (!bus) {
 14.1479 +		err("unable to allocate bus");
 14.1480 +		goto err_alloc_bus;
 14.1481 +	}
 14.1482 +
 14.1483 +	xhci->bus = bus;
 14.1484 +	bus->bus_name = "XHCI";
 14.1485 +	bus->hcpriv = xhci;
 14.1486 +
 14.1487 +	usb_register_bus(xhci->bus);
 14.1488 +
 14.1489 +	/* Initialize the root hub */
 14.1490 +
 14.1491 +	xhci->rh.numports = 0;
 14.1492 +
 14.1493 +	xhci->bus->root_hub = xhci->rh.dev = usb_alloc_dev(NULL, xhci->bus);
 14.1494 +	if (!xhci->rh.dev) {
 14.1495 +		err("unable to allocate root hub");
 14.1496 +		goto err_alloc_root_hub;
 14.1497 +	}
 14.1498 +
 14.1499 +	xhci->state = 0;
 14.1500 +
 14.1501 +	return 0;
 14.1502 +
 14.1503 +/*
 14.1504 + * error exits:
 14.1505 + */
 14.1506 +err_start_root_hub:
 14.1507 +	free_irq(xhci->irq, xhci);
 14.1508 +	xhci->irq = -1;
 14.1509 +
 14.1510 +err_alloc_root_hub:
 14.1511 +	usb_free_bus(xhci->bus);
 14.1512 +	xhci->bus = NULL;
 14.1513 +
 14.1514 +err_alloc_bus:
 14.1515 +	free_xhci(xhci);
 14.1516 +
 14.1517 +err_alloc_xhci:
 14.1518 +	return retval;
 14.1519 +}
 14.1520 +
 14.1521 +static void usbif_status_change(usbif_fe_interface_status_changed_t *status)
 14.1522 +{
 14.1523 +    ctrl_msg_t                   cmsg;
 14.1524 +    usbif_fe_interface_connect_t up;
 14.1525 +    long rc;
 14.1526 +    usbif_t *usbif;
 14.1527 +
 14.1528 +    switch ( status->status )
 14.1529 +    {
 14.1530 +    case USBIF_INTERFACE_STATUS_DESTROYED:
 14.1531 +        printk(KERN_WARNING "Unexpected usbif-DESTROYED message in state %d\n",
 14.1532 +               xhci->state);
 14.1533 +        break;
 14.1534 +
 14.1535 +    case USBIF_INTERFACE_STATUS_DISCONNECTED:
 14.1536 +        if ( xhci->state != USBIF_STATE_CLOSED )
 14.1537 +        {
 14.1538 +            printk(KERN_WARNING "Unexpected usbif-DISCONNECTED message"
 14.1539 +                   " in state %d\n", xhci->state);
 14.1540 +            break;
 14.1541 +            /* Not bothering to do recovery here for now.  Keep things
 14.1542 +             * simple. */
 14.1543 +        }
 14.1544 +
 14.1545 +        /* Move from CLOSED to DISCONNECTED state. */
 14.1546 +        xhci->usbif = usbif = (usbif_t *)__get_free_page(GFP_KERNEL);
 14.1547 +        usbif->req_prod = usbif->resp_prod = 0;
 14.1548 +        xhci->state  = USBIF_STATE_DISCONNECTED;
 14.1549 +
 14.1550 +        /* Construct an interface-CONNECT message for the domain controller. */
 14.1551 +        cmsg.type      = CMSG_USBIF_FE;
 14.1552 +        cmsg.subtype   = CMSG_USBIF_FE_INTERFACE_CONNECT;
 14.1553 +        cmsg.length    = sizeof(usbif_fe_interface_connect_t);
 14.1554 +        up.shmem_frame = virt_to_machine(usbif) >> PAGE_SHIFT;
 14.1555 +        memcpy(cmsg.msg, &up, sizeof(up));
 14.1556 +        
 14.1557 +        /* Tell the controller to bring up the interface. */
 14.1558 +        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 14.1559 +        break;
 14.1560 +
 14.1561 +    case USBIF_INTERFACE_STATUS_CONNECTED:
 14.1562 +        if ( xhci->state == USBIF_STATE_CLOSED )
 14.1563 +        {
 14.1564 +            printk(KERN_WARNING "Unexpected usbif-CONNECTED message"
 14.1565 +                   " in state %d\n", xhci->state);
 14.1566 +            break;
 14.1567 +        }
 14.1568 +
 14.1569 +        xhci->evtchn = status->evtchn;
 14.1570 +        xhci->irq = bind_evtchn_to_irq(xhci->evtchn);
 14.1571 +	xhci->bandwidth = status->bandwidth;
 14.1572 +	xhci->rh.numports = status->num_ports;
 14.1573 +
 14.1574 +        xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports, GFP_KERNEL);
 14.1575 +        memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports);
 14.1576 +
 14.1577 +        printk("rh.dev @ %p\n", xhci->rh.dev);
 14.1578 +
 14.1579 +	usb_connect(xhci->rh.dev);
 14.1580 +
 14.1581 +	if (usb_new_device(xhci->rh.dev) != 0) {
 14.1582 +		err("unable to start root hub");
 14.1583 +	}
 14.1584 +
 14.1585 +	/* Allocate the appropriate USB bandwidth here...  Need to
 14.1586 +	* somehow know what the total available is thought to be so we
 14.1587 +	* can calculate the reservation correctly. */
 14.1588 + 	usb_claim_bandwidth(xhci->rh.dev, xhci->rh.urb,
 14.1589 + 			    1000 - xhci->bandwidth, 0);
 14.1590 +
 14.1591 +        if ( (rc = request_irq(xhci->irq, xhci_interrupt, 
 14.1592 +                               SA_SAMPLE_RANDOM, "usbif", xhci)) )
 14.1593 +                printk(KERN_ALERT"usbfront request_irq failed (%ld)\n",rc);
 14.1594 +
 14.1595 +	printk(KERN_INFO __FILE__ ": USB XHCI: SHM at %p (0x%lx), EVTCHN %d IRQ %d\n",
 14.1596 +               xhci->usbif, virt_to_machine(xhci->usbif), xhci->evtchn, xhci->irq);
 14.1597 +
 14.1598 +        xhci->state = USBIF_STATE_CONNECTED;
 14.1599 +        
 14.1600 +        break;
 14.1601 +
 14.1602 +    default:
 14.1603 +        printk(KERN_WARNING "Status change to unknown value %d\n", 
 14.1604 +               status->status);
 14.1605 +        break;
 14.1606 +    }
 14.1607 +}
 14.1608 +
 14.1609 +
 14.1610 +static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 14.1611 +{
 14.1612 +    switch ( msg->subtype )
 14.1613 +    {
 14.1614 +    case CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED:
 14.1615 +        if ( msg->length != sizeof(usbif_fe_interface_status_changed_t) )
 14.1616 +            goto parse_error;
 14.1617 +        usbif_status_change((usbif_fe_interface_status_changed_t *)
 14.1618 +                            &msg->msg[0]);
 14.1619 +        break;        
 14.1620 +
 14.1621 +        /* New interface...? */
 14.1622 +    default:
 14.1623 +        goto parse_error;
 14.1624 +    }
 14.1625 +
 14.1626 +    ctrl_if_send_response(msg);
 14.1627 +    return;
 14.1628 +
 14.1629 + parse_error:
 14.1630 +    msg->length = 0;
 14.1631 +    ctrl_if_send_response(msg);
 14.1632 +}
 14.1633 +
 14.1634 +
 14.1635 +static int __init xhci_hcd_init(void)
 14.1636 +{
 14.1637 +	int retval = -ENOMEM, i;
 14.1638 +        usbif_fe_interface_status_changed_t st;
 14.1639 +        control_msg_t cmsg;
 14.1640 +
 14.1641 +	if ( (xen_start_info.flags & SIF_INITDOMAIN)
 14.1642 +	     || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
 14.1643 +                return 0;
 14.1644 +
 14.1645 +	info(DRIVER_DESC " " DRIVER_VERSION);
 14.1646 +
 14.1647 +	if (debug) {
 14.1648 +		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
 14.1649 +		if (!errbuf)
 14.1650 +			goto errbuf_failed;
 14.1651 +	}
 14.1652 +
 14.1653 +	xhci_up_cachep = kmem_cache_create("xhci_urb_priv",
 14.1654 +		sizeof(struct urb_priv), 0, 0, NULL, NULL);
 14.1655 +	if (!xhci_up_cachep)
 14.1656 +		goto up_failed;
 14.1657 +
 14.1658 +        /* Lazily avoid unloading issues for now. ;-)*/
 14.1659 +	MOD_INC_USE_COUNT;
 14.1660 +
 14.1661 +        /* Let the domain controller know we're here.  For now we wait until
 14.1662 +         * connection, as for the block and net drivers.  This is only strictly
 14.1663 +         * necessary if we're going to boot off a USB device. */
 14.1664 +        printk(KERN_INFO "Initialising Xen virtual USB hub\n");
 14.1665 +    
 14.1666 +        (void)ctrl_if_register_receiver(CMSG_USBIF_FE, usbif_ctrlif_rx,
 14.1667 +                                        CALLBACK_IN_BLOCKING_CONTEXT);
 14.1668 +        
 14.1669 +	alloc_xhci();
 14.1670 +
 14.1671 +        /* Send a driver-UP notification to the domain controller. */
 14.1672 +        cmsg.type      = CMSG_USBIF_FE;
 14.1673 +        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
 14.1674 +        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
 14.1675 +        st.status      = USBIF_DRIVER_STATUS_UP;
 14.1676 +        memcpy(cmsg.msg, &st, sizeof(st));
 14.1677 +        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 14.1678 +        
 14.1679 +        /*
 14.1680 +         * We should read 'nr_interfaces' from response message and wait
 14.1681 +         * for notifications before proceeding. For now we assume that we
 14.1682 +         * will be notified of exactly one interface.
 14.1683 +         */
 14.1684 +        for ( i=0; (xhci->state != USBIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
 14.1685 +        {
 14.1686 +            set_current_state(TASK_INTERRUPTIBLE);
 14.1687 +            schedule_timeout(1);
 14.1688 +        }
 14.1689 +        
 14.1690 +        if (xhci->state != USBIF_STATE_CONNECTED)
 14.1691 +            printk(KERN_INFO "Timeout connecting USB frontend driver!\n");
 14.1692 +	
 14.1693 +	return 0;
 14.1694 +
 14.1695 +up_failed:
 14.1696 +
 14.1697 +	if (errbuf)
 14.1698 +		kfree(errbuf);
 14.1699 +
 14.1700 +errbuf_failed:
 14.1701 +
 14.1702 +	return retval;
 14.1703 +}
 14.1704 +
 14.1705 +static void __exit xhci_hcd_cleanup(void) 
 14.1706 +{
 14.1707 +	if (kmem_cache_destroy(xhci_up_cachep))
 14.1708 +		printk(KERN_INFO "xhci: not all urb_priv's were freed\n");
 14.1709 +
 14.1710 +//        release_xhci(); do some calls here
 14.1711 +
 14.1712 +
 14.1713 +	if (errbuf)
 14.1714 +		kfree(errbuf);
 14.1715 +}
 14.1716 +
 14.1717 +module_init(xhci_hcd_init);
 14.1718 +module_exit(xhci_hcd_cleanup);
 14.1719 +
 14.1720 +MODULE_AUTHOR(DRIVER_AUTHOR);
 14.1721 +MODULE_DESCRIPTION(DRIVER_DESC);
 14.1722 +MODULE_LICENSE("GPL");
 14.1723 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/xhci.h	Mon Jan 24 10:19:03 2005 +0000
    15.3 @@ -0,0 +1,210 @@
    15.4 +#ifndef __LINUX_XHCI_H
    15.5 +#define __LINUX_XHCI_H
    15.6 +
    15.7 +#include <linux/list.h>
    15.8 +#include <linux/usb.h>
    15.9 +#include "../usbif.h"
   15.10 +#include <linux/spinlock.h>
   15.11 +
   15.12 +#define XHCI_NUMFRAMES		1024	/* in the frame list [array] */
   15.13 +#define XHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
   15.14 +#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
   15.15 +
   15.16 +/* In the absence of actual hardware state, we maintain the current known state
   15.17 + * of the virtual hub ports in this data structure.
   15.18 + */
   15.19 +typedef struct
   15.20 +{
   15.21 +        unsigned int cs     :1;     /* Connection status.  do we really need this /and/ ccs? */
   15.22 +        unsigned int cs_chg :1; /* Connection status change.  */
   15.23 +        unsigned int pe     :1;     /* Port enable.               */
   15.24 +        unsigned int pe_chg :1; /* Port enable change.        */
   15.25 +        unsigned int ccs    :1;    /* Current connect status.    */
   15.26 +        unsigned int susp   :1;   /* Suspended.                 */
   15.27 +        unsigned int lsda   :1;   /* Low speed device attached. */
   15.28 +        unsigned int pr     :1;     /* Port reset.                */
   15.29 +        
   15.30 +    /* Device info? */
   15.31 +} xhci_port_t;
   15.32 +
   15.33 +struct xhci_frame_list {
   15.34 +	__u32 frame[XHCI_NUMFRAMES];
   15.35 +
   15.36 +	void *frame_cpu[XHCI_NUMFRAMES];
   15.37 +};
   15.38 +
   15.39 +struct urb_priv;
   15.40 +
   15.41 +#define xhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
   15.42 +#define xhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
   15.43 +
   15.44 +#define xhci_maxlen(token)	((token) >> 21)
   15.45 +#define xhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */
   15.46 +#define xhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
   15.47 +#define xhci_endpoint(token)	(((token) >> 15) & 0xf)
   15.48 +#define xhci_devaddr(token)	(((token) >> 8) & 0x7f)
   15.49 +#define xhci_devep(token)	(((token) >> 8) & 0x7ff)
   15.50 +#define xhci_packetid(token)	((token) & TD_TOKEN_PID_MASK)
   15.51 +#define xhci_packetout(token)	(xhci_packetid(token) != USB_PID_IN)
   15.52 +#define xhci_packetin(token)	(xhci_packetid(token) == USB_PID_IN)
   15.53 +
   15.54 +struct virt_root_hub {
   15.55 +	struct usb_device *dev;
   15.56 +	int devnum;		/* Address of Root Hub endpoint */
   15.57 +	struct urb *urb;
   15.58 +	void *int_addr;
   15.59 +	int send;
   15.60 +	int interval;
   15.61 +	int numports;
   15.62 +	int c_p_r[8];
   15.63 +	struct timer_list rh_int_timer;
   15.64 +        spinlock_t port_state_lock;
   15.65 +        xhci_port_t *ports;       /*  */
   15.66 +};
   15.67 +
   15.68 +/*
   15.69 + * This describes the full xhci information.
   15.70 + *
   15.71 + * Note how the "proper" USB information is just
   15.72 + * a subset of what the full implementation needs.
   15.73 + */
   15.74 +struct xhci {
   15.75 +
   15.76 +#ifdef CONFIG_PROC_FS
   15.77 +	/* procfs */
   15.78 +	int num;
   15.79 +	struct proc_dir_entry *proc_entry;
   15.80 +#endif
   15.81 +
   15.82 +        int evtchn;                        /* Interdom channel to backend */
   15.83 +        int irq;                           /* Bound to evtchn */
   15.84 +        int state;                         /* State of this USB interface */
   15.85 +        unsigned long bandwidth;
   15.86 +        int handle;
   15.87 +
   15.88 +	struct usb_bus *bus;
   15.89 +
   15.90 +	spinlock_t frame_list_lock;
   15.91 +	struct xhci_frame_list *fl;		/* P: xhci->frame_list_lock */
   15.92 +	int is_suspended;
   15.93 +
   15.94 +	/* Main list of URB's currently controlled by this HC */
   15.95 +	spinlock_t urb_list_lock;
   15.96 +	struct list_head urb_list;		/* P: xhci->urb_list_lock */
   15.97 +
   15.98 +	/* List of asynchronously unlinked URB's */
   15.99 +	spinlock_t urb_remove_list_lock;
  15.100 +	struct list_head urb_remove_list;	/* P: xhci->urb_remove_list_lock */
  15.101 +
  15.102 +	/* List of URB's awaiting completion callback */
  15.103 +	spinlock_t complete_list_lock;
  15.104 +	struct list_head complete_list;		/* P: xhci->complete_list_lock */
  15.105 +
  15.106 +	struct virt_root_hub rh;	/* private data of the virtual root hub */
  15.107 +
  15.108 +        spinlock_t response_lock;
  15.109 +
  15.110 +        usbif_t *usbif;
  15.111 +        int usb_resp_cons;
  15.112 +};
  15.113 +
  15.114 +struct urb_priv {
  15.115 +	struct urb *urb;
  15.116 +        usbif_iso_t *schedule;
  15.117 +	struct usb_device *dev;
  15.118 +
  15.119 +        int in_progress : 1;	        /* QH was queued (not linked in) */
  15.120 +	int short_control_packet : 1;	/* If we get a short packet during */
  15.121 +					/*  a control transfer, retrigger */
  15.122 +					/*  the status phase */
  15.123 +
  15.124 +	int status;			/* Final status */
  15.125 +
  15.126 +	unsigned long inserttime;	/* In jiffies */
  15.127 +
  15.128 +	struct list_head queue_list;	/* P: xhci->frame_list_lock */
  15.129 +	struct list_head complete_list;	/* P: xhci->complete_list_lock */
  15.130 +};
  15.131 +
  15.132 +/*
  15.133 + * Locking in xhci.c
  15.134 + *
  15.135 + * spinlocks are used extensively to protect the many lists and data
  15.136 + * structures we have. It's not that pretty, but it's necessary. We
  15.137 + * need to be done with all of the locks (except complete_list_lock) when
  15.138 + * we call urb->complete. I've tried to make it simple enough so I don't
  15.139 + * have to spend hours racking my brain trying to figure out if the
  15.140 + * locking is safe.
  15.141 + *
  15.142 + * Here's the safe locking order to prevent deadlocks:
  15.143 + *
  15.144 + * #1 xhci->urb_list_lock
  15.145 + * #2 urb->lock
  15.146 + * #3 xhci->urb_remove_list_lock, xhci->frame_list_lock, 
  15.147 + *   xhci->qh_remove_list_lock
  15.148 + * #4 xhci->complete_list_lock
  15.149 + *
  15.150 + * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
  15.151 + * at the lowest level FIRST and NEVER grab locks at the same level at the
  15.152 + * same time.
  15.153 + * 
  15.154 + * So, if you need xhci->urb_list_lock, grab it before you grab urb->lock
  15.155 + */
  15.156 +
  15.157 +/* -------------------------------------------------------------------------
  15.158 +   Virtual Root HUB
  15.159 +   ------------------------------------------------------------------------- */
  15.160 +/* destination of request */
  15.161 +#define RH_DEVICE		0x00
  15.162 +#define RH_INTERFACE		0x01
  15.163 +#define RH_ENDPOINT		0x02
  15.164 +#define RH_OTHER		0x03
  15.165 +
  15.166 +#define RH_CLASS		0x20
  15.167 +#define RH_VENDOR		0x40
  15.168 +
  15.169 +/* Requests: bRequest << 8 | bmRequestType */
  15.170 +#define RH_GET_STATUS		0x0080
  15.171 +#define RH_CLEAR_FEATURE	0x0100
  15.172 +#define RH_SET_FEATURE		0x0300
  15.173 +#define RH_SET_ADDRESS		0x0500
  15.174 +#define RH_GET_DESCRIPTOR	0x0680
  15.175 +#define RH_SET_DESCRIPTOR	0x0700
  15.176 +#define RH_GET_CONFIGURATION	0x0880
  15.177 +#define RH_SET_CONFIGURATION	0x0900
  15.178 +#define RH_GET_STATE		0x0280
  15.179 +#define RH_GET_INTERFACE	0x0A80
  15.180 +#define RH_SET_INTERFACE	0x0B00
  15.181 +#define RH_SYNC_FRAME		0x0C80
  15.182 +/* Our Vendor Specific Request */
  15.183 +#define RH_SET_EP		0x2000
  15.184 +
  15.185 +/* Hub port features */
  15.186 +#define RH_PORT_CONNECTION	0x00
  15.187 +#define RH_PORT_ENABLE		0x01
  15.188 +#define RH_PORT_SUSPEND		0x02
  15.189 +#define RH_PORT_OVER_CURRENT	0x03
  15.190 +#define RH_PORT_RESET		0x04
  15.191 +#define RH_PORT_POWER		0x08
  15.192 +#define RH_PORT_LOW_SPEED	0x09
  15.193 +#define RH_C_PORT_CONNECTION	0x10
  15.194 +#define RH_C_PORT_ENABLE	0x11
  15.195 +#define RH_C_PORT_SUSPEND	0x12
  15.196 +#define RH_C_PORT_OVER_CURRENT	0x13
  15.197 +#define RH_C_PORT_RESET		0x14
  15.198 +
  15.199 +/* Hub features */
  15.200 +#define RH_C_HUB_LOCAL_POWER	0x00
  15.201 +#define RH_C_HUB_OVER_CURRENT	0x01
  15.202 +#define RH_DEVICE_REMOTE_WAKEUP	0x00
  15.203 +#define RH_ENDPOINT_STALL	0x01
  15.204 +
  15.205 +/* Our Vendor Specific feature */
  15.206 +#define RH_REMOVE_EP		0x00
  15.207 +
  15.208 +#define RH_ACK			0x01
  15.209 +#define RH_REQ_ERR		-1
  15.210 +#define RH_NACK			0x00
  15.211 +
  15.212 +#endif
  15.213 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/usbif.h	Mon Jan 24 10:19:03 2005 +0000
    16.3 @@ -0,0 +1,111 @@
    16.4 +/******************************************************************************
    16.5 + * usbif.h
    16.6 + * 
    16.7 + * Unified block-device I/O interface for Xen guest OSes.
    16.8 + * 
    16.9 + * Copyright (c) 2003-2004, Keir Fraser
   16.10 + */
   16.11 +
   16.12 +#ifndef __SHARED_USBIF_H__
   16.13 +#define __SHARED_USBIF_H__
   16.14 +
   16.15 +#define usbif_vdev_t   u16
   16.16 +#define usbif_sector_t u64
   16.17 +
   16.18 +#define USBIF_OP_IO      0
   16.19 +#define USBIF_OP_PROBE   1 /* Is there a device on this port? */
   16.20 +#define USBIF_OP_RESET   2 /* Reset a virtual USB port.       */
   16.21 +
   16.22 +/* NB. Ring size must be small enough for sizeof(usbif_ring_t) <= PAGE_SIZE. */
   16.23 +#define USBIF_RING_SIZE        64
   16.24 +
   16.25 +/* XXX this does not want to be here!  it really ought to be dynamic but it can
   16.26 + * live here for now */
   16.27 +#define NUM_PORTS 1
   16.28 +
   16.29 +typedef struct {
   16.30 +    unsigned long  id;           /*  0: private guest value, echoed in resp  */
   16.31 +    u8             operation;    /*  4: USBIF_OP_???                         */
   16.32 +    u8  __pad1;
   16.33 +    usbif_vdev_t   port;         /* 6 : guest virtual USB port               */
   16.34 +    unsigned long  devnum :7;    /* 8 : Device address, as seen by the guest.*/
   16.35 +    unsigned long  endpoint :4;  /* Device endpoint.                         */
   16.36 +    unsigned long  direction :1; /* Pipe direction.                          */
   16.37 +    unsigned long  speed :1;     /* Pipe speed.                              */
   16.38 +    unsigned long  pipe_type :2; /* Pipe type (iso, bulk, int, ctrl)         */
   16.39 +    unsigned long  __pad2 :18;
   16.40 +    unsigned long  transfer_buffer; /* 12: Machine address */
   16.41 +    unsigned long  length;          /* 16: Buffer length */
   16.42 +    unsigned long  transfer_flags;  /* 20: For now just pass Linux transfer
   16.43 +                                     * flags - this may change. */
   16.44 +    unsigned char setup[8];         /* 22 Embed setup packets directly. */
   16.45 +    unsigned long  iso_schedule;    /* 30 Machine address of transfer sched (iso
   16.46 +                                     * only) */
   16.47 +    unsigned long num_iso;        /* 34 : length of iso schedule */
   16.48 +    unsigned long timeout;        /* 38: timeout in ms */
   16.49 +} PACKED usbif_request_t; /* 42 */
   16.50 +/* Data we need to pass:
   16.51 + * - Transparently handle short packets or complain at us?
   16.52 + */
   16.53 +
   16.54 +typedef struct {
   16.55 +    unsigned long   id;              /* 0: copied from request         */
   16.56 +    u8              operation;       /* 4: copied from request         */
   16.57 +    u8              data;            /* 5: Small chunk of in-band data */
   16.58 +    s16             status;          /* 6: USBIF_RSP_???               */
   16.59 +    unsigned long   transfer_mutex;  /* Used for cancelling requests atomically. */
   16.60 +    unsigned long    length;          /* 8: How much data we really got */
   16.61 +} PACKED usbif_response_t;
   16.62 +
   16.63 +#define USBIF_RSP_ERROR  -1 /* non-specific 'error' */
   16.64 +#define USBIF_RSP_OKAY    0 /* non-specific 'okay'  */
   16.65 +
   16.66 +/*
   16.67 + * We use a special capitalised type name because it is _essential_ that all 
   16.68 + * arithmetic on indexes is done on an integer type of the correct size.
   16.69 + */
   16.70 +typedef u32 USBIF_RING_IDX;
   16.71 +
   16.72 +/*
   16.73 + * Ring indexes are 'free running'. That is, they are not stored modulo the
   16.74 + * size of the ring buffer. The following macro converts a free-running counter
   16.75 + * into a value that can directly index a ring-buffer array.
   16.76 + */
   16.77 +#define MASK_USBIF_IDX(_i) ((_i)&(USBIF_RING_SIZE-1))
   16.78 +
   16.79 +typedef struct {
   16.80 +    USBIF_RING_IDX req_prod;  /*  0: Request producer. Updated by front-end. */
   16.81 +    USBIF_RING_IDX resp_prod; /*  4: Response producer. Updated by back-end. */
   16.82 +
   16.83 +    union {                   /*  8 */
   16.84 +        usbif_request_t  req;
   16.85 +        usbif_response_t resp;
   16.86 +    } PACKED ring[USBIF_RING_SIZE];
   16.87 +} PACKED usbif_t;
   16.88 +
   16.89 +
   16.90 +
   16.91 +/*
   16.92 + * USBIF_OP_PROBE:
   16.93 + * The request format for a probe request is constrained as follows:
   16.94 + *  @operation   == USBIF_OP_PROBE
   16.95 + *  @nr_segments == size of probe buffer in pages
   16.96 + *  @device      == unused (zero)
   16.97 + *  @id          == any value (echoed in response message)
   16.98 + *  @sector_num  == unused (zero)
   16.99 + *  @frame_and_sects == list of page-sized buffers.
  16.100 + *                       (i.e., @first_sect == 0, @last_sect == 7).
  16.101 + * 
  16.102 + * The response is a list of vdisk_t elements copied into the out-of-band
  16.103 + * probe buffer. On success the response status field contains the number
  16.104 + * of vdisk_t elements.
  16.105 + */
  16.106 +
  16.107 +typedef struct {
  16.108 +    unsigned long length; /* IN = expected, OUT = actual */
  16.109 +    unsigned long buffer_offset;  /* IN offset in buffer specified in main
  16.110 +                                     packet */
  16.111 +    unsigned long status; /* OUT Status for this packet. */
  16.112 +} usbif_iso_t;
  16.113 +
  16.114 +#endif /* __SHARED_USBIF_H__ */
    17.1 --- a/linux-2.6.10-xen-sparse/arch/xen/Kconfig	Fri Jan 21 13:52:28 2005 +0000
    17.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/Kconfig	Mon Jan 24 10:19:03 2005 +0000
    17.3 @@ -32,8 +32,7 @@ config XEN_PRIVILEGED_GUEST
    17.4  
    17.5  config XEN_PHYSDEV_ACCESS
    17.6  	bool "Physical device access"
    17.7 -	default y if XEN_PRIVILEGED_GUEST
    17.8 -	default n if !XEN_PRIVILEGED_GUEST
    17.9 +	default XEN_PRIVILEGED_GUEST
   17.10  	help
   17.11  	  Assume access is available to physical hardware devices
   17.12            (e.g., hard drives, network cards). This allows you to configure
   17.13 @@ -42,16 +41,16 @@ config XEN_PHYSDEV_ACCESS
   17.14  
   17.15  config XEN_BLKDEV_BACKEND
   17.16          bool "Block-device backend driver"
   17.17 -        default y if XEN_PHYSDEV_ACCESS
   17.18 -        default n if !XEN_PHYSDEV_ACCESS
   17.19 +      depends on XEN_PHYSDEV_ACCESS
   17.20 +        default y
   17.21          help
   17.22            The block-device backend driver allows the kernel to export its
   17.23            block devices to other guests via a high-performance shared-memory
   17.24            interface.
   17.25  
   17.26 -if XEN_BLKDEV_BACKEND
   17.27  config XEN_BLKDEV_TAP_BE
   17.28          bool "Block Tap support for backend driver (DANGEROUS)"
   17.29 +      depends on XEN_BLDEV_BACKEND
   17.30          default n
   17.31          help
   17.32            If you intend to use the block tap driver, the backend domain will
   17.33 @@ -61,12 +60,11 @@ config XEN_BLKDEV_TAP_BE
   17.34            security risk, and so should ONLY be used for development
   17.35            with the blktap.  This option will be removed as the block drivers are
   17.36            modified to use grant tables.
   17.37 -endif
   17.38  
   17.39  config XEN_NETDEV_BACKEND
   17.40          bool "Network-device backend driver"
   17.41 -        default y if XEN_PHYSDEV_ACCESS
   17.42 -        default n if !XEN_PHYSDEV_ACCESS
   17.43 +      depends on XEN_PHYSDEV_ACCESS
   17.44 +        default y
   17.45          help
   17.46            The network-device backend driver allows the kernel to export its
   17.47            network devices to other guests via a high-performance shared-memory
   17.48 @@ -90,9 +88,9 @@ config XEN_NETDEV_FRONTEND
   17.49            dedicated device-driver domain, or your master control domain
   17.50            (domain 0), then you almost certainly want to say Y here.
   17.51  
   17.52 -if XEN_NETDEV_FRONTEND
   17.53  config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
   17.54          bool "Pipelined transmitter (DANGEROUS)"
   17.55 +	depends on XEN_NETDEV_FRONTEND
   17.56          default n
   17.57          help
   17.58            The driver will assume that the backend is pipelining packets for
   17.59 @@ -106,7 +104,6 @@ config XEN_NETDEV_FRONTEND_PIPELINED_TRA
   17.60            like reassembling packets to perform firewall filtering; or if you
   17.61            are unsure; or if you experience network hangs when this option is
   17.62            enabled; then you must say N here.
   17.63 -endif
   17.64  
   17.65  config XEN_BLKDEV_TAP
   17.66          bool "Block device tap driver"
   17.67 @@ -133,40 +130,28 @@ config XEN_SCRUB_PAGES
   17.68            If security is not a concern then you may increase performance by
   17.69            saying N.
   17.70  
   17.71 +choice
   17.72 +        prompt "Processor Type"
   17.73 +        default X86
   17.74 +
   17.75 +config X86
   17.76 +        bool "X86"
   17.77 +        help
   17.78 +          Choose this option if your computer is a X86 architecture.
   17.79 +
   17.80 +config X86_64
   17.81 +        bool "X86_64"
   17.82 +        help
   17.83 +          Choose this option if your computer is a X86 architecture.
   17.84 +
   17.85 +endchoice
   17.86 +
   17.87  endmenu
   17.88  
   17.89  config HAVE_ARCH_DEV_ALLOC_SKB
   17.90  	bool
   17.91  	default y
   17.92  
   17.93 -#config VT
   17.94 -#	bool
   17.95 -#	default y
   17.96 -
   17.97 -#config VT_CONSOLE
   17.98 -#	bool
   17.99 -#	default y
  17.100 -
  17.101 -#config HW_CONSOLE
  17.102 -#	bool
  17.103 -#	default y
  17.104 -
  17.105 -choice
  17.106 -	prompt "Processor Type"
  17.107 -	default X86
  17.108 -
  17.109 -config X86
  17.110 -	bool "X86"
  17.111 -	help
  17.112 -	  Choose this option if your computer is a X86 architecture.
  17.113 -
  17.114 -config X86_64
  17.115 -	bool "X86_64"
  17.116 -	help
  17.117 -	  Choose this option if your computer is a X86 architecture.
  17.118 -
  17.119 -endchoice
  17.120 -
  17.121  source "init/Kconfig"
  17.122  
  17.123  if X86
    18.1 --- a/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig	Fri Jan 21 13:52:28 2005 +0000
    18.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig	Mon Jan 24 10:19:03 2005 +0000
    18.3 @@ -160,15 +160,8 @@ CONFIG_PCMCIA_PROBE=y
    18.4  #
    18.5  # Kernel hacking
    18.6  #
    18.7 -CONFIG_DEBUG_KERNEL=y
    18.8 +# CONFIG_DEBUG_KERNEL is not set
    18.9  CONFIG_EARLY_PRINTK=y
   18.10 -# CONFIG_DEBUG_STACKOVERFLOW is not set
   18.11 -# CONFIG_DEBUG_STACK_USAGE is not set
   18.12 -CONFIG_DEBUG_SLAB=y
   18.13 -CONFIG_MAGIC_SYSRQ=y
   18.14 -# CONFIG_DEBUG_SPINLOCK is not set
   18.15 -CONFIG_DEBUG_PAGEALLOC=y
   18.16 -# CONFIG_DEBUG_INFO is not set
   18.17  # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
   18.18  # CONFIG_FRAME_POINTER is not set
   18.19  # CONFIG_4KSTACKS is not set
    19.1 --- a/linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig	Fri Jan 21 13:52:28 2005 +0000
    19.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig	Mon Jan 24 10:19:03 2005 +0000
    19.3 @@ -129,15 +129,8 @@ CONFIG_HAVE_DEC_LOCK=y
    19.4  #
    19.5  # Kernel hacking
    19.6  #
    19.7 -CONFIG_DEBUG_KERNEL=y
    19.8 +# CONFIG_DEBUG_KERNEL is not set
    19.9  CONFIG_EARLY_PRINTK=y
   19.10 -# CONFIG_DEBUG_STACKOVERFLOW is not set
   19.11 -# CONFIG_DEBUG_STACK_USAGE is not set
   19.12 -CONFIG_DEBUG_SLAB=y
   19.13 -# CONFIG_MAGIC_SYSRQ is not set
   19.14 -# CONFIG_DEBUG_SPINLOCK is not set
   19.15 -CONFIG_DEBUG_PAGEALLOC=y
   19.16 -# CONFIG_DEBUG_INFO is not set
   19.17  # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
   19.18  # CONFIG_FRAME_POINTER is not set
   19.19  # CONFIG_4KSTACKS is not set
    20.1 --- a/tools/python/xen/lowlevel/xu/xu.c	Fri Jan 21 13:52:28 2005 +0000
    20.2 +++ b/tools/python/xen/lowlevel/xu/xu.c	Mon Jan 24 10:19:03 2005 +0000
    20.3 @@ -562,6 +562,24 @@ static PyTypeObject xu_notifier_type = {
    20.4          PyDict_SetItemString(dict, #_field, obj);                         \
    20.5      } while ( 0 )
    20.6  
    20.7 +#define PSTR2CHAR(_struct, _field)                                        \
    20.8 + do {                                                                     \
    20.9 +     PyObject *obj;                                                       \
   20.10 +        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
   20.11 +        {                                                                 \
   20.12 +            if ( PyString_Check(obj) )                                    \
   20.13 +            {                                                             \
   20.14 +                char *buffer = PyString_AsString(obj);                    \
   20.15 +                                                                          \
   20.16 +                strcpy(((_struct *)&xum->msg.msg[0])->_field,             \
   20.17 +                        buffer);                                          \
   20.18 +                /* Should complain about length - think later */          \
   20.19 +                dict_items_parsed++;                                      \
   20.20 +            }                                                             \
   20.21 +        }                                                                 \
   20.22 +        xum->msg.length = sizeof(_struct);                                \
   20.23 + } while ( 0 )
   20.24 +
   20.25  typedef struct {
   20.26      PyObject_HEAD;
   20.27      control_msg_t msg;
   20.28 @@ -753,6 +771,52 @@ static PyObject *xu_message_get_payload(
   20.29      case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
   20.30          C2P(netif_be_driver_status_t, status, Int, Long);
   20.31          return dict;
   20.32 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
   20.33 +        C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
   20.34 +        C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
   20.35 +        C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
   20.36 +        C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
   20.37 +	C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
   20.38 +        return dict;
   20.39 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
   20.40 +        C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
   20.41 +        return dict;
   20.42 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
   20.43 +        C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
   20.44 +        return dict;
   20.45 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
   20.46 +        return dict;
   20.47 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
   20.48 +        C2P(usbif_be_create_t, domid, Int, Long);
   20.49 +        C2P(usbif_be_create_t, status, Int, Long);
   20.50 +        return dict;
   20.51 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
   20.52 +        C2P(usbif_be_destroy_t, domid, Int, Long);
   20.53 +        C2P(usbif_be_destroy_t, status, Int, Long);
   20.54 +        return dict;
   20.55 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
   20.56 +        C2P(usbif_be_connect_t, domid, Int, Long);
   20.57 +        C2P(usbif_be_connect_t, shmem_frame, Int, Long);
   20.58 +        C2P(usbif_be_connect_t, evtchn, Int, Long);
   20.59 +        C2P(usbif_be_connect_t, bandwidth, Int, Long);
   20.60 +        C2P(usbif_be_connect_t, status, Int, Long);
   20.61 +        return dict;
   20.62 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
   20.63 +        C2P(usbif_be_disconnect_t, domid, Int, Long);
   20.64 +        C2P(usbif_be_disconnect_t, status, Int, Long);
   20.65 +        return dict;
   20.66 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
   20.67 +        C2P(usbif_be_driver_status_changed_t, status, Int, Long);
   20.68 +        return dict;
   20.69 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
   20.70 +        C2P(usbif_be_claim_port_t, domid, Int, Long);
   20.71 +        C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
   20.72 +        C2P(usbif_be_claim_port_t, status, Int, Long);
   20.73 +        C2P(usbif_be_claim_port_t, path, String, String);
   20.74 +        return dict;
   20.75 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
   20.76 +        C2P(usbif_be_release_port_t, path, String, String);
   20.77 +        return dict;
   20.78      case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
   20.79          C2P(mem_request_t, target, Int, Long);
   20.80          C2P(mem_request_t, status, Int, Long);
   20.81 @@ -922,6 +986,53 @@ static PyObject *xu_message_new(PyObject
   20.82          P2C(mem_request_t, target, u32);
   20.83          P2C(mem_request_t, status, u32);
   20.84          break;
   20.85 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
   20.86 +        P2C(usbif_fe_interface_status_changed_t, status, u32);
   20.87 +        P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
   20.88 +        P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
   20.89 +        P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
   20.90 +	P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
   20.91 +        break;
   20.92 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
   20.93 +        P2C(usbif_fe_driver_status_changed_t, status, u32);
   20.94 +        break;
   20.95 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
   20.96 +        P2C(usbif_fe_interface_connect_t, shmem_frame, memory_t);
   20.97 +        break;
   20.98 +    case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
   20.99 +        break;
  20.100 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
  20.101 +        P2C(usbif_be_create_t, domid, domid_t);
  20.102 +        P2C(usbif_be_create_t, status, u32);
  20.103 +        break;
  20.104 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
  20.105 +        P2C(usbif_be_destroy_t, domid, domid_t);
  20.106 +        P2C(usbif_be_destroy_t, status, u32);
  20.107 +        break;
  20.108 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
  20.109 +        P2C(usbif_be_connect_t, domid, domid_t);
  20.110 +        P2C(usbif_be_connect_t, shmem_frame, memory_t);
  20.111 +        P2C(usbif_be_connect_t, evtchn, u32);
  20.112 +        P2C(usbif_be_connect_t, bandwidth, u32);
  20.113 +        P2C(usbif_be_connect_t, status, u32);
  20.114 +        break;
  20.115 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
  20.116 +        P2C(usbif_be_disconnect_t, domid, domid_t);
  20.117 +        P2C(usbif_be_disconnect_t, status, u32);
  20.118 +        break;
  20.119 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
  20.120 +        P2C(usbif_be_driver_status_changed_t, status, u32);
  20.121 +        break;
  20.122 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
  20.123 +        P2C(usbif_be_claim_port_t, domid, domid_t);
  20.124 +        P2C(usbif_be_claim_port_t, usbif_port, u32);
  20.125 +        P2C(usbif_be_claim_port_t, status, u32);
  20.126 +        PSTR2CHAR(usbif_be_claim_port_t, path);
  20.127 +        printf("dict items parsed = %d", dict_items_parsed);
  20.128 +        break;
  20.129 +    case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
  20.130 +        PSTR2CHAR(usbif_be_release_port_t, path);
  20.131 +        break;
  20.132      }
  20.133  
  20.134      if ( dict_items_parsed != PyDict_Size(payload) )
    21.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Jan 21 13:52:28 2005 +0000
    21.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jan 24 10:19:03 2005 +0000
    21.3 @@ -658,6 +658,7 @@ class XendDomainInfo:
    21.4          """
    21.5          self.release_vifs()
    21.6          self.release_vbds()
    21.7 +        self.release_usbifs()
    21.8          
    21.9          self.devices = {}
   21.10          self.device_index = {}
   21.11 @@ -682,6 +683,15 @@ class XendDomainInfo:
   21.12              log.debug("Destroying vbds for domain %d", self.dom)
   21.13              ctrl.destroy()
   21.14  
   21.15 +    def release_usbifs(self):
   21.16 +        """Release vm virtual USB devices (usbifs).
   21.17 +        """
   21.18 +        if self.dom is None: return
   21.19 +        ctrl = xend.usbif_get(self.dom)
   21.20 +        if ctrl:
   21.21 +            log.debug("Destroying usbifs for domain %d", self.dom)
   21.22 +            ctrl.destroy()
   21.23 +
   21.24      def show(self):
   21.25          """Print virtual machine info.
   21.26          """
   21.27 @@ -994,6 +1004,8 @@ class XendDomainInfo:
   21.28                  self.blkif_backend = 1
   21.29              elif name == 'netif':
   21.30                  self.netif_backend = 1
   21.31 +            elif name == 'usbif':
   21.32 +                self.usbif_backend = 1
   21.33              else:
   21.34                  raise VmError('invalid backend type:' + str(name))
   21.35  
   21.36 @@ -1174,6 +1186,23 @@ def vm_dev_vif(vm, val, index, change=0)
   21.37      defer.addCallback(cbok)
   21.38      return defer
   21.39  
   21.40 +def vm_dev_usb(vm, val, index):
   21.41 +    """Attach the relevant physical ports to the domains' USB interface.
   21.42 +
   21.43 +    @param vm:    virtual machine
   21.44 +    @param val:   USB interface config
   21.45 +    @param index: USB interface index
   21.46 +    @return: deferred
   21.47 +    """
   21.48 +    ctrl = xend.usbif_create(vm.dom, recreate=vm.recreate)
   21.49 +    log.debug("Creating USB interface dom=%d", vm.dom)
   21.50 +    defer = ctrl.attachDevice(val, recreate=vm.recreate)
   21.51 +    def cbok(path):
   21.52 +        vm.add_device('usb', val[1][1])
   21.53 +        return path
   21.54 +    defer.addCallback(cbok)
   21.55 +    return defer
   21.56 +
   21.57  def vm_dev_vbd(vm, val, index, change=0):
   21.58      """Create a virtual block device (vbd).
   21.59  
   21.60 @@ -1278,6 +1307,7 @@ add_image_handler('vmx',  vm_image_vmx)
   21.61  add_device_handler('vif',  vm_dev_vif)
   21.62  add_device_handler('vbd',  vm_dev_vbd)
   21.63  add_device_handler('pci',  vm_dev_pci)
   21.64 +add_device_handler('usb',  vm_dev_usb)
   21.65  
   21.66  # Ignore the fields we already handle.
   21.67  add_config_handler('name',       vm_field_ignore)
    22.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Fri Jan 21 13:52:28 2005 +0000
    22.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Mon Jan 24 10:19:03 2005 +0000
    22.3 @@ -40,6 +40,7 @@ from xen.util.ip import _readline, _read
    22.4  import channel
    22.5  import blkif
    22.6  import netif
    22.7 +import usbif
    22.8  import console
    22.9  import domain
   22.10  from params import *
   22.11 @@ -261,6 +262,7 @@ class EventProtocol(protocol.Protocol):
   22.12          val += self.daemon.consoles()
   22.13          val += self.daemon.blkifs()
   22.14          val += self.daemon.netifs()
   22.15 +        val += self.daemon.usbifs()
   22.16          return val
   22.17  
   22.18      def op_sys_subscribe(self, name, v):
   22.19 @@ -617,6 +619,7 @@ class Daemon:
   22.20          self.domainCF = domain.DomainControllerFactory()
   22.21          self.blkifCF = blkif.BlkifControllerFactory()
   22.22          self.netifCF = netif.NetifControllerFactory()
   22.23 +        self.usbifCF = usbif.UsbifControllerFactory()
   22.24          self.consoleCF = console.ConsoleControllerFactory()
   22.25  
   22.26      def listenEvent(self):
   22.27 @@ -683,6 +686,15 @@ class Daemon:
   22.28      def netif_get(self, dom):
   22.29          return self.netifCF.getControllerByDom(dom)
   22.30  
   22.31 +    def usbif_create(self, dom, recreate=0):
   22.32 +        return self.usbifCF.getController(dom)
   22.33 +    
   22.34 +    def usbifs(self):
   22.35 +        return [ x.sxpr() for x in self.usbifCF.getControllers() ]
   22.36 +
   22.37 +    def usbif_get(self, dom):
   22.38 +        return self.usbifCF.getControllerByDom(dom)
   22.39 +
   22.40      def console_create(self, dom, console_port=None):
   22.41          """Create a console for a domain.
   22.42          """
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/python/xen/xend/server/SrvUsbif.py	Mon Jan 24 10:19:03 2005 +0000
    23.3 @@ -0,0 +1,249 @@
    23.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    23.5 +
    23.6 +from twisted.protocols import http
    23.7 +
    23.8 +from xen.xend import sxp
    23.9 +from xen.xend import XendDomain
   23.10 +from xen.xend import XendConsole
   23.11 +from xen.xend import PrettyPrint
   23.12 +from xen.xend.Args import FormFn
   23.13 +
   23.14 +from SrvDir import SrvDir
   23.15 +
   23.16 +class SrvDomain(SrvDir):
   23.17 +    """Service managing a single domain.
   23.18 +    """
   23.19 +
   23.20 +    def __init__(self, dom):
   23.21 +        SrvDir.__init__(self)
   23.22 +        self.dom = dom
   23.23 +        self.xd = XendDomain.instance()
   23.24 +        self.xconsole = XendConsole.instance()
   23.25 +
   23.26 +    def op_configure(self, op, req):
   23.27 +        """Configure an existing domain.
   23.28 +        Configure is unusual in that it requires a domain id,
   23.29 +        not a domain name.
   23.30 +        """
   23.31 +        fn = FormFn(self.xd.domain_configure,
   23.32 +                    [['dom', 'int'],
   23.33 +                     ['config', 'sxpr']])
   23.34 +        deferred = fn(req.args, {'dom': self.dom.dom})
   23.35 +        deferred.addErrback(self._op_configure_err, req)
   23.36 +        return deferred
   23.37 +
   23.38 +    def _op_configure_err(self, err, req):
   23.39 +        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
   23.40 +        return str(err)
   23.41 +        
   23.42 +    def op_unpause(self, op, req):
   23.43 +        val = self.xd.domain_unpause(self.dom.name)
   23.44 +        return val
   23.45 +        
   23.46 +    def op_pause(self, op, req):
   23.47 +        val = self.xd.domain_pause(self.dom.name)
   23.48 +        return val
   23.49 +
   23.50 +    def op_shutdown(self, op, req):
   23.51 +        fn = FormFn(self.xd.domain_shutdown,
   23.52 +                    [['dom', 'str'],
   23.53 +                     ['reason', 'str']])
   23.54 +        val = fn(req.args, {'dom': self.dom.id})
   23.55 +        req.setResponseCode(http.ACCEPTED)
   23.56 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   23.57 +        return val
   23.58 +
   23.59 +    def op_destroy(self, op, req):
   23.60 +        fn = FormFn(self.xd.domain_destroy,
   23.61 +                    [['dom', 'str'],
   23.62 +                     ['reason', 'str']])
   23.63 +        val = fn(req.args, {'dom': self.dom.id})
   23.64 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   23.65 +        return val
   23.66 +
   23.67 +    def op_save(self, op, req):
   23.68 +        fn = FormFn(self.xd.domain_save,
   23.69 +                    [['dom', 'str'],
   23.70 +                     ['file', 'str']])
   23.71 +        deferred = fn(req.args, {'dom': self.dom.id})
   23.72 +        deferred.addCallback(self._op_save_cb, req)
   23.73 +        deferred.addErrback(self._op_save_err, req)
   23.74 +        return deferred
   23.75 +
   23.76 +    def _op_save_cb(self, val, req):
   23.77 +        return 0
   23.78 +
   23.79 +    def _op_save_err(self, err, req):
   23.80 +        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
   23.81 +        return str(err)
   23.82 +        
   23.83 +    def op_migrate(self, op, req):
   23.84 +        fn = FormFn(self.xd.domain_migrate,
   23.85 +                    [['dom', 'str'],
   23.86 +                     ['destination', 'str'],
   23.87 +                     ['live', 'int']])
   23.88 +        deferred = fn(req.args, {'dom': self.dom.id})
   23.89 +        print 'op_migrate>', deferred
   23.90 +        deferred.addCallback(self._op_migrate_cb, req)
   23.91 +        deferred.addErrback(self._op_migrate_err, req)
   23.92 +        return deferred
   23.93 +
   23.94 +    def _op_migrate_cb(self, info, req):
   23.95 +        print '_op_migrate_cb>', info, req
   23.96 +        #req.setResponseCode(http.ACCEPTED)
   23.97 +        host = info.dst_host
   23.98 +        port = info.dst_port
   23.99 +        dom  = info.dst_dom
  23.100 +        url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
  23.101 +        req.setHeader("Location", url)
  23.102 +        print '_op_migrate_cb> url=', url
  23.103 +        return url
  23.104 +
  23.105 +    def _op_migrate_err(self, err, req):
  23.106 +        print '_op_migrate_err>', err, req
  23.107 +        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
  23.108 +        return str(err)
  23.109 +
  23.110 +    def op_pincpu(self, op, req):
  23.111 +        fn = FormFn(self.xd.domain_pincpu,
  23.112 +                    [['dom', 'str'],
  23.113 +                     ['cpu', 'int']])
  23.114 +        val = fn(req.args, {'dom': self.dom.id})
  23.115 +        return val
  23.116 +
  23.117 +    def op_cpu_bvt_set(self, op, req):
  23.118 +        fn = FormFn(self.xd.domain_cpu_bvt_set,
  23.119 +                    [['dom', 'str'],
  23.120 +                     ['mcuadv', 'int'],
  23.121 +                     ['warpback', 'int'],
  23.122 +                     ['warpvalue', 'int'],
  23.123 +                     ['warpl', 'long'],
  23.124 +                     ['warpu', 'long']])
  23.125 +        val = fn(req.args, {'dom': self.dom.id})
  23.126 +        return val
  23.127 +    
  23.128 +    def op_cpu_fbvt_set(self, op, req):
  23.129 +        fn = FormFn(self.xd.domain_cpu_fbvt_set,
  23.130 +                    [['dom', 'str'],
  23.131 +                     ['mcuadv', 'int'],
  23.132 +                     ['warp', 'int'],
  23.133 +                     ['warpl', 'int'],
  23.134 +                     ['warpu', 'int']])
  23.135 +        val = fn(req.args, {'dom': self.dom.id})
  23.136 +        return val
  23.137 +
  23.138 +    def op_cpu_atropos_set(self, op, req):
  23.139 +        fn = FormFn(self.xd.domain_cpu_atropos_set,
  23.140 +                    [['dom', 'str'],
  23.141 +                     ['period', 'int'],
  23.142 +                     ['slice', 'int'],
  23.143 +                     ['latency', 'int'],
  23.144 +                     ['xtratime', 'int']])
  23.145 +        val = fn(req.args, {'dom': self.dom.id})
  23.146 +        return val
  23.147 +
  23.148 +    def op_maxmem_set(self, op, req):
  23.149 +        fn = FormFn(self.xd.domain_maxmem_set,
  23.150 +                    [['dom', 'str'],
  23.151 +                     ['memory', 'int']])
  23.152 +        val = fn(req.args, {'dom': self.dom.id})
  23.153 +        return val
  23.154 +
  23.155 +    def op_device_create(self, op, req):
  23.156 +        fn = FormFn(self.xd.domain_device_create,
  23.157 +                    [['dom', 'str'],
  23.158 +                     ['config', 'sxpr']])
  23.159 +        d = fn(req.args, {'dom': self.dom.id})
  23.160 +        return d
  23.161 +
  23.162 +    def op_device_destroy(self, op, req):
  23.163 +        fn = FormFn(self.xd.domain_device_destroy,
  23.164 +                    [['dom', 'str'],
  23.165 +                     ['type', 'str'],
  23.166 +                     ['idx', 'str']])
  23.167 +        val = fn(req.args, {'dom': self.dom.id})
  23.168 +        return val
  23.169 +                
  23.170 +    def op_vifs(self, op, req):
  23.171 +        devs = self.xd.domain_vif_ls(self.dom.id)
  23.172 +        return [ dev.sxpr() for dev in devs ]
  23.173 +
  23.174 +    def op_vif(self, op, req):
  23.175 +        fn = FormFn(self.xd.domain_vif_get,
  23.176 +                    [['dom', 'str'],
  23.177 +                     ['vif', 'str']])
  23.178 +        val = fn(req.args, {'dom': self.dom.id})
  23.179 +        return val
  23.180 +
  23.181 +    def op_vbds(self, op, req):
  23.182 +        devs = self.xd.domain_vbd_ls(self.dom.id)
  23.183 +        return [ dev.sxpr() for dev in devs ]
  23.184 +
  23.185 +    def op_vbd(self, op, req):
  23.186 +        fn = FormFn(self.xd.domain_vbd_get,
  23.187 +                    [['dom', 'str'],
  23.188 +                     ['vbd', 'str']])
  23.189 +        val = fn(req.args, {'dom': self.dom.id})
  23.190 +        return val
  23.191 +
  23.192 +    def render_POST(self, req):
  23.193 +        return self.perform(req)
  23.194 +        
  23.195 +    def render_GET(self, req):
  23.196 +        op = req.args.get('op')
  23.197 +        if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd']:
  23.198 +            return self.perform(req)
  23.199 +        if self.use_sxp(req):
  23.200 +            req.setHeader("Content-Type", sxp.mime_type)
  23.201 +            sxp.show(self.dom.sxpr(), out=req)
  23.202 +        else:
  23.203 +            req.write('<html><head></head><body>')
  23.204 +            self.print_path(req)
  23.205 +            #self.ls()
  23.206 +            req.write('<p>%s</p>' % self.dom)
  23.207 +            if self.dom.console:
  23.208 +                cinfo = self.dom.console
  23.209 +                cid = str(cinfo.console_port)
  23.210 +                #todo: Local xref: need to know server prefix.
  23.211 +                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
  23.212 +                          % (cid, cid))
  23.213 +                req.write('<p><a href="%s">Connect to console</a></p>'
  23.214 +                          % cinfo.uri())
  23.215 +            if self.dom.config:
  23.216 +                req.write("<code><pre>")
  23.217 +                PrettyPrint.prettyprint(self.dom.config, out=req)
  23.218 +                req.write("</pre></code>")
  23.219 +            self.form(req)
  23.220 +            req.write('</body></html>')
  23.221 +        return ''
  23.222 +
  23.223 +    def form(self, req):
  23.224 +        url = req.prePathURL()
  23.225 +        req.write('<form method="post" action="%s">' % url)
  23.226 +        req.write('<input type="submit" name="op" value="unpause">')
  23.227 +        req.write('<input type="submit" name="op" value="pause">')
  23.228 +        req.write('</form>')
  23.229 +
  23.230 +        req.write('<form method="post" action="%s">' % url)
  23.231 +        req.write('<input type="submit" name="op" value="destroy">')
  23.232 +        req.write('<input type="radio" name="reason" value="halt" checked>Halt')
  23.233 +        req.write('<input type="radio" name="reason" value="reboot">Reboot')
  23.234 +        req.write('</form>')
  23.235 +
  23.236 +        req.write('<form method="post" action="%s">' % url)
  23.237 +        req.write('<input type="submit" name="op" value="shutdown">')
  23.238 +        req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
  23.239 +        req.write('<input type="radio" name="reason" value="halt">Halt')
  23.240 +        req.write('<input type="radio" name="reason" value="reboot">Reboot')
  23.241 +        req.write('</form>')
  23.242 +        
  23.243 +        req.write('<form method="post" action="%s">' % url)
  23.244 +        req.write('<br><input type="submit" name="op" value="save">')
  23.245 +        req.write(' To file: <input type="text" name="file">')
  23.246 +        req.write('</form>')
  23.247 +        
  23.248 +        req.write('<form method="post" action="%s">' % url)
  23.249 +        req.write('<br><input type="submit" name="op" value="migrate">')
  23.250 +        req.write(' To host: <input type="text" name="destination">')
  23.251 +        req.write('<input type="checkbox" name="live" value="1">Live')
  23.252 +        req.write('</form>')
    24.1 --- a/tools/python/xen/xend/server/messages.py	Fri Jan 21 13:52:28 2005 +0000
    24.2 +++ b/tools/python/xen/xend/server/messages.py	Mon Jan 24 10:19:03 2005 +0000
    24.3 @@ -189,6 +189,70 @@ netif_formats = {
    24.4  msg_formats.update(netif_formats)
    24.5  
    24.6  #============================================================================
    24.7 +# USB interface message types.
    24.8 +#============================================================================
    24.9 +
   24.10 +CMSG_USBIF_BE = 8
   24.11 +CMSG_USBIF_FE = 9
   24.12 +
   24.13 +CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED = 0
   24.14 +
   24.15 +CMSG_USBIF_FE_DRIVER_STATUS_CHANGED = 32
   24.16 +CMSG_USBIF_FE_INTERFACE_CONNECT     = 33
   24.17 +CMSG_USBIF_FE_INTERFACE_DISCONNECT  = 34
   24.18 +
   24.19 +USBIF_DRIVER_STATUS_DOWN = 0
   24.20 +USBIF_DRIVER_STATUS_UP   = 1
   24.21 +
   24.22 +USBIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
   24.23 +USBIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
   24.24 +USBIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
   24.25 +
   24.26 +CMSG_USBIF_BE_CREATE = 0
   24.27 +CMSG_USBIF_BE_DESTROY = 1
   24.28 +CMSG_USBIF_BE_CONNECT = 2
   24.29 +
   24.30 +CMSG_USBIF_BE_DISCONNECT = 3
   24.31 +CMSG_USBIF_BE_CLAIM_PORT = 4
   24.32 +CMSG_USBIF_BE_RELEASE_PORT = 5
   24.33 +
   24.34 +CMSG_USBIF_BE_DRIVER_STATUS_CHANGED = 32
   24.35 +
   24.36 +USBIF_BE_STATUS_OKAY = 0
   24.37 +USBIF_BE_STATUS_ERROR = 1
   24.38 +
   24.39 +USBIF_BE_STATUS_INTERFACE_EXISTS = 2
   24.40 +USBIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
   24.41 +USBIF_BE_STATUS_INTERFACE_CONNECTED = 4
   24.42 +USBIF_BE_STATUS_OUT_OF_MEMORY = 7
   24.43 +USBIF_BE_STATUS_MAPPING_ERROR = 9
   24.44 +
   24.45 +usbif_formats = {
   24.46 +    'usbif_be_create_t':
   24.47 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE),
   24.48 +    'usbif_be_destroy_t':
   24.49 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY),
   24.50 +    'usbif_be_connect_t':
   24.51 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT),
   24.52 +    'usbif_be_disconnect_t':
   24.53 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT),
   24.54 +    'usbif_be_claim_port_t':
   24.55 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT),
   24.56 +    'usbif_be_release_port_t':
   24.57 +    (CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT),
   24.58 +    'usbif_fe_interface_status_changed_t':
   24.59 +    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED),
   24.60 +    'usbif_fe_driver_status_changed_t':
   24.61 +    (CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED),
   24.62 +    'usbif_fe_interface_connect_t':
   24.63 +    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT),
   24.64 +    'usbif_fe_interface_disconnect_t':
   24.65 +    (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT)
   24.66 +    }
   24.67 +    
   24.68 +msg_formats.update(usbif_formats)
   24.69 +
   24.70 +#============================================================================
   24.71  # Domain shutdown message types.
   24.72  #============================================================================
   24.73  
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/python/xen/xend/server/usbif.py	Mon Jan 24 10:19:03 2005 +0000
    25.3 @@ -0,0 +1,368 @@
    25.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    25.5 +# Copyright (C) 2004 Intel Research Cambridge
    25.6 +# Copyright (C) 2004 Mark Williamson <mark.williamson@cl.cam.ac.uk>
    25.7 +"""Support for virtual USB hubs.
    25.8 +"""
    25.9 +
   25.10 +from twisted.internet import defer
   25.11 +#defer.Deferred.debug = 1
   25.12 +
   25.13 +from xen.xend import sxp
   25.14 +from xen.xend.XendLogging import log
   25.15 +from xen.xend.XendError import XendError
   25.16 +
   25.17 +import channel
   25.18 +import controller
   25.19 +from messages import *
   25.20 +
   25.21 +class UsbifBackendController(controller.BackendController):
   25.22 +    """ Handler for the 'back-end' channel to a USB hub domain.
   25.23 +    Must be connected using connect() before it can be used.
   25.24 +    Do not create directly - use getBackend() on the UsbifController.
   25.25 +    """
   25.26 +
   25.27 +    def __init__(self, ctrl, dom):
   25.28 +        controller.BackendController.__init__(self, ctrl, dom)
   25.29 +        self.connected = 0
   25.30 +        self.evtchn = None
   25.31 +        self.addMethod(CMSG_USBIF_BE,
   25.32 +                       CMSG_USBIF_BE_DRIVER_STATUS_CHANGED,
   25.33 +                       self.recv_be_driver_status_changed)
   25.34 +        self.registerChannel()
   25.35 +
   25.36 +    def __str__(self):
   25.37 +        return '<UsbifBackendController %d>' % (self.dom)
   25.38 +
   25.39 +    def recv_be_driver_status_changed(self, msg, req):
   25.40 +        """Request handler for be_driver_status_changed messages.
   25.41 +        
   25.42 +        @param msg: message
   25.43 +        @type  msg: xu message
   25.44 +        @param req: request flag (true if the msg is a request)
   25.45 +        @type  req: bool
   25.46 +        """
   25.47 +        val = unpackMsg('usbif_be_driver_status_changed_t', msg)
   25.48 +        status = val['status']
   25.49 +
   25.50 +class UsbifBackendInterface(controller.BackendInterface):
   25.51 +    """Handler for the 'back-end' channel to a network device driver domain
   25.52 +    on behalf of a front-end domain.
   25.53 +
   25.54 +    Each network device is handled separately, so we add no functionality
   25.55 +    here.
   25.56 +    """
   25.57 +    def __init__(self, ctrl, dom):
   25.58 +        controller.BackendInterface.__init__(self, ctrl, dom, 0)
   25.59 +        self.connected = 0
   25.60 +        self.connecting = False
   25.61 +
   25.62 +    def connect(self, recreate=0):
   25.63 +        """Connect the controller to the usbif control interface.
   25.64 +
   25.65 +        @param recreate: true if after xend restart
   25.66 +        @return: deferred
   25.67 +        """
   25.68 +        log.debug("Connecting usbif %s", str(self))
   25.69 +        if recreate or self.connected or self.connecting:
   25.70 +            d = defer.succeed(self)
   25.71 +        else:
   25.72 +            self.connecting = True
   25.73 +            d = self.send_be_create()
   25.74 +            d.addCallback(self.respond_be_create)
   25.75 +        return d
   25.76 +        
   25.77 +    def send_be_create(self):
   25.78 +        d = defer.Deferred()
   25.79 +        msg = packMsg('usbif_be_create_t',
   25.80 +                      { 'domid'        : self.controller.dom })
   25.81 +        self.writeRequest(msg, response=d)
   25.82 +        return d
   25.83 +
   25.84 +    def respond_be_create(self, msg):
   25.85 +        val = unpackMsg('usbif_be_create_t', msg)
   25.86 +        log.debug('>UsbifBackendController>respond_be_create> %s', str(val))
   25.87 +        self.connected = True
   25.88 +        return self
   25.89 +    
   25.90 +    def destroy(self):
   25.91 +        """Disconnect from the usbif control interface and destroy it.
   25.92 +        """
   25.93 +        def cb_destroy(val):
   25.94 +            self.send_be_destroy()
   25.95 +        d = defer.Deferred()
   25.96 +        d.addCallback(cb_destroy)
   25.97 +        self.send_be_disconnect(response=d)
   25.98 +        
   25.99 +    def send_be_disconnect(self, response=None):
  25.100 +        log.debug('>UsbifBackendController>send_be_disconnect> %s', str(self))
  25.101 +        msg = packMsg('usbif_be_disconnect_t',
  25.102 +                      { 'domid'        : self.controller.dom })
  25.103 +        self.writeRequest(msg, response=response)
  25.104 +
  25.105 +    def send_be_destroy(self, response=None):
  25.106 +        log.debug('>UsbifBackendController>send_be_destroy> %s', str(self))
  25.107 +        msg = packMsg('usbif_be_destroy_t',
  25.108 +                      { 'domid'        : self.controller.dom })
  25.109 +        self.writeRequest(msg, response=response)
  25.110 +
  25.111 +    def send_be_claim_port(self, path):
  25.112 +        d=defer.Deferred()
  25.113 +        log.debug(">UsbifBackendController>send_be_claim_port> about to claim port %s" % path)
  25.114 +        def cb(blah): log.debug(">UsbifBackendController> Claim port completed")
  25.115 +        d.addCallback(cb)
  25.116 +        msg = packMsg('usbif_be_claim_port_t',
  25.117 +                      { 'domid'        : self.controller.dom,
  25.118 +                        'path'         : path,
  25.119 +                        'usbif_port'   : self.controller.devices[path],
  25.120 +                        'status'       : 0})
  25.121 +        self.writeRequest(msg, response=d)
  25.122 +        # No need to add any callbacks, since the guest polls its virtual ports
  25.123 +        # anyhow, somewhat like a UHCI controller ;-)
  25.124 +        return d
  25.125 +
  25.126 +    def send_be_release_port(self, path):
  25.127 +        d=defer.Deferred()
  25.128 +        def cb(blah): log.debug(">UsbifBackendController> Release port completed")
  25.129 +        d.addCallback(cb)
  25.130 +        msg = packMsg('usbif_be_release_port_t',
  25.131 +                      { 'domid'        : self.controller.dom,
  25.132 +                        'path'         : path })
  25.133 +        self.writeRequest(msg, response)        
  25.134 +        # No need to add any callbacks, since the guest polls its virtual ports
  25.135 +        # anyhow, somewhat like a UHCI controller ;-)
  25.136 +    
  25.137 +    def connectInterface(self, val):
  25.138 +        self.evtchn = channel.eventChannel(0, self.controller.dom)
  25.139 +        log.debug(">UsbifBackendController>connectInterface> connecting usbif to event channel %s ports=%d:%d",
  25.140 +                  str(self), self.evtchn['port1'], self.evtchn['port2'])
  25.141 +        msg = packMsg('usbif_be_connect_t',
  25.142 +                      { 'domid'        : self.controller.dom,
  25.143 +                        'evtchn'       : self.evtchn['port1'],
  25.144 +                        'shmem_frame'  : val['shmem_frame'],
  25.145 +                        'bandwidth'    : 500 # XXX fix bandwidth!
  25.146 +                        })
  25.147 +        d = defer.Deferred()
  25.148 +        d.addCallback(self.respond_be_connect)
  25.149 +        self.writeRequest(msg, response=d)
  25.150 +
  25.151 +    def respond_be_connect(self, msg):
  25.152 +        """Response handler for a be_connect message.
  25.153 +
  25.154 +        @param msg: message
  25.155 +        @type  msg: xu message
  25.156 +        """
  25.157 +        val = unpackMsg('usbif_be_connect_t', msg)
  25.158 +        log.debug('>UsbifBackendController>respond_be_connect> %s, %s', str(self), str(val))
  25.159 +        d = defer.Deferred()
  25.160 +        def cb(blah):
  25.161 +            log.debug(">UsbifBackendController> Successfully connected USB interface for domain %d" % self.controller.dom)
  25.162 +            self.controller.claim_ports()
  25.163 +        d.addCallback(cb)
  25.164 +        self.send_fe_interface_status_changed(d)
  25.165 +            
  25.166 +    def send_fe_interface_status_changed(self, response=None):
  25.167 +        msg = packMsg('usbif_fe_interface_status_changed_t',
  25.168 +                      { 'status' : USBIF_INTERFACE_STATUS_CONNECTED,
  25.169 +                        'domid'  : 0, ## FIXME: should be domid of backend
  25.170 +                        'evtchn' : self.evtchn['port2'],
  25.171 +                        'bandwidth' : 500,
  25.172 +                        'num_ports'    : len(self.controller.devices.keys())})
  25.173 +        self.controller.writeRequest(msg, response=response)
  25.174 +
  25.175 +        
  25.176 +class UsbifControllerFactory(controller.SplitControllerFactory):
  25.177 +    """Factory for creating USB interface controllers.
  25.178 +    """
  25.179 +
  25.180 +    def __init__(self):
  25.181 +        controller.ControllerFactory.__init__(self)
  25.182 +        self.backendControllers = {}
  25.183 +
  25.184 +    def createController(self, dom, recreate=0):
  25.185 +        """Create a USB device controller for a domain.
  25.186 +
  25.187 +        @param dom: domain
  25.188 +        @type  dom: int
  25.189 +        @param recreate: if true it's a recreate (after xend restart)
  25.190 +        @type  recreate: bool
  25.191 +        @return: block device controller
  25.192 +        @rtype: UsbifController
  25.193 +        """
  25.194 +        usbif = self.getControllerByDom(dom)
  25.195 +        if usbif is None:
  25.196 +            usbif = UsbifController(self, dom)
  25.197 +            self.addController(usbif)
  25.198 +        return usbif
  25.199 +
  25.200 +    def getDomainDevices(self, dom):
  25.201 +        """Get the block devices for a domain.
  25.202 +
  25.203 +        @param dom: domain
  25.204 +        @type  dom: int
  25.205 +        @return: devices
  25.206 +        @rtype:  [device]
  25.207 +        """
  25.208 +        usbif = self.getControllerByDom(dom)
  25.209 +        return (usbif and usbif.getDevices()) or []
  25.210 +
  25.211 +    def getDomainDevice(self, dom, vdev):
  25.212 +        """Get a block device from a domain.
  25.213 +
  25.214 +        @param dom: domain
  25.215 +        @type  dom: int
  25.216 +        @param vdev: device index
  25.217 +        @type  vdev: int
  25.218 +        @return: device
  25.219 +        @rtype:  device
  25.220 +        """
  25.221 +        usbif = self.getControllerByDom(dom)
  25.222 +        return (usbif and usbif.getDevice(vdev)) or None
  25.223 +    
  25.224 +    def createBackendInterface(self, ctrl, dom, handle):
  25.225 +        """Create a network device backend interface.
  25.226 +
  25.227 +        @param ctrl: controller
  25.228 +        @param dom: backend domain
  25.229 +        @param handle: interface handle
  25.230 +        @return: backend interface
  25.231 +        """
  25.232 +        return UsbifBackendInterface(ctrl, dom)
  25.233 +
  25.234 +    def getBackendController(self, dom):
  25.235 +        """Get the backend controller for a domain, creating
  25.236 +        if necessary.
  25.237 +
  25.238 +        @param dom: backend domain
  25.239 +        @return: backend controller
  25.240 +        """
  25.241 +        b = self.getBackendControllerByDomain(dom)
  25.242 +        if b is None:
  25.243 +            b = self.createBackendController(dom)
  25.244 +            self.backendControllers[b.dom] = b
  25.245 +        return b
  25.246 +
  25.247 +    def createBackendController(self, dom):
  25.248 +        return UsbifBackendController(self, dom)
  25.249 +
  25.250 +class UsbifController(controller.SplitController):
  25.251 +    """USB device interface controller. Handles all USB devices
  25.252 +    for a domain.
  25.253 +    """
  25.254 +    
  25.255 +    def __init__(self, factory, dom):
  25.256 +        """Create a USB device controller.
  25.257 +        Do not call directly - use createController() on the factory instead.
  25.258 +        """
  25.259 +        controller.SplitController.__init__(self, factory, dom)
  25.260 +        self.num_ports = 0
  25.261 +        self.devices = {}
  25.262 +        self.addMethod(CMSG_USBIF_FE,
  25.263 +                       CMSG_USBIF_FE_DRIVER_STATUS_CHANGED,
  25.264 +                       self.recv_fe_driver_status_changed)
  25.265 +        self.addMethod(CMSG_USBIF_FE,
  25.266 +                       CMSG_USBIF_FE_INTERFACE_CONNECT,
  25.267 +                       self.recv_fe_interface_connect)
  25.268 +        self.registerChannel()
  25.269 +        try:
  25.270 +            self.backendDomain = 0 #int(sxp.child_value(config, 'backend', '0')) TODO: configurable backends
  25.271 +        except:
  25.272 +            raise XendError('invalid backend domain')
  25.273 +
  25.274 +
  25.275 +    def sxpr(self):
  25.276 +        val = ['usbif', ['dom', self.dom]]
  25.277 +        return val
  25.278 +
  25.279 +    def createBackend(self, dom, handle):
  25.280 +        return UsbifBackendController(self, dom, handle)
  25.281 +
  25.282 +    def getDevices(self):
  25.283 +        return self.devices.values()
  25.284 +
  25.285 +    def attachDevice(self, path, recreate=0):
  25.286 +        """Add privileges for a particular device to the domain.
  25.287 +        @param path: the Linux-style path to the device port
  25.288 +        """
  25.289 +        self.devices[path[1][1]] = self.num_ports
  25.290 +        self.num_ports += 1
  25.291 +        log.debug(">UsbifController>attachDevice> device: %s, port: %d" %
  25.292 +                  (str(path), self.num_ports ) )
  25.293 +
  25.294 +        backend =self.getBackendInterface(self.backendDomain)
  25.295 +
  25.296 +        def cb(blah):
  25.297 +            log.debug(">UsbifController> Backend created")
  25.298 +            pass
  25.299 +        d = backend.connect()
  25.300 +        d.addCallback(cb) # Chaining the claim port operation
  25.301 +        return d
  25.302 +
  25.303 +
  25.304 +    def removeDevice(self, path):
  25.305 +        self.delDevice(path)
  25.306 +        backend = self.getBackendInterface(self.backendDomain)
  25.307 +        return backend.send_be_release_port(path)
  25.308 +
  25.309 +    def delDevice(self, path):
  25.310 +        if path in self.devices:
  25.311 +            del self.devices[path]
  25.312 +
  25.313 +    def attachPort(self, path, recreate=0):
  25.314 +        """Attach a device to the specified interface.
  25.315 +        On success the returned deferred will be called with the device.
  25.316 +
  25.317 +        @return: deferred
  25.318 +        @rtype:  Deferred
  25.319 +        """
  25.320 +        return self.attachDevice(path)
  25.321 +
  25.322 +    def destroy(self):
  25.323 +        """Destroy the controller and all devices.
  25.324 +        """
  25.325 +        log.debug("Destroying usbif domain=%d", self.dom)
  25.326 +        self.destroyBackends()
  25.327 +
  25.328 +    def destroyDevices(self):
  25.329 +        """Destroy all devices.
  25.330 +        """
  25.331 +        for path in self.getDevices():
  25.332 +            self.removeDevice(path)
  25.333 +
  25.334 +    def destroyBackends(self):
  25.335 +        for backend in self.getBackendInterfaces():
  25.336 +            backend.destroy()
  25.337 +
  25.338 +    def recv_fe_driver_status_changed(self, msg, req):
  25.339 +        val = unpackMsg('usbif_fe_driver_status_changed_t', msg)
  25.340 +        log.debug('>UsbifController>recv_fe_driver_status_changed> %s', str(val))
  25.341 +        # For each backend?
  25.342 +        msg = packMsg('usbif_fe_interface_status_changed_t',
  25.343 +                      { 'status' : USBIF_INTERFACE_STATUS_DISCONNECTED,
  25.344 +                        'domid'  : 0, ## FIXME: should be domid of backend
  25.345 +                        'evtchn' : 0 })
  25.346 +        d = defer.Deferred()
  25.347 +        d.addCallback(self.disconnected_resp)
  25.348 +        self.writeRequest(msg)
  25.349 +
  25.350 +    def disconnected_resp(self, msg):
  25.351 +        val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
  25.352 +        if val['status'] != USBIF_INTERFACE_STATUS_DISCONNECTED:
  25.353 +            log.error(">UsbifController>disconnected_resp> unexpected status change")
  25.354 +        else:
  25.355 +            log.debug(">UsbifController>disconnected_resp> interface disconnected OK")
  25.356 +
  25.357 +    def recv_fe_interface_connect(self, msg, req):
  25.358 +        val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
  25.359 +        log.debug(">UsbifController>recv_fe_interface_connect> notifying backend")
  25.360 +        backend = self.getBackendInterfaceByHandle(0)
  25.361 +        if backend:
  25.362 +            d = backend.connectInterface(val)
  25.363 +        else:
  25.364 +            log.error('>UsbifController>recv_fe_interface_connect> unknown interface')
  25.365 +
  25.366 +    def claim_ports(self):
  25.367 +        backend = self.getBackendInterfaceByHandle(0)
  25.368 +        for path in self.devices.keys():
  25.369 +            log.debug(">UsbifController>claim_ports> claiming port... %s" % path)
  25.370 +            backend.send_be_claim_port(path)
  25.371 +
    26.1 --- a/tools/python/xen/xm/create.py	Fri Jan 21 13:52:28 2005 +0000
    26.2 +++ b/tools/python/xen/xm/create.py	Mon Jan 24 10:19:03 2005 +0000
    26.3 @@ -151,6 +151,11 @@ gopts.var('pci', val='BUS,DEV,FUNC',
    26.4           For example '-pci c0,02,1a'.
    26.5           The option may be repeated to add more than one pci device.""")
    26.6  
    26.7 +gopts.var('usb', val='PATH',
    26.8 +          fn=append_value, default=[],
    26.9 +          use="""Add a physical USB port to a domain, as specified by the path
   26.10 +          to that port.  This option may be repeated to add more than one port.""")
   26.11 +
   26.12  gopts.var('ipaddr', val="IPADDR",
   26.13            fn=append_value, default=[],
   26.14            use="Add an IP address to the domain.")
   26.15 @@ -273,6 +278,11 @@ def configure_pci(config_devs, vals):
   26.16          config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
   26.17          config_devs.append(['device', config_pci])
   26.18  
   26.19 +def configure_usb(config_devs, vals):
   26.20 +    for path in vals.usb:
   26.21 +        config_usb = ['usb', ['path', path]]
   26.22 +        config_devs.append(['device', config_usb])
   26.23 +
   26.24  def randomMAC():
   26.25      """Generate a random MAC address.
   26.26  
   26.27 @@ -371,6 +381,7 @@ def make_config(vals):
   26.28      configure_disks(config_devs, vals)
   26.29      configure_pci(config_devs, vals)
   26.30      configure_vifs(config_devs, vals)
   26.31 +    configure_usb(config_devs, vals)
   26.32      configure_vmx(config_devs, vals)
   26.33      config += config_devs
   26.34      return config
    27.1 --- a/tools/xcs/xcs.c	Fri Jan 21 13:52:28 2005 +0000
    27.2 +++ b/tools/xcs/xcs.c	Mon Jan 24 10:19:03 2005 +0000
    27.3 @@ -96,7 +96,7 @@ static void init_interfaces(void)
    27.4  static control_channel_t *add_interface(u32 dom, int local_port, 
    27.5                                          int remote_port)
    27.6  {
    27.7 -    control_channel_t *cc, *oldcc;
    27.8 +    control_channel_t *cc=NULL, *oldcc;
    27.9      int ret;
   27.10      
   27.11      if (cc_list[dom_to_port[dom]] != NULL)
    28.1 --- a/xen/arch/x86/dom0_ops.c	Fri Jan 21 13:52:28 2005 +0000
    28.2 +++ b/xen/arch/x86/dom0_ops.c	Mon Jan 24 10:19:03 2005 +0000
    28.3 @@ -137,6 +137,164 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
    28.4      }
    28.5      break;
    28.6  
    28.7 +    case DOM0_IOPL:
    28.8 +    {
    28.9 +        extern long do_iopl(domid_t, unsigned int);
   28.10 +        ret = do_iopl(op->u.iopl.domain, op->u.iopl.iopl);
   28.11 +    }
   28.12 +    break;
   28.13 +
   28.14 +    case DOM0_PHYSINFO:
   28.15 +    {
   28.16 +        dom0_physinfo_t *pi = &op->u.physinfo;
   28.17 +
   28.18 +        pi->ht_per_core = opt_noht ? 1 : ht_per_core;
   28.19 +        pi->cores       = smp_num_cpus / pi->ht_per_core;
   28.20 +        pi->total_pages = max_page;
   28.21 +        pi->free_pages  = avail_domheap_pages();
   28.22 +        pi->cpu_khz     = cpu_khz;
   28.23 +
   28.24 +        copy_to_user(u_dom0_op, op, sizeof(*op));
   28.25 +        ret = 0;
   28.26 +    }
   28.27 +    break;
   28.28 +    
   28.29 +    case DOM0_GETPAGEFRAMEINFO:
   28.30 +    {
   28.31 +        struct pfn_info *page;
   28.32 +        unsigned long pfn = op->u.getpageframeinfo.pfn;
   28.33 +        domid_t dom = op->u.getpageframeinfo.domain;
   28.34 +        struct domain *d;
   28.35 +
   28.36 +        ret = -EINVAL;
   28.37 +
   28.38 +        if ( unlikely(pfn >= max_page) || 
   28.39 +             unlikely((d = find_domain_by_id(dom)) == NULL) )
   28.40 +            break;
   28.41 +
   28.42 +        page = &frame_table[pfn];
   28.43 +
   28.44 +        if ( likely(get_page(page, d)) )
   28.45 +        {
   28.46 +            ret = 0;
   28.47 +
   28.48 +            op->u.getpageframeinfo.type = NOTAB;
   28.49 +
   28.50 +            if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
   28.51 +            {
   28.52 +                switch ( page->u.inuse.type_info & PGT_type_mask )
   28.53 +                {
   28.54 +                case PGT_l1_page_table:
   28.55 +                    op->u.getpageframeinfo.type = L1TAB;
   28.56 +                    break;
   28.57 +                case PGT_l2_page_table:
   28.58 +                    op->u.getpageframeinfo.type = L2TAB;
   28.59 +                    break;
   28.60 +                case PGT_l3_page_table:
   28.61 +                    op->u.getpageframeinfo.type = L3TAB;
   28.62 +                    break;
   28.63 +                case PGT_l4_page_table:
   28.64 +                    op->u.getpageframeinfo.type = L4TAB;
   28.65 +                    break;
   28.66 +                }
   28.67 +            }
   28.68 +            
   28.69 +            put_page(page);
   28.70 +        }
   28.71 +
   28.72 +        put_domain(d);
   28.73 +
   28.74 +        copy_to_user(u_dom0_op, op, sizeof(*op));
   28.75 +    }
   28.76 +    break;
   28.77 +
   28.78 +    case DOM0_GETPAGEFRAMEINFO2:
   28.79 +    {
   28.80 +#define GPF2_BATCH 128
   28.81 +        int n,j;
   28.82 +        int num = op->u.getpageframeinfo2.num;
   28.83 +        domid_t dom = op->u.getpageframeinfo2.domain;
   28.84 +        unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
   28.85 +        struct domain *d;
   28.86 +        unsigned long l_arr[GPF2_BATCH];
   28.87 +        ret = -ESRCH;
   28.88 +
   28.89 +        if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
   28.90 +            break;
   28.91 +
   28.92 +        if ( unlikely(num > 1024) )
   28.93 +        {
   28.94 +            ret = -E2BIG;
   28.95 +            break;
   28.96 +        }
   28.97 + 
   28.98 +        ret = 0;
   28.99 +        for( n = 0; n < num; )
  28.100 +        {
  28.101 +            int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
  28.102 +
  28.103 +            if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) )
  28.104 +            {
  28.105 +                ret = -EINVAL;
  28.106 +                break;
  28.107 +            }
  28.108 +     
  28.109 +            for( j = 0; j < k; j++ )
  28.110 +            {      
  28.111 +                struct pfn_info *page;
  28.112 +                unsigned long mfn = l_arr[j];
  28.113 +
  28.114 +                if ( unlikely(mfn >= max_page) )
  28.115 +                    goto e2_err;
  28.116 +
  28.117 +                page = &frame_table[mfn];
  28.118 +  
  28.119 +                if ( likely(get_page(page, d)) )
  28.120 +                {
  28.121 +                    unsigned long type = 0;
  28.122 +
  28.123 +                    switch( page->u.inuse.type_info & PGT_type_mask )
  28.124 +                    {
  28.125 +                    case PGT_l1_page_table:
  28.126 +                        type = L1TAB;
  28.127 +                        break;
  28.128 +                    case PGT_l2_page_table:
  28.129 +                        type = L2TAB;
  28.130 +                        break;
  28.131 +                    case PGT_l3_page_table:
  28.132 +                        type = L3TAB;
  28.133 +                        break;
  28.134 +                    case PGT_l4_page_table:
  28.135 +                        type = L4TAB;
  28.136 +                        break;
  28.137 +                    }
  28.138 +
  28.139 +                    if ( page->u.inuse.type_info & PGT_pinned )
  28.140 +                        type |= LPINTAB;
  28.141 +                    l_arr[j] |= type;
  28.142 +                    put_page(page);
  28.143 +                }
  28.144 +                else
  28.145 +                {
  28.146 +                e2_err:
  28.147 +                    l_arr[j] |= XTAB;
  28.148 +                }
  28.149 +
  28.150 +            }
  28.151 +
  28.152 +            if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) )
  28.153 +            {
  28.154 +                ret = -EINVAL;
  28.155 +                break;
  28.156 +            }
  28.157 +
  28.158 +            n += j;
  28.159 +        }
  28.160 +
  28.161 +        put_domain(d);
  28.162 +    }
  28.163 +    break;
  28.164 +
  28.165      default:
  28.166          ret = -ENOSYS;
  28.167  
    29.1 --- a/xen/arch/x86/domain.c	Fri Jan 21 13:52:28 2005 +0000
    29.2 +++ b/xen/arch/x86/domain.c	Mon Jan 24 10:19:03 2005 +0000
    29.3 @@ -203,6 +203,66 @@ void machine_halt(void)
    29.4      __machine_halt(NULL);
    29.5  }
    29.6  
    29.7 +void dump_pageframe_info(struct domain *d)
    29.8 +{
    29.9 +    struct pfn_info *page;
   29.10 +    struct list_head *ent;
   29.11 +
   29.12 +    if ( d->tot_pages < 10 )
   29.13 +    {
   29.14 +        list_for_each ( ent, &d->page_list )
   29.15 +        {
   29.16 +            page = list_entry(ent, struct pfn_info, list);
   29.17 +            printk("Page %08x: caf=%08x, taf=%08x\n",
   29.18 +                   page_to_phys(page), page->count_info,
   29.19 +                   page->u.inuse.type_info);
   29.20 +        }
   29.21 +    }
   29.22 +    
   29.23 +    page = virt_to_page(d->shared_info);
   29.24 +    printk("Shared_info@%08x: caf=%08x, taf=%08x\n",
   29.25 +           page_to_phys(page), page->count_info,
   29.26 +           page->u.inuse.type_info);
   29.27 +}
   29.28 +
   29.29 +xmem_cache_t *domain_struct_cachep;
   29.30 +xmem_cache_t *exec_domain_struct_cachep;
   29.31 +
   29.32 +void __init domain_startofday(void)
   29.33 +{
   29.34 +    domain_struct_cachep = xmem_cache_create(
   29.35 +        "domain_cache", sizeof(struct domain),
   29.36 +        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
   29.37 +    if ( domain_struct_cachep == NULL )
   29.38 +        panic("No slab cache for domain structs.");
   29.39 +
   29.40 +    exec_domain_struct_cachep = xmem_cache_create(
   29.41 +        "exec_dom_cache", sizeof(struct exec_domain),
   29.42 +        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
   29.43 +    if ( exec_domain_struct_cachep == NULL )
   29.44 +        BUG();
   29.45 +}
   29.46 +
   29.47 +struct domain *arch_alloc_domain_struct(void)
   29.48 +{
   29.49 +    return xmem_cache_alloc(domain_struct_cachep);
   29.50 +}
   29.51 +
   29.52 +void arch_free_domain_struct(struct domain *d)
   29.53 +{
   29.54 +    xmem_cache_free(domain_struct_cachep, d);
   29.55 +}
   29.56 +
   29.57 +struct exec_domain *arch_alloc_exec_domain_struct(void)
   29.58 +{
   29.59 +    return xmem_cache_alloc(exec_domain_struct_cachep);
   29.60 +}
   29.61 +
   29.62 +void arch_free_exec_domain_struct(struct exec_domain *ed)
   29.63 +{
   29.64 +    xmem_cache_free(exec_domain_struct_cachep, ed);
   29.65 +}
   29.66 +
   29.67  void free_perdomain_pt(struct domain *d)
   29.68  {
   29.69      free_xenheap_page((unsigned long)d->mm_perdomain_pt);
    30.1 --- a/xen/arch/x86/memory.c	Fri Jan 21 13:52:28 2005 +0000
    30.2 +++ b/xen/arch/x86/memory.c	Mon Jan 24 10:19:03 2005 +0000
    30.3 @@ -961,7 +961,7 @@ int new_guest_cr3(unsigned long pfn)
    30.4      }
    30.5      else
    30.6      {
    30.7 -        MEM_LOG("Error while installing new baseptr %08lx", ptr);
    30.8 +        MEM_LOG("Error while installing new baseptr %08lx", pfn);
    30.9      }
   30.10  
   30.11      return okay;
   30.12 @@ -1341,7 +1341,7 @@ int do_mmu_update(
   30.13  
   30.14      LOCK_BIGLOCK(d);
   30.15  
   30.16 -    cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
   30.17 +    cleanup_writable_pagetable(d);
   30.18  
   30.19      /*
   30.20       * If we are resuming after preemption, read how much work we have already
   30.21 @@ -1572,7 +1572,7 @@ int do_update_va_mapping(unsigned long p
   30.22  
   30.23      LOCK_BIGLOCK(d);
   30.24  
   30.25 -    cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
   30.26 +    cleanup_writable_pagetable(d);
   30.27  
   30.28      /*
   30.29       * XXX When we make this support 4MB superpages we should also deal with 
    31.1 --- a/xen/common/Makefile	Fri Jan 21 13:52:28 2005 +0000
    31.2 +++ b/xen/common/Makefile	Mon Jan 24 10:19:03 2005 +0000
    31.3 @@ -2,6 +2,8 @@
    31.4  include $(BASEDIR)/Rules.mk
    31.5  
    31.6  ifeq ($(TARGET_ARCH),ia64) 
    31.7 +OBJS := $(subst dom_mem_ops.o,,$(OBJS))
    31.8 +OBJS := $(subst grant_table.o,,$(OBJS))
    31.9  OBJS := $(subst page_alloc.o,,$(OBJS))
   31.10  OBJS := $(subst slab.o,,$(OBJS))
   31.11  endif
    32.1 --- a/xen/common/dom0_ops.c	Fri Jan 21 13:52:28 2005 +0000
    32.2 +++ b/xen/common/dom0_ops.c	Mon Jan 24 10:19:03 2005 +0000
    32.3 @@ -412,62 +412,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    32.4      }
    32.5      break;
    32.6  
    32.7 -    case DOM0_GETPAGEFRAMEINFO:
    32.8 -    {
    32.9 -        struct pfn_info *page;
   32.10 -        unsigned long pfn = op->u.getpageframeinfo.pfn;
   32.11 -        domid_t dom = op->u.getpageframeinfo.domain;
   32.12 -        struct domain *d;
   32.13 -
   32.14 -        ret = -EINVAL;
   32.15 -
   32.16 -        if ( unlikely(pfn >= max_page) || 
   32.17 -             unlikely((d = find_domain_by_id(dom)) == NULL) )
   32.18 -            break;
   32.19 -
   32.20 -        page = &frame_table[pfn];
   32.21 -
   32.22 -        if ( likely(get_page(page, d)) )
   32.23 -        {
   32.24 -            ret = 0;
   32.25 -
   32.26 -            op->u.getpageframeinfo.type = NOTAB;
   32.27 -
   32.28 -            if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
   32.29 -            {
   32.30 -                switch ( page->u.inuse.type_info & PGT_type_mask )
   32.31 -                {
   32.32 -                case PGT_l1_page_table:
   32.33 -                    op->u.getpageframeinfo.type = L1TAB;
   32.34 -                    break;
   32.35 -                case PGT_l2_page_table:
   32.36 -                    op->u.getpageframeinfo.type = L2TAB;
   32.37 -                    break;
   32.38 -                case PGT_l3_page_table:
   32.39 -                    op->u.getpageframeinfo.type = L3TAB;
   32.40 -                    break;
   32.41 -                case PGT_l4_page_table:
   32.42 -                    op->u.getpageframeinfo.type = L4TAB;
   32.43 -                    break;
   32.44 -                }
   32.45 -            }
   32.46 -            
   32.47 -            put_page(page);
   32.48 -        }
   32.49 -
   32.50 -        put_domain(d);
   32.51 -
   32.52 -        copy_to_user(u_dom0_op, op, sizeof(*op));
   32.53 -    }
   32.54 -    break;
   32.55 -
   32.56 -    case DOM0_IOPL:
   32.57 -    {
   32.58 -        extern long do_iopl(domid_t, unsigned int);
   32.59 -        ret = do_iopl(op->u.iopl.domain, op->u.iopl.iopl);
   32.60 -    }
   32.61 -    break;
   32.62 -
   32.63  #ifdef XEN_DEBUGGER
   32.64      case DOM0_DEBUG:
   32.65      {
   32.66 @@ -504,21 +448,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   32.67      }
   32.68      break;
   32.69  
   32.70 -    case DOM0_PHYSINFO:
   32.71 -    {
   32.72 -        dom0_physinfo_t *pi = &op->u.physinfo;
   32.73 -
   32.74 -        pi->ht_per_core = opt_noht ? 1 : ht_per_core;
   32.75 -        pi->cores       = smp_num_cpus / pi->ht_per_core;
   32.76 -        pi->total_pages = max_page;
   32.77 -        pi->free_pages  = avail_domheap_pages();
   32.78 -        pi->cpu_khz     = cpu_khz;
   32.79 -
   32.80 -        copy_to_user(u_dom0_op, op, sizeof(*op));
   32.81 -        ret = 0;
   32.82 -    }
   32.83 -    break;
   32.84 -    
   32.85      case DOM0_PCIDEV_ACCESS:
   32.86      {
   32.87          extern int physdev_pci_access_modify(domid_t, int, int, int, int);
   32.88 @@ -571,93 +500,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   32.89      }
   32.90      break;
   32.91  
   32.92 -    case DOM0_GETPAGEFRAMEINFO2:
   32.93 -    {
   32.94 -#define GPF2_BATCH 128
   32.95 -        int n,j;
   32.96 -        int num = op->u.getpageframeinfo2.num;
   32.97 -        domid_t dom = op->u.getpageframeinfo2.domain;
   32.98 -        unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
   32.99 -        struct domain *d;
  32.100 -        unsigned long l_arr[GPF2_BATCH];
  32.101 -        ret = -ESRCH;
  32.102 -
  32.103 -        if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
  32.104 -            break;
  32.105 -
  32.106 -        if ( unlikely(num > 1024) )
  32.107 -        {
  32.108 -            ret = -E2BIG;
  32.109 -            break;
  32.110 -        }
  32.111 - 
  32.112 -        ret = 0;
  32.113 -        for( n = 0; n < num; )
  32.114 -        {
  32.115 -            int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
  32.116 -
  32.117 -            if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) )
  32.118 -            {
  32.119 -                ret = -EINVAL;
  32.120 -                break;
  32.121 -            }
  32.122 -     
  32.123 -            for( j = 0; j < k; j++ )
  32.124 -            {      
  32.125 -                struct pfn_info *page;
  32.126 -                unsigned long mfn = l_arr[j];
  32.127 -
  32.128 -                if ( unlikely(mfn >= max_page) )
  32.129 -                    goto e2_err;
  32.130 -
  32.131 -                page = &frame_table[mfn];
  32.132 -  
  32.133 -                if ( likely(get_page(page, d)) )
  32.134 -                {
  32.135 -                    unsigned long type = 0;
  32.136 -
  32.137 -                    switch( page->u.inuse.type_info & PGT_type_mask )
  32.138 -                    {
  32.139 -                    case PGT_l1_page_table:
  32.140 -                        type = L1TAB;
  32.141 -                        break;
  32.142 -                    case PGT_l2_page_table:
  32.143 -                        type = L2TAB;
  32.144 -                        break;
  32.145 -                    case PGT_l3_page_table:
  32.146 -                        type = L3TAB;
  32.147 -                        break;
  32.148 -                    case PGT_l4_page_table:
  32.149 -                        type = L4TAB;
  32.150 -                        break;
  32.151 -                    }
  32.152 -
  32.153 -                    if ( page->u.inuse.type_info & PGT_pinned )
  32.154 -                        type |= LPINTAB;
  32.155 -                    l_arr[j] |= type;
  32.156 -                    put_page(page);
  32.157 -                }
  32.158 -                else
  32.159 -                {
  32.160 -                e2_err:
  32.161 -                    l_arr[j] |= XTAB;
  32.162 -                }
  32.163 -
  32.164 -            }
  32.165 -
  32.166 -            if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) )
  32.167 -            {
  32.168 -                ret = -EINVAL;
  32.169 -                break;
  32.170 -            }
  32.171 -
  32.172 -            n += j;
  32.173 -        }
  32.174 -
  32.175 -        put_domain(d);
  32.176 -    }
  32.177 -    break;
  32.178 -
  32.179      case DOM0_SETDOMAINVMASSIST:
  32.180      {
  32.181          struct domain *d; 
    33.1 --- a/xen/common/domain.c	Fri Jan 21 13:52:28 2005 +0000
    33.2 +++ b/xen/common/domain.c	Mon Jan 24 10:19:03 2005 +0000
    33.3 @@ -23,25 +23,8 @@ rwlock_t domlist_lock = RW_LOCK_UNLOCKED
    33.4  struct domain *domain_hash[DOMAIN_HASH_SIZE];
    33.5  struct domain *domain_list;
    33.6  
    33.7 -xmem_cache_t *domain_struct_cachep;
    33.8 -xmem_cache_t *exec_domain_struct_cachep;
    33.9  struct domain *dom0;
   33.10  
   33.11 -void __init domain_startofday(void)
   33.12 -{
   33.13 -    domain_struct_cachep = xmem_cache_create(
   33.14 -        "domain_cache", sizeof(struct domain),
   33.15 -        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
   33.16 -    if ( domain_struct_cachep == NULL )
   33.17 -        BUG();
   33.18 -
   33.19 -    exec_domain_struct_cachep = xmem_cache_create(
   33.20 -        "exec_dom_cache", sizeof(struct exec_domain),
   33.21 -        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
   33.22 -    if ( exec_domain_struct_cachep == NULL )
   33.23 -        BUG();
   33.24 -}
   33.25 -
   33.26  struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
   33.27  {
   33.28      struct domain *d, **pd;
   33.29 @@ -225,8 +208,8 @@ unsigned int alloc_new_dom_mem(struct do
   33.30              return -ENOMEM;
   33.31          }
   33.32  
   33.33 -        /* initialise to machine_to_phys_mapping table to likely pfn */
   33.34 -        machine_to_phys_mapping[page-frame_table] = alloc_pfns;
   33.35 +        /* Initialise the machine-to-phys mapping for this page. */
   33.36 +        set_machinetophys(page_to_pfn(page), alloc_pfns);
   33.37      }
   33.38  
   33.39      return 0;
   33.40 @@ -371,7 +354,7 @@ long do_boot_vcpu(unsigned long vcpu, fu
   33.41   out:
   33.42      if ( c != NULL )
   33.43          xfree(c);
   33.44 -    xmem_cache_free(exec_domain_struct_cachep, d->exec_domain[vcpu]);
   33.45 +    arch_free_exec_domain_struct(d->exec_domain[vcpu]);
   33.46      d->exec_domain[vcpu] = NULL;
   33.47      return rc;
   33.48  }
    34.1 --- a/xen/common/elf.c	Fri Jan 21 13:52:28 2005 +0000
    34.2 +++ b/xen/common/elf.c	Mon Jan 24 10:19:03 2005 +0000
    34.3 @@ -10,6 +10,14 @@
    34.4  #include <xen/mm.h>
    34.5  #include <xen/elf.h>
    34.6  
    34.7 +#ifdef CONFIG_X86
    34.8 +#define FORCE_XENELF_IMAGE 1
    34.9 +#define ELF_ADDR           p_vaddr
   34.10 +#elif defined(__ia64__)
   34.11 +#define FORCE_XENELF_IMAGE 0
   34.12 +#define ELF_ADDR           p_paddr
   34.13 +#endif
   34.14 +
   34.15  static inline int is_loadable_phdr(Elf_Phdr *phdr)
   34.16  {
   34.17      return ((phdr->p_type == PT_LOAD) &&
   34.18 @@ -84,7 +92,9 @@ int parseelfimage(char *elfbase,
   34.19      if ( guestinfo == NULL )
   34.20      {
   34.21          printk("Not a Xen-ELF image: '__xen_guest' section not found.\n");
   34.22 +#ifndef FORCE_XENELF_IMAGE
   34.23          return -EINVAL;
   34.24 +#endif
   34.25      }
   34.26  
   34.27      for ( h = 0; h < ehdr->e_phnum; h++ ) 
   34.28 @@ -92,10 +102,10 @@ int parseelfimage(char *elfbase,
   34.29          phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
   34.30          if ( !is_loadable_phdr(phdr) )
   34.31              continue;
   34.32 -        if ( phdr->p_vaddr < kernstart )
   34.33 -            kernstart = phdr->p_vaddr;
   34.34 -        if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
   34.35 -            kernend = phdr->p_vaddr + phdr->p_memsz;
   34.36 +        if ( phdr->ELF_ADDR < kernstart )
   34.37 +            kernstart = phdr->ELF_ADDR;
   34.38 +        if ( (phdr->ELF_ADDR + phdr->p_memsz) > kernend )
   34.39 +            kernend = phdr->ELF_ADDR + phdr->p_memsz;
   34.40      }
   34.41  
   34.42      if ( (kernstart > kernend) || 
   34.43 @@ -107,11 +117,15 @@ int parseelfimage(char *elfbase,
   34.44      }
   34.45  
   34.46      dsi->v_start = kernstart;
   34.47 -    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
   34.48 -        dsi->v_start = simple_strtoul(p+10, &p, 0);
   34.49  
   34.50 -    if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
   34.51 -        dsi->use_writable_pagetables = 1;
   34.52 +    if ( guestinfo != NULL )
   34.53 +    {
   34.54 +        if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
   34.55 +            dsi->v_start = simple_strtoul(p+10, &p, 0);
   34.56 +        
   34.57 +        if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
   34.58 +            dsi->use_writable_pagetables = 1;
   34.59 +    }
   34.60  
   34.61      dsi->v_kernstart = kernstart;
   34.62      dsi->v_kernend   = kernend;
   34.63 @@ -132,10 +146,10 @@ int loadelfimage(char *elfbase)
   34.64          if ( !is_loadable_phdr(phdr) )
   34.65              continue;
   34.66          if ( phdr->p_filesz != 0 )
   34.67 -            memcpy((char *)phdr->p_vaddr, elfbase + phdr->p_offset, 
   34.68 +            memcpy((char *)phdr->ELF_ADDR, elfbase + phdr->p_offset, 
   34.69                     phdr->p_filesz);
   34.70          if ( phdr->p_memsz > phdr->p_filesz )
   34.71 -            memset((char *)phdr->p_vaddr + phdr->p_filesz, 0, 
   34.72 +            memset((char *)phdr->ELF_ADDR + phdr->p_filesz, 0, 
   34.73                     phdr->p_memsz - phdr->p_filesz);
   34.74      }
   34.75  
    35.1 --- a/xen/common/keyhandler.c	Fri Jan 21 13:52:28 2005 +0000
    35.2 +++ b/xen/common/keyhandler.c	Mon Jan 24 10:19:03 2005 +0000
    35.3 @@ -98,8 +98,6 @@ void do_task_queues(unsigned char key)
    35.4      struct domain *d;
    35.5      struct exec_domain *ed;
    35.6      s_time_t       now = NOW();
    35.7 -    struct list_head *ent;
    35.8 -    struct pfn_info  *page;
    35.9  
   35.10      printk("'%c' pressed -> dumping task queues (now=0x%X:%08X)\n", key,
   35.11             (u32)(now>>32), (u32)now); 
   35.12 @@ -112,21 +110,7 @@ void do_task_queues(unsigned char key)
   35.13                 "xenheap_pages=%d\n", d->id, d->d_flags,
   35.14                 atomic_read(&d->refcnt), d->tot_pages, d->xenheap_pages);
   35.15  
   35.16 -        if ( d->tot_pages < 10 )
   35.17 -        {
   35.18 -            list_for_each ( ent, &d->page_list )
   35.19 -            {
   35.20 -                page = list_entry(ent, struct pfn_info, list);
   35.21 -                printk("Page %08x: caf=%08x, taf=%08x\n",
   35.22 -                       page_to_phys(page), page->count_info,
   35.23 -                       page->u.inuse.type_info);
   35.24 -            }
   35.25 -        }
   35.26 -
   35.27 -        page = virt_to_page(d->shared_info);
   35.28 -        printk("Shared_info@%08x: caf=%08x, taf=%08x\n",
   35.29 -               page_to_phys(page), page->count_info,
   35.30 -               page->u.inuse.type_info);
   35.31 +        dump_pageframe_info(d);
   35.32                 
   35.33          for_each_exec_domain ( d, ed ) {
   35.34              printk("Guest: %p CPU %d [has=%c] flags=%lx "
    36.1 --- a/xen/common/schedule.c	Fri Jan 21 13:52:28 2005 +0000
    36.2 +++ b/xen/common/schedule.c	Mon Jan 24 10:19:03 2005 +0000
    36.3 @@ -89,17 +89,14 @@ static struct scheduler ops;
    36.4  /* Per-CPU periodic timer sends an event to the currently-executing domain. */
    36.5  static struct ac_timer t_timer[NR_CPUS]; 
    36.6  
    36.7 -extern xmem_cache_t *domain_struct_cachep;
    36.8 -extern xmem_cache_t *exec_domain_struct_cachep;
    36.9 -
   36.10  void free_domain_struct(struct domain *d)
   36.11  {
   36.12      struct exec_domain *ed;
   36.13  
   36.14      SCHED_OP(free_task, d);
   36.15      for_each_exec_domain(d, ed)
   36.16 -        xmem_cache_free(exec_domain_struct_cachep, ed);
   36.17 -    xmem_cache_free(domain_struct_cachep, d);
   36.18 +        arch_free_exec_domain_struct(ed);
   36.19 +    arch_free_domain_struct(d);
   36.20  }
   36.21  
   36.22  struct exec_domain *alloc_exec_domain_struct(struct domain *d,
   36.23 @@ -109,7 +106,7 @@ struct exec_domain *alloc_exec_domain_st
   36.24  
   36.25      ASSERT( d->exec_domain[vcpu] == NULL );
   36.26  
   36.27 -    if ( (ed = xmem_cache_alloc(exec_domain_struct_cachep)) == NULL )
   36.28 +    if ( (ed = arch_alloc_exec_domain_struct()) == NULL )
   36.29          return NULL;
   36.30  
   36.31      memset(ed, 0, sizeof(*ed));
   36.32 @@ -143,7 +140,7 @@ struct exec_domain *alloc_exec_domain_st
   36.33  
   36.34   out:
   36.35      d->exec_domain[vcpu] = NULL;
   36.36 -    xmem_cache_free(exec_domain_struct_cachep, ed);
   36.37 +    arch_free_exec_domain_struct(ed);
   36.38  
   36.39      return NULL;
   36.40  }
   36.41 @@ -152,7 +149,7 @@ struct domain *alloc_domain_struct(void)
   36.42  {
   36.43      struct domain *d;
   36.44  
   36.45 -    if ( (d = xmem_cache_alloc(domain_struct_cachep)) == NULL )
   36.46 +    if ( (d = arch_alloc_domain_struct()) == NULL )
   36.47          return NULL;
   36.48      
   36.49      memset(d, 0, sizeof(*d));
   36.50 @@ -163,7 +160,7 @@ struct domain *alloc_domain_struct(void)
   36.51      return d;
   36.52  
   36.53   out:
   36.54 -    xmem_cache_free(domain_struct_cachep, d);
   36.55 +    arch_free_domain_struct(d);
   36.56      return NULL;
   36.57  }
   36.58  
   36.59 @@ -379,8 +376,7 @@ void __enter_scheduler(void)
   36.60      if ( !is_idle_task(current->domain) )
   36.61      {
   36.62          LOCK_BIGLOCK(current->domain);
   36.63 -        cleanup_writable_pagetable(
   36.64 -            prev->domain, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
   36.65 +        cleanup_writable_pagetable(prev->domain);
   36.66          UNLOCK_BIGLOCK(current->domain);
   36.67      }
   36.68  
    37.1 --- a/xen/common/softirq.c	Fri Jan 21 13:52:28 2005 +0000
    37.2 +++ b/xen/common/softirq.c	Mon Jan 24 10:19:03 2005 +0000
    37.3 @@ -15,7 +15,9 @@
    37.4  #include <xen/sched.h>
    37.5  #include <xen/softirq.h>
    37.6  
    37.7 +#ifndef __ARCH_IRQ_STAT
    37.8  irq_cpustat_t irq_stat[NR_CPUS];
    37.9 +#endif
   37.10  
   37.11  static softirq_handler softirq_handlers[NR_SOFTIRQS];
   37.12  
    38.1 --- a/xen/drivers/char/console.c	Fri Jan 21 13:52:28 2005 +0000
    38.2 +++ b/xen/drivers/char/console.c	Mon Jan 24 10:19:03 2005 +0000
    38.3 @@ -18,6 +18,7 @@
    38.4  #include <xen/serial.h>
    38.5  #include <xen/keyhandler.h>
    38.6  #include <asm/uaccess.h>
    38.7 +#include <asm/mm.h>
    38.8  
    38.9  /* opt_console: comma-separated list of console outputs. */
   38.10  static unsigned char opt_console[30] = "com1,vga";
   38.11 @@ -31,7 +32,7 @@ static unsigned char opt_conswitch[5] = 
   38.12  string_param("conswitch", opt_conswitch);
   38.13  
   38.14  static int xpos, ypos;
   38.15 -static unsigned char *video = __va(0xB8000);
   38.16 +static unsigned char *video;
   38.17  
   38.18  #define CONSOLE_RING_SIZE 16392
   38.19  typedef struct console_ring_st
   38.20 @@ -137,6 +138,8 @@ static void init_vga(void)
   38.21          return;
   38.22      }
   38.23  
   38.24 +    video = __va(0xB8000);
   38.25 +
   38.26      tmp = inb(0x3da);
   38.27      outb(0x00, 0x3c0);
   38.28      
    39.1 --- a/xen/drivers/char/serial.c	Fri Jan 21 13:52:28 2005 +0000
    39.2 +++ b/xen/drivers/char/serial.c	Mon Jan 24 10:19:03 2005 +0000
    39.3 @@ -100,6 +100,16 @@ static uart_t com[2] = {
    39.4  #define UART_ENABLED(_u) ((_u)->baud != 0)
    39.5  #define DISABLE_UART(_u) ((_u)->baud = 0)
    39.6  
    39.7 +#ifdef CONFIG_X86
    39.8 +static inline int arch_serial_putc(uart_t *uart, unsigned char c)
    39.9 +{
   39.10 +    int space;
   39.11 +    if ( (space = (inb(uart->io_base + LSR) & LSR_THRE)) )
   39.12 +        outb(c, uart->io_base + THR);
   39.13 +    return space;
   39.14 +}
   39.15 +#endif
   39.16 +
   39.17  
   39.18  /***********************
   39.19   * PRIVATE FUNCTIONS
   39.20 @@ -151,8 +161,7 @@ static inline void __serial_putc(uart_t 
   39.21  
   39.22      do { 
   39.23          spin_lock_irqsave(&uart->lock, flags);
   39.24 -        if ( (space = (inb(uart->io_base + LSR) & LSR_THRE)) )
   39.25 -            outb(c, uart->io_base + THR);
   39.26 +        space = arch_serial_putc(uart, c);
   39.27          spin_unlock_irqrestore(&uart->lock, flags);
   39.28      }
   39.29      while ( !space );
    40.1 --- a/xen/include/asm-x86/mm.h	Fri Jan 21 13:52:28 2005 +0000
    40.2 +++ b/xen/include/asm-x86/mm.h	Mon Jan 24 10:19:03 2005 +0000
    40.3 @@ -233,6 +233,8 @@ extern unsigned long m2p_start_mfn;
    40.4  #define phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
    40.5  #endif
    40.6  
    40.7 +#define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
    40.8 +
    40.9  #define DEFAULT_GDT_ENTRIES     (LAST_RESERVED_GDT_ENTRY+1)
   40.10  #define DEFAULT_GDT_ADDRESS     ((unsigned long)gdt_table)
   40.11  
   40.12 @@ -294,10 +296,11 @@ do {                                    
   40.13              ptwr_flush(PTWR_PT_INACTIVE);                                   \
   40.14  } while ( 0 )
   40.15  
   40.16 -#define cleanup_writable_pagetable(_d, _w)                                \
   40.17 +#define cleanup_writable_pagetable(_d)                                    \
   40.18      do {                                                                  \
   40.19          if ( unlikely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) ) \
   40.20 -        __cleanup_writable_pagetable(_w);                                 \
   40.21 +        __cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE |                \
   40.22 +                                     PTWR_CLEANUP_INACTIVE);              \
   40.23      } while ( 0 )
   40.24  
   40.25  #ifndef NDEBUG
    41.1 --- a/xen/include/public/arch-x86_32.h	Fri Jan 21 13:52:28 2005 +0000
    41.2 +++ b/xen/include/public/arch-x86_32.h	Mon Jan 24 10:19:03 2005 +0000
    41.3 @@ -9,6 +9,11 @@
    41.4  #ifndef __XEN_PUBLIC_ARCH_X86_32_H__
    41.5  #define __XEN_PUBLIC_ARCH_X86_32_H__
    41.6  
    41.7 +#ifndef PACKED
    41.8 +/* GCC-specific way to pack structure definitions (no implicit padding). */
    41.9 +#define PACKED __attribute__ ((packed))
   41.10 +#endif
   41.11 +
   41.12  /*
   41.13   * Pointers and other address fields inside interface structures are padded to
   41.14   * 64 bits. This means that field alignments aren't different between 32- and
    42.1 --- a/xen/include/public/arch-x86_64.h	Fri Jan 21 13:52:28 2005 +0000
    42.2 +++ b/xen/include/public/arch-x86_64.h	Mon Jan 24 10:19:03 2005 +0000
    42.3 @@ -9,6 +9,11 @@
    42.4  #ifndef __XEN_PUBLIC_ARCH_X86_64_H__
    42.5  #define __XEN_PUBLIC_ARCH_X86_64_H__
    42.6  
    42.7 +#ifndef PACKED
    42.8 +/* GCC-specific way to pack structure definitions (no implicit padding). */
    42.9 +#define PACKED __attribute__ ((packed))
   42.10 +#endif
   42.11 +
   42.12  /* Pointers are naturally 64 bits in this architecture; no padding needed. */
   42.13  #define _MEMORY_PADDING(_X)
   42.14  #define MEMORY_PADDING 
    43.1 --- a/xen/include/public/io/domain_controller.h	Fri Jan 21 13:52:28 2005 +0000
    43.2 +++ b/xen/include/public/io/domain_controller.h	Mon Jan 24 10:19:03 2005 +0000
    43.3 @@ -64,7 +64,8 @@ typedef struct {
    43.4  #define CMSG_NETIF_FE       4  /* Network-device frontend */
    43.5  #define CMSG_SHUTDOWN       6  /* Shutdown messages       */
    43.6  #define CMSG_MEM_REQUEST    7  /* Memory reservation reqs */
    43.7 -
    43.8 +#define CMSG_USBIF_BE       8  /* USB controller backend  */
    43.9 +#define CMSG_USBIF_FE       9  /* USB controller frontend */
   43.10  
   43.11  /******************************************************************************
   43.12   * CONSOLE DEFINITIONS
   43.13 @@ -554,6 +555,208 @@ typedef struct {
   43.14  } PACKED netif_be_driver_status_t; /* 4 bytes */
   43.15  
   43.16  
   43.17 +
   43.18 +/******************************************************************************
   43.19 + * USB-INTERFACE FRONTEND DEFINITIONS
   43.20 + */
   43.21 +
   43.22 +/* Messages from domain controller to guest. */
   43.23 +#define CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED   0
   43.24 +
   43.25 +/* Messages from guest to domain controller. */
   43.26 +#define CMSG_USBIF_FE_DRIVER_STATUS_CHANGED     32
   43.27 +#define CMSG_USBIF_FE_INTERFACE_CONNECT         33
   43.28 +#define CMSG_USBIF_FE_INTERFACE_DISCONNECT      34
   43.29 +/*
   43.30 + * CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED:
   43.31 + *  Notify a guest about a status change on one of its block interfaces.
   43.32 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
   43.33 + *   1. The shared-memory frame is available for reuse.
   43.34 + *   2. Any unacknowledged messages pending on the interface were dropped.
   43.35 + */
   43.36 +#define USBIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
   43.37 +#define USBIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
   43.38 +#define USBIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
   43.39 +typedef struct {
   43.40 +    u32 status; /*  0 */
   43.41 +    u16 evtchn; /*  4: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
   43.42 +    domid_t domid; /* 6: status != BLKIF_INTERFACE_STATUS_DESTROYED */
   43.43 +    u32 bandwidth; /* 8 */
   43.44 +    u32 num_ports; /* 12 */
   43.45 +} PACKED usbif_fe_interface_status_changed_t; /* 12 bytes */
   43.46 +
   43.47 +/*
   43.48 + * CMSG_USBIF_FE_DRIVER_STATUS_CHANGED:
   43.49 + *  Notify the domain controller that the front-end driver is DOWN or UP.
   43.50 + *  When the driver goes DOWN then the controller will send no more
   43.51 + *  status-change notifications.
   43.52 + *  If the driver goes DOWN while interfaces are still UP, the domain
   43.53 + *  will automatically take the interfaces DOWN.
   43.54 + * 
   43.55 + *  NB. The controller should not send an INTERFACE_STATUS_CHANGED message
   43.56 + *  for interfaces that are active when it receives an UP notification. We
   43.57 + *  expect that the frontend driver will query those interfaces itself.
   43.58 + */
   43.59 +#define USBIF_DRIVER_STATUS_DOWN   0
   43.60 +#define USBIF_DRIVER_STATUS_UP     1
   43.61 +typedef struct {
   43.62 +    /* IN */
   43.63 +    u32 status;        /*  0: USBIF_DRIVER_STATUS_??? */
   43.64 +} PACKED usbif_fe_driver_status_changed_t; /* 4 bytes */
   43.65 +
   43.66 +/*
   43.67 + * CMSG_USBIF_FE_INTERFACE_CONNECT:
   43.68 + *  If successful, the domain controller will acknowledge with a
   43.69 + *  STATUS_CONNECTED message.
   43.70 + */
   43.71 +typedef struct {
   43.72 +    u32      __pad;
   43.73 +    memory_t shmem_frame; /*  8 */
   43.74 +    MEMORY_PADDING;
   43.75 +} PACKED usbif_fe_interface_connect_t; /* 16 bytes */
   43.76 +
   43.77 +/*
   43.78 + * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
   43.79 + *  If successful, the domain controller will acknowledge with a
   43.80 + *  STATUS_DISCONNECTED message.
   43.81 + */
   43.82 +typedef struct {} PACKED usbif_fe_interface_disconnect_t; /* 4 bytes */
   43.83 +
   43.84 +
   43.85 +/******************************************************************************
   43.86 + * USB-INTERFACE BACKEND DEFINITIONS
   43.87 + */
   43.88 +
   43.89 +/* Messages from domain controller. */
   43.90 +#define CMSG_USBIF_BE_CREATE       0  /* Create a new block-device interface. */
   43.91 +#define CMSG_USBIF_BE_DESTROY      1  /* Destroy a block-device interface.    */
   43.92 +#define CMSG_USBIF_BE_CONNECT      2  /* Connect i/f to remote driver.        */
   43.93 +#define CMSG_USBIF_BE_DISCONNECT   3  /* Disconnect i/f from remote driver.   */
   43.94 +#define CMSG_USBIF_BE_CLAIM_PORT   4  /* Claim host port for a domain.        */
   43.95 +#define CMSG_USBIF_BE_RELEASE_PORT 5  /* Release host port.                   */
   43.96 +/* Messages to domain controller. */
   43.97 +#define CMSG_USBIF_BE_DRIVER_STATUS_CHANGED 32
   43.98 +
   43.99 +/* Non-specific 'okay' return. */
  43.100 +#define USBIF_BE_STATUS_OKAY                0
  43.101 +/* Non-specific 'error' return. */
  43.102 +#define USBIF_BE_STATUS_ERROR               1
  43.103 +/* The following are specific error returns. */
  43.104 +#define USBIF_BE_STATUS_INTERFACE_EXISTS    2
  43.105 +#define USBIF_BE_STATUS_INTERFACE_NOT_FOUND 3
  43.106 +#define USBIF_BE_STATUS_INTERFACE_CONNECTED 4
  43.107 +#define USBIF_BE_STATUS_OUT_OF_MEMORY       7
  43.108 +#define USBIF_BE_STATUS_MAPPING_ERROR       9
  43.109 +
  43.110 +/* This macro can be used to create an array of descriptive error strings. */
  43.111 +#define USBIF_BE_STATUS_ERRORS {    \
  43.112 +    "Okay",                         \
  43.113 +    "Non-specific error",           \
  43.114 +    "Interface already exists",     \
  43.115 +    "Interface not found",          \
  43.116 +    "Interface is still connected", \
  43.117 +    "Out of memory",                \
  43.118 +    "Could not map domain memory" }
  43.119 +
  43.120 +/*
  43.121 + * CMSG_USBIF_BE_CREATE:
  43.122 + *  When the driver sends a successful response then the interface is fully
  43.123 + *  created. The controller will send a DOWN notification to the front-end
  43.124 + *  driver.
  43.125 + */
  43.126 +typedef struct { 
  43.127 +    /* IN */
  43.128 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
  43.129 +    u16        __pad;
  43.130 +    /* OUT */
  43.131 +    u32        status;        /*  8 */
  43.132 +} PACKED usbif_be_create_t; /* 12 bytes */
  43.133 +
  43.134 +/*
  43.135 + * CMSG_USBIF_BE_DESTROY:
  43.136 + *  When the driver sends a successful response then the interface is fully
  43.137 + *  torn down. The controller will send a DESTROYED notification to the
  43.138 + *  front-end driver.
  43.139 + */
  43.140 +typedef struct { 
  43.141 +    /* IN */
  43.142 +    domid_t    domid;         /*  0: Identify interface to be destroyed. */
  43.143 +    u16        __pad;
  43.144 +    /* OUT */
  43.145 +    u32        status;        /*  8 */
  43.146 +} PACKED usbif_be_destroy_t; /* 12 bytes */
  43.147 +
  43.148 +/*
  43.149 + * CMSG_USBIF_BE_CONNECT:
  43.150 + *  When the driver sends a successful response then the interface is fully
  43.151 + *  connected. The controller will send a CONNECTED notification to the
  43.152 + *  front-end driver.
  43.153 + */
  43.154 +typedef struct { 
  43.155 +    /* IN */
  43.156 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
  43.157 +    u16        __pad;
  43.158 +    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
  43.159 +    MEMORY_PADDING;
  43.160 +    u32        evtchn;        /* 16: Event channel for notifications.    */
  43.161 +    u32        bandwidth;     /* 20: Bandwidth allocated for isoch / int - us
  43.162 +                               * per 1ms frame (ie between 0 and 900 or 800
  43.163 +                               * depending on USB version). */
  43.164 +    /* OUT */
  43.165 +    u32        status;        /* 24 */
  43.166 +} PACKED usbif_be_connect_t;  /* 28 bytes */
  43.167 +
  43.168 +/*
  43.169 + * CMSG_USBIF_BE_DISCONNECT:
  43.170 + *  When the driver sends a successful response then the interface is fully
  43.171 + *  disconnected. The controller will send a DOWN notification to the front-end
  43.172 + *  driver.
  43.173 + */
  43.174 +typedef struct { 
  43.175 +    /* IN */
  43.176 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
  43.177 +    u16        __pad;
  43.178 +    /* OUT */
  43.179 +    u32        status;        /*  8 */
  43.180 +} PACKED usbif_be_disconnect_t; /* 12 bytes */
  43.181 +
  43.182 +/*
  43.183 + * CMSG_USBIF_BE_DRIVER_STATUS_CHANGED:
  43.184 + *  Notify the domain controller that the back-end driver is DOWN or UP.
  43.185 + *  If the driver goes DOWN while interfaces are still UP, the controller
  43.186 + *  will automatically send DOWN notifications.
  43.187 + */
  43.188 +typedef struct {
  43.189 +    u32        status;        /*  0: USBIF_DRIVER_STATUS_??? */
  43.190 +} PACKED usbif_be_driver_status_changed_t; /* 4 bytes */
  43.191 +
  43.192 +#define USB_PATH_LEN 16
  43.193 +
  43.194 +/*
  43.195 + * CMSG_USBIF_BE_CLAIM_PORT:
  43.196 + * Instruct the backend driver to claim any device plugged into the specified
  43.197 + * host port and to allow the specified domain to control that port.
  43.198 + */
  43.199 +typedef struct 
  43.200 +{
  43.201 +    /* IN */
  43.202 +    domid_t  domid;        /* 0:  which domain                 */
  43.203 +    u32      usbif_port;   /* 6:  port on the virtual root hub */
  43.204 +    u32      status;       /* 10: status of operation          */
  43.205 +    char path[USB_PATH_LEN]; /* Currently specified in the Linux style - may need to be
  43.206 +                    * converted to some OS-independent format at some stage. */
  43.207 +} PACKED usbif_be_claim_port_t;
  43.208 +
  43.209 +/*
  43.210 + * CMSG_USBIF_BE_RELEASE_PORT: 
  43.211 + * Instruct the backend driver to release any device plugged into the specified
  43.212 + * host port.
  43.213 + */
  43.214 +typedef struct
  43.215 +{
  43.216 +    char     path[USB_PATH_LEN];
  43.217 +} PACKED usbif_be_release_port_t;
  43.218 +
  43.219  /******************************************************************************
  43.220   * SHUTDOWN DEFINITIONS
  43.221   */
    44.1 --- a/xen/include/public/xen.h	Fri Jan 21 13:52:28 2005 +0000
    44.2 +++ b/xen/include/public/xen.h	Mon Jan 24 10:19:03 2005 +0000
    44.3 @@ -9,11 +9,6 @@
    44.4  #ifndef __XEN_PUBLIC_XEN_H__
    44.5  #define __XEN_PUBLIC_XEN_H__
    44.6  
    44.7 -#ifndef PACKED
    44.8 -/* GCC-specific way to pack structure definitions (no implicit padding). */
    44.9 -#define PACKED __attribute__ ((packed))
   44.10 -#endif
   44.11 -
   44.12  #if defined(__i386__)
   44.13  #include "arch-x86_32.h"
   44.14  #elif defined(__x86_64__)
   44.15 @@ -426,7 +421,7 @@ typedef struct {
   44.16  #define SIF_INITDOMAIN    (1<<1)  /* Is this the initial control domain? */
   44.17  #define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
   44.18  #define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
   44.19 -
   44.20 +#define SIF_USB_BE_DOMAIN (1<<6)  /* Is this a usb backend domain? */
   44.21  /* For use in guest OSes. */
   44.22  extern shared_info_t *HYPERVISOR_shared_info;
   44.23  
    45.1 --- a/xen/include/xen/domain.h	Fri Jan 21 13:52:28 2005 +0000
    45.2 +++ b/xen/include/xen/domain.h	Mon Jan 24 10:19:03 2005 +0000
    45.3 @@ -2,13 +2,21 @@
    45.4  #ifndef __XEN_DOMAIN_H__
    45.5  #define __XEN_DOMAIN_H__
    45.6  
    45.7 -extern void domain_startofday(void);
    45.8 -
    45.9  /*
   45.10   * Arch-specifics.
   45.11   */
   45.12  
   45.13 -extern void arch_do_createdomain(struct exec_domain *d);
   45.14 +extern void domain_startofday(void);
   45.15 +
   45.16 +extern struct domain *arch_alloc_domain_struct(void);
   45.17 +
   45.18 +extern void arch_free_domain_struct(struct domain *d);
   45.19 +
   45.20 +struct exec_domain *arch_alloc_exec_domain_struct(void);
   45.21 +
   45.22 +extern void arch_free_exec_domain_struct(struct exec_domain *ed);
   45.23 +
   45.24 +extern void arch_do_createdomain(struct exec_domain *ed);
   45.25  
   45.26  extern int  arch_final_setup_guestos(
   45.27      struct exec_domain *d, full_execution_context_t *c);
   45.28 @@ -17,4 +25,6 @@ extern void free_perdomain_pt(struct dom
   45.29  
   45.30  extern void domain_relinquish_memory(struct domain *d);
   45.31  
   45.32 +extern void dump_pageframe_info(struct domain *d);
   45.33 +
   45.34  #endif /* __XEN_DOMAIN_H__ */
    46.1 --- a/xen/include/xen/grant_table.h	Fri Jan 21 13:52:28 2005 +0000
    46.2 +++ b/xen/include/xen/grant_table.h	Mon Jan 24 10:19:03 2005 +0000
    46.3 @@ -25,7 +25,6 @@
    46.4  #define __XEN_GRANT_H__
    46.5  
    46.6  #include <xen/config.h>
    46.7 -#include <xen/mm.h>
    46.8  #include <public/grant_table.h>
    46.9  
   46.10  /* Active grant entry - used for shadowing GTF_permit_access grants. */
    47.1 --- a/xen/include/xen/slab.h	Fri Jan 21 13:52:28 2005 +0000
    47.2 +++ b/xen/include/xen/slab.h	Mon Jan 24 10:19:03 2005 +0000
    47.3 @@ -6,6 +6,14 @@
    47.4  #ifndef __SLAB_H__
    47.5  #define __SLAB_H__
    47.6  
    47.7 +#include <xen/config.h>
    47.8 +
    47.9 +#ifdef __ARCH_HAS_SLAB_ALLOCATOR
   47.10 +
   47.11 +#include <asm/slab.h>
   47.12 +
   47.13 +#else
   47.14 +
   47.15  typedef struct xmem_cache_s xmem_cache_t;
   47.16  
   47.17  #include <xen/mm.h>
   47.18 @@ -44,4 +52,6 @@ extern int xmem_cache_reap(void);
   47.19  
   47.20  extern void dump_slabinfo();
   47.21  
   47.22 +#endif /* __ARCH_HAS_SLAB_ALLOCATOR */
   47.23 +
   47.24  #endif /* __SLAB_H__ */