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
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel