WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC] [PATCH] serial port discovery and zilog device driver

To: xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
Subject: [XenPPC] [PATCH] serial port discovery and zilog device driver
From: Maria Butrico <butrico@xxxxxxxxxxxxxx>
Date: Thu, 25 May 2006 12:29:17 -0400
Delivery-date: Thu, 25 May 2006 09:33:33 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>

summary:    serial port discovery and zilog device driver.

diff -r 2039069d08ca xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c    Wed May 24 17:09:51 2006 -0500
+++ b/xen/arch/ppc/boot_of.c    Thu May 25 12:21:06 2006 -0400
@@ -27,6 +27,9 @@
 #include <public/of-devtree.h>
 #include <asm/page.h>
 #include <asm/io.h>
+#include <xen/string.h>
+#include <xen/serial.h>
+#include <asm-ppc/uart.h>
 #include "exceptions.h"
 
 static ulong of_vec;
@@ -36,7 +39,13 @@ static char bootargs[256];
 static char bootargs[256];
 static char dom0args[256];
 
-extern struct ns16550_defaults ns16550;
+struct uart uarts[] = {
+    { .type = ns16550,    .uart_name = "ns16550", .p_sign = "isa",
+          .gp_sign = "ht",     .uart_init_func = ns16550_init },
+    { .type = pmac_zilog, .uart_name = "zilog",   .p_sign = "escc",
+          .gp_sign = "mac-io", .uart_init_func = pmac_zilog_init },
+};
+struct platform_serial_port global_serial_port;
 
 #undef OF_DEBUG
 
@@ -48,6 +57,11 @@ extern struct ns16550_defaults ns16550;
 
 #define of_panic(MSG...) \
     do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
