diff -r e410857fd83c drivers/xen/blkback/common.h
--- a/drivers/xen/blkback/common.h	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/common.h	Thu Oct 23 18:27:29 2008 +0900
@@ -100,6 +100,8 @@ void blkif_disconnect(blkif_t *blkif);
 void blkif_disconnect(blkif_t *blkif);
 void blkif_free(blkif_t *blkif);
 int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+int blkif_attach(blkif_t *blkif, unsigned long shared_page,
+                 unsigned int evtchn);
 
 #define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
 #define blkif_put(_b)					\
diff -r e410857fd83c drivers/xen/blkback/interface.c
--- a/drivers/xen/blkback/interface.c	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/interface.c	Wed Nov 19 14:07:06 2008 +0900
@@ -144,6 +144,47 @@ int blkif_map(blkif_t *blkif, unsigned l
 	return 0;
 }
 
+int blkif_attach(blkif_t *blkif, unsigned long shared_page, 
+		 unsigned int evtchn)
+{
+	/* Sorry! Only 32bit curretly. */
+	blkif_x86_32_sring_t *sring_x86_32;
+	int err;
+
+	/* Already connected through? */
+	if (blkif->irq)
+		return 0;
+
+	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+		return -ENOMEM;
+
+	err = map_frontend_page(blkif, shared_page);
+	if (err) {
+		free_vm_area(blkif->blk_ring_area);
+		return err;
+	}
+
+	sring_x86_32 = 
+		(blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
+	BACK_RING_ATTACH(&blkif->blk_rings.x86_32, 
+			 sring_x86_32, PAGE_SIZE);
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif);
+	if (err < 0)
+	{
+		unmap_frontend_page(blkif);
+		free_vm_area(blkif->blk_ring_area);
+		blkif->blk_rings.common.sring = NULL;
+		return err;
+	}
+	blkif->irq = err;
+
+	blkif->blk_rings.x86_32.req_cons = blkif->blk_rings.x86_32.rsp_prod_pvt;
+
+	return 0;
+}
+
 void blkif_disconnect(blkif_t *blkif)
 {
 	if (blkif->xenblkd) {
diff -r e410857fd83c drivers/xen/blkback/xenbus.c
--- a/drivers/xen/blkback/xenbus.c	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/blkback/xenbus.c	Tue Nov 18 21:08:41 2008 +0900
@@ -39,6 +39,7 @@ struct backend_info
 
 static void connect(struct backend_info *);
 static int connect_ring(struct backend_info *);
+static int attach_ring(struct backend_info *);
 static void backend_changed(struct xenbus_watch *, const char **,
 			    unsigned int);
 
@@ -376,6 +377,16 @@ static void frontend_changed(struct xenb
 		update_blkif_status(be->blkif);
 		break;
 
+	case XenbusStateAttached:
+		if (dev->state == XenbusStateAttached)
+			break;
+
+		err = attach_ring(be);
+		if (err)
+			break;
+		update_blkif_status(be->blkif);
+		break;
+
 	case XenbusStateClosing:
 		blkif_disconnect(be->blkif);
 		xenbus_switch_state(dev, XenbusStateClosing);
@@ -515,6 +526,54 @@ static int connect_ring(struct backend_i
 	return 0;
 }
 
+static int attach_ring(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long ring_ref;
+	unsigned int evtchn;
+	char protocol[64] = "";
+	int err;
+
+	DPRINTK("%s", dev->otherend);
+
+	err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", &ring_ref,
+						"event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+						 "reading %s/ring-ref and event-channel",
+						 dev->otherend);
+		return err;
+	}
+
+	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+			    "%63s", protocol, NULL);
+	if (err)
+		strcpy(protocol, "unspecified, assuming native");
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+	else {
+		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+		return -1;
+	}
+	printk(KERN_INFO
+	       "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
+	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
+
+	/* Map the shared frame, irq etc. */
+	err = blkif_attach(be->blkif, ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
+				 ring_ref, evtchn);
+		return err;
+	}
+
+	return 0;
+}
 
 /* ** Driver Registration ** */
 
diff -r e410857fd83c drivers/xen/netback/common.h
--- a/drivers/xen/netback/common.h	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/netback/common.h	Sun Nov 16 11:39:49 2008 +0900
@@ -182,6 +182,8 @@ netif_t *netif_alloc(domid_t domid, unsi
 netif_t *netif_alloc(domid_t domid, unsigned int handle);
 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
 	      unsigned long rx_ring_ref, unsigned int evtchn);
+int netif_attach(netif_t *netif, unsigned long tx_ring_ref,
+		 unsigned long rx_ring_ref, unsigned int evtchn);
 
 #define netif_get(_b) (atomic_inc(&(_b)->refcnt))
 #define netif_put(_b)						\
diff -r e410857fd83c drivers/xen/netback/interface.c
--- a/drivers/xen/netback/interface.c	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/netback/interface.c	Tue Nov 18 21:12:57 2008 +0900
@@ -303,6 +303,64 @@ err_rx:
 	return err;
 }
 
+int netif_attach(netif_t *netif, unsigned long tx_ring_ref,
+				 unsigned long rx_ring_ref, unsigned int evtchn)
+{
+	int err = -ENOMEM;
+	netif_tx_sring_t *txs;
+	netif_rx_sring_t *rxs;
+
+	/* Already connected through? */
+	if (netif->irq)
+		return 0;
+
+	netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (netif->tx_comms_area == NULL)
+		return -ENOMEM;
+	netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (netif->rx_comms_area == NULL)
+		goto err_rx;
+
+	err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
+	if (err)
+		goto err_map;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		netif->domid, evtchn, netif_be_int, 0,
+		netif->dev->name, netif);
+	if (err < 0)
+		goto err_hypervisor;
+	netif->irq = err;
+	disable_irq(netif->irq);
+
+	txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
+	BACK_RING_ATTACH(&netif->tx, txs, PAGE_SIZE);
+
+	rxs = (netif_rx_sring_t *)
+		((char *)netif->rx_comms_area->addr);
+	BACK_RING_ATTACH(&netif->rx, rxs, PAGE_SIZE);
+
+	netif->rx.req_cons = netif->rx.sring->rsp_prod;
+	netif->rx_req_cons_peek = netif->rx.req_cons;
+
+	netif_get(netif);
+
+	rtnl_lock();
+	netback_carrier_on(netif);
+	if (netif_running(netif->dev))
+		__netif_up(netif);
+	rtnl_unlock();
+
+	return 0;
+err_hypervisor:
+	unmap_frontend_pages(netif);
+err_map:
+	free_vm_area(netif->rx_comms_area);
+err_rx:
+	free_vm_area(netif->tx_comms_area);
+	return err;
+}
+
 void netif_disconnect(netif_t *netif)
 {
 	if (netback_carrier_ok(netif)) {
diff -r e410857fd83c drivers/xen/netback/xenbus.c
--- a/drivers/xen/netback/xenbus.c	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/netback/xenbus.c	Tue Nov 18 21:08:41 2008 +0900
@@ -30,7 +30,9 @@
 
 
 static int connect_rings(struct backend_info *);
+static int attach_rings(struct backend_info *);
 static void connect(struct backend_info *);
+static void attach(struct backend_info *);
 static void backend_create_netif(struct backend_info *be);
 
 static int netback_remove(struct xenbus_device *dev)
@@ -239,6 +241,12 @@ static void frontend_changed(struct xenb
 			connect(be);
 		break;
 
+	case XenbusStateAttached:
+		backend_create_netif(be);
+		if (be->netif)
+			attach(be);
+		break;
+
 	case XenbusStateClosing:
 		if (be->netif) {
 			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
@@ -347,6 +355,29 @@ static void connect(struct backend_info 
 	netif_wake_queue(be->netif->dev);
 }
 
+static void attach(struct backend_info *be)
+{
+	int err;
+	struct xenbus_device *dev = be->dev;
+
+	err = attach_rings(be);
+	if (err)
+		return;
+
+	err = xen_net_read_mac(dev, be->netif->fe_dev_addr);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+		return;
+	}
+
+	xen_net_read_rate(dev, &be->netif->credit_bytes,
+			  &be->netif->credit_usec);
+	be->netif->remaining_credit = be->netif->credit_bytes;
+
+	xenbus_switch_state(dev, XenbusStateAttached);
+
+	netif_wake_queue(be->netif->dev);
+}
 
 static int connect_rings(struct backend_info *be)
 {
@@ -427,6 +458,84 @@ static int connect_rings(struct backend_
 	return 0;
 }
 
+static int attach_rings(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long tx_ring_ref, rx_ring_ref;
+	unsigned int evtchn, rx_copy;
+	int err;
+	int val;
+
+	DPRINTK("");
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "tx-ring-ref", "%lu", &tx_ring_ref,
+			    "rx-ring-ref", "%lu", &rx_ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
+			   &rx_copy);
+	if (err == -ENOENT) {
+		err = 0;
+		rx_copy = 0;
+	}
+	if (err < 0) {
+		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
+				 dev->otherend);
+		return err;
+	}
+	be->netif->copying_receiver = !!rx_copy;
+
+	if (be->netif->dev->tx_queue_len != 0) {
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+				 "feature-rx-notify", "%d", &val) < 0)
+			val = 0;
+		if (val)
+			be->netif->can_queue = 1;
+		else
+			/* Must be non-zero for pfifo_fast to work. */
+			be->netif->dev->tx_queue_len = 1;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features |= NETIF_F_SG;
+		be->netif->dev->features |= NETIF_F_SG;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
+			 &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features |= NETIF_F_TSO;
+		be->netif->dev->features |= NETIF_F_TSO;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
+			 "%d", &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features &= ~NETIF_F_IP_CSUM;
+		be->netif->dev->features &= ~NETIF_F_IP_CSUM;
+	}
+
+	/* Map the shared frame, irq etc. */
+	err = netif_attach(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "mapping shared-frames %lu/%lu port %u",
+				 tx_ring_ref, rx_ring_ref, evtchn);
+		return err;
+	}
+	return 0;
+}
 
 /* ** Driver Registration ** */
 
