Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>
summary: RFC: serial device detection, nohv mode detection, early zilog
device driver
The device driver was patched from rhype, linux and the ns
device code. This patch cannot be applied to tip. Code
execution stops, on a g5, in the vicinity of mpic.
diff -r 56e1802303e5 xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/boot_of.c Thu May 4 13:19:28 2006 -0400
@@ -24,6 +24,11 @@
#include <xen/compile.h>
#include <public/of-devtree.h>
#include <asm/page.h>
+#include <xen/string.h>
+#include <xen/serial.h>
+#include "platform.h"
+
+struct global_hardware_stuff global_hs;
static ulong of_vec;
static ulong of_msr;
@@ -32,8 +37,6 @@ static char bootargs[256];
static char bootargs[256];
static char dom0args[256];
-extern unsigned int timebase_freq;
-
#undef OF_DEBUG
#ifdef OF_DEBUG
@@ -44,6 +47,11 @@ extern unsigned int timebase_freq;
#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;
@@ -104,9 +112,9 @@ static int __init of_write(int ih, const
return rets[0];
}
-static int of_printf(const char *fmt, ...)
+int of_printf(const char *fmt, ...) // Maria was static
__attribute__ ((format (printf, 1, 2)));
-static int __init of_printf(const char *fmt, ...)
+int __init of_printf(const char *fmt, ...) // Maria was static
{
static char buf[1024];
va_list args;
@@ -152,6 +160,7 @@ static int __init of_getprop(int ph, con
if (rets[0] == OF_FAILURE) {
DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
+ if (buflen > 0) memset(buf, 0, 1);
return OF_FAILURE;
}
@@ -301,6 +310,7 @@ static int __init of_instance_to_package
return rets[0];
}
+#endif
static int __init of_getparent(int ph)
{
@@ -311,8 +321,6 @@ static int __init of_getparent(int ph)
DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
return rets[0];
}
-
-#endif
extern char _start[];
extern char _end[];
@@ -331,7 +339,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",
@@ -786,12 +793,303 @@ static void boot_of_module(ulong r3, ulo
}
-int __init boot_of_serial(void)
-{
- /* right now we are punting and using mambo writes which is the
- * hardcoded setup */
-
- return 1;
+static void search_by_property_value(int p, const char *prop_name,
+ const char *prop_value)
+{
+ int pnext; /* of handdle */
+
+ do {
+ // does this package have the property 'prop_name' with
+ // value "prop_value"?
+ char of_property[256];
+ of_property[0] = '\0';
+ of_getprop(p, prop_name, of_property, sizeof (of_property));
+ if (strncmp(of_property, prop_value, sizeof (prop_value)) == 0) {
+ char path[256];
+ int sz = of_package_to_path(p, path, sizeof(path));
+ of_printf("\npackage with property '%s' with value '%s' found. "
+ "path is %s (size %d)\n", prop_name, prop_value,
+ path, sz);
+#ifdef OF_DEBUG
+ // Print all its properties
+ char name[128];
+ int result = of_nextprop(p, 0, name); /* first prop. */
+ while (result > 0) {
+ int sz;
+ u64 obj[1024];
+ sz = of_getproplen(p, name);
+ if (sz > 0) {
+ int actual = of_getprop(p, name, obj, sz);
+ of_printf("device property *%s* size %d value %s ",
+ name, actual, (char*)obj);
+ int i;
+ for (i=0; i<=(actual/sizeof(obj[0])); i++)
+ of_printf("0x%016lx ", obj[i]);
+ of_printf("\n");
+ } else if (0 == sz) {
+ of_printf("device property *%s* size 0\n",
+ name);
+ }
+
+ result = of_nextprop(p, name, name);
+ }
+#endif
+ }
+
+ /* do children first */
+ pnext = of_getchild(p);
+ if (pnext != 0) {
+ search_by_property_value(pnext, prop_name, prop_value);
+ }
+
+ p = of_getpeer(p);
+ } while (p != OF_FAILURE && p != 0);
+}
+
+
+struct uart uarts[] = {
+ { .type = ns16550, .p_sign = "escc", .gp_sign = "mac-io",
+ .uart_init_func = ns16550_init },
+ { .type = pmac_zilog,
+ .uart_init_func = pmac_zilog_init },
+};
+
+/*
+ * Returns the value of the property '/#size-cells'
+ */
+int __init boot_of_get_sizecells_prop()
+{
+ int of_root;
+ u32 cell = 1;
+
+ of_root = of_finddevice("/");
+ if (of_root == OF_FAILURE) of_panic("no root package\n");
+
+ of_getprop(of_root, "#size-cells", &cell, sizeof(cell));
+ return cell;
+}
+
+/*
+ * return 0 is a serial port that makes sense for the platform is found.
+ * OF_FAILURE if no serial port can be found
+ */
+int __init boot_of_serial()
+{
+ int p, ofout; /* of handle */
+ int rc;
+ char of_property[256];
+ char ofout_path[256] = {0,};
+ const char serial[] = "serial";
+ const char macio[] = "mac-io";
+ const char escc[] = "escc";
+
+ #ifdef OF_DEBUG
+ {
+ p = of_finddevice("/");
+ const char device_type[] = "device_type";
+ search_by_property_value(p, device_type, serial);
+ }
+ #endif
+
+ /* 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 {
+ s32 iout; /* ihandle ?? */
+ /*
+ * Our last chance is to figure out the package for
+ * the current console and hopefully discover it to be
+ * a serial device.
+ */
+ p = of_finddevice("/chosen");
+ if (p != OF_FAILURE) {
+ rc = of_getprop(p, "stdout", &iout, sizeof(iout));
+ }
+ if (rc != OF_FAILURE) {
+ rc = of_instance_to_path(iout, ofout_path, sizeof(ofout_path));
+ if (rc != OF_FAILURE)
+ ofout = of_finddevice(ofout_path);
+ }
+ }
+
+ DBG("serial port OF handle=0x%x\n", ofout);
+
+ if (OF_FAILURE == ofout) {
+ /* can try the rtas device. Code not written yet */
+ of_printf("Could not find any serial device\n");
+ return OF_FAILURE;
+ }
+
+
+ /* Now we have the OF handle of the serial device. Let's find out
+ * what it is and its address.
+ *
+ * The device must have of type 'serial'
+ *
+ * If the grandparent directory has the name 'mac-io', then this must
+ * be a power mac. The serial device is a zilog.
+ *
+ * Otherwise (we are assuming that) the grandparent has the name
+ * 'pci' and the parent 'isa'. The serial device is a NS16550.
+ *
+ * And what about the ns16750?
+ *
+ */
+ rc = of_getprop(ofout, "device_type", of_property, sizeof(of_property));
+
+ union of_pci_hi {
+ u32 word;
+ struct {
+ u32 opa_n: 1; /* relocatable */
+ u32 opa_p: 1; /* prefetchable */
+ u32 opa_t: 1; /* aliased */
+ u32 _opa_res: 3;
+ u32 opa_s: 2; /* space code */
+ u32 opa_b: 8; /* bus number */
+ u32 opa_d: 5; /* device number */
+ u32 opa_f: 3; /* function number */
+ u32 opa_r: 8; /* register number */
+ } bits;
+ };
+ struct of_pci_addr_s {
+ union of_pci_hi opa_hi;
+ u32 opa_mid;
+ u32 opa_lo;
+ };
+
+ if (strncmp(of_property, serial, sizeof(serial))) {
+ of_printf("Serial device is not serial\n");
+ return OF_FAILURE;
+ }
+
+ 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));
+ if (0 == strncmp(of_property, macio, sizeof(macio))) {
+ struct reg_property32 {
+ u32 address;
+ u32 size;
+ } reg;
+ struct of_pci_range32_s {
+ struct of_pci_addr_s opr_addr;
+ u32 opr_phys;
+ u32 opr_size;
+ } r32;
+
+ of_getprop(parent, "device_type", of_property, sizeof(of_property));
+ if (strncmp(of_property, escc, sizeof(escc))) {
+ of_printf("Serial device parent's type is not escc\n");
+ return OF_FAILURE;
+ }
+
+ if (global_hs.platform_type != pmac) {
+ of_printf("WARNING: serial device found in path mac-io"
+ "but we don't think this is a power mac\n");
+ return OF_FAILURE;
+ }
+
+ global_hs.uart_type = pmac_zilog;
+
+ of_getprop(grandparent , "ranges", &r32, sizeof(r32));
+ of_getprop(ofout, "reg", ®, sizeof(reg));
+
+ of_printf("reg property address=0x%08x size=0x%08x\n",
+ reg.address, reg.size);
+ of_printf("ranges property %x:%x:%x %x %x\n",
+ r32.opr_addr.opa_hi.word,
+ r32.opr_addr.opa_mid,
+ r32.opr_addr.opa_lo,
+ r32.opr_phys, r32.opr_size);
+
+ global_hs.serial_port.uart_io_base = reg.address;
+ global_hs.serial_port.isa_io_base = r32.opr_phys;
+ } else {
+ /* grandparent directory is not 'mac-io'. We are assuming 'pci/isa' */
+ struct isa_reg_property {
+ u32 space;
+ u32 address;
+ u32 size;
+ } isa_reg;
+ struct of_pci_range64_s {
+ struct of_pci_addr_s opr_addr;
+ u32 opr_phys_hi;
+ u32 opr_phys_lo;
+ u32 opr_size_hi;
+ u32 opr_size_lo;
+ } r64;
+ u32 clock;
+
+ global_hs.uart_type = ns16550;
+
+ of_getprop(grandparent , "ranges", &r64, sizeof(r64));
+ of_getprop(ofout, "clock-frequency", &clock, sizeof (clock));
+ of_getprop(ofout, "reg", &isa_reg, sizeof(isa_reg));
+
+ 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:%x %x:%x\n",
+ r64.opr_addr.opa_hi.word,
+ r64.opr_addr.opa_mid,
+ r64.opr_addr.opa_lo,
+ r64.opr_phys_hi,
+ r64.opr_phys_lo,
+ r64.opr_size_hi, r64.opr_size_lo);
+
+ global_hs.serial_port.uart_io_base = isa_reg.address;
+ global_hs.serial_port.isa_io_base =
+ (((u64)r64.opr_phys_hi) << 32) | r64.opr_phys_lo;
+ global_hs.serial_port.clock = clock;
+ }
+
+ int i, s;
+ s = sizeof(uarts) / sizeof (struct uart);
+ for (i = 0; i < s; i++ ) {
+ if (uarts[i].type == global_hs.uart_type) {
+ global_hs.serial_port.uart_p = &(uarts[i]);
+ }
+ }
+
+ /* io_addr = isa_io_base + uart_io_base; */
+ of_printf("%s: serial type=%d io base=0x%016lx isa io@=0x%016lx "
+ "clock=%d\n",
+ __func__, global_hs.uart_type,
+ global_hs.serial_port.uart_io_base,
+ global_hs.serial_port.isa_io_base,
+ global_hs.serial_port.clock
+ );
+
+ return 0;
}
int __init boot_of_cpus(void)
@@ -825,6 +1123,157 @@ int __init boot_of_rtas(void)
return 1;
}
+/*
+ * Returns the length of the OF compatible property; OF_FAILURE on error
+ * The value of the property itself is returned in the first parameter.
+ */
+int __init boot_of_get_compatible_prop(char *cstring, int cstring_size)
+{
+ int of_root;
+ int comp_length;
+
+ of_root = of_finddevice("/");
+ if (of_root == OF_FAILURE) of_panic("no root package\n");
+
+ comp_length = of_getprop(of_root, "compatible", cstring, cstring_size);
+ #if 0
+ if (comp_length != OF_FAILURE) {
+ // null separated string yuck
+ int used_length;
+ of_printf("%s :\n", __func__);
+ for (used_length = 0; used_length < comp_length; used_length++) {
+ if (cstring[used_length] == '\0' ) {
+ of_printf(" NULL\n");
+ } else {
+ of_printf("%c", cstring[used_length]);
+ }
+ }
+ }
+ #endif
+
+ return comp_length;
+}
+
+int pmac_init() {
+ /*
+ * Power Macintosh' do not distinguish between supervisor and
+ * hypervisor mode. Hence, we run, if at all, with in a special
+ * mode called non-hypervisor hypervisor. (nohv)
+ */
+ of_printf("Non hypervisor hardware found.\n");
+ global_hs.hv_supported = 0;
+ return 0;
+}
+
+int maple_init() {
+ global_hs.hv_supported = 1;
+ return 0;
+}
+
+struct platform platforms[] = {
+ { .type = pmac, .compat_s = "Power Macintosh", .init_func = pmac_init },
+ { .type = maple, .compat_s = "Momentum,Maple", .init_func = maple_init },
+};
+
+/*
+ * Does the compatible of property indicate that the platform is a Power
+ * Macintosh, or a maple (hardware or simulated), or ..
+ * return 0 if not an known value;
+ */
+int __init boot_of_platform(char * compatible_p, int c_length)
+{
+
+ char *cmpstr;
+ int used_length;
+
+ // loop over each null terminated piece of the compatible property
+ for (cmpstr = compatible_p, used_length = 0; used_length < c_length;
+ cmpstr = &compatible_p[used_length]) {
+ int i, s;
+ s = sizeof(platforms) / sizeof(struct platform);
+ for (i = 0; i < s; i++) {
+ if (strstr(cmpstr, platforms[i].compat_s)) {
+ global_hs.platform_type = platforms[i].type;
+ return platforms[i].init_func();
+ }
+ }
+ used_length += strlen(cmpstr) + 1;
+ }
+
+ of_printf("Warning: boot_of::%s is not aware of this machine type. "
+ "Compatible is:\n", __func__);
+ {
+ int used_length;
+ for (used_length = 0; used_length < c_length; used_length++) {
+ if (compatible_p[used_length] == '\0' ) {
+ of_printf(" NULL ");
+ } else {
+ of_printf("%c", compatible_p[used_length]);
+ }
+ }
+ }
+ of_printf("\n");
+ return OF_FAILURE;
+}
+
+void __init boot_of_hardware_specific()
+{
+ int rc;
+ char compatible_string[256];
+ int compatible_length;
+
+ memset(&global_hs, 0, sizeof(global_hs));
+
+ compatible_length = boot_of_get_compatible_prop(compatible_string,
+ sizeof(compatible_string));
+
+ if (compatible_length != OF_FAILURE) {
+ rc = boot_of_platform(compatible_string, compatible_length);
+#if 0
+ cell = boot_of_get_sizecells_prop();
+ switch (rc) {
+ default:
+ of_printf("Warning: %s is not aware of this machine type %d\n",
+ __func__, rc);
+ break;
+
+ case 0:
+ // did not learn anything
+ break;
+
+ case PMAC_HARDWARE:
+ global_hs.platform_type = rc;
+ if (cell != 1) of_panic("powermac with cell %d\n", cell);
+
+ /*
+ * Power Macintosh' do not distinguish between supervisor and
+ * hypervisor mode. Hence, we run, if at all, with in a special
+ * mode called non-hypervisor hypervisor. (nohv)
+ */
+ of_printf("Non hypervisor hardware found.\n");
+ global_hs.hv_supported = 0;
+ opt_nohv = 1;
+ break;
+
+ case MAPLE_GENERIC:
+ global_hs.platform_type = rc;
+ if (cell != 2) of_panic("maple like thing with cell %d\n", cell);
+ global_hs.hv_supported = 1;
+ break;
+ }
+#endif
+ }
+
+ of_printf("%s: platform type=%d uart type=%d hv=%d\n", __func__,
+ global_hs.platform_type,
+ global_hs.uart_type,
+ global_hs.hv_supported);
+
+ boot_of_serial();
+ boot_of_rtas();
+}
+
+
multiboot_info_t __init *boot_of_init(
ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
{
@@ -858,13 +1307,20 @@ multiboot_info_t __init *boot_of_init(
boot_of_probemem(&mbi);
boot_of_bootargs(&mbi);
boot_of_module(r3, r4, &mbi);
- boot_of_serial();
boot_of_cpus();
- boot_of_rtas();
+
+ /* Note: serial and rtas were before cpus, but should really happen after
hardware
+ * specific, since we want to use the machine type as a hint of where/what
+ * the serial device might be
+ *
+ * If serial initalization needs to be before cpus, then we need to move up
+ * hardware specific as well.
+ */
+ boot_of_hardware_specific();
/* end of OF */
- of_printf("closing OF stdout...\n");
- of_call("close", 1, 0, &of_out);
+ //of_printf("closing OF stdout...\n"); Maria
+ //of_call("close", 1, 0, &of_out); Maria
of_getprop(bof_chosen, "stdin", &of_in, sizeof (of_in));
@@ -872,7 +1328,7 @@ multiboot_info_t __init *boot_of_init(
of_call("close", 1, 0, &of_in);
}
- of_call("quiesce", 0, 0, NULL);
+ //of_call("quiesce", 0, 0, NULL); Maria
return &mbi;
}
diff -r 56e1802303e5 xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/setup.c Thu May 4 13:19:28 2006 -0400
@@ -36,12 +36,21 @@
#include <asm/cache.h>
#include <asm/debugger.h>
#include <asm/delay.h>
+#include "platform.h"
unsigned long xenheap_phys_end;
/* opt_noht: If true, Hyperthreading is ignored. */
int opt_noht = 0;
boolean_param("noht", opt_noht);
+
+extern struct global_hardware_stuff global_hs;
+
+/* opt_nohv: If true, hardware has no hypervisor (HV) mode or nohv boot
+ * parameter was specified.
+ */
+int opt_nohv = 0;
+boolean_param("nohv", opt_nohv);
int opt_earlygdb = 0;
boolean_param("earlygdb", opt_earlygdb);
@@ -167,7 +176,10 @@ static void __init __start_xen(multiboot
cmdline_parse(__va((ulong)mbi->cmdline));
/* We initialise the serial devices very early so we can get debugging. */
- /* XXX find this in device tree */
+ {
+ /*
+ * the type of device is recorded in the global hardware stuff struct
+ */
struct ns16550_defaults ns16550 = {
.baud = BAUD_AUTO,
.data_bits = 8,
@@ -175,9 +187,11 @@ static void __init __start_xen(multiboot
.stop_bits = 1,
/* On maple this is 10, but we run in poll mode at the moment */
.irq = 0,
- .io_base = 0x3f8,
};
- ns16550_init(0, &ns16550);
+ ns16550.io_base = global_hs.serial_port.isa_io_base +
+ global_hs.serial_port.uart_io_base;
+ global_hs.serial_port.uart_p->uart_init_func(0, &ns16550);
+ }
serial_init_preirq();
init_console();
@@ -282,6 +296,8 @@ static void __init __start_xen(multiboot
if (dom0 == NULL)
panic("Error creating domain 0\n");
set_bit(_DOMF_privileged, &dom0->domain_flags);
+ if (opt_nohv)
+ set_bit(_DOMF_prob, &dom0->domain_flags);
/* Grab the DOM0 command line. Skip past the image name. */
cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
diff -r 56e1802303e5 xen/drivers/char/Makefile
--- a/xen/drivers/char/Makefile Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/drivers/char/Makefile Thu May 4 13:19:28 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 56e1802303e5 xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/drivers/char/ns16550.c Thu May 4 13:19:28 2006 -0400
@@ -269,7 +269,7 @@ static struct uart_driver ns16550_driver
.getc = ns16550_getc
};
-static int parse_parity_char(int c)
+int parse_parity_char(int c)
{
switch ( c )
{
diff -r 56e1802303e5 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/include/xen/sched.h Thu May 4 13:19:28 2006 -0400
@@ -392,6 +392,10 @@ extern struct domain *domain_list;
/* Domain is being debugged by controller software. */
#define _DOMF_debugging 4
#define DOMF_debugging (1UL<<_DOMF_debugging)
+ /* run domain in prob mode */
+#define _DOMF_prob 7
+#define DOMF_prob (1UL<<_DOMF_prob)
+
static inline int vcpu_runnable(struct vcpu *v)
{
diff -r 56e1802303e5 xen/include/xen/serial.h
--- a/xen/include/xen/serial.h Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/include/xen/serial.h Thu May 4 13:19:28 2006 -0400
@@ -8,6 +8,8 @@
#ifndef __XEN_SERIAL_H__
#define __XEN_SERIAL_H__
+
+#include <xen/spinlock.h>
struct cpu_user_regs;
@@ -123,6 +125,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 56e1802303e5 xen/arch/ppc/platform.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/platform.h Thu May 4 13:19:28 2006 -0400
@@ -0,0 +1,33 @@
+#ifndef _PLATFORM_H
+#define _PLATFORM_H
+
+enum platform_type { pmac, maple };
+struct platform {
+ enum platform_type type;
+ char *compat_s;
+ int (*init_func)(void);
+};
+
+enum uart_type { ns16550, pmac_zilog };
+struct uart {
+ enum uart_type type;
+ 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 {
+ u64 uart_io_base;
+ u64 isa_io_base;
+ struct uart *uart_p;
+ u32 clock;
+};
+
+struct global_hardware_stuff {
+ enum platform_type platform_type;
+ enum uart_type uart_type;
+
+ int hv_supported;
+ struct platform_serial_port serial_port;
+};
+#endif /* #ifndef _PLATFORM_H */
diff -r 56e1802303e5 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 4 13:19:28 2006 -0400
@@ -0,0 +1,426 @@
+/*
+ * 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"
+
+int of_printf(const char *fmt, ...);
+
+/* from rhype and linux */
+
+struct uart_pmac_port uaps[MAX_ZS_PORTS];
+
+extern int parse_parity_char(int c);
+
+#define PANIC(_f) \
+ { \
+ of_printf( "ERROR: " _f "\n"); \
+ }
+
+/* internal */
+static char pmac_zilog_read_reg(struct uart_port *uart, int reg, int verbose)
+{
+ if (verbose)
+ of_printf("%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)
+ of_printf("%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) ) {
+ of_printf("%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 )) {
+ of_printf("%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)) {
+ of_printf("%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 56e1802303e5 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 4 13:19:28 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__ */
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel