Subject: [PATCH/RFC 5/5] s390 zlive device drivers

From: Carsten Otte <[EMAIL PROTECTED]>
From: Christian Borntraeger <[EMAIL PROTECTED]>
From: Martin Peschke <[EMAIL PROTECTED]>

This patch contains the userland parts that connect to the set of paravirtual
device drivers posted last week
o zlick <-> vnet
o zldisk <-> vdisk
o zlconsole <-> guest_console
o zldev <-> vdev

In addition to that, a vt220 backend that uses the sclp interface is provided.
A guest linux can drive this backend using the existing console driver
(linux/driver/s390/char/sclp_vt220.c)
This is an alternative to the basic diagnose based console driver as there
are several console programs that provide vt220 emulation.

Signed-off-by: Carsten Otte <[EMAIL PROTECTED]>
---
 drivers/Makefile           |   26 ++
 drivers/zlconsole.c        |  112 ++++++++++
 drivers/zldev.c            |  151 ++++++++++++++
 drivers/zldisk.c           |   71 ++++++
 drivers/zldisk_aio.c       |  467 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/zldisk_disk_info.c |  145 +++++++++++++
 drivers/zlick.c            |  273 ++++++++++++++++++++++++++
 drivers/zlvt220.c          |  119 +++++++++++
 include/zldev.h            |   19 +
 include/zldisk.h           |   27 ++
 include/zldisk_trace.h     |   29 ++
 11 files changed, 1439 insertions(+)

Index: zlive/drivers/Makefile
===================================================================
--- /dev/null
+++ zlive/drivers/Makefile
@@ -0,0 +1,26 @@
+# z/Live diag makefile
+# Copyright IBM Corp. 2007
+# Author: Carsten Otte <[EMAIL PROTECTED]>
+# This file is licensed under the terms of the GNU General Public License(GPL)
+
+%.o : %.c ; echo "     Compiling       " $<; $(CC) $(CFLAGS) -c $<
+
+OBJS := drivers_autoinit.o zldev.o zldisk.o zldisk_aio.o
+OBJS += zldisk_disk_info.o zlick.o zlconsole.o
+
+all: $(OBJS)
+clean:
+       rm -f $(OBJS) drivers_autoinit.c
+
+drivers_autoinit.c: zldev.c zldisk.c zldisk_aio.c zldisk_disk_info.c zlick.c 
zlconsole.c
+       echo "  Creating        " $@
+       echo "//Makefile generated" >$@
+       echo "#define __ZLAUTOINIT(f) void f(void);" >>$@
+       cat $^ |grep __ZLAUTOINIT >>$@
+       echo "#undef __ZLAUTOINIT" >>$@
+       echo "#define __ZLAUTOINIT(f) { f(); };" >>$@
+       echo "void autoinit_drivers(void) {" >>$@
+       cat $^ |grep __ZLAUTOINIT >>$@
+       echo "}" >>$@
+
+.PHONY: clean all
Index: zlive/drivers/zlconsole.c
===================================================================
--- /dev/null
+++ zlive/drivers/zlconsole.c
@@ -0,0 +1,112 @@
+/*
+ * z/Live console device driver
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <atomic.h>
+#include <sys/poll.h>
+#include <linux/errno.h>
+
+#include <zlautoinit.h>
+#include <zlmessage.h>
+#include <zlio_signal.h>
+#include <zldiag.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <zlinterrupt.h>
+
+atomic_t zlconsole_interrupt;
+
+static int diag_sync_write(struct zlcpu *cpu)
+{
+       debug("console sync write");
+       cpu->gpr->regs[2] = write((int)cpu->gpr->regs[2],
+                       (const char*)(cpu->gpr->regs[3]+glo_origin),
+                       (size_t) cpu->gpr->regs[4]);
+       return may_do_cpu_work(cpu);
+}
+
+static int diag_sync_read(struct zlcpu *cpu)
+{
+       struct pollfd pfd = { (int)cpu->gpr->regs[2], POLLIN, 0 };
+       ssize_t ret;
+
+       debug("console sync read");
+       atomic_set (&zlconsole_interrupt, 1); //enable interrupt
+
+       if (poll(&pfd, 1, 0) == 0) {
+               debug ("no read data");
+               cpu->gpr->regs[2]=-EAGAIN;
+               return may_do_cpu_work(cpu);
+       }
+       do {
+               ret = read((int)cpu->gpr->regs[2],
+                           (char*)(cpu->gpr->regs[3]+glo_origin),
+                           (size_t) cpu->gpr->regs[4]);
+       } while ((ret < 0) && (errno == EINTR));
+       cpu->gpr->regs[2] = ret;
+       return may_do_cpu_work(cpu);
+}
+
+static int do_console_interrupt(struct zlcpu *cpu, void* arg, int cleanup)
+{
+       arg=arg; // dont warn
+
+       if (cleanup) {
+               log ("cpu %d: dropping console interrupt from workqueue", 
cpu->cpuno);
+               return 0;
+       }
+       if (ext_int_masked(cpu))
+               return -EAGAIN;
+       debug("delivering console int");
+       return enter_extint(cpu, EXTINT_ZLCONSOLE);
+}
+
+static void console_interrupt(void)
+{
+       struct zlcpu *cpu;
+       cpu = get_interrupt_cpu();
+       if (!cpu)
+               report_it ("cannot get CPU to deliver interrupt");
+       debug("got cpu %d", cpu->cpuno);
+       add_cpu_work_kick(cpu, do_console_interrupt, NULL);
+       put_cpu(cpu);
+}
+
+static void console_sigio_handler(int fd, int band)
+{
+       int istat;
+
+       if (band & POLLOUT)
+               return;
+       debug ("Got console interrupt for %d", fd);
+       do {
+               istat = atomic_read(&zlconsole_interrupt);
+               if (istat == 0)
+                       return;
+       } while (atomic_compare_and_swap(istat, 0, &zlconsole_interrupt));
+       console_interrupt();
+       return;
+}
+
+
+void zlconsole_init(void)
+{
+       register_diagnose_handler (DIAG_SYNC_WRITE, diag_sync_write);
+       register_diagnose_handler (DIAG_SYNC_READ,  diag_sync_read);
+       atomic_set (&zlconsole_interrupt, 1); //enable interrupt
+       /* allow the process to receive IO signals */
+       fcntl(STDIN_FILENO, F_SETOWN, getpid());
+       fcntl(STDIN_FILENO, F_SETSIG, IOSIGNAL);
+       register_sigio_fd(STDIN_FILENO, console_sigio_handler);
+       fcntl(STDIN_FILENO, F_SETFL, FASYNC);
+}
+
+__ZLAUTOINIT(zlconsole_init)
+
Index: zlive/drivers/zldev.c
===================================================================
--- /dev/null
+++ zlive/drivers/zldev.c
@@ -0,0 +1,151 @@
+/*
+ * z/Live device virtualization layer
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include <zlautoinit.h>
+#include <zlconfig.h>
+#include <zldev.h>
+#include <zlglobals.h>
+#include <zlmessage.h>
+#include <zlcpu.h>
+#include <zldiag.h>
+#include <zlreset.h>
+
+/* the lock protects both lists */
+static pthread_mutex_t zldev_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct zllist zldev_new_devices    = EMPTY_LIST(zldev_new_devices);
+static struct zllist zldev_gone_devices   = EMPTY_LIST(zldev_gone_devices);
+static struct zllist zldev_active_devices = EMPTY_LIST(zldev_active_devices);
+
+static int zldev_hotplug(char symname[128], char hostid[128])
+{
+       int rc;
+       struct zlive_dev *dev;
+
+       pthread_mutex_lock(&zldev_lock);
+       if (zllist_is_empty(&zldev_new_devices)) {
+               rc = -ENODEV;
+               goto out_unlock;
+       }
+
+       //get a device from new_devices, move it to active devices
+       dev = zllist_get(zldev_new_devices.next, struct zlive_dev, list);
+       zllist_del(&dev->list);
+       zllist_add_end(&dev->list, &zldev_active_devices);
+
+       //copy relevant info to kernel buffer
+       memcpy(symname+glo_origin, dev->symname, 128);
+       memcpy(hostid+glo_origin,  dev->hostid,  128);
+
+       rc = dev->zldev_type;
+out_unlock:
+       pthread_mutex_unlock(&zldev_lock);
+       return rc;
+}
+
+static int diag_zldev_hotplug(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zldev_hotplug(
+               (char *)(cpu->gpr->regs[2]),
+               (char *)(cpu->gpr->regs[3]));
+       return may_do_cpu_work(cpu);
+}
+
+static void zldev_parse_devlist(char* string, int devtype)
+{
+       char *pos = string;
+       int len;
+       struct zlive_dev *dev;
+
+next:
+       dev = malloc(sizeof(struct zlive_dev));
+       memset (dev, 0, sizeof(struct zlive_dev));
+
+       // scan for colon seperator
+       for (len=0; pos[len] != ':';len++)
+               if (pos[len] == '\0')
+                       goto out_free;
+
+       if ((len<0) || (len>127))
+               goto skip;
+
+       memcpy(dev->symname, pos, len);
+       pos=pos+len+1;
+
+       // scan for comma seperator
+       for (len=0; (pos[len] != ',') && (pos[len] != '\0'); len++);
+
+       if ((len<0) || (len>127))
+               goto skip;
+
+       memcpy(dev->hostid, pos, len);
+       dev->zldev_type = devtype;
+
+       // add device to zldisk_new_devices
+       zllist_add_end(&dev->list, &zldev_new_devices);
+
+       if (pos[len] == '\0')
+               return;
+       pos=pos+len+1;
+       goto next;
+
+skip:
+       //skip this entry
+       free(dev);
+       while ((*pos != '\0') && (*pos != ':'))
+               pos++;
+       if (*pos == '\0')
+               return;
+       goto next;
+out_free:
+       free(dev);
+}
+
+static void zldev_prepare_coldplug(void)
+{
+       pthread_mutex_lock(&zldev_lock);
+       zldev_parse_devlist(get_configentry(glo_activesection, "disks"),
+                           ZLDEV_TYPE_DISK);
+       zldev_parse_devlist(get_configentry(glo_activesection, "network"),
+                              ZLDEV_TYPE_NET);
+       pthread_mutex_unlock(&zldev_lock);
+}
+
+/* Handles the reset for every device */
+static int zldev_reset_handler(void)
+{
+       struct zlive_dev *dev;
+
+       pthread_mutex_lock(&zldev_lock);
+       while (1) {
+               if (zllist_is_empty(&zldev_active_devices))
+                       break;
+               //get a device from new_devices, move it to active devices
+               dev = zllist_get(zldev_active_devices.next, struct zlive_dev, 
list);
+               zllist_del(&dev->list);
+               zllist_add_end(&dev->list, &zldev_new_devices);
+       }
+       pthread_mutex_unlock(&zldev_lock);
+       return 0;
+}
+
+static struct reset_call_register zldev_reset_register = {
+       .handler = zldev_reset_handler,
+};
+
+void zldev_init(void) {
+       zldev_prepare_coldplug();
+       register_reset_handler(&zldev_reset_register);
+       register_diagnose_handler (DIAG_ZLDEV_HOTPLUG, diag_zldev_hotplug);
+}
+
+__ZLAUTOINIT(zldev_init)
Index: zlive/drivers/zldisk.c
===================================================================
--- /dev/null
+++ zlive/drivers/zldisk.c
@@ -0,0 +1,71 @@
+/*
+ * z/Live virtual block device driver
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <linux/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <zldisk.h>
+#include <zlautoinit.h>
+#include <zlcpu.h>
+#include <zldiag.h>
+
+static int zldisk_open(const char *name, int read_only, void *irq_page)
+{
+       int fd, rc;
+
+       if (read_only)
+               fd = open(name, O_RDONLY|O_DIRECT);
+       else
+               fd = open(name, O_RDWR|O_DIRECT);
+
+       if (fd < 0)
+               fd = -errno;
+
+       else {
+               rc = zldisk_setup_aio(fd, irq_page);
+               if (rc) {
+                       close(fd);
+                       fd = rc;
+               }
+       }
+
+       return fd;
+}
+
+static int zldisk_close(int fd)
+{
+       return zldisk_free(fd);
+}
+
+static int diag_zldisk_open(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zldisk_open((const 
char*)(cpu->gpr->regs[2]+glo_origin),
+                                       (int)cpu->gpr->regs[3],
+                                       (void*)(cpu->gpr->regs[4])+glo_origin);
+       return may_do_cpu_work(cpu);
+}
+
+static int diag_zldisk_close(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zldisk_close((int)cpu->gpr->regs[2]);
+       return may_do_cpu_work(cpu);
+}
+
+void zldisk_init(void)
+{
+       register_diagnose_handler(DIAG_ZLDISK_OPEN, diag_zldisk_open);
+       register_diagnose_handler(DIAG_ZLDISK_CLOSE, diag_zldisk_close);
+}
+
+__ZLAUTOINIT(zldisk_init)
Index: zlive/drivers/zldisk_aio.c
===================================================================
--- /dev/null
+++ zlive/drivers/zldisk_aio.c
@@ -0,0 +1,467 @@
+/*
+ * z/Live virtual block device driver
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <stdlib.h>
+#include <libaio.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include <zldisk.h>
+#include <zlmessage.h>
+#include <zlautoinit.h>
+#include <zllist.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <zldiag.h>
+#include <zldisk_trace.h>
+#include <zlreset.h>
+#include <zlinterrupt.h>
+
+#define ZLDISK_WRITE 1
+#define ZLDISK_READ  0
+
+#define AIO_STATUS_GETEVENTS 0
+#define AIO_STATUS_POLLING   1
+#define AIO_STATUS_IDLE      2
+#define AIO_STATUS_EXIT      3
+
+struct zldisk_request {
+        unsigned long buf;
+        unsigned long count;
+};
+
+typedef struct zldisk_request (*zldisk_req_t)[256];
+
+struct zldisk_response {
+       unsigned long intparm;
+       unsigned long count;
+       unsigned long failed;
+};
+
+typedef struct zldisk_response (*zldisk_irq_t)[170];
+
+struct zldisk_fd {
+       struct zllist          list;
+       int                    fd;
+       zldisk_irq_t           irq_page;
+       struct zllist          idle_containers;
+       pthread_mutex_t        aio_lock;
+       pthread_cond_t         aio_wait;
+       pthread_t              aio_thread;
+       int                    aio_status;
+       unsigned long          aio_pending;
+       io_context_t           context;
+};
+
+struct zldisk_iocb_container {
+       struct zllist     list;
+       struct iocb       iocb;
+       void *            parm;
+       struct zldisk_fd* zfd;
+};
+
+static struct zllist   zldisk_fds = {&zldisk_fds, &zldisk_fds};
+static pthread_mutex_t zldisk_fds_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static struct zldisk_fd * zldisk_get_fd(int fd)
+{
+       struct zllist* entry;
+       struct zldisk_fd *zfd;
+       pthread_mutex_lock(&zldisk_fds_lock);
+       for (entry = zldisk_fds.next; entry != &zldisk_fds;
+            entry = entry->next) {
+               zfd = (struct zldisk_fd*)entry;
+               if (zfd->fd == fd)
+                       goto found;
+       }
+       pthread_mutex_unlock(&zldisk_fds_lock);
+       return NULL; // not found
+found:
+       //FIXME: we can grab a per-fd lock as perf improvement
+       return zfd;
+}
+
+static void zldisk_put_fd(struct zldisk_fd *zfd)
+{
+       //FIXME: we can use a per-fd lock as perf improvement
+       zfd=zfd; //ignored for now
+       pthread_mutex_unlock(&zldisk_fds_lock);
+}
+
+static struct zldisk_iocb_container * zldisk_get_iocb_container(
+       struct zldisk_fd *zfd)
+{
+       struct zldisk_iocb_container *rc;
+
+       if (zllist_is_empty(&zfd->idle_containers))
+               return NULL;
+
+       rc = (struct zldisk_iocb_container *)zfd->idle_containers.next;
+       zllist_del(zfd->idle_containers.next);
+       memset (rc, 0, sizeof(struct zldisk_iocb_container));
+       return rc;
+}
+
+static void zldisk_put_iocb_container (struct zldisk_fd* zfd,
+                                      struct zldisk_iocb_container *cont)
+{
+       zllist_add(&cont->list, &zfd->idle_containers);
+}
+
+static int __getevents(struct zldisk_fd *zfd, int wait)
+{
+       int i,count;
+       struct io_event event[512];
+       struct zldisk_iocb_container* cont;
+
+       memset(zfd->irq_page, 0, 4096);
+       memset(event, 0, 512*sizeof(struct io_event));
+       if (wait) {
+               pthread_mutex_unlock(&zfd->aio_lock);
+               count = io_getevents(zfd->context,
+                                    1, 170, event, NULL);
+               if (count == 0)
+                       report_it ("io_getevents returned zero");
+               debug ("io_getevents returned %d", count);
+               pthread_mutex_lock(&zfd->aio_lock);
+       } else
+               count = io_getevents(zfd->context,
+                                    0, 170, event, NULL);
+       if (count<=0)
+               return count; // no more events, or error
+
+       for (i=0; i<count; i++) {
+               cont = zllist_get(event[i].obj, struct zldisk_iocb_container, 
iocb);
+               (*zfd->irq_page)[i].intparm = (unsigned long) cont->parm;
+               (*zfd->irq_page)[i].count   = cont->iocb.u.c.nbytes;
+               __trace_receive_iocb(zfd->fd, cont->iocb.u.c.buf, 
cont->iocb.u.c.nbytes, (unsigned long)(&((*zfd->irq_page)[i].intparm)), cont, 
event[i].obj);
+               zldisk_put_iocb_container(zfd, cont);
+       };
+       zfd->aio_pending-=count;
+       return count;
+}
+
+static int __do_interrupt(struct zlcpu *cpu, void* arg, int cleanup)
+{
+       struct lowcore *lowcore;
+       int index = (int)(long)arg;
+
+       if (cleanup) {
+               log ("cpu %d: dropping zldisk interrupt from workqueue", 
cpu->cpuno);
+               return 0;
+       }
+
+       // may we ask for interruption?
+       if (ext_int_masked(cpu))
+               return -EAGAIN;
+
+       // deliver interrupt parameter ...
+       lowcore = (struct lowcore *) (glo_origin + cl_get_prefix(cpu));
+       lowcore->ext_params = index;
+
+       // ...and the corresponding interrupt
+       return enter_extint(cpu, EXTINT_ZLDISK);
+}
+
+static int
+diag_zldisk_getevents(struct zlcpu *cpu)
+{
+       struct zldisk_fd *zfd;
+       int fd = (int)cpu->gpr->regs[2];
+
+       zfd = zldisk_get_fd(fd);
+       pthread_mutex_lock(&zfd->aio_lock);
+
+       if (zfd->aio_status != AIO_STATUS_POLLING)
+               report_it ("aio status is corrupted");
+       cpu->gpr->regs[2] = (int) __getevents(zfd, 0);
+       if ((int)cpu->gpr->regs[2] <= 0) {
+               if (zfd->aio_pending) {
+                       zfd->aio_status = AIO_STATUS_GETEVENTS;
+                       pthread_cond_signal(&zfd->aio_wait);
+               } else {
+                       // no need to signal POLLING => IDLE
+                       zfd->aio_status = AIO_STATUS_IDLE;
+                       pthread_cond_signal(&zfd->aio_wait);
+               }
+       }
+       pthread_mutex_unlock(&zfd->aio_lock);
+       debug ("got %ld events", cpu->gpr->regs[2]);
+       zldisk_put_fd(zfd);
+       return 0;
+}
+
+
+/* call this with aio_lock[index] held(!) */
+static void __deliver_zldisk_int(struct zldisk_fd *zfd)
+{
+       struct zlcpu *cpu = get_interrupt_cpu();
+
+       if (!cpu)
+               report_it("cannot get interrupt cpu, loosing interrupt");
+       debug ("adding zldisk int to cpu %d", cpu->cpuno);
+       zfd->aio_status = AIO_STATUS_POLLING;
+       add_cpu_work_kick(cpu, __do_interrupt, (void*)(long)zfd->fd);
+       put_cpu(cpu);
+}
+
+
+
+static void *__aio_thread(void *arg)
+{
+       int numevents;
+       struct zldisk_fd *zfd = (struct zldisk_fd *)arg;
+       sigset_t sigs;
+       int rc;
+
+       //block signals: SIGINT, SIGIO
+       sigemptyset (&sigs);
+       sigaddset   (&sigs, SIGINT);
+       sigaddset   (&sigs, SIGIO);
+       sigprocmask (SIG_BLOCK, &sigs, NULL);
+       debug ("ait start");
+
+       do {
+               pthread_mutex_lock(&zfd->aio_lock);
+               switch (zfd->aio_status) {
+               case AIO_STATUS_POLLING:
+               case AIO_STATUS_IDLE:
+                       //interrupt processing in progress, or no iocbs active
+                       debug ("ait idle/polling");
+                       pthread_cond_wait(&zfd->aio_wait,&zfd->aio_lock);
+                       break;
+               case AIO_STATUS_GETEVENTS:
+                       debug ("ait getevents");
+
+                       numevents = __getevents(zfd, 1);
+                       if (zfd->aio_status != AIO_STATUS_GETEVENTS)
+                               report_it("aio status was corrupted while 
waiting for events");
+                       zfd->aio_status = AIO_STATUS_POLLING;
+                       __deliver_zldisk_int(zfd);
+                       break;
+               case AIO_STATUS_EXIT:
+                       debug ("ait exit");
+                       rc = io_destroy(zfd->context);
+                       if (rc)
+                               log ("cannot destroy io context fd %d",
+                                    zfd->fd);
+                       zfd->context = NULL;
+                       //FIXME cleanup idle and busy containers
+                       pthread_mutex_unlock(&zfd->aio_lock);
+                       while (!zllist_is_empty(&zfd->idle_containers)) {
+                               struct zldisk_iocb_container *cont;
+                               cont = (struct zldisk_iocb_container *)
+                                       zfd->idle_containers.next;
+                               zllist_del(&cont->list);
+                               free(cont);
+                       }
+                       pthread_exit(NULL); // bye...
+               }
+               pthread_mutex_unlock(&zfd->aio_lock);
+               pthread_testcancel();
+               if (glo_stopcpus)
+                       pthread_exit(NULL);
+       } while (1);
+       return NULL; // avoid warning (grr..)
+}
+
+int zldisk_setup_aio(int fd, void* irq_page)
+{
+       struct zldisk_fd* zfd;
+       struct zldisk_iocb_container* cont;
+       int i, rc;
+
+       zfd = calloc(1,sizeof(struct zldisk_fd));
+       if (!zfd) {
+               rc = -ENOMEM;
+               goto free;
+       }
+
+       zllist_init(&zfd->list);
+       zllist_init(&zfd->idle_containers);
+
+       if (!zllist_is_empty(&zfd->list))
+               report_it ("list is empty");
+
+       for (i=0; i<ZLDISK_EVENTS_PER_CONTEXT; i++) {
+               cont = calloc(1,sizeof(struct zldisk_iocb_container));
+               if (!cont) {
+                       rc = -ENOMEM;
+                       goto free;
+               }
+               zllist_add(&cont->list, &zfd->idle_containers);
+       }
+
+       zfd->fd = fd;
+       rc = io_setup(ZLDISK_EVENTS_PER_CONTEXT, &zfd->context);
+       if (rc != 0) {
+               goto free;
+       }
+
+       pthread_mutex_init(&zfd->aio_lock, NULL);
+       zfd->aio_status = AIO_STATUS_IDLE;
+       zfd->irq_page = (zldisk_irq_t)irq_page;
+       pthread_cond_init(&zfd->aio_wait, NULL);
+       pthread_create(&zfd->aio_thread, NULL, __aio_thread, (void*) zfd);
+
+       pthread_mutex_lock(&zldisk_fds_lock);
+       zllist_add(&zfd->list, &zldisk_fds);
+       pthread_mutex_unlock(&zldisk_fds_lock);
+       debug ("success: fd %d context %lx", zfd->fd, (long) zfd->context);
+       goto out;
+
+free:
+       debug ("free rc %d", rc);
+       while (!zllist_is_empty(&zfd->idle_containers)) {
+               cont = (struct zldisk_iocb_container *)
+                       zfd->idle_containers.next;
+               zllist_del(&cont->list);
+               free(cont);
+       }
+       free(zfd);
+out:
+       debug ("zldisk open complete, rc is %d", rc);
+       return rc;
+}
+
+static int zldisk_submit_req(int fd, zldisk_req_t submit_page,
+                            int op, unsigned long start_offset, int nrreq,
+                            unsigned long parm)
+{
+       int i, rc;
+       struct zldisk_iocb_container *cont;
+       struct iocb                  *iocbp;
+       struct zldisk_fd             *zfd = zldisk_get_fd(fd);
+       unsigned long offset = start_offset;
+
+       debug ("op %d, offset %ld, nr %d, parm %lx\n", op, start_offset, nrreq, 
parm);
+       if (!zfd)
+               report_it("cannot find file descriptor. not set up?");
+
+       for (i=0; i<nrreq; i++) {
+               pthread_mutex_lock(&zfd->aio_lock);
+               cont = zldisk_get_iocb_container(zfd);
+               if (!cont) {
+                       debug ("no container\n");
+                       pthread_mutex_unlock(&zfd->aio_lock);
+                       break;
+               }
+               cont->iocb.aio_fildes = fd;
+               cont->zfd=zfd;
+               cont->parm=(void*)parm;
+               if (op == ZLDISK_WRITE)
+                       io_prep_pwrite(&cont->iocb, fd, 
(void*)((*submit_page)[i].buf+glo_origin),
+                                      (*submit_page)[i].count, offset);
+               else
+                       io_prep_pread(&cont->iocb, fd, 
(void*)((*submit_page)[i].buf+glo_origin),
+                                     (*submit_page)[i].count, offset);
+               offset += (*submit_page)[i].count;
+               iocbp = &cont->iocb;
+               __trace_submit_iocb(op, fd, (void*) (*submit_page)[i].buf, 
cont->iocb.u.c.nbytes, parm, cont);
+               rc = io_submit(zfd->context, 1, &iocbp);
+               if (rc == 1) {
+                       if (zfd->aio_status == AIO_STATUS_IDLE) {
+                               if (zfd->aio_pending)
+                                       report_it ("incorrect aio accounting");
+                               zfd->aio_status = AIO_STATUS_GETEVENTS;
+                               pthread_cond_signal(&zfd->aio_wait);
+                       }
+                       zfd->aio_pending += rc;
+               } else if (rc < 0){
+                       log ("cannot submit iocb %p, for context %lx, " \
+                            "rc was %d", &cont->iocb, (long)zfd->context, rc);
+                       zllist_add(&cont->list, &zfd->idle_containers);
+                       pthread_mutex_unlock(&zfd->aio_lock);
+                       zldisk_put_fd(zfd);
+                       if (i)
+                               return i;
+                       if (rc == -EAGAIN)
+                               return 0;
+                       return rc;
+               } else
+                       report_it("io submit has returned %d", rc);
+
+               pthread_mutex_unlock(&zfd->aio_lock);
+       }
+
+       zldisk_put_fd(zfd);
+       return i;
+}
+
+static int diag_zldisk_submit_req(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zldisk_submit_req(
+               (int) cpu->gpr->regs[2],
+               (void*)(unsigned long) (cpu->gpr->regs[3]+glo_origin),
+               (int)cpu->gpr->regs[4],
+               (unsigned long)cpu->gpr->regs[5],
+               (int)cpu->gpr->regs[6],
+               (unsigned long)cpu->gpr->regs[7]);
+       return may_do_cpu_work(cpu);
+}
+
+
+/* Releases all ressources of a zldisk_fd */
+static void zldisk_free_zfd(struct zldisk_fd *zfd)
+{
+       pthread_mutex_lock(&zfd->aio_lock);
+       zfd->aio_status=AIO_STATUS_EXIT;
+       pthread_cond_signal(&zfd->aio_wait);
+       pthread_mutex_unlock(&zfd->aio_lock);
+       pthread_join(zfd->aio_thread, NULL);
+       zllist_del(&zfd->list);
+       close(zfd->fd);
+       free(zfd);
+}
+
+/* Release all ressources from a file descriptor, associated with zldisk */
+int zldisk_free(int fd)
+{
+       static struct zldisk_fd *zfd;
+       zfd = zldisk_get_fd(fd);
+       if (!zfd)
+               return -ENOENT;
+       zldisk_free_zfd(zfd);
+       zldisk_put_fd(zfd);
+       return 0;
+}
+
+/* FIXME. zldev has currently no knowledge which device is used
+by any of out guest controller drivers.
[EMAIL PROTECTED]: The cleanup from this function is missing from the close
+funciton of zldisk */
+static int zldisk_reset_handler(void)
+{
+       struct zldisk_fd *zfd;
+
+       pthread_mutex_lock(&zldisk_fds_lock);
+       while (!zllist_is_empty(&zldisk_fds)) {
+               zfd = zllist_get(zldisk_fds.next, struct zldisk_fd, list);
+               zldisk_free_zfd(zfd);
+       }
+       pthread_mutex_unlock(&zldisk_fds_lock);
+       return 0;
+}
+
+static struct reset_call_register zldisk_reset_register = {
+       .handler = zldisk_reset_handler,
+};
+
+
+void
+zldisk_aio_init(void)
+{
+       register_reset_handler(&zldisk_reset_register);
+       register_diagnose_handler(DIAG_ZLDISK_SUBMIT_REQ,
+                                  diag_zldisk_submit_req);
+       register_diagnose_handler(DIAG_ZLDISK_GETEVENTS,
+                                  diag_zldisk_getevents);
+}
+
+__ZLAUTOINIT(zldisk_aio_init)
Index: zlive/drivers/zldisk_disk_info.c
===================================================================
--- /dev/null
+++ zlive/drivers/zldisk_disk_info.c
@@ -0,0 +1,145 @@
+/*
+ * z/Live virtual block device driver device information handling
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <linux/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <zldisk.h>
+#include <zlmessage.h>
+#include <zlcpu.h>
+#include <zlconfig.h>
+#include <zldiag.h>
+#include <zlautoinit.h>
+
+static void __info_blk(char *fullname, int* blocksize, long* size, int* 
read_only)
+{
+       int fd;
+
+       //open device
+       fd = open(fullname, O_RDWR);
+       /* if something goes wrong, have a placeholder with blocksize */
+       if (fd<0) {
+               log("cannot open device %s ", fullname);
+               *blocksize = 0;
+               return;
+       }
+
+       if (ioctl(fd, BLKSSZGET, blocksize)) {
+               log("unable to query blocksize %s", fullname);
+               *blocksize = 0;
+               goto close;
+       }
+
+       if (ioctl(fd, BLKGETSIZE, size)) {
+               log("unable to query size of %s", fullname);
+               *blocksize = 0;
+               goto close;
+       }
+       if (ioctl(fd, BLKROGET, read_only)) {
+               log("unable to query ro attribute of %s", fullname);
+               *blocksize = 0;
+       }
+close:
+       close(fd);
+}
+
+static void __info_reg(char *fullname, int* blocksize, long* size, int* 
read_only)
+{
+       struct stat status;
+       int fd;
+
+       fd = open(fullname, O_RDWR);
+       if (fd==-1) {
+               log("cannot open file %s readwrite: %d", fullname, errno);
+               *read_only = 1;
+               fd = open(fullname, O_RDONLY);
+       } else {
+               log("can open %s readwrite", fullname);
+               *read_only = 0;
+       }
+       if (fd==-1) {
+               log("cannot open file %s readonly: %d", fullname, errno);
+               *blocksize = 0;
+               return;
+       }
+       if (fstat(fd, &status)) {
+               log("cannot stat file %s: %d ", fullname, errno);
+               *blocksize = 0;
+               goto close;
+       }
+       *blocksize = (int) status.st_blksize;
+       *size = (long) status.st_size>>9;
+ close:
+       close(fd);
+       return;
+}
+
+static int zldisk_disk_info(char name[128], int* blocksize, long* size, int* 
read_only)
+{
+       struct stat status;
+       int rc;
+
+       rc = stat(name, &status);
+       if (rc) {
+               log("cannot stat zldisk device %s ", name);
+               *blocksize = 0;
+               *size = 0;
+               * read_only = 0;
+               goto out;
+       }
+
+       // do we have at least read permission?
+       if (access(name, F_OK|R_OK)) {
+               screen ("insufficient permissions on zldisk device %s",
+                       name);
+               *blocksize=0;
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       // get disk info
+       if (S_ISBLK(status.st_mode))
+               __info_blk(name, blocksize, size, read_only);
+       else if (S_ISREG(status.st_mode))
+               __info_reg(name, blocksize, size, read_only);
+       else {
+               screen ("unsupported file type on zldisk device %s",
+                       name);
+               rc = -EAGAIN;
+               *blocksize=0;
+               goto out;
+       }
+       rc = 0;
+ out:
+       return rc;
+}
+
+static int diag_zldisk_disk_info(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = 
zldisk_disk_info((char*)(cpu->gpr->regs[2]+glo_origin),
+                               (int*)(cpu->gpr->regs[3]+glo_origin),
+                               (long*)(cpu->gpr->regs[4]+glo_origin),
+                               (int*)(cpu->gpr->regs[5]+glo_origin));
+       return may_do_cpu_work(cpu);
+}
+
+void zldisk_disk_info_init(void)
+{
+       register_diagnose_handler(DIAG_ZLDISK_DISK_INFO,
+                                 diag_zldisk_disk_info);
+}
+
+__ZLAUTOINIT(zldisk_disk_info_init)
Index: zlive/drivers/zlick.c
===================================================================
--- /dev/null
+++ zlive/drivers/zlick.c
@@ -0,0 +1,273 @@
+/*
+ * z/Live insular communication knack
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <zlglobals.h>
+#include <zlconfig.h>
+#include <zlautoinit.h>
+#include <zlmessage.h>
+#include <zlio_signal.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <zldiag.h>
+#include <zlreset.h>
+#include <zlinterrupt.h>
+
+/* from kernel includes */
+struct zlick_info {
+       int linktype;
+       int maxmtu;
+};
+
+
+#define ZLICK_IOCTL_ID 'Z'
+#define ZLICK_REGISTER_CTL _IOW(ZLICK_IOCTL_ID ,0, unsigned long long)
+#define ZLICK_INTERRUPT _IOW(ZLICK_IOCTL_ID, 1, int)
+#define ZLICK_INFO _IOR(ZLICK_IOCTL_ID, 2, struct zlick_info *)
+
+#define ZLICK_IRQ_START_RX 0
+#define ZLICK_IRQ_START_TX 1
+
+static struct zllist zlick_users = {&zlick_users, &zlick_users};
+static pthread_mutex_t zlick_users_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct zlick_user {
+       struct zllist head;
+       int fd;
+};
+
+
+static int zlick_info(char *name, int *linktype)
+{
+       int fd,rc;
+       struct zlick_info info;
+       fd = open(name, O_RDWR);
+       if (fd == -1)
+               return fd;
+       rc = ioctl(fd, ZLICK_INFO, &info);
+       if (rc)
+               return rc;
+       *linktype = info.linktype;
+       close(fd);
+       return 0;
+}
+
+
+static int diag_zlick_info(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zlick_info( (char *) cpu->gpr->regs[2],
+                                       (int*) cpu->gpr->regs[3]);
+       return may_do_cpu_work(cpu);
+}
+
+
+static int __zlick_interrupt(struct zlcpu *cpu, void* arg, int cleanup)
+{
+       struct lowcore *lowcore;
+       unsigned int* parm = (unsigned int*)arg;
+
+       if (cleanup) {
+               log ("cpu %d: dropping zlick interrupt from workqueue", 
cpu->cpuno);
+               free(parm);
+               return 0;
+       }
+       // may we ask for interruption?
+       if (ext_int_masked(cpu))
+               return -EAGAIN;
+       // deliver interrupt parameter ...
+       lowcore = (struct lowcore *) (glo_origin + cl_get_prefix(cpu));
+       lowcore->ext_params = *parm;
+       free(parm);
+       debug ("delivering g-interrupt type %d", lowcore->ext_params);
+       // ...and the corresponding interrupt
+       return enter_extint(cpu, EXTINT_ZLICK);
+}
+
+static void zlick_interrupt (int fd, int utype)
+{
+       unsigned int *ext_parm;
+       struct zlcpu *cpu;
+
+       debug ("got g-interrupt type %d", utype);
+
+       ext_parm = malloc(sizeof(int));
+
+       if (!ext_parm)
+               report_it("out of memory");
+
+       if (utype>>2)
+               report_it("cannot handle interrupt type");
+
+       /* the leftmost two bits must be zero */
+       if (fd & 0xc0000000)
+               report_it("too many file descriptors");
+
+       *ext_parm =  (fd << 2) | utype;
+       cpu = get_interrupt_cpu();
+
+       add_cpu_work_kick(cpu, __zlick_interrupt, ext_parm);
+
+       put_cpu(cpu);
+}
+
+
+
+static void zlick_sigio(int fd, int band)
+{
+       if (band & POLLIN)
+               zlick_interrupt(fd, ZLICK_IRQ_START_RX);
+       if (band & POLLOUT)
+               zlick_interrupt(fd, ZLICK_IRQ_START_TX);
+}
+
+static int zlick_open(char *name, void* control)
+{
+       int rc;
+       struct zlick_user *zu;
+
+       unsigned long long uaddr = (unsigned long long) control;
+
+       zu = malloc(sizeof(*zu));
+       if (!zu)
+               report_it("zlick: out of memory\n");
+
+       zu->fd = open(name, O_RDWR);
+       if (zu->fd == -1)
+               return zu->fd;
+       /* allow the process to receive SIGIO */
+       fcntl(zu->fd, F_SETOWN, getpid());
+        /* Make the file descriptor asynchronous (the manual page says only
+          O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
+       fcntl(zu->fd, F_SETFL, FASYNC);
+       fcntl(zu->fd,F_SETSIG,IOSIGNAL);
+       register_sigio_fd(zu->fd, &zlick_sigio);
+       rc = ioctl(zu->fd, ZLICK_REGISTER_CTL, &uaddr);
+       if (rc == -1) {
+               close(zu->fd);
+               free(zu);
+               return rc;
+       }
+       pthread_mutex_lock(&zlick_users_lock);
+       zllist_add(&zu->head, &zlick_users);
+       pthread_mutex_unlock(&zlick_users_lock);
+       return zu->fd;
+}
+
+static int diag_zlick_open(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zlick_open( (char *) cpu->gpr->regs[2],
+                                       (void *) cpu->gpr->regs[3]);
+       return may_do_cpu_work(cpu);
+}
+
+static void
+zlick_send_irq(int fd, int type)
+{
+       int utype = type;
+
+       debug("got h-interrupt type %d", type);
+       ioctl(fd, ZLICK_INTERRUPT, &utype);
+}
+
+static int
+diag_zlick_send_irq(struct zlcpu *cpu)
+{
+       zlick_send_irq((int)cpu->gpr->regs[2], (int)cpu->gpr->regs[3]);
+       return may_do_cpu_work(cpu);
+}
+
+static void
+zlick_release(int fd)
+{
+       struct zllist *zll;
+       struct zlick_user *entry;
+
+       pthread_mutex_lock(&zlick_users_lock);
+       for (zll=zlick_users.next; zll!=&zlick_users; zll=zll->next) {
+               entry = (struct zlick_user *) zll;
+               if (fd == entry->fd) {
+                       debug("closing fd %d", fd);
+                       close(fd);
+               }
+       }
+       pthread_mutex_unlock(&zlick_users_lock);
+       close(fd);
+}
+
+static int
+diag_zlick_release(struct zlcpu *cpu)
+{
+       zlick_release((int)cpu->gpr->regs[2]);
+       return may_do_cpu_work(cpu);
+}
+
+static int
+zlick_ip(int add, uint32_t addr, uint32_t mask, uint32_t broadcast)
+{
+       debug("Got IP event %d %X %X %X\n", add, addr, mask, broadcast);
+       return 0; //FIXME: implement
+}
+
+static int
+diag_zlick_ip(struct zlcpu *cpu)
+{
+       cpu->gpr->regs[2] = zlick_ip((int) cpu->gpr->regs[2],
+                                    (uint32_t) cpu->gpr->regs[3],
+                                    (uint32_t) cpu->gpr->regs[4],
+                                    (uint32_t) cpu->gpr->regs[5]);
+       return may_do_cpu_work(cpu);
+}
+
+/*  FIXME. zldev has currently no knowledge which device is used
+    by any of our guest controller drivers. we might want to move some
+    code to zldev?*/
+static int zlick_reset_handler(void)
+{
+       struct zlick_user *entry;
+
+       pthread_mutex_lock(&zlick_users_lock);
+       while (!zllist_is_empty(&zlick_users)) {
+               entry = zllist_get(zlick_users.next, struct zlick_user, head);
+               close(entry->fd);
+               zllist_del(&entry->head);
+               free(entry);
+       }
+       pthread_mutex_unlock(&zlick_users_lock);
+       return 0;
+}
+
+static struct reset_call_register zlick_reset_register = {
+       .handler = zlick_reset_handler,
+};
+
+
+
+void zlick_init(void)
+{
+       register_reset_handler(&zlick_reset_register);
+       register_diagnose_handler (DIAG_ZLICK_INFO, diag_zlick_info);
+       register_diagnose_handler (DIAG_ZLICK_OPEN, diag_zlick_open);
+       register_diagnose_handler (DIAG_ZLICK_SEND_IRQ, diag_zlick_send_irq);
+       register_diagnose_handler (DIAG_ZLICK_RELEASE, diag_zlick_release);
+       register_diagnose_handler (DIAG_ZLICK_IP, diag_zlick_ip);
+}
+
+__ZLAUTOINIT(zlick_init)
Index: zlive/drivers/zlvt220.c
===================================================================
--- /dev/null
+++ zlive/drivers/zlvt220.c
@@ -0,0 +1,119 @@
+/*
+ * z/Live console device driver
+ * Copyright IBM Corp. 2007
+ * Author: Martin Peschke <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <atomic.h>
+#include <sys/poll.h>
+#include <linux/errno.h>
+
+#include <zlautoinit.h>
+#include <zlmessage.h>
+#include <zlio_signal.h>
+#include <zldiag.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <zlsclp.h>
+
+static atomic_t zlvt220_interrupt;
+static int zlvt220_fd;
+#define ZLVT220_SESSION_RUNNING 0x1
+static int zlvt220_status = 0;
+
+static uint16_t zlvt220_receive(struct event_buffer_header *event)
+{
+       char *data = (char *)event + sizeof(struct event_buffer_header);
+       int size = event->length - sizeof(struct event_buffer_header);
+
+       if (!(zlvt220_status & ZLVT220_SESSION_RUNNING))
+               return SCLP_RC_TARGET_IN_IMPROPER_STATE;
+       // FIXME: does architecture require either all or nothing to be written?
+       if (write(zlvt220_fd, data, size) != size)
+               return SCLP_RC_OUT_OF_MEMORY;
+       event->flags &= SCLP_EVENT_BUFFER_ACCEPTED;
+       return SCLP_RC_NORMAL_COMPLETION;
+}
+
+static uint16_t zlvt220_send(void *__event, uint16_t length)
+{
+       struct pollfd pfd = { zlvt220_fd, POLLIN, 0 };
+       struct event_buffer_ascii_console_read *event = __event;
+       uint16_t dlength = length - sizeof(struct 
event_buffer_ascii_console_read);
+       ssize_t count;
+
+       if (!(zlvt220_status & ZLVT220_SESSION_RUNNING))
+               return SCLP_RC_TARGET_IN_IMPROPER_STATE;
+       if (poll(&pfd, 1, 0) == 0)
+               return SCLP_RC_NO_EVENT_BUFFERS_STORED;
+
+       do {
+               count = read(zlvt220_fd, event->data, dlength);
+       } while ((count < 0) && (errno == EINTR));
+       if (count == 0)
+               return SCLP_RC_EVENT_BUFFERS_SUPPRESSED;
+
+       event->header.length = sizeof(struct event_buffer_ascii_console_read) + 
count;
+       event->header.type = SCLP_EVENT_ASCII_CONSOLE;
+       event->header.flags &= ~SCLP_EVENT_BUFFER_ACCEPTED;
+       // FIXME: Linux implementation ignores session start/end - so do we
+       event->type = SCLP_ASCII_CONSOLE_DATA;
+
+       if (poll(&pfd, 1, 0) > 0)
+               return SCLP_RC_SOME_EVENTS_SUPPRESSED;
+       return SCLP_RC_NORMAL_COMPLETION;
+}
+
+void console_sigio_handler(int fd, int band)
+{
+       int istat;
+
+       if (band & POLLOUT)
+               return;
+       debug ("Got console interrupt for %d", fd);
+       do {
+               istat = atomic_read(&zlvt220_interrupt);
+               if (istat == 0) {
+                       debug ("Loosing vt220 interrupt for %d", fd);
+                       return;
+               }
+       } while (atomic_compare_and_swap(istat, 0, &zlvt220_interrupt));
+       debug ("Raising vt220 interrupt for %d", fd);
+       sclp_interrupt(SCLP_EVENT_DATA_PENDING_INDICATOR);
+       return;
+}
+
+static struct sclp_event_types ascii_console = {
+       .send_mask = SCLP_EVENT_MASK_ASCII_CONSOLE,
+       .receive_mask = SCLP_EVENT_MASK_ASCII_CONSOLE,
+       .send = zlvt220_send,
+       .receive = zlvt220_receive
+};
+
+void zlvt220_init(void)
+{
+       atomic_set(&zlvt220_interrupt, 1);
+
+       zlvt220_fd = open("/dev/tty", O_RDWR);
+       if (zlvt220_fd < 0) {
+               log("could not open /dev/tty for sclp ascii console (%i, %i)",
+                   zlvt220_fd, errno);
+               return;
+       }
+
+       fcntl(zlvt220_fd, F_SETOWN, getpid());
+       fcntl(zlvt220_fd, F_SETSIG, IOSIGNAL);
+       register_sigio_fd(zlvt220_fd, console_sigio_handler);
+       fcntl(zlvt220_fd, F_SETFL, FASYNC);
+       zlvt220_status = ZLVT220_SESSION_RUNNING;
+
+       sclp_register_event(&ascii_console);
+}
+
+__ZLAUTOINIT(zlvt220_init)
+
Index: zlive/include/zldev.h
===================================================================
--- /dev/null
+++ zlive/include/zldev.h
@@ -0,0 +1,19 @@
+/*
+ * z/Live device virtualization layer
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zllist.h>
+
+#define ZLDEV_TYPE_DISK     0
+#define ZLDEV_TYPE_NET      1
+
+struct zlive_dev {
+       unsigned int        zldev_type;
+       char                symname[128];
+       char                hostid[128];
+       struct zllist       list;
+};
Index: zlive/include/zldisk.h
===================================================================
--- /dev/null
+++ zlive/include/zldisk.h
@@ -0,0 +1,27 @@
+/*
+ * z/Live virtual block device driver header file
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#ifndef __ZLDISK_H
+#define __ZLDISK_H
+#include <libaio.h>
+
+#include <zllist.h>
+
+#define ZLDISK_EVENTS_PER_CONTEXT 1024
+
+//from linux/fs.h
+#define BLKSSZGET  _IO(0x12,104)
+#define BLKROGET   _IO(0x12,94)
+#define BLKGETSIZE _IO(0x12,96)
+
+//in drivers/zldisk_aio.c
+extern int zldisk_setup_aio(int, void*);
+extern int zldisk_free(int fd);
+
+
+#endif //defined __ZLDISK_H
Index: zlive/include/zldisk_trace.h
===================================================================
--- /dev/null
+++ zlive/include/zldisk_trace.h
@@ -0,0 +1,29 @@
+/*
+ * z/Live virtual block device driver tracing header file
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#undef ZLDISK_TRACE
+
+#ifdef ZLDISK_TRACE
+static inline void __trace_submit_iocb(int op, int fd, void* buf, long count,
+                                      unsigned long parm, void* cont)
+{
+       debug ("buf %p, fd %d, count %ld, bio %lx, container %p -- op %d",
+              buf, fd, count, parm, cont, op);
+}
+
+static inline void __trace_receive_iocb(int fd, void* buf, long count,
+                                       unsigned long parm, void *cont, void 
*iocb)
+{
+       debug ("buf %p, fd %d, count %ld, bio %lx, container %p, iocb %p",
+              buf, fd, count, parm, cont, iocb);
+}
+#else
+#define __trace_submit_iocb(a...) do{}while(0)
+#define __trace_receive_iocb(a...) do{}while(0)
+
+#endif //defined ZLDISK_TRACE



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to