diff -r e410857fd83c drivers/xen/xenbus/xenbus_client.c
--- a/drivers/xen/xenbus/xenbus_client.c	Wed Oct 22 14:55:29 2008 +0100
+++ b/drivers/xen/xenbus/xenbus_client.c	Tue Oct 28 15:37:22 2008 +0900
@@ -52,7 +52,8 @@ const char *xenbus_strstate(enum xenbus_
 		[ XenbusStateInitialised  ] = "Initialised",
 		[ XenbusStateConnected    ] = "Connected",
 		[ XenbusStateClosing      ] = "Closing",
-		[ XenbusStateClosed	  ] = "Closed",
+		[ XenbusStateClosed       ] = "Closed",
+		[ XenbusStateAttached	  ] = "Attached",
 	};
 	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
 }
diff -r e410857fd83c include/xen/interface/io/xenbus.h
--- a/include/xen/interface/io/xenbus.h	Wed Oct 22 14:55:29 2008 +0100
+++ b/include/xen/interface/io/xenbus.h	Mon Oct 27 13:33:14 2008 +0900
@@ -63,7 +63,9 @@ enum xenbus_state {
      */
     XenbusStateReconfiguring = 7,
 
-    XenbusStateReconfigured  = 8
+    XenbusStateReconfigured  = 8,
+
+    XenbusStateAttached      = 9
 };
 typedef enum xenbus_state XenbusState;
 