+
+#define _IF_OF_FAILURE_RET(rc)             \
+        if (unlikely((rc)==OF_FAILURE))  { \
+            return OF_FAILURE;             \
+        }
 
 struct of_service {
     u32 ofs_service;
@@ -366,7 +380,6 @@ static void boot_of_probemem(multiboot_i
     root = of_finddevice("/");
     p = of_getchild(root);
 
-    /* code is writen to assume sizes of 1 */
     of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
     of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
     DBG("%s: address_cells=%d  size_cells=%d\n",
@@ -702,7 +715,7 @@ static ulong find_space(u32 size, ulong 
     ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
     ulong base;
 
-    of_printf("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%lx\n",
+    DBG("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%lx\n",
                     __func__, space_base, eomem, size, align);
     base = ALIGN_UP(space_base, PAGE_SIZE);
     if ((base + size) >= 0x4000000) return 0;
@@ -714,7 +727,7 @@ static ulong find_space(u32 size, ulong 
         return base;
     } else {
         for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
-            of_printf("Trying 0x%016lx\n", base);
+            DBG("Trying 0x%016lx\n", base);
             if (of_claim((void*)base, size) != OF_FAILURE) {
                 space_base = base + size;
                 return base;
@@ -760,20 +773,221 @@ static void __init boot_of_fix_maple(voi
     }
 }
     
-static int __init boot_of_serial(void *oftree)
-{
-    int n;
-    int p;
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The number of integers in each size entry is
+ * determined by the value of the #size-cells property of this node (the node 
in which the ranges property appears)
+ * or 1 if the #size-cells property is absent.
+ *
+ *
+ * pg 177, property "reg"
+ *
+ * The number of integers in each size entry is determined by the value of the 
"#size-cells" property in the parent node.
+ * If the parent node has no such property, the value is one.
+ */
+static void boot_of_serial_ns16550(int ofout, int parent, int grandparent)
+{
+    u32 addr_cells, size_cells;
+
+    /* the struct isa_reg_property is for a value of 2 for #address-cells and a
+     * value of 1 for #size-cells (of the parent).  
+     */
+    struct isa_reg_property {
+        u32 space;
+        u32 address;
+        u32 size;
+    } isa_reg;
+
+    struct of_pci_range64_s {
+        u32 flags;
+        u32 opa_mid;
+        u32 opa_lo;
+        u32 opr_phys_hi;
+        u32 opr_phys_lo;
+        u32 opr_size_hi;
+        u32 opr_size_lo;
+    } r64;
+    u32 clock;
+
+    /* note that if a property does not exist, then the 3rd parameter to
+     * of_getprop is *not* altered
+     */
+    addr_cells = 2;
+    size_cells = 1;
+    of_getprop(grandparent, "#address-cells", &addr_cells, sizeof(addr_cells));
+    of_getprop(grandparent, "#size-cells", &size_cells, sizeof(size_cells));
+    DBG("In %s: value for grandparent #address-cells %d "
+                 "and #size-cells %d\n",
+                 __func__, addr_cells, size_cells);
+    of_getprop(grandparent , "ranges", &r64, sizeof(r64));
+
+    addr_cells = 2;
+    size_cells = 1;
+    of_getprop(ofout, "#address-cells", &addr_cells, sizeof(addr_cells));
+    of_getprop(parent, "#size-cells", &size_cells, sizeof(size_cells));
+    DBG("In %s: value for #address-cells %d "
+                 "and #size-cells %d\n",
+                 __func__, addr_cells, size_cells);
+   
+    of_getprop(ofout, "reg", &isa_reg, sizeof(isa_reg));
+
+    of_getprop(ofout, "clock-frequency", &clock, sizeof (clock));
+
+    of_printf("reg property address=0x%08x  size=0x%08x\n",
+                    isa_reg.address, isa_reg.size);
+    of_printf("ranges property %x:%x %x:%x\n",
+                 r64.opr_phys_hi, r64.opr_phys_lo,
+                 r64.opr_size_hi, r64.opr_size_lo);
+
+    global_serial_port.uart_io_base = isa_reg.address;
+    isa_io_base = r64.opr_phys_hi;
+    isa_io_base <<= 32;
+    isa_io_base |= r64.opr_phys_lo;
+    global_serial_port.clock = clock;
+}
+
+static void boot_of_serial_zilog(int ofout, int parent, int grandparent)
+{
+    u32 addr_cells, size_cells;
+
+    /* the struct reg_property32 is for a value of 1 for #address-cells and
+     * a value of 1 for #size-cells.
+     */
+    struct reg_property32 {
+        u32 address;
+        u32 size;
+    } reg;
+
+    /* the struct of_pic_range32_s is for a value of 1 of #address-cells 
+     * for ?? and a value of 1 for #size-cells. 
+     */
+    struct of_pci_range32_s {
+        u32 flags;
+        u32 opa_mid;
+        u32 opa_lo;
+        u32 opr_phys;
+        u32 opr_size;
+    } r32;
+
+    addr_cells = 2;
+    size_cells = 1;
+    of_getprop(grandparent, "#address-cells", &addr_cells, sizeof(addr_cells));
+    of_getprop(grandparent, "#size-cells", &size_cells, sizeof(size_cells));
+    DBG("In %s: value for grandparent #address-cells %d "
+                 "or #size-cells %d\n",
+                 __func__, addr_cells, size_cells);
+    of_getprop(grandparent , "ranges", &r32, sizeof(r32));
+
+    addr_cells = 2;
+    size_cells = 1;
+    of_getprop(ofout, "#address-cells", &addr_cells, sizeof(addr_cells));
+    of_getprop(parent, "#size-cells", &size_cells, sizeof(size_cells));
+    DBG("In %s %d: value for #address-cells %d "
+                 "or #size-cells %d\n",
+                 __func__, addr_cells, size_cells);
+    of_getprop(ofout, "reg", &reg, sizeof(reg));
+
+    of_printf("reg property address=0x%08x  size=0x%08x\n",
+                        reg.address, reg.size);
+    of_printf("ranges property %x %x\n",
+                            r32.opr_phys, r32.opr_size);
+
+    global_serial_port.uart_io_base = reg.address;
+    isa_io_base = r32.opr_phys;
+}
+
+/*
+ * return OF_FAILURE if it cannot find the serial device
+ * the of handle of the serial device otherwise
+ */
+static int __init boot_of_serial_simple_probe(void)
+{
+    int node;
+    char buf[64];
+
+    node = of_instance_to_package(of_out);
+    if (node == OF_FAILURE) {
+        return OF_FAILURE;
+    }
+
+    buf[0] = '\0';
+    of_getprop(node, "device_type", buf, sizeof (buf));
+    if (strstr(buf, "serial") == NULL) {
+        return OF_FAILURE;
+    }
+
+    return node;
+}
+
+/*
+ * return OF_FAILURE if it cannot find the serial device
+ * the of handle of the serial device otherwise
+ */
+static int __init boot_of_serial_canonical_probe()
+{
+    int p, ofout;      /* of handle */
     int rc;
-    u32 val[3];
+    char ofout_path[256] = {0,};
+    const char serial[] = "serial";
+
+    /* copied and adapted from rhype */
+    ofout_path[0] = '\0';
+    ofout = OF_FAILURE;
+
+    /* probe /options tree */
+    rc = p = of_finddevice("/options");
+    if (p != OF_FAILURE) {
+        rc = of_getprop(p, "output-device", ofout_path,
+                        sizeof(ofout_path));
+    } 
+    if (OF_FAILURE == rc) {
+        strncpy(ofout_path, serial, sizeof(serial));
+    }
+
+    /*
+     * if the options are not a path (they do not start with '/')
+     * then they are aliases and we must look them up.  we look it
+     * up in aliases because it is possible that the OF does not
+     * support finddevice() of an alias.
+     */
+    if (ofout_path[0] != '/') {
+        p = of_finddevice("/aliases");
+        if (p != OF_FAILURE) {
+            char alias[256];
+            memcpy(alias, ofout_path, sizeof(alias));
+            rc = of_getprop(p, alias, ofout_path, sizeof (ofout_path));
+        }
+    }
+
+    if (OF_FAILURE != rc) {
+        ofout = of_finddevice(ofout_path);
+    } else {
+        /*
+         * Our last chance is to figure out the package for
+         * the current console and hopefully discover it to be
+         * a serial device.
+         */
+        /* of_out is the phandle of the property 'stdout' of
+         *'chosen'.
+         */
+        rc = of_instance_to_path(of_out, ofout_path, sizeof(ofout_path));
+        if (rc != OF_FAILURE) {
+            ofout = of_finddevice(ofout_path);
+        }
+    }
+
+    return ofout;
+}
+
+static void __init boot_of_serial_prune(void *oftree, int n)
+{
     char buf[128];
-
-    n = of_instance_to_package(of_out);
-    if (n == OF_FAILURE) {
-        of_panic("instance-to-package of /chosen/stdout: failed\n");
-    }
-
-    /* prune this from the oftree */
+    int rc;
+
+    /* prune serial device from OF tree */
     rc = of_package_to_path(n, buf, sizeof(buf));
     if (rc == OF_FAILURE) {
         of_panic("package-to-path of /chosen/stdout: failed\n");
@@ -782,54 +996,121 @@ static int __init boot_of_serial(void *o
               "  since Xen will be using it for console\n", buf);
     rc = ofd_prune_path(oftree, buf);
     if (rc < 0) {
-        of_panic("prune path \"%s\" failed\n", buf);
-    }
-    
-
-    p = of_getparent(n);
-    if (p == OF_FAILURE) {
-        of_panic("no parent for: 0x%x\n", n);
-    }
-
-    buf[0] = '\0';
-    of_getprop(p, "device_type", buf, sizeof (buf));
-    if (strstr(buf, "isa") == NULL) {
-        of_panic("only ISA UARTS supported\n");
-    }
-
-    /* should get this from devtree */
-    isa_io_base = 0xf4000000;
-    of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
-
-    buf[0] = '\0';
-    of_getprop(n, "device_type", buf, sizeof (buf));
-    if (strstr(buf, "serial") == NULL) {
-        of_panic("only UARTS supported\n");
-    }
-
-    rc = of_getprop(n, "reg", val, sizeof (val));
+       of_panic("prune path \"%s\" failed\n", buf);
+    }
+}
+
+/*
+ * return 0 is a serial port is found.
+ * OF_FAILURE if no serial port can be found
+ */
+static int __init boot_of_serial(void *oftree)
+{
+    int ofout;      /* of handle */
+    int rc;
+    char of_property[256];
+    const char serial[] = "serial";
+    u32 interrupts, baud;
+
+    memset(&global_serial_port, 0, sizeof(global_serial_port));
+
+    ofout = boot_of_serial_simple_probe();
+    if (OF_FAILURE == ofout) {
+        of_printf("Warning %s: simple probe of serial device failed.\n",
+                  __func__);
+        ofout = boot_of_serial_canonical_probe();
+    }
+
+    DBG("serial port OF handle=0x%x\n", ofout);
+
+    if (OF_FAILURE == ofout) {
+        of_printf("Could not find serial device.\n");
+        return OF_FAILURE;
+    }
+
+    /* Now we have the OF handle of the serial device.  The device
+     * must have type 'serial'.
+     */
+    rc = of_getprop(ofout, "device_type", of_property, sizeof(of_property));
+    if (strncmp(of_property, serial, sizeof(serial))) {
+        of_printf("Serial device is not serial\n");
+        return OF_FAILURE;
+    }
+
+    /*
+     * Remove the device from the ofd tree
+     */
+    boot_of_serial_prune(oftree, ofout);
+
+    interrupts = 0;
+    rc = of_getprop(ofout, "interrupts", &interrupts, sizeof(interrupts));
     if (rc == OF_FAILURE) {
-        of_panic("%s: no location for serial port\n", __func__);
-    }
-    ns16550.io_base = val[1];
-
-    ns16550.baud = BAUD_AUTO;
-    ns16550.data_bits = 8;
-    ns16550.parity = 'n';
-    ns16550.stop_bits = 1;
-
-    rc = of_getprop(n, "interrupts", val, sizeof (val));
+        of_printf("%s: no ISRC\n", __func__);
+        global_serial_port.interrupts = 0;
+    } else {
+        of_printf("%s: ISRC 0x%x\n", __func__, interrupts);
+        global_serial_port.interrupts = interrupts;
+    }
+
+    baud = 0;
+    rc = of_getprop(ofout, "current-speed", &baud, sizeof(baud));
     if (rc == OF_FAILURE) {
-        of_printf("%s: no ISRC, forcing poll mode\n", __func__);
-        ns16550.irq = 0;
+        global_serial_port.baud = 0;
     } else {
-        ns16550.irq = val[0];
-        of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
-                  __func__, ns16550.irq);
-        ns16550.irq = 0;
-    }
-
-    return 1;
+        global_serial_port.baud = baud;
+    }
+
+    /*
+     * Look at the name of the grandparent directory and try to match it
+     * to known names.
+     */
+    int parent, grandparent;        /* of handles */
+    parent = of_getparent(ofout);
+    _IF_OF_FAILURE_RET(parent);
+    grandparent = of_getparent(parent);
+    _IF_OF_FAILURE_RET(grandparent);
+
+    of_getprop(grandparent, "name", of_property, sizeof(of_property));
+    /* 
+     * Loop over the known uarts and try and find a match
+     */
+    int i;
+    for (i = 0; i < ARRAY_SIZE(uarts); i++) {
+        if (!strcmp(of_property, uarts[i].gp_sign)) {
+            of_getprop(parent, "device_type", of_property,
+                            sizeof(of_property));
+            if (strncmp(of_property, uarts[i].p_sign,
+                                    sizeof(uarts[i].p_sign))) {
+                of_printf("Serial device parent's type (%s) is not "
+                          "expected(%s).\n", of_property, uarts[i].p_sign);
+                return OF_FAILURE;
+            }
+
+            of_printf("Found uart of type %s\n", uarts[i].uart_name);
+            global_serial_port.uart_p = &(uarts[i]);
+
+            if (pmac_zilog == uarts[i].type)
+                    boot_of_serial_zilog(ofout, parent, grandparent);
+            else
+                    boot_of_serial_ns16550(ofout, parent, grandparent);
+
+            of_printf("%s: serial type=%d  io base=0x%016lx "
+                      "isa io@=0x%016lx  clock=%d  interrupts=0x%x "
+                      "baud=%d\n",
+                      __func__, global_serial_port.uart_p->type,
+                      global_serial_port.uart_io_base,
+                      isa_io_base,
+                      global_serial_port.clock,
+                      global_serial_port.interrupts,
+                      global_serial_port.baud
+                     );
+
+            return 0;
+        }
+    }
+    of_printf("Warning: boot_of::%s is not aware of this uart type.  "
+              "%s is:\n", __func__, of_property);
+    return OF_FAILURE;
 }
 
 static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
diff -r 2039069d08ca xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c      Wed May 24 17:09:51 2006 -0500
+++ b/xen/arch/ppc/setup.c      Thu May 25 12:21:06 2006 -0400
@@ -37,6 +37,7 @@
 #include <asm/cache.h>
 #include <asm/debugger.h>
 #include <asm/delay.h>
+#include <asm-ppc/uart.h>
 #include "exceptions.h"
 
 #define DEBUG
@@ -61,15 +62,14 @@ cpumask_t cpu_sibling_map[NR_CPUS] __rea
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
 
-/* XXX get this from ISA node in device tree */
-ulong isa_io_base;
-struct ns16550_defaults ns16550;
-
 struct vcpu *idle_vcpu[NR_CPUS];
 extern void idle_loop(void);
 
 /* move us to a header file */
 extern void initialize_keytable(void);
+
+extern struct platform_serial_port global_serial_port;
+ulong isa_io_base;
 
 int is_kernel_text(unsigned long addr)
 {
@@ -164,7 +164,22 @@ static void __init __start_xen(multiboot
     if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
         cmdline_parse(__va((ulong)mbi->cmdline));
 
-    ns16550_init(0, &ns16550);
+    /* We initialise the serial devices very early so we can get debugging. */
+    {
+    /*
+     * the type of device is recorded in the global hardware stuff struct
+     */
+    struct ns16550_defaults ns16550 = {
+        .data_bits = 8,
+        .parity    = 'n',
+        .stop_bits = 1,
+        .irq       = 0,
+    };
+    ns16550.io_base = isa_io_base +
+                      global_serial_port.uart_io_base;
+    ns16550.baud = global_serial_port.baud;
+    global_serial_port.uart_p->uart_init_func(0, &ns16550);
+    }
     serial_init_preirq();
 
     init_console();
diff -r 2039069d08ca xen/drivers/char/Makefile
--- a/xen/drivers/char/Makefile Wed May 24 17:09:51 2006 -0500
+++ b/xen/drivers/char/Makefile Thu May 25 12:21:06 2006 -0400
@@ -1,5 +1,6 @@ obj-y += console.o
 obj-y += console.o
 obj-y += ns16550.o
+obj-y += pmac_zilog.o
 obj-y += serial.o
 
 # Object file contains changeset and compiler information.
diff -r 2039069d08ca xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Wed May 24 17:09:51 2006 -0500
+++ b/xen/drivers/char/ns16550.c        Thu May 25 12:21:06 2006 -0400
@@ -276,7 +276,7 @@ static struct uart_driver ns16550_driver
     .irq          = ns16550_irq
 };
 
-static int parse_parity_char(int c)
+int parse_parity_char(int c)
 {
     switch ( c )
     {
diff -r 2039069d08ca xen/include/xen/serial.h
--- a/xen/include/xen/serial.h  Wed May 24 17:09:51 2006 -0500
+++ b/xen/include/xen/serial.h  Thu May 25 12:21:06 2006 -0400
@@ -8,6 +8,8 @@
 
 #ifndef __XEN_SERIAL_H__
 #define __XEN_SERIAL_H__
+
+#include <xen/spinlock.h>
 
 struct cpu_user_regs;
 
@@ -128,6 +130,7 @@ struct ns16550_defaults {
     unsigned long io_base; /* default io_base address */
 };
 void ns16550_init(int index, struct ns16550_defaults *defaults);
+void pmac_zilog_init(int index, struct ns16550_defaults *defaults);
 
 /* Baud rate was pre-configured before invoking the UART driver. */
 #define BAUD_AUTO (-1)
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.c
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/drivers/char/pmac_zilog.c     Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * $Id: zilog.c,v 1.3 2005/05/05 20:51:04 mostrows Exp $
+ */
+
+/*
+ * linux/drivers/serial/pmac_zilog.c
+ * 
+ * Driver for PowerMac Z85c30 based ESCC cell found in the
+ * "macio" ASICs of various PowerMac models
+ * 
+ * Copyright (C) 2003 Ben. Herrenschmidt (benh@xxxxxxxxxxxxxxxxxxx)
+ *
+ * Derived from drivers/macintosh/macserial.c by Paul Mackerras
+ * and drivers/serial/sunzilog.c by David S. Miller
+ *
+ * Hrm... actually, I ripped most of sunzilog (Thanks David !) and
+ * adapted special tweaks needed for us. I don't think it's worth
+ * merging back those though. The DMA code still has to get in
+ * and once done, I expect that driver to remain fairly stable in
+ * the long term, unless we change the driver model again...
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * 2004-08-06 Harald Welte <laforge@xxxxxxxxxxxx>
+ *     - Enable BREAK interrupt
+ *     - Add support for sysreq
+ *
+ * TODO:   - Add DMA support
+ *         - Defer port shutdown to a few seconds after close
+ *         - maybe put something right into uap->clk_divisor
+ */
+
+/******************************************************************************
+ * pmac_zilog.c
+ * 
+ * From rhype and linux
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/serial.h>
+#include <xen/iocap.h>
+#include <asm/io.h>
+#include <xen/delay.h>
+#include "pmac_zilog.h"
+
+#undef ZILOG_DEBUG
+#ifdef ZILOG_DEBUG
+int of_printf(const char *fmt, ...);
+#define DBG(args...) of_printf(args)
+#else
+#define DBG(args...)
+#endif
+
+
+/* from rhype and linux */
+
+struct uart_pmac_port uaps[MAX_ZS_PORTS];
+
+extern int parse_parity_char(int c);
+
+#define PANIC(_f)                        \
+    {                                    \
+    printk( "ERROR: " _f "\n");       \
+    }
+
+/* internal */
+static char pmac_zilog_read_reg(struct uart_port *uart, int reg, int verbose)
+{
+    if (verbose)
+        DBG("%s: readb 0x%x\n", __func__, uart->remapped_io_base + reg);
+    return readb(uart->remapped_io_base + reg);
+}
+
+/* internal */
+static void pmac_zilog_write_reg(struct uart_port *uart, int reg, char c, int 
verbose)
+{
+    if (verbose)
+        DBG("%s: writeb 0x%x  0x%02x\n", __func__, uart->remapped_io_base + 
reg, c);
+    writeb(c, uart->remapped_io_base + reg);
+}
+
+/* internal */
+/* Note this is equivalent to linux read_zsreg followed by the bit AND */
+static int pmac_zilog_chkbit(struct uart_port *ops, int reg, int bit)
+{
+    char c;
+
+    // to read any register (but 0), first write the register number to the
+    // control register, then read the control register
+    // 
+    if (reg != 0) { pmac_zilog_write_reg(ops, REG_CONTROL, reg, 0); }
+    c = pmac_zilog_read_reg(ops, REG_CONTROL, 0);
+    return (c & bit) == bit;
+}
+
+/* internal from linux */
+/* 
+ * Load all registers to reprogram the port
+ * This function must only be called when the TX is not busy.  The UART
+ * port lock must be held and local interrupts disabled.
+ */
+static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs)
+{
+       int i;
+
+       if (ZS_IS_ASLEEP(uap))
+               return;
+
+       /* Let pending transmits finish.  */
+       for (i = 0; i < 1000; i++) {
+               unsigned char stat = read_zsreg(uap, R1);
+               if (stat & ALL_SNT)
+                       break;
+               udelay(100);
+       }
+
+       ZS_CLEARERR(uap);
+       zssync(uap);
+       ZS_CLEARFIFO(uap);
+       zssync(uap);
+       ZS_CLEARERR(uap);
+
+       /* Disable all interrupts.  */
+       write_zsreg(uap, R1,
+                   regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
+
+       /* Set parity, sync config, stop bits, and clock divisor.  */
+       write_zsreg(uap, R4, regs[R4]);
+
+       /* Set misc. TX/RX control bits.  */
+       write_zsreg(uap, R10, regs[R10]);
+
+       /* Set TX/RX controls sans the enable bits.  */
+               write_zsreg(uap, R3, regs[R3] & ~RxENABLE);
+               write_zsreg(uap, R5, regs[R5] & ~TxENABLE);
+
+       /* now set R7 "prime" on ESCC */
+       write_zsreg(uap, R15, regs[R15] | EN85C30);
+       write_zsreg(uap, R7, regs[R7P]);
+
+       /* make sure we use R7 "non-prime" on ESCC */
+       write_zsreg(uap, R15, regs[R15] & ~EN85C30);
+
+       /* Synchronous mode config.  */
+       write_zsreg(uap, R6, regs[R6]);
+       write_zsreg(uap, R7, regs[R7]);
+
+       /* Disable baud generator.  */
+       write_zsreg(uap, R14, regs[R14] & ~BRENAB);
+
+       /* Clock mode control.  */
+       write_zsreg(uap, R11, regs[R11]);
+
+       /* Lower and upper byte of baud rate generator divisor.  */
+       write_zsreg(uap, R12, regs[R12]);
+       write_zsreg(uap, R13, regs[R13]);
+       
+       /* Now rewrite R14, with BRENAB (if set).  */
+       write_zsreg(uap, R14, regs[R14]);
+
+       /* Reset external status interrupts.  */
+       write_zsreg(uap, R0, RES_EXT_INT);
+       write_zsreg(uap, R0, RES_EXT_INT);
+
+       /* Rewrite R3/R5, this time without enables masked.  */
+       write_zsreg(uap, R3, regs[R3]);
+       write_zsreg(uap, R5, regs[R5]);
+
+       /* Rewrite R1, this time without IRQ enabled masked.  */
+       write_zsreg(uap, R1, regs[R1]);
+
+       /* Enable interrupts */
+       write_zsreg(uap, R9, regs[R9]);
+}
+
+static void pmac_zilog_init_preirq(struct serial_port *port)
+{
+    struct uart_pmac_port *uap = port->uart;
+    struct uart_port *uart = &(uap->port);
+    unsigned int divisor;
+
+    uart->remapped_io_base = (char *)ioremap(uart->io_base, 8);
+
+    /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
+    /* parity, data bit (8 or bust) and stop bits todo */
+    
+#define LINUX_PMAC_ZILOG_INIT
+#ifdef LINUX_PMAC_ZILOG_INIT
+    /* from Linux's __pmz_startup().  Modified */
+    {
+        uap->flags = PMACZILOG_FLAG_IS_CHANNEL_A
+                | PMACZILOG_FLAG_IS_IRDA 
+                ;
+                     
+       memset(&uap->curregs, 0, sizeof(uap->curregs));
+
+       /* Power up the SCC & underlying hardware (modem/irda) */
+       //(void) pmz_set_scc_power(uap, 1);  TODO?
+
+       /* Nice buggy HW ... */
+       //pmz_fix_zero_bug_scc(uap);  TODO
+
+       /* Reset the channel */
+       uap->curregs[R9] = 0;
+       write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB);
+       zssync(uap);
+       udelay(10);
+       write_zsreg(uap, 9, 0);
+       zssync(uap);
+
+       /* Clear the interrupt registers */
+       write_zsreg(uap, R1, 0);
+       write_zsreg(uap, R0, ERR_RES);
+       write_zsreg(uap, R0, ERR_RES);
+       write_zsreg(uap, R0, RES_H_IUS);
+       write_zsreg(uap, R0, RES_H_IUS);
+
+       /* Setup some valid baud rate */
+       uap->curregs[R4] = X16CLK | SB1;
+       uap->curregs[R3] = Rx8;
+       uap->curregs[R5] = Tx8 | RTS;
+       if (!ZS_IS_IRDA(uap))
+               uap->curregs[R5] |= DTR;
+
+        /* baud divisor */
+#define UART_CLOCK_HZ 0
+        if ( uart->baud == BAUD_AUTO ) {
+           divisor = read_zsreg(uap, R12);
+            divisor |= read_zsreg(uap, R13) << 8;
+            uart->baud = UART_CLOCK_HZ / (divisor * 16);
+        } else {
+            /* Baud rate specified: program it into the divisor latch. */
+            divisor = UART_CLOCK_HZ / (uart->baud * 16);
+           uap->curregs[R12] = (char)divisor;  /* baud divisor lower byte */
+           uap->curregs[R13] = (char)(divisor >> 8);  /* upper byte */
+        }
+        
+       uap->curregs[R14] = BRENAB;
+
+       /* Clear handshaking, enable BREAK interrupts */
+       /* uap->curregs[R15] = BRKIE;  we don't want interrupts */
+
+       /* Master interrupt enable */
+       /* uap->curregs[R9] |= NV | MIE;  we don't want interrupts */
+
+       pmz_load_zsregs(uap, uap->curregs);
+
+       /* Enable receiver and transmitter.  */
+       write_zsreg(uap, R3, uap->curregs[R3] |= RxENABLE);
+       write_zsreg(uap, R5, uap->curregs[R5] |= TxENABLE);
+
+       /* Remember status for DCD/CTS changes */
+       uap->prev_status = read_zsreg(uap, R0);
+
+    }
+#endif  /* #ifdef LINUX_PMAC_ZILOG_INIT */
+
+    /* Enable and clear the FIFOs. Set a large trigger threshold. */
+    port->tx_fifo_size = 2048;
+}
+
+static void pmac_zilog_init_postirq(struct serial_port *port)
+{
+        PANIC("postirq!");
+}
+
+/* internal */
+static int pmac_zilog_write_avail(struct uart_port *ops)
+{
+    if (pmac_zilog_chkbit(ops, 0, Tx_BUF_EMP) &&
+        pmac_zilog_chkbit(ops, 1, ALL_SNT)) {
+        return 2048;
+    }
+    return 0;
+}
+
+/* Transmit FIFO ready to receive up to @tx_fifo_size characters? */
+static int pmac_zilog_tx_empty(struct serial_port *port)
+{
+    struct uart_pmac_port *uap = port->uart;
+    struct uart_port *uart = &(uap->port);
+    
+    static int call_count = 0;  // debug
+    call_count++;
+    if ((call_count < 1) ) {
+            DBG("%s: count=%d\n", __func__, call_count);
+    }
+    
+    return pmac_zilog_write_avail(uart);
+}
+
+static void pmac_zilog_putc(struct serial_port *port, char c)
+{
+    struct uart_pmac_port *uap = port->uart;
+    struct uart_port *uart = &(uap->port);
+    
+    static int call_count = 0;  // debug
+    call_count++;
+    if ((call_count < 1 )) {
+            DBG("%s: count=%d\n", __func__, call_count);
+    }
+
+    pmac_zilog_write_reg(uart, REG_DATA, c, 0);
+}
+
+/* internal */
+static int pmac_zilog_read_avail(struct uart_port *ops)
+{
+    char c = pmac_zilog_read_reg(ops, REG_CONTROL, 0);
+    if (c & Rx_CH_AV) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/* Get a character from the serial line: returns 0 if none available. */
+static int pmac_zilog_getc(struct serial_port *port, char *pc)
+{
+    struct uart_pmac_port *uap = port->uart;
+    struct uart_port *uart = &(uap->port);
+    int rc;
+    
+    static int call_count = 0;  // debug
+    call_count++;
+    if ((call_count < 1)) {
+            DBG("%s: count=%d\n", __func__, call_count);
+    }
+
+    if (pmac_zilog_read_avail(uart)) {
+        *pc = pmac_zilog_read_reg(uart, REG_DATA, 0);
+        rc = 1;
+    } else {
+        rc = 0;
+    }
+
+    return rc;
+}
+
+#define PARSE_ERR(_f, _a...)                 \
+    do {                                     \
+        printk( "ERROR: " _f "\n" , ## _a ); \
+        return;                              \
+    } while ( 0 )
+                                                                               
 
+static struct uart_driver pmac_zilog_driver = {
+    .init_preirq  = pmac_zilog_init_preirq,
+    .init_postirq = pmac_zilog_init_postirq,
+    .endboot      = NULL,
+    .tx_empty     = pmac_zilog_tx_empty,
+    .putc         = pmac_zilog_putc,
+    .getc         = pmac_zilog_getc
+};
+
+/* internal */
+static void pmac_zilog_parse_port_config(struct uart_port *uart, char *conf)
+{
+    /* Sanity checks. */
+    if ( (uart->baud != BAUD_AUTO) &&
+         ((uart->baud < 1200) || (uart->baud > 115200)) )
+        PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
+    if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
+        PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
+    if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
+        PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
+    if ( uart->io_base == 0 )
+        PARSE_ERR("I/O base address must be specified.");
+}
+
+void pmac_zilog_init(int index, struct ns16550_defaults *defaults)
+{
+    if ( (index < 0) || (index >= MAX_ZS_PORTS) ) 
+            return;
+    
+    memset(&uaps[index], 0, sizeof(struct uart_pmac_port));
+    
+    if ( defaults != NULL )
+    {
+        uaps[index].port.baud      = defaults->baud;
+        uaps[index].port.data_bits = defaults->data_bits;
+        uaps[index].port.parity    = parse_parity_char(defaults->parity);
+        uaps[index].port.stop_bits = defaults->stop_bits;
+        uaps[index].port.irq       = defaults->irq;
+        uaps[index].port.io_base   = defaults->io_base;
+    }
+
+    pmac_zilog_parse_port_config(&(uaps[index].port), NULL);
+
+    /* Register with generic serial driver. */
+    serial_register_uart(index, &pmac_zilog_driver, &uaps[index]);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.h
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/drivers/char/pmac_zilog.h     Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,405 @@
+#ifndef __PMAC_ZILOG_H__
+#define __PMAC_ZILOG_H__
+/****
+ * Linux code drivers/serial/pmac_zilog.h
+ * missing copyright notice in Linux tree
+ */
+
+/* Xen additions */
+/* copy of ns16550 in ns16550.c */
+struct uart_port {
+    int baud, data_bits, parity, stop_bits, irq;
+    unsigned long io_base;   /* I/O port or memory-mapped I/O address. */
+    char *remapped_io_base;  /* Remapped virtual address of mmap I/O.  */
+    /* UART with IRQ line: interrupt-driven I/O. */
+    struct irqaction irqaction;
+    /* UART with no IRQ line: periodically-polled I/O. */
+    struct timer timer;
+};
+struct termios {
+};
+/* end Xen additions */
+
+#define pmz_debug(fmt,arg...)  dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
+
+/*
+ * At most 2 ESCCs with 2 ports each
+ */
+#define MAX_ZS_PORTS   4
+
+/* 
+ * We wrap our port structure around the generic uart_port.
+ */
+#define NUM_ZSREGS    17
+
+struct uart_pmac_port {
+       struct uart_port                port;
+       struct uart_pmac_port           *mate;
+
+       /* macio_dev for the escc holding this port (maybe be null on
+        * early inited port)
+        */
+       struct macio_dev                *dev;
+       /* device node to this port, this points to one of 2 childs
+        * of "escc" node (ie. ch-a or ch-b)
+        */
+       struct device_node              *node;
+
+       /* Port type as obtained from device tree (IRDA, modem, ...) */
+       int                             port_type;
+       u8                              curregs[NUM_ZSREGS];
+
+       unsigned int                    flags;
+#define PMACZILOG_FLAG_IS_CONS         0x00000001
+#define PMACZILOG_FLAG_IS_KGDB         0x00000002
+#define PMACZILOG_FLAG_MODEM_STATUS    0x00000004
+#define PMACZILOG_FLAG_IS_CHANNEL_A    0x00000008
+#define PMACZILOG_FLAG_REGS_HELD       0x00000010
+#define PMACZILOG_FLAG_TX_STOPPED      0x00000020
+#define PMACZILOG_FLAG_TX_ACTIVE       0x00000040
+#define PMACZILOG_FLAG_ENABLED          0x00000080
+#define PMACZILOG_FLAG_IS_IRDA         0x00000100
+#define PMACZILOG_FLAG_IS_INTMODEM     0x00000200
+#define PMACZILOG_FLAG_HAS_DMA         0x00000400
+#define PMACZILOG_FLAG_RSRC_REQUESTED  0x00000800
+#define PMACZILOG_FLAG_IS_ASLEEP       0x00001000
+#define PMACZILOG_FLAG_IS_OPEN         0x00002000
+#define PMACZILOG_FLAG_IS_IRQ_ON       0x00004000
+#define PMACZILOG_FLAG_IS_EXTCLK       0x00008000
+#define PMACZILOG_FLAG_BREAK           0x00010000
+
+       unsigned char                   parity_mask;
+       unsigned char                   prev_status;
+
+       volatile u8                     __iomem *control_reg;
+       volatile u8                     __iomem *data_reg;
+
+       unsigned int                    tx_dma_irq;
+       unsigned int                    rx_dma_irq;
+       volatile struct dbdma_regs      __iomem *tx_dma_regs;
+       volatile struct dbdma_regs      __iomem *rx_dma_regs;
+
+       struct termios                  termios_cache;
+};
+
+#define to_pmz(p) ((struct uart_pmac_port *)(p))
+
+static inline struct uart_pmac_port *pmz_get_port_A(struct uart_pmac_port *uap)
+{
+       if (uap->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
+               return uap;
+       return uap->mate;
+}
+
+/*
+ * Register acessors. Note that we don't need to enforce a recovery
+ * delay on PCI PowerMac hardware, it's dealt in HW by the MacIO chip,
+ * though if we try to use this driver on older machines, we might have
+ * to add it back
+ */
+static inline u8 read_zsreg(struct uart_pmac_port *port, u8 reg)
+{
+       if (reg != 0)
+               writeb(reg, port->control_reg);
+       return readb(port->control_reg);
+}
+
+static inline void write_zsreg(struct uart_pmac_port *port, u8 reg, u8 value)
+{
+       if (reg != 0)
+               writeb(reg, port->control_reg);
+       writeb(value, port->control_reg);
+}
+
+static inline u8 read_zsdata(struct uart_pmac_port *port)
+{
+       return readb(port->data_reg);
+}
+
+static inline void write_zsdata(struct uart_pmac_port *port, u8 data)
+{
+       writeb(data, port->data_reg);
+}
+
+static inline void zssync(struct uart_pmac_port *port)
+{
+       (void)readb(port->control_reg);
+}
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+#define ZS_CLOCK         3686400       /* Z8530 RTxC input clock rate */
+
+/* The Zilog register set */
+
+#define        FLAG    0x7e
+
+/* Write Register 0 */
+#define        R0      0               /* Register selects */
+#define        R1      1
+#define        R2      2
+#define        R3      3
+#define        R4      4
+#define        R5      5
+#define        R6      6
+#define        R7      7
+#define        R8      8
+#define        R9      9
+#define        R10     10
+#define        R11     11
+#define        R12     12
+#define        R13     13
+#define        R14     14
+#define        R15     15
+#define        R7P     16
+
+#define        NULLCODE        0       /* Null Code */
+#define        POINT_HIGH      0x8     /* Select upper half of registers */
+#define        RES_EXT_INT     0x10    /* Reset Ext. Status Interrupts */
+#define        SEND_ABORT      0x18    /* HDLC Abort */
+#define        RES_RxINT_FC    0x20    /* Reset RxINT on First Character */
+#define        RES_Tx_P        0x28    /* Reset TxINT Pending */
+#define        ERR_RES         0x30    /* Error Reset */
+#define        RES_H_IUS       0x38    /* Reset highest IUS */
+
+#define        RES_Rx_CRC      0x40    /* Reset Rx CRC Checker */
+#define        RES_Tx_CRC      0x80    /* Reset Tx CRC Checker */
+#define        RES_EOM_L       0xC0    /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define        EXT_INT_ENAB    0x1     /* Ext Int Enable */
+#define        TxINT_ENAB      0x2     /* Tx Int Enable */
+#define        PAR_SPEC        0x4     /* Parity is special condition */
+
+#define        RxINT_DISAB     0       /* Rx Int Disable */
+#define        RxINT_FCERR     0x8     /* Rx Int on First Character Only or 
Error */
+#define        INT_ALL_Rx      0x10    /* Int on all Rx Characters or error */
+#define        INT_ERR_Rx      0x18    /* Int on error only */
+#define RxINT_MASK     0x18
+
+#define        WT_RDY_RT       0x20    /* W/Req reflects recv if 1, xmit if 0 
*/
+#define        WT_FN_RDYFN     0x40    /* W/Req pin is DMA request if 1, wait 
if 0 */
+#define        WT_RDY_ENAB     0x80    /* Enable W/Req pin */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define        RxENABLE        0x1     /* Rx Enable */
+#define        SYNC_L_INH      0x2     /* Sync Character Load Inhibit */
+#define        ADD_SM          0x4     /* Address Search Mode (SDLC) */
+#define        RxCRC_ENAB      0x8     /* Rx CRC Enable */
+#define        ENT_HM          0x10    /* Enter Hunt Mode */
+#define        AUTO_ENAB       0x20    /* Auto Enables */
+#define        Rx5             0x0     /* Rx 5 Bits/Character */
+#define        Rx7             0x40    /* Rx 7 Bits/Character */
+#define        Rx6             0x80    /* Rx 6 Bits/Character */
+#define        Rx8             0xc0    /* Rx 8 Bits/Character */
+#define RxN_MASK       0xc0
+
+/* Write Register 4 */
+
+#define        PAR_ENAB        0x1     /* Parity Enable */
+#define        PAR_EVEN        0x2     /* Parity Even/Odd* */
+
+#define        SYNC_ENAB       0       /* Sync Modes Enable */
+#define        SB1             0x4     /* 1 stop bit/char */
+#define        SB15            0x8     /* 1.5 stop bits/char */
+#define        SB2             0xc     /* 2 stop bits/char */
+#define SB_MASK                0xc
+
+#define        MONSYNC         0       /* 8 Bit Sync character */
+#define        BISYNC          0x10    /* 16 bit sync character */
+#define        SDLC            0x20    /* SDLC Mode (01111110 Sync Flag) */
+#define        EXTSYNC         0x30    /* External Sync Mode */
+
+#define        X1CLK           0x0     /* x1 clock mode */
+#define        X16CLK          0x40    /* x16 clock mode */
+#define        X32CLK          0x80    /* x32 clock mode */
+#define        X64CLK          0xC0    /* x64 clock mode */
+#define XCLK_MASK      0xC0
+
+/* Write Register 5 */
+
+#define        TxCRC_ENAB      0x1     /* Tx CRC Enable */
+#define        RTS             0x2     /* RTS */
+#define        SDLC_CRC        0x4     /* SDLC/CRC-16 */
+#define        TxENABLE        0x8     /* Tx Enable */
+#define        SND_BRK         0x10    /* Send Break */
+#define        Tx5             0x0     /* Tx 5 bits (or less)/character */
+#define        Tx7             0x20    /* Tx 7 bits/character */
+#define        Tx6             0x40    /* Tx 6 bits/character */
+#define        Tx8             0x60    /* Tx 8 bits/character */
+#define TxN_MASK       0x60
+#define        DTR             0x80    /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 7' (Some enhanced feature control) */
+#define        ENEXREAD        0x40    /* Enable read of some write registers 
*/
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define        VIS     1       /* Vector Includes Status */
+#define        NV      2       /* No Vector */
+#define        DLC     4       /* Disable Lower Chain */
+#define        MIE     8       /* Master Interrupt Enable */
+#define        STATHI  0x10    /* Status high */
+#define        NORESET 0       /* No reset on write to R9 */
+#define        CHRB    0x40    /* Reset channel B */
+#define        CHRA    0x80    /* Reset channel A */
+#define        FHWRES  0xc0    /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define        BIT6    1       /* 6 bit/8bit sync */
+#define        LOOPMODE 2      /* SDLC Loop mode */
+#define        ABUNDER 4       /* Abort/flag on SDLC xmit underrun */
+#define        MARKIDLE 8      /* Mark/flag on idle */
+#define        GAOP    0x10    /* Go active on poll */
+#define        NRZ     0       /* NRZ mode */
+#define        NRZI    0x20    /* NRZI mode */
+#define        FM1     0x40    /* FM1 (transition = 1) */
+#define        FM0     0x60    /* FM0 (transition = 0) */
+#define        CRCPS   0x80    /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define        TRxCXT  0       /* TRxC = Xtal output */
+#define        TRxCTC  1       /* TRxC = Transmit clock */
+#define        TRxCBR  2       /* TRxC = BR Generator Output */
+#define        TRxCDP  3       /* TRxC = DPLL output */
+#define        TRxCOI  4       /* TRxC O/I */
+#define        TCRTxCP 0       /* Transmit clock = RTxC pin */
+#define        TCTRxCP 8       /* Transmit clock = TRxC pin */
+#define        TCBR    0x10    /* Transmit clock = BR Generator output */
+#define        TCDPLL  0x18    /* Transmit clock = DPLL output */
+#define        RCRTxCP 0       /* Receive clock = RTxC pin */
+#define        RCTRxCP 0x20    /* Receive clock = TRxC pin */
+#define        RCBR    0x40    /* Receive clock = BR Generator output */
+#define        RCDPLL  0x60    /* Receive clock = DPLL output */
+#define        RTxCX   0x80    /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define        BRENAB  1       /* Baud rate generator enable */
+#define        BRSRC   2       /* Baud rate generator source */
+#define        DTRREQ  4       /* DTR/Request function */
+#define        AUTOECHO 8      /* Auto Echo */
+#define        LOOPBAK 0x10    /* Local loopback */
+#define        SEARCH  0x20    /* Enter search mode */
+#define        RMC     0x40    /* Reset missing clock */
+#define        DISDPLL 0x60    /* Disable DPLL */
+#define        SSBR    0x80    /* Set DPLL source = BR generator */
+#define        SSRTxC  0xa0    /* Set DPLL source = RTxC */
+#define        SFMM    0xc0    /* Set FM mode */
+#define        SNRZI   0xe0    /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define        EN85C30 1       /* Enable some 85c30-enhanced registers */
+#define        ZCIE    2       /* Zero count IE */
+#define        ENSTFIFO 4      /* Enable status FIFO (SDLC) */
+#define        DCDIE   8       /* DCD IE */
+#define        SYNCIE  0x10    /* Sync/hunt IE */
+#define        CTSIE   0x20    /* CTS IE */
+#define        TxUIE   0x40    /* Tx Underrun/EOM IE */
+#define        BRKIE   0x80    /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define        Rx_CH_AV        0x1     /* Rx Character Available */
+#define        ZCOUNT          0x2     /* Zero count */
+#define        Tx_BUF_EMP      0x4     /* Tx Buffer empty */
+#define        DCD             0x8     /* DCD */
+#define        SYNC_HUNT       0x10    /* Sync/hunt */
+#define        CTS             0x20    /* CTS */
+#define        TxEOM           0x40    /* Tx underrun */
+#define        BRK_ABRT        0x80    /* Break/Abort */
+
+/* Read Register 1 */
+#define        ALL_SNT         0x1     /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define        RES3            0x8     /* 0/3 */
+#define        RES4            0x4     /* 0/4 */
+#define        RES5            0xc     /* 0/5 */
+#define        RES6            0x2     /* 0/6 */
+#define        RES7            0xa     /* 0/7 */
+#define        RES8            0x6     /* 0/8 */
+#define        RES18           0xe     /* 1/8 */
+#define        RES28           0x0     /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define        PAR_ERR         0x10    /* Parity error */
+#define        Rx_OVR          0x20    /* Rx Overrun Error */
+#define        CRC_ERR         0x40    /* CRC/Framing Error */
+#define        END_FR          0x80    /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+#define        CHB_Tx_EMPTY    0x00
+#define        CHB_EXT_STAT    0x02
+#define        CHB_Rx_AVAIL    0x04
+#define        CHB_SPECIAL     0x06
+#define        CHA_Tx_EMPTY    0x08
+#define        CHA_EXT_STAT    0x0a
+#define        CHA_Rx_AVAIL    0x0c
+#define        CHA_SPECIAL     0x0e
+#define        STATUS_MASK     0x06
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define        CHBEXT  0x1             /* Channel B Ext/Stat IP */
+#define        CHBTxIP 0x2             /* Channel B Tx IP */
+#define        CHBRxIP 0x4             /* Channel B Rx IP */
+#define        CHAEXT  0x8             /* Channel A Ext/Stat IP */
+#define        CHATxIP 0x10            /* Channel A Tx IP */
+#define        CHARxIP 0x20            /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10  (misc status bits) */
+#define        ONLOOP  2               /* On loop */
+#define        LOOPSEND 0x10           /* Loop sending */
+#define        CLK2MIS 0x40            /* Two clocks missing */
+#define        CLK1MIS 0x80            /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc macros */
+#define ZS_CLEARERR(port)    (write_zsreg(port, 0, ERR_RES))
+#define ZS_CLEARFIFO(port)   do { volatile unsigned char garbage; \
+                                    garbage = read_zsdata(port); \
+                                    garbage = read_zsdata(port); \
+                                    garbage = read_zsdata(port); \
+                               } while(0)
+
+#define ZS_IS_CONS(UP)                 ((UP)->flags & PMACZILOG_FLAG_IS_CONS)
+#define ZS_IS_KGDB(UP)                 ((UP)->flags & PMACZILOG_FLAG_IS_KGDB)
+#define ZS_IS_CHANNEL_A(UP)            ((UP)->flags & 
PMACZILOG_FLAG_IS_CHANNEL_A)
+#define ZS_REGS_HELD(UP)               ((UP)->flags & PMACZILOG_FLAG_REGS_HELD)
+#define ZS_TX_STOPPED(UP)              ((UP)->flags & 
PMACZILOG_FLAG_TX_STOPPED)
+#define ZS_TX_ACTIVE(UP)               ((UP)->flags & PMACZILOG_FLAG_TX_ACTIVE)
+#define ZS_WANTS_MODEM_STATUS(UP)      ((UP)->flags & 
PMACZILOG_FLAG_MODEM_STATUS)
+#define ZS_IS_IRDA(UP)                 ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
+#define ZS_IS_INTMODEM(UP)             ((UP)->flags & 
PMACZILOG_FLAG_IS_INTMODEM)
+#define ZS_HAS_DMA(UP)                 ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
+#define ZS_IS_ASLEEP(UP)                       ((UP)->flags & 
PMACZILOG_FLAG_IS_ASLEEP)
+#define ZS_IS_OPEN(UP)                 ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
+#define ZS_IS_IRQ_ON(UP)                       ((UP)->flags & 
PMACZILOG_FLAG_IS_IRQ_ON)
+#define ZS_IS_EXTCLK(UP)                       ((UP)->flags & 
PMACZILOG_FLAG_IS_EXTCLK)
+
+/* Xen additions */
+#define REG_CONTROL     R0
+#define REG_DATA        0x10
+/* end Xen additions */
+#endif /* __PMAC_ZILOG_H__ */
diff -r 2039069d08ca xen/drivers/char/pmac_zilog.o
Binary file xen/drivers/char/pmac_zilog.o has changed
diff -r 2039069d08ca xen/include/asm-ppc/uart.h
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/include/asm-ppc/uart.h        Thu May 25 12:21:06 2006 -0400
@@ -0,0 +1,22 @@
+#ifndef _UART_H
+#define _UART_H
+#include <xen/serial.h>
+
+enum uart_type { ns16550 = 1, pmac_zilog = 2 };
+
+struct uart {
+    enum uart_type type;
+    char *uart_name;
+    char *p_sign;       // parernt directory signature
+    char *gp_sign;      // grandparent directory signature
+    void (* uart_init_func) (int i, struct ns16550_defaults * init_struct);
+};
+
+struct platform_serial_port {
+    unsigned long uart_io_base;
+    struct uart *uart_p;
+    u32 interrupts;
+    u32 clock;
+    u32 baud;
+};
+#endif  /* #ifndef _UART_H */

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [XenPPC] [PATCH] serial port discovery and zilog device driver, Maria Butrico <=