summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-09-15 00:18:23 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-09-15 00:18:23 +0000
commit5fe1122075a91dd9427cde8baa9eefbdc3f28107 (patch)
treee80b2954f2c7c4be92e75efbd7a572cdd409e3c8
parent44990ac744d55caf3033500f7b131e85548e5bb7 (diff)
Orion update.
-rw-r--r--arch/mips/orion/Makefile18
-rw-r--r--arch/mips/orion/char.c844
-rw-r--r--arch/mips/orion/irq.c44
-rw-r--r--arch/mips/orion/misc.c2
-rw-r--r--arch/mips/orion/orion.hw.init.c4140
-rw-r--r--arch/mips/orion/promcon.c135
-rw-r--r--arch/mips/orion/serial.8530.c815
-rw-r--r--arch/mips/orion/setup.c12
-rw-r--r--arch/mips/orion/zs.c2182
-rw-r--r--arch/mips/orion/zs.h405
10 files changed, 8543 insertions, 54 deletions
diff --git a/arch/mips/orion/Makefile b/arch/mips/orion/Makefile
index a42da1b0d..60ac12423 100644
--- a/arch/mips/orion/Makefile
+++ b/arch/mips/orion/Makefile
@@ -13,7 +13,8 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-OBJS = promcon.o char.o serial.8530.o orion.hw.init.o setup.o irq.o int-handler.o
+OBJS = promcon.o char.o serial.8530.o orion.hw.init.o setup.o irq.o \
+ int-handler.o zs.o
all: orionkern.a
@@ -21,8 +22,17 @@ orionkern.a: $(OBJS) initrd.o #no_initrd.o
$(AR) rcs orionkern.a $(OBJS) initrd.o #no_initrd.o
sync
-initrd.c: piggyback ramdisk.image.gz
- ./piggyback initrd < ramdisk.image.gz > initrd.c
+#
+# I usually have this mounted through loopback so I can
+# change it and let the makefile include it automatically
+# -- Cort <cort@fsmlabs.com>
+#
+#ramdisk.image.gz: ramdisk.image
+# gzip -vf9 < ramdisk.image > ramdisk.image.gz
+
+initrd.c: piggyback ramdisk.image
+ gzip -vf9 < ramdisk.image | ./piggyback initrd > initrd.c
+ rm -f ramdisk.image.gz
piggyback: piggyback.c
$(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c
@@ -41,7 +51,7 @@ orion.ctl: patchapp ../../../vmlinux
dep:
clean:
- rm -f patchapp orion.bin orion.nosym orion.ctl initrd.c
+ rm -f patchapp orion.bin orion.nosym orion.ctl initrd.c piggyback
dummy:
diff --git a/arch/mips/orion/char.c b/arch/mips/orion/char.c
new file mode 100644
index 000000000..e1d632e89
--- /dev/null
+++ b/arch/mips/orion/char.c
@@ -0,0 +1,844 @@
+# 1 "/root/root4/orion/os/regaeos/sys/libmyc/char.c"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/os/regaeos/sys/include/char.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct char_driver_struct char_driver_t;
+typedef struct char_port_struct char_port_t;
+
+extern int char_driver_count;
+extern int char_port_count;
+
+extern char_driver_t char_drivers[];
+extern char_port_t char_ports[];
+
+
+
+struct char_driver_struct {
+ int (*write)(char_port_t *port,char *buf, int len);
+ int (*read)(char_port_t *port,char *buf, int size);
+ int (*put_char)(char_port_t *port, char ch);
+ int (*get_char)(char_port_t *port);
+ int (*chars_in_buf)(char_port_t *port);
+
+ void (*flush_chars)(char_port_t *port);
+ int (*write_room)(char_port_t *port);
+};
+
+struct char_port_struct {
+ char port_name[10];
+ char_driver_t *driver;
+};
+
+int char_register_driver(char_driver_t *drv);
+
+
+
+
+int write(int fd, char *buf, int len);
+int read(int fd, char *buf, int len);
+int putchar(char ch);
+int getchar();
+int chars_in_buf();
+
+# 29 "/root/root4/orion/os/regaeos/sys/libmyc/char.c" 2
+
+# 1 "/root/root4/orion/os/regaeos/include/rstdio.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/os/regaeos/include/std_type.h" 1
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/os/regaeos/include/../sys/include/basics.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef char S8;
+typedef unsigned char U8;
+typedef short S16;
+typedef unsigned short U16;
+typedef int S32;
+typedef unsigned int U32;
+typedef int BOOL;
+
+
+
+
+
+
+
+
+
+
+
+typedef U32 (*U32FUNC)();
+typedef S32 (*S32FUNC)();
+typedef void (*VFUNC)();
+
+
+
+
+
+
+
+
+# 12 "/root/root4/orion/os/regaeos/include/std_type.h" 2
+
+
+typedef float F32;
+typedef double F64;
+
+
+typedef F32 Matrix4[4][4];
+typedef F32 Vector4[4];
+typedef F64 Vector4d[4];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 13 "/root/root4/orion/os/regaeos/include/rstdio.h" 2
+
+# 1 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/stdarg.h" 1 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 1 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 27 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 3
+
+
+typedef char * __gnuc_va_list;
+
+
+
+
+
+
+
+
+
+
+enum {
+ __no_type_class = -1,
+ __void_type_class,
+ __integer_type_class,
+ __char_type_class,
+ __enumeral_type_class,
+ __boolean_type_class,
+ __pointer_type_class,
+ __reference_type_class,
+ __offset_type_class,
+ __real_type_class,
+ __complex_type_class,
+ __function_type_class,
+ __method_type_class,
+ __record_type_class,
+ __union_type_class,
+ __array_type_class,
+ __string_type_class,
+ __set_type_class,
+ __file_type_class,
+ __lang_type_class
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/usr/local/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/include/sgidefs.h" 1 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 76 "/usr/local/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/include/sgidefs.h" 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 89 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 2 3
+
+
+
+
+# 119 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 3
+
+
+
+
+# 165 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 3
+
+
+
+void va_end (__gnuc_va_list);
+
+
+
+# 232 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 3
+
+
+
+
+
+
+
+
+# 253 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/va-mips.h" 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 27 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/stdarg.h" 2 3
+
+# 136 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/stdarg.h" 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 175 "/usr/local/lib/gcc-lib/mips-linux/2.95/include/stdarg.h" 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __gnuc_va_list va_list;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 14 "/root/root4/orion/os/regaeos/include/rstdio.h" 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ U8 *_ptr;
+ S32 _cnt;
+ U8 *_buf;
+ U32 _flags;
+ U32 _file;
+} FILE;
+
+extern FILE _iob[10 ];
+
+
+extern int fclose(FILE *);
+extern int fflush(FILE *);
+extern FILE *fopen(const char *, const char *);
+extern int fprintf(FILE *, const char *, ...);
+
+extern int fscanf(FILE *, const char *, ...);
+
+extern int printf(const char *, ...);
+extern int printf2(const char *, ...);
+extern int scanf(const char *, ...);
+
+extern int sprintf(char *, const char *, ...);
+extern int sscanf(const char *, const char *, ...);
+
+extern int vfprintf(FILE *, const char *, va_list);
+extern int vprintf(const char *, va_list);
+extern int vsprintf(char *, const char *, va_list);
+
+extern int fgetc(FILE *);
+extern char *fgets(char *, int, FILE *);
+extern int fputc(int, FILE *);
+extern int fputs(const char *, FILE *);
+extern int getc(FILE *);
+extern int getchar(void);
+extern char *gets(char *);
+extern int putc(int, FILE *);
+extern int putchar(char);
+extern int puts(const char *);
+extern int ungetc(int, FILE *);
+extern U32 fread(void *, U32, U32, FILE *);
+extern U32 fwrite(const void *, U32, U32, FILE *);
+extern int fgetpos(FILE *, U32 *);
+extern int fseek(FILE *, long, int);
+extern int fsetpos(FILE *, const U32 *);
+extern long ftell(FILE *);
+extern void rewind(FILE *);
+extern void clearerr(FILE *);
+extern int feof(FILE *);
+extern int ferror(FILE *);
+extern void perror(const char *);
+
+extern int __filbuf(FILE *);
+extern int __flsbuf(int, FILE *);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 30 "/root/root4/orion/os/regaeos/sys/libmyc/char.c" 2
+
+
+
+
+
+
+
+
+
+int char_driver_count = 0;
+int char_port_count = 0;
+
+char_driver_t char_drivers[2 ];
+char_port_t char_ports[2 ];
+
+int char_generic_read(char_port_t *pt, char *buf, int size) {
+ int numread = 0;
+ int char_read;
+
+ while ((numread < size) &&
+ ((char_read = pt->driver->get_char(pt)) >= 0)) {
+ *buf = char_read;
+ numread++;
+ }
+
+ return (numread);
+}
+
+int char_generic_write(char_port_t *pt, char *buf, int len) {
+ while (len) {
+ pt->driver->put_char(pt,*buf);
+
+ buf++; len--;
+ }
+}
+
+
+
+
+
+
+int char_register_driver(char_driver_t *drv) {
+ int index = -1;
+
+ if (drv->read == 0 ) {
+ drv->read = char_generic_read;
+ }
+ if (drv->write == 0 ) {
+ drv->write = char_generic_write;
+ }
+
+ if (char_driver_count < 2 ) {
+ index = char_driver_count;
+ char_drivers[char_driver_count] = *drv;
+ char_driver_count++;
+ }
+
+ if (char_port_count < 2 ) {
+ char_ports[char_port_count].driver =
+ &char_drivers[index];
+ sprintf(char_ports[char_port_count].port_name,
+ ":COM%d",char_port_count);
+ char_port_count++;
+ }
+
+ return (index);
+}
+
+
+int null_func() {
+ return -1;
+}
+
+
+
+# 1 "/root/root4/orion/os/regaeos/include/serial.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void SerialSetup(U32 baud, U32 console, U32 host, U32 intr_desc);
+extern void SerialPollOn(void);
+extern void SerialPollOff(void);
+extern void SerialPollInit(void);
+extern U32 SerialPollConsts(U32 typecode);
+extern U8 SerialPollConin(void);
+extern void SerialPollConout(U8 c,int hexify);
+extern U32 SerialPollHststs(U32 typecode);
+extern U8 SerialPollHstin(void);
+void SerialPollHstout(U8 c);
+void *SerialIntInit(U32 channel,
+void (*rx_isr)(U32 channel),
+void (*tx_char)(U32 unit, U32 isr_flag));
+U32 SerialIntBaud(U32 channel, void *hdp, U32 baudrate);
+void SerialIntRxioff(U32 channel, void *hdp);
+void SerialIntRxion(U32 channel, void *hdp);
+void SerialIntTxioff(U32 channel, void *hdp);
+void SerialIntTxion(U32 channel, void *hdp);
+U32 SerialIntRead(U32 channel, void *hdp, U8 *ch_ptr);
+U32 SerialIntWrite(U32 channel, void *hdp, U8 ch);
+
+
+# 105 "/root/root4/orion/os/regaeos/sys/libmyc/char.c" 2
+
+
+int ch_typ_rs_chars_in_buf(char_port_t *pt) {
+ int c;
+ SerialPollConsts(0);
+ if ((c = SerialPollConsts(0 )) == 0 ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int ch_typ_rs_putchar(char_port_t *pt,char ch) {
+ SerialPollConout(ch,1);
+ return 0;
+}
+
+int ch_typ_rs_getchar(char_port_t *pt) {
+ int c;
+
+ if ((c = SerialPollConsts(0 )) == 0 ) {
+ return (-1) ;
+ }
+ else if (c == 2 ) {
+ return 2 ;
+ }
+ else {
+ return SerialPollConin();
+ }
+}
+
+
+# 154 "/root/root4/orion/os/regaeos/sys/libmyc/char.c"
+
+
+
+
+void init_char_drivers() {
+ char_driver_t a_drv;
+
+
+
+ a_drv.read = 0 ;
+ a_drv.write = 0 ;
+ a_drv.chars_in_buf = ch_typ_rs_chars_in_buf;
+ a_drv.put_char = ch_typ_rs_putchar;
+ a_drv.get_char = ch_typ_rs_getchar;
+
+ char_register_driver(&a_drv);
+
+
+# 181 "/root/root4/orion/os/regaeos/sys/libmyc/char.c"
+
+
+}
+
+
+int chwrite(int fd,char *buf, int len) {
+ char_port_t *pt;
+
+ if (fd < char_port_count) {
+ pt = &char_ports[fd];
+ return (pt->driver->write(pt,buf,len));
+ }
+ return -1;
+}
+
+int chread(int fd,char *buf, int len) {
+ char_port_t *pt;
+
+ if (fd < char_port_count) {
+ pt = &char_ports[fd];
+ return (pt->driver->read(pt,buf,len));
+ }
+ return -1;
+}
+
+int putchar(char ch) {
+ char_port_t *pt;
+ int fd = 0;
+
+ if (fd < char_port_count) {
+ pt = &char_ports[fd];
+ return (pt->driver->put_char(pt,ch));
+ }
+ return -1;
+}
+
+# 229 "/root/root4/orion/os/regaeos/sys/libmyc/char.c"
+
+
diff --git a/arch/mips/orion/irq.c b/arch/mips/orion/irq.c
index 58d9ae3bf..ef7ca082f 100644
--- a/arch/mips/orion/irq.c
+++ b/arch/mips/orion/irq.c
@@ -25,12 +25,17 @@
void (*board_time_init)(struct irqaction *irq);
extern asmlinkage void orionIRQ(void);
+irq_cpustat_t irq_stat [NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
unsigned long spurious_count = 0;
irq_desc_t irq_desc[NR_IRQS];
+irq_desc_t *irq_desc_base=&irq_desc[0];
static void galileo_ack(unsigned int irq_nr)
{
- *((unsigned long *) (((unsigned)( 0x14000000 )|0xA0000000) + 0xC18) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+ ((( 0 )&0xff0000)>>8)+ ((( 0 )&0xff000000)>>24)) ;
+ *((unsigned long *) (((unsigned)(0x14000000)|0xA0000000) + 0xC18)) =
+ cpu_to_le32(0);
}
struct hw_interrupt_type galileo_pic = {
@@ -91,10 +96,9 @@ void enable_irq(unsigned int irq_nr)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
*/
+
void __init orion_time_init(struct irqaction *irq)
{
- __u32 timer_count;
-
irq_desc[2].handler = &galileo_pic;
irq_desc[2].action = irq;
@@ -102,19 +106,23 @@ void __init orion_time_init(struct irqaction *irq)
* appearance init's the timer.
* -- Cort
*/
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0x864) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+ ((( 0 )&0xff0000)>>8)+ ((( 0 )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0x864)) =
+ cpu_to_le32(0);
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0x850) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+ ((( 0 )&0xff0000)>>8)+ ((( 0 )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0x850)) =
+ cpu_to_le32(0);
- timer_count = 300000000/100;
-
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0x850) ) = (((( timer_count )&0xff)<<24)+ ((( timer_count )&0xff00)<<8)+ ((( timer_count )&0xff0000)>>8)+ ((( timer_count )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0x850)) =
+ cpu_to_le32(50000000/HZ);
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0xC1C) ) = (((( 0x100 )&0xff)<<24)+ ((( 0x100 )&0xff00)<<8)+ ((( 0x100 )&0xff0000)>>8)+ ((( 0x100 )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0xC1C)) =
+ cpu_to_le32(0x100);
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0x864) ) = (((( 0x03 )&0xff)<<24)+ ((( 0x03 )&0xff00)<<8)+ ((( 0x03 )&0xff0000)>>8)+ ((( 0x03 )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0x864)) =
+ cpu_to_le32(0x03);
- *((__u32 *) (((unsigned)( 0x14000000 )|0xA0000000) + 0xC18) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+ ((( 0 )&0xff0000)>>8)+ ((( 0 )&0xff000000)>>24)) ;
+ *((__u32 *) (((unsigned)(0x14000000)|0xA0000000) + 0xC18)) =
+ cpu_to_le32(0);
}
int get_irq_list(char *buf)
@@ -150,7 +158,7 @@ int get_irq_list(char *buf)
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
struct irqaction *action;
- int do_random, cpu;
+ int cpu;
int status;
cpu = smp_processor_id();
@@ -180,10 +188,18 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
irq_desc[irq].handler->enable(irq);
}
}
+ else
+ {
+ spurious_count++;
+ printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq);
+ disable_irq(irq);
+ if (irq_desc[irq].handler->end)
+ irq_desc[irq].handler->end(irq);
+ }
irq_exit(cpu);
- if (softirq_active(cpu)&softirq_mask(cpu))
+ if (softirq_state[cpu].active&softirq_state[cpu].mask)
do_softirq();
/* unmasking and bottom half handling is done magically for us. */
@@ -252,6 +268,7 @@ void free_irq(unsigned int irq, void *dev_id)
request_irq(irq, NULL, 0, NULL, dev_id);
}
+
unsigned long probe_irq_on (void)
{
return 0;
@@ -271,6 +288,7 @@ int orion_irq_cannonicalize(int i)
void __init init_IRQ(void)
{
+
irq_cannonicalize = orion_irq_cannonicalize;
set_except_vector(0, orionIRQ);
}
diff --git a/arch/mips/orion/misc.c b/arch/mips/orion/misc.c
index 0d8881058..1c6d9e2fa 100644
--- a/arch/mips/orion/misc.c
+++ b/arch/mips/orion/misc.c
@@ -35,8 +35,10 @@
#include <asm/stackframe.h>
#include <asm/system.h>
#include <asm/cpu.h>
+#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
#include <asm/mc146818rtc.h>
char arcs_cmdline[CL_SIZE] = {0, };
diff --git a/arch/mips/orion/orion.hw.init.c b/arch/mips/orion/orion.hw.init.c
new file mode 100644
index 000000000..e7e178cd3
--- /dev/null
+++ b/arch/mips/orion/orion.hw.init.c
@@ -0,0 +1,4140 @@
+# 1 "/root/root4/orion/hw/orion.hw.init.c"
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/hw/include/hw.boot.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/compiler.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 32 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/struct.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 34 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/debug.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void DataDump (char *banner, void *data, int size);
+extern void intr_printf (char *mesg);
+extern void polled_printf (char *format, ...);
+extern void debug_printf (char *format, ...);
+extern void StackDump (void);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 107 "/root/root4/orion/hw/include/../../cosine/common/inc/debug.h"
+
+
+
+
+
+
+
+
+
+
+# 126 "/root/root4/orion/hw/include/../../cosine/common/inc/debug.h"
+
+# 137 "/root/root4/orion/hw/include/../../cosine/common/inc/debug.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 37 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.types.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char uchar_t;
+typedef unsigned short ushort_t;
+typedef unsigned int uint_t;
+typedef unsigned long ulong_t;
+
+typedef unsigned char uint8_t;
+typedef char sint8_t;
+
+typedef unsigned short uint16_t;
+typedef short sint16_t;
+
+typedef unsigned int uint32_t;
+typedef int sint32_t;
+
+
+typedef unsigned long long uint64_t;
+typedef long long sint64_t;
+
+
+typedef sint8_t S8;
+typedef sint8_t s8;
+
+typedef uint8_t U8;
+typedef uint8_t u8;
+
+typedef sint16_t S16;
+typedef sint16_t s16;
+
+typedef uint16_t U16;
+typedef uint16_t u16;
+
+typedef sint32_t S32;
+typedef sint32_t s32;
+
+typedef uint32_t U32;
+typedef uint32_t u32;
+
+
+typedef sint64_t S64;
+typedef sint64_t s64;
+
+typedef uint64_t U64;
+typedef uint64_t u64;
+
+
+typedef uint32_t BOOL;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 110 "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.types.h"
+
+
+
+
+# 41 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.pci.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void pci_cpuDevNum(int *bus, int *device);
+extern int pci_getMaxBusNo(void);
+extern void *pci_intrToVecNum (int intrLine, int bus,
+ int device);
+extern int pci_findDevice (int deviceId, int vendorId,
+ int index, uint32_t * bus, uint32_t * device);
+extern void pci_intrOn (int intrLine);
+extern void pci_intrOff (int intrLine);
+
+
+extern int pci_read (
+ int bus,
+ int device,
+ int function,
+ int reg,
+ long *data
+ );
+
+extern int pci_write (
+ int bus,
+ int device,
+ int function,
+ int reg,
+ long data
+ );
+
+extern long pci_getByte (
+ long data,
+ int byte
+);
+extern long pci_setByte (
+ long data,
+ long pciData,
+ int byte
+);
+extern long pci_getWord (
+ long data,
+ int word
+);
+extern long pci_setWord (
+ long data,
+ long pciData,
+ int word
+);
+
+
+extern void pci_scan (void);
+extern int pci_findDevice (
+ int deviceId,
+ int vendorId,
+ int index,
+ uint32_t * bus,
+ uint32_t * device
+ );
+
+
+
+# 42 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.vm.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void *vm_VirtToPhy (void *x);
+extern void *vm_PhyToVirt (void *x, int attributes);
+
+
+
+
+extern int vm_IsCacheReadCoherent (void);
+extern int vm_IsCacheWriteCoherent (void);
+
+
+
+
+
+
+
+
+
+
+
+extern void vm_InvalidateInstructionCache (void *start, int size);
+extern void vm_InvalidateDataCache (void *start, int size);
+extern void vm_FlushDataCache (void *start, int size);
+extern void vm_FlushAndInvalidateDataCache (void *start, int size);
+
+
+
+
+
+
+
+
+
+
+
+
+static inline
+void *
+vm_VirtToPhy (void *x)
+{
+
+ return (void *)(((int)x) & ~0xE0000000);
+}
+static inline
+void *
+vm_PhyToVirt (void *x, int attributes)
+{
+ int bits = 0;
+ void *vaddr;
+
+ { { if (! ( attributes != 0 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "attributes != 0", "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.vm.h", 66); asm(" break "); } } ; } ;
+
+ { { if (! ( (((int)x) & 0xE0000000) == 0 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "(((int)x) & 0xE0000000) == 0", "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.vm.h", 68); asm(" break "); } } ; } ;
+ if (attributes & 0x01 )
+ bits = 0x80000000;
+ else if (attributes & 0x02 )
+ bits = 0xA0000000;
+
+
+
+ vaddr = (void *)((((int)x) & ~0xE0000000) | bits);
+ return vaddr;
+}
+# 100 "/root/root4/orion/hw/include/../../cosine/hwdeps/inc/hw.vm.h"
+
+static inline
+int
+vm_IsCacheReadCoherent (void)
+{
+ return 1 ;
+}
+static inline
+int
+vm_IsCacheWriteCoherent (void)
+{
+ return 1 ;
+}
+
+static inline
+void
+vm_InvalidateInstructionCache (void *start, int size)
+{
+ extern Sys_Clear_Cache (void *, int);
+ Sys_Clear_Cache (start, size);
+}
+static inline
+void
+vm_InvalidateDataCache (void *start, int size)
+{
+ extern Sys_Inval_Dcache (void *, int);
+ Sys_Inval_Dcache (start, size);
+}
+void
+static inline
+vm_FlushDataCache (void *start, int size)
+{
+ extern Sys_Flush_Dcache ();
+ Sys_Flush_Dcache ();
+}
+void
+static inline
+vm_FlushAndInvalidateDataCache (void *start, int size)
+{
+ extern Sys_Clear_Dcache (void *, int);
+ Sys_Clear_Dcache (start, size);
+}
+
+
+
+
+
+
+
+
+# 43 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/ipsx/inc/ipsx.includes.h" 1
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/hw/ipsx/inc/pe_id.h" 1
+
+
+
+
+
+
+
+
+
+
+
+typedef uint16_t ipsx_pe_type_t;
+typedef uint16_t ipsx_pe_id_t;
+typedef ipsx_pe_type_t ipsx_blade_type_t;
+typedef ipsx_pe_id_t ipsx_slot_id_t;
+
+typedef uint16_t address_space_t;
+
+typedef uint16_t ipsx_lqid_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern address_space_t local_address_space_id;
+extern ipsx_slot_id_t local_slot_id;
+extern ipsx_pe_id_t local_pe_id;
+extern ipsx_pe_type_t local_pe_type;
+extern ipsx_blade_type_t local_blade_type;
+
+
+
+
+
+extern void ipsx_pe_down (
+ address_space_t address_id
+ );
+extern void ipsx_pe_up (
+ address_space_t address_id
+ );
+extern void ipsx_blade_down (
+ address_space_t address_id
+ );
+extern void ipsx_blade_up (
+ address_space_t address_id
+ );
+extern void ipsx_validate_slot_id (
+ ipsx_slot_id_t slot_id
+ );
+
+
+extern int ipsx_is_pe_live (
+ address_space_t address_id
+ );
+extern int ipsx_is_blade_live (
+ address_space_t address_id
+ );
+extern int ipsx_is_address_space_functional (
+ address_space_t address_id
+ );
+
+
+
+
+
+extern ipsx_slot_id_t ipsx_get_slot_id (
+ address_space_t address_id
+ );
+extern ipsx_pe_id_t ipsx_get_pe_id (
+ address_space_t address_id
+ );
+
+extern address_space_t ipsx_construct_address_id (
+ ipsx_slot_id_t slot_id,
+ ipsx_pe_id_t pe_id
+ );
+
+extern address_space_t ipsx_get_my_address_id ();
+extern ipsx_slot_id_t ipsx_get_my_slot_id ();
+extern ipsx_pe_id_t ipsx_get_my_pe_id ();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern address_space_t ipsx_start_slot_address_id (
+ ipsx_slot_id_t slot_id
+ );
+extern address_space_t ipsx_next_slot_address_id (
+ address_space_t address_id
+ );
+extern address_space_t ipsx_end_slot_address_id (
+ ipsx_slot_id_t slot_id
+ );
+
+
+
+
+
+
+
+static inline
+address_space_t ipsx_get_my_address_id ()
+{
+ return local_address_space_id;
+}
+
+static inline
+ipsx_slot_id_t ipsx_get_my_slot_id ()
+{
+ return local_slot_id;
+}
+
+static inline
+ipsx_pe_id_t ipsx_get_my_pe_id ()
+{
+ return local_pe_id;
+}
+
+static inline
+address_space_t ipsx_construct_address_id (
+ ipsx_slot_id_t slot_id,
+ ipsx_pe_id_t pe_id
+ )
+{
+ { { if (! ( slot_id <= 127 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "slot_id <= 127", "/root/root4/orion/hw/ipsx/inc/pe_id.h", 155); asm(" break "); } } ; } ;
+ { { if (! ( pe_id <= 7 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "pe_id <= 7", "/root/root4/orion/hw/ipsx/inc/pe_id.h", 156); asm(" break "); } } ; } ;
+ slot_id &= 0x7F ;
+ slot_id <<= 8 ;
+ pe_id &= 0x0F ;
+ pe_id <<= 0 ;
+ return (0x80F0 | slot_id | pe_id);
+}
+static inline
+ipsx_slot_id_t ipsx_get_slot_id (
+ address_space_t address_id
+ )
+{
+ return ((address_id >> 8 ) & 0x7F );
+}
+static inline
+ipsx_pe_id_t ipsx_get_pe_id (
+ address_space_t address_id
+ )
+{
+ return ((address_id >> 0 ) & 0x0F );
+}
+
+static inline
+address_space_t ipsx_start_slot_address_id (
+ ipsx_slot_id_t slot_id
+ )
+{
+ { { if (! ( slot_id < 127 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "slot_id < 127", "/root/root4/orion/hw/ipsx/inc/pe_id.h", 183); asm(" break "); } } ; } ;
+ return ipsx_construct_address_id (slot_id, 0 );
+}
+static inline
+address_space_t ipsx_next_slot_address_id (
+ address_space_t address_id
+ )
+{
+ ipsx_pe_id_t pe_id = ipsx_get_pe_id (address_id);
+ pe_id ++;
+ return ipsx_construct_address_id (
+ ipsx_get_slot_id (address_id), pe_id);
+}
+static inline
+address_space_t ipsx_end_slot_address_id (
+ ipsx_slot_id_t slot_id
+ )
+{
+ { { if (! ( slot_id < 127 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "slot_id < 127", "/root/root4/orion/hw/ipsx/inc/pe_id.h", 201); asm(" break "); } } ; } ;
+ return ipsx_construct_address_id (slot_id, 7 );
+}
+
+
+
+# 12 "/root/root4/orion/hw/include/../../cosine/ipsx/inc/ipsx.includes.h" 2
+
+# 1 "/root/root4/orion/hw/ipsx/inc/pe_attrib.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef uint32_t ipsx_pe_capability_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 59 "/root/root4/orion/hw/ipsx/inc/pe_attrib.h"
+
+
+extern char *ipsx_filename_extensions[];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void ipsx_mng_register_pe_type (
+ address_space_t address_id,
+ ipsx_pe_type_t type
+ );
+extern ipsx_blade_type_t ipsx_get_blade_type (
+ ipsx_slot_id_t slot_id
+ );
+extern ipsx_pe_type_t ipsx_get_pe_type (
+ address_space_t address_id
+ );
+extern ipsx_pe_capability_t ipsx_get_pe_capability (
+ address_space_t address_id
+ );
+
+extern int ipsx_check_pe_for_capability (
+ address_space_t address_id,
+ ipsx_pe_capability_t capability
+ );
+
+
+typedef struct rls_results_s rls_results_t;
+
+extern int ipsx_get_pe_by_type (
+ address_space_t start_addr,
+ ipsx_pe_type_t type,
+ rls_results_t *results,
+ int max_results
+ );
+extern int ipsx_get_pe_by_capability (
+ address_space_t start_addr,
+ ipsx_pe_capability_t capability,
+ rls_results_t *results,
+ int max_results
+ );
+
+
+
+
+
+static inline
+ipsx_blade_type_t
+ipsx_get_blade_type (
+ address_space_t address_id
+ )
+{
+ ipsx_slot_id_t slot_id = ipsx_get_slot_id (address_id);
+
+ return ipsx_get_pe_type (ipsx_construct_address_id (slot_id, 0 ));
+}
+
+static inline
+int
+ipsx_check_pe_for_capability (
+ address_space_t address_id,
+ ipsx_pe_capability_t capability
+ )
+{
+ return (0 != (capability & ipsx_get_pe_capability (address_id)));
+}
+
+
+
+
+# 13 "/root/root4/orion/hw/include/../../cosine/ipsx/inc/ipsx.includes.h" 2
+
+
+
+# 46 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/bits.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern uint16_t BIT_SWAP16 (uint16_t x);
+extern uint32_t BIT_SWAP32 (uint32_t x);
+
+extern uint16_t GET16 (uint8_t *x);
+extern uint32_t GET32 (uint8_t *x);
+
+extern void PUT16 (uint8_t *x, uint16_t val);
+extern void PUT32 (uint8_t *x, uint32_t val);
+
+
+
+
+
+static inline
+uint16_t
+BIT_SWAP16 (uint16_t x)
+{
+ return (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8));
+}
+static inline
+uint32_t
+BIT_SWAP32 (uint32_t x)
+{
+ return ( ((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) |
+ ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24) );
+}
+
+
+
+static inline
+uint16_t
+GET16 (uint8_t *x)
+{
+ uint16_t val;
+ val = *x++;
+ val <<= 8;
+ val |= *x;
+ return val;
+}
+static inline
+uint32_t
+GET32 (uint8_t *x)
+{
+ uint32_t val;
+ val = *x++;
+ val <<= 8;
+ val |= *x++;
+ val <<= 8;
+ val |= *x++;
+ val <<= 8;
+ val |= *x;
+ return val;
+}
+
+
+
+static inline
+void
+PUT16 (uint8_t *x, uint16_t val)
+{
+ *x++ = (uint8_t) val;
+ val >>= 8;
+ *x = (uint8_t) val;
+}
+static inline
+void
+PUT32 (uint8_t *x, uint32_t val)
+{
+ *x++ = (uint8_t) val;
+ val >>= 8;
+ *x++ = (uint8_t) val;
+ val >>= 8;
+ *x++ = (uint8_t) val;
+ val >>= 8;
+ *x = (uint8_t) val;
+}
+
+
+
+
+# 51 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/tokval.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef
+struct tokval_s
+{
+ int value;
+ char *token;
+} tokval_t;
+
+static inline
+char *
+tok_val2tok(int value, tokval_t *table, int numOfEntries, char *default_token)
+{
+ static char * undef = "Unknown";
+ int i;
+
+ for(i = 0; i < numOfEntries; i++, table++)
+ {
+ if(table->value == value)
+ return table->token;
+ }
+ return (default_token != ((void *) 0) )? default_token: "Unknown";
+}
+
+static inline
+int
+tok_tok2val(char *token, tokval_t *table, int numOfEntries, int default_value)
+{
+ int i;
+
+ for(i = 0; i < numOfEntries; i++, table++)
+ {
+ if(strcmp(table->token,token) == 0)
+ return table->value;
+ }
+ return default_value;
+}
+
+
+
+# 52 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/custom.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 53 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef
+struct dlcl_list_s
+{
+ struct dlcl_list_s *next;
+ struct dlcl_list_s *prev;
+} dlcl_list_t;
+
+
+
+
+
+extern int dlcl_ListIsValid (dlcl_list_t *l);
+extern int dlcl_ListIsEmpty (dlcl_list_t *l);
+extern void dlcl_ListInit (dlcl_list_t *l);
+extern dlcl_list_t *dlcl_ListPrev (dlcl_list_t *l);
+extern dlcl_list_t *dlcl_ListNext (dlcl_list_t *l);
+extern void dlcl_ListAdd (dlcl_list_t *l1,dlcl_list_t *l2);
+extern void dlcl_ListAddSingleton (dlcl_list_t *l1,dlcl_list_t *single);
+extern void dlcl_ListAddNew (dlcl_list_t *l1, dlcl_list_t *new);
+extern void dlcl_ListAddNewAfter (dlcl_list_t *l1, dlcl_list_t *new);
+extern void dlcl_ListRemove (dlcl_list_t *l);
+
+
+
+
+
+
+
+
+static inline
+int
+dlcl_ListIsValid (
+ dlcl_list_t *l
+)
+{
+ return ((l != ((void *) 0) ) &&
+ (l->prev != ((void *) 0) ) &&
+ (l->next != ((void *) 0) ) &&
+ (l->prev->next == l->next->prev));
+}
+static inline
+int
+dlcl_ListIsEmpty (
+ dlcl_list_t *l
+)
+{
+ { { if (! ( dlcl_ListIsValid (l) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 60); asm(" break "); } } ; } ;
+ return (l->prev == l);
+}
+static inline
+void
+dlcl_ListInit (
+ dlcl_list_t *l
+)
+{
+ l->prev = l->next = l;
+}
+static inline
+dlcl_list_t *
+dlcl_ListPrev (
+ dlcl_list_t *l
+)
+{
+ { { if (! ( dlcl_ListIsValid (l) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 77); asm(" break "); } } ; } ;
+ return l->prev;
+}
+static inline
+dlcl_list_t *
+dlcl_ListNext (
+ dlcl_list_t *l
+)
+{
+ { { if (! ( dlcl_ListIsValid (l) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 86); asm(" break "); } } ; } ;
+ return l->next;
+}
+static inline
+void
+dlcl_ListAdd (
+ dlcl_list_t *l1,
+ dlcl_list_t *l2
+)
+{
+ dlcl_list_t *l1_last;
+ dlcl_list_t *l2_last;
+
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 99); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l2) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l2)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 100); asm(" break "); } } ; } ;
+ l1_last = l1->prev;
+ l2_last = l2->prev;
+
+ l1_last->next = l2;
+ l2->prev = l1_last;
+ l2_last->next = l1;
+ l1->prev = l2_last;
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 108); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l2) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l2)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 109); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l1_last) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1_last)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 110); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l2_last) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l2_last)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 111); asm(" break "); } } ; } ;
+}
+static inline
+void
+dlcl_ListAddSingleton (
+ dlcl_list_t *l1,
+ dlcl_list_t *single
+)
+{
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 120); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (single) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (single)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 121); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsEmpty (single) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsEmpty (single)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 122); asm(" break "); } } ; } ;
+
+ single->next = l1;
+ single->prev = l1->prev;
+
+ l1->prev->next = single;
+ l1->prev = single;
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 129); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (single) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (single)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 130); asm(" break "); } } ; } ;
+}
+static inline
+void
+dlcl_ListAddNew (
+ dlcl_list_t *l1,
+ dlcl_list_t *new
+)
+{
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 139); asm(" break "); } } ; } ;
+
+ new->next = l1;
+ new->prev = l1->prev;
+
+ l1->prev->next = new;
+ l1->prev = new;
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 146); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (new) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (new)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 147); asm(" break "); } } ; } ;
+}
+static inline
+void
+dlcl_ListAddNewAfter (
+ dlcl_list_t *l1,
+ dlcl_list_t *new
+)
+{
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 156); asm(" break "); } } ; } ;
+
+ new->next = l1->next;
+ new->prev = l1;
+
+ l1->next->prev = new;
+ l1->next = new;
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 163); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (new) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (new)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 164); asm(" break "); } } ; } ;
+}
+static inline
+void
+dlcl_ListRemove (
+ dlcl_list_t *l
+)
+{
+ { { if (! ( dlcl_ListIsValid (l) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 172); asm(" break "); } } ; } ;
+ l->prev->next = l->next;
+ l->next->prev = l->prev;
+ { { if (! ( dlcl_ListIsValid (l->prev) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l->prev)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 175); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l->next) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l->next)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 176); asm(" break "); } } ; } ;
+ l->prev = l->next = l;
+ { { if (! ( dlcl_ListIsValid (l) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 178); asm(" break "); } } ; } ;
+}
+static inline
+void
+dlcl_ListInsertBefore (
+ dlcl_list_t *l1,
+ dlcl_list_t *l2
+)
+{
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 187); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l2) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l2)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 188); asm(" break "); } } ; } ;
+ dlcl_ListAdd (l1,l2);
+}
+static inline
+void
+dlcl_ListInsertAfter (
+ dlcl_list_t *l1,
+ dlcl_list_t *l2
+)
+{
+ { { if (! ( dlcl_ListIsValid (l1) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l1)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 198); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (l2) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (l2)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 199); asm(" break "); } } ; } ;
+ dlcl_ListAdd (l1->next,l2);
+}
+
+static inline
+void
+dlcl_ListDump (
+ dlcl_list_t *l
+)
+{
+ printf ("dlcl element %lx, next %lx, prev %lx\n",
+ (long) l, (long) l->next, (long) l->prev);
+}
+
+static inline
+void
+dlcl_insert_in_order (
+ dlcl_list_t *list,
+ dlcl_list_t *element,
+ int (*compare)(dlcl_list_t *e1, dlcl_list_t *e2)
+)
+{
+
+ if (dlcl_ListIsEmpty (list))
+ {
+ dlcl_ListAdd (list,element);
+ }
+ else
+ {
+ dlcl_list_t *next;
+ next = dlcl_ListNext (list);
+ while (next != list)
+ {
+ if ((*compare)(element,next) < 0)
+ {
+ break;
+ }
+ next = dlcl_ListNext (next);
+ }
+ if (next == list)
+ {
+
+ next = dlcl_ListPrev (next);
+ }
+ if ((*compare)(element,next) < 0)
+ {
+ dlcl_ListInsertBefore (next, element);
+ { { if (! ( dlcl_ListPrev (next) == element )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListPrev (next) == element", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 246); asm(" break "); } } ; } ;
+ }
+ else
+ {
+ dlcl_ListInsertAfter (next, element);
+ { { if (! ( dlcl_ListNext (next) == element )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListNext (next) == element", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 251); asm(" break "); } } ; } ;
+ }
+ }
+ { { if (! ( ! dlcl_ListIsEmpty (list) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "! dlcl_ListIsEmpty (list)", "/root/root4/orion/hw/include/../../cosine/common/inc/dlclist.h", 254); asm(" break "); } } ; } ;
+}
+
+
+
+
+
+# 54 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef
+struct q_head_s
+{
+ dlcl_list_t head;
+ int count;
+} q_head_t;
+
+typedef dlcl_list_t q_element_t;
+
+
+
+extern int q_isEmpty (q_head_t *qh);
+extern int q_elementNotInQueue (q_element_t *qe);
+extern int q_hasElement (q_head_t *qh,q_element_t *qe);
+extern int q_count (q_head_t *qh);
+extern void q_headInit (q_head_t *qh);
+extern void q_elementInit (q_element_t *qe);
+extern void q_addToTail (q_head_t *qh,q_element_t *qe);
+extern void q_addToHead (q_head_t *qh,q_element_t *qe);
+extern void q_concatenate (q_head_t *destination,q_head_t *source);
+extern q_element_t *q_get (q_head_t *qh);
+extern void q_deleteElement (q_head_t *qh,q_element_t *elem);
+extern q_element_t *q_first (q_head_t *qh);
+extern q_element_t *q_last (q_head_t *qh);
+extern q_element_t *q_next (q_head_t *qh,q_element_t *qe);
+extern q_element_t *q_prev (q_element_t *qe);
+
+
+
+
+
+
+static inline
+int
+q_isEmpty (
+ q_head_t *qh
+)
+{
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 52); asm(" break "); } } ; } ;
+ return dlcl_ListIsEmpty (&qh->head);
+}
+static inline
+int
+q_elementNotInQueue (
+ q_element_t *qe
+)
+{
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 61); asm(" break "); } } ; } ;
+ return dlcl_ListIsEmpty (qe);
+}
+
+static inline
+int
+q_hasElement (
+ q_head_t *qh,
+ q_element_t *qe
+)
+{
+ q_element_t *curr;
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 73); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 74); asm(" break "); } } ; } ;
+ for (curr = qh->head.next; curr != &qh->head; curr = curr->next)
+ {
+ if (curr == qe)
+ return 1 ;
+ }
+ return 0 ;
+}
+
+static inline
+int
+q_count (
+ q_head_t *qh
+)
+{
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 89); asm(" break "); } } ; } ;
+ return qh->count;
+}
+
+
+
+static inline
+void
+q_headInit (
+ q_head_t *qh
+)
+{
+ dlcl_ListInit (&qh->head);
+ qh->count = 0;
+}
+
+static inline
+void
+q_elementInit (
+ q_element_t *qe
+)
+{
+ dlcl_ListInit (qe);
+}
+
+
+
+static inline
+void
+q_addToTail (
+ q_head_t *qh,
+ q_element_t *qe
+)
+{
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 123); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 124); asm(" break "); } } ; } ;
+ { { if (! ( q_elementNotInQueue (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_elementNotInQueue (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 125); asm(" break "); } } ; } ;
+ dlcl_ListAddSingleton (&qh->head, qe);
+ qh->count ++;
+}
+
+static inline
+void
+q_addToHead (
+ q_head_t *qh,
+ q_element_t *qe
+)
+{
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 137); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 138); asm(" break "); } } ; } ;
+ { { if (! ( q_elementNotInQueue (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_elementNotInQueue (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 139); asm(" break "); } } ; } ;
+ dlcl_ListAddSingleton (qh->head.next, qe);
+ qh->count ++;
+}
+
+static inline
+void
+q_concatenate (
+ q_head_t *destination,
+ q_head_t *source
+)
+{
+ { { if (! ( dlcl_ListIsValid (&destination->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&destination->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 151); asm(" break "); } } ; } ;
+ { { if (! ( dlcl_ListIsValid (&source->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&source->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 152); asm(" break "); } } ; } ;
+ if (! q_isEmpty (source))
+ {
+ dlcl_list_t *srcList;
+
+ srcList = source->head.next;
+ dlcl_ListRemove (&source->head);
+ dlcl_ListAdd (&destination->head, srcList);
+ destination->count += source->count;
+ source->count = 0;
+ }
+}
+
+
+static inline
+q_element_t *
+q_get (
+ q_head_t *qh
+)
+{
+ q_element_t *ret = ((void *) 0) ;
+
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 174); asm(" break "); } } ; } ;
+ if (! q_isEmpty (qh))
+ {
+ { { if (! ( q_count (qh) > 0 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_count (qh) > 0", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 177); asm(" break "); } } ; } ;
+ ret = qh->head.next;
+ dlcl_ListRemove (ret);
+ qh->count --;
+ }
+ return ret;
+}
+
+static inline
+void
+q_deleteElement (
+ q_head_t *qh,
+ q_element_t *elem
+)
+{
+ { { if (! ( dlcl_ListIsValid (elem) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (elem)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 192); asm(" break "); } } ; } ;
+ { { if (! ( ! q_isEmpty (qh) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "! q_isEmpty (qh)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 193); asm(" break "); } } ; } ;
+ { { if (! ( q_count (qh) > 0 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_count (qh) > 0", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 194); asm(" break "); } } ; } ;
+ { { if (! ( q_hasElement (qh, elem) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_hasElement (qh, elem)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 195); asm(" break "); } } ; } ;
+ dlcl_ListRemove (elem);
+ qh->count --;
+ { { if (! ( q_count (qh) >= 0 )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "q_count (qh) >= 0", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 198); asm(" break "); } } ; } ;
+}
+
+
+
+static inline
+q_element_t *
+q_first (
+ q_head_t *qh
+)
+{
+ q_element_t *ret = ((void *) 0) ;
+
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 211); asm(" break "); } } ; } ;
+ if (! q_isEmpty (qh))
+ {
+ ret = qh->head.next;
+ }
+ return ret;
+}
+
+static inline
+q_element_t *
+q_last (
+ q_head_t *qh
+)
+{
+ q_element_t *ret = ((void *) 0) ;
+
+ { { if (! ( dlcl_ListIsValid (&qh->head) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (&qh->head)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 227); asm(" break "); } } ; } ;
+ if (! q_isEmpty (qh))
+ {
+ ret = qh->head.prev;
+ }
+ return ret;
+}
+
+static inline
+q_element_t *
+q_next (
+ q_head_t *qh,
+ q_element_t *qe
+)
+{
+ q_element_t *ret = ((void *) 0) ;
+
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 244); asm(" break "); } } ; } ;
+ { { if (! ( ! q_elementNotInQueue (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "! q_elementNotInQueue (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 245); asm(" break "); } } ; } ;
+ if (qe->next != &qh->head)
+ {
+ ret = qe->next;
+ }
+ return ret;
+}
+
+static inline
+q_element_t *
+q_prev (
+ q_element_t *qe
+)
+{
+ q_element_t *ret = ((void *) 0) ;
+
+ { { if (! ( dlcl_ListIsValid (qe) )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "dlcl_ListIsValid (qe)", "/root/root4/orion/hw/include/../../cosine/common/inc/queue.h", 261); asm(" break "); } } ; } ;
+ if (! dlcl_ListIsEmpty (qe))
+ {
+ ret = qe->prev;
+ }
+ return ret;
+}
+
+
+
+
+
+
+# 55 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct tlv1_s {
+ uchar_t tag;
+ uchar_t length;
+};
+typedef struct tlv1_s tlv1_t;
+
+struct tlv2_s {
+ ushort_t tag;
+ ushort_t length;
+};
+typedef struct tlv2_s tlv2_t;
+
+struct tlv3_s {
+ ulong_t tag;
+ ulong_t length;
+};
+typedef struct tlv3_s tlv3_t;
+
+
+
+
+
+static inline
+tlv1_t *tlv1_get_next_tag(tlv1_t *tlv_p, uchar_t tag)
+{
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 57); asm(" break "); } } ; } ;
+ while(tlv_p->tag != 0xFF ) {
+ if (tlv_p->tag == tag)
+ return tlv_p;
+ tlv_p = (tlv1_t *)((char *) tlv_p + sizeof(tlv1_t) + tlv_p ->length) ;
+ }
+
+ return ((void *) 0) ;
+}
+static inline
+void tlv1_get_value(tlv1_t *tlv_p, void *value_p)
+{
+ { { if (! ( value_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "value_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 69); asm(" break "); } } ; } ;
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 70); asm(" break "); } } ; } ;
+ memcpy(value_p, (char *)(tlv_p+1), tlv_p->length);
+}
+
+static inline
+tlv2_t *tlv2_get_next_tag(tlv2_t *tlv_p, ushort_t tag)
+{
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 77); asm(" break "); } } ; } ;
+ while(tlv_p->tag != 0xFFFF ) {
+ if (tlv_p->tag == tag)
+ return tlv_p;
+ tlv_p = (tlv2_t *)((char *) tlv_p + sizeof(tlv2_t) + tlv_p ->length) ;
+ }
+
+ return ((void *) 0) ;
+}
+static inline
+void tlv2_get_value(tlv2_t *tlv_p, void *value_p)
+{
+ { { if (! ( value_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "value_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 89); asm(" break "); } } ; } ;
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 90); asm(" break "); } } ; } ;
+ memcpy(value_p, (char *)(tlv_p+1), tlv_p->length);
+}
+
+static inline
+tlv3_t *tlv3_get_next_tag(tlv3_t *tlv_p, ulong_t tag)
+{
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 97); asm(" break "); } } ; } ;
+ while(tlv_p->tag != 0xFFFFFFFF ) {
+ if (tlv_p->tag == tag)
+ return tlv_p;
+ tlv_p = (tlv3_t *)((char *) tlv_p + sizeof(tlv3_t) + tlv_p ->length) ;
+ }
+
+ return ((void *) 0) ;
+}
+static inline
+void tlv3_get_value(tlv3_t *tlv_p, void *value_p)
+{
+ { { if (! ( value_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "value_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 109); asm(" break "); } } ; } ;
+ { { if (! ( tlv_p )) { extern _cosine_task_suspend_on_error (void); printf ("Assertion: \"%s\"\n\tfailed in file %s at line %d\n", "tlv_p", "/root/root4/orion/hw/include/../../cosine/common/inc/tlv.h", 110); asm(" break "); } } ; } ;
+ memcpy(value_p, (char *)(tlv_p+1), tlv_p->length);
+}
+
+
+
+
+
+
+# 56 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+
+# 1 "/root/root4/orion/hw/include/../../cosine/common/inc/modules.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 60 "/root/root4/orion/hw/include/hw.boot.h" 2
+
+
+
+
+# 11 "/root/root4/orion/hw/orion.hw.init.c" 2
+
+# 1 "/root/root4/orion/hw/include/board.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/hw/include/board_map.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/os/regaeos/include/cpu4000.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef U32 instr_t;
+
+
+
+
+
+
+
+
+
+# 17 "/root/root4/orion/hw/include/board_map.h" 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 1 "/root/root4/orion/hw/include/gt64120.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 190 "/root/root4/orion/hw/include/board_map.h" 2
+
+
+
+
+
+
+
+
+
+# 19 "/root/root4/orion/hw/include/board.h" 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 12 "/root/root4/orion/hw/orion.hw.init.c" 2
+
+
+# 1 "/root/root4/orion/hw/include/qpic.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct Qpic_Registers_S
+{
+ U16 QpicId;
+ U16 MiscCtrl;
+ U16 IntStat;
+ U16 IntMask;
+ U16 BusErrorCapture[2];
+ U16 Status;
+
+
+ U16 filler[0x79];
+
+
+ U16 LocalBusConfig[32];
+} Qpic_Registers_T;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 14 "/root/root4/orion/hw/orion.hw.init.c" 2
+
+# 1 "/root/root4/orion/hw/include/cupid.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct Cupid_Registers_S
+{
+ U16 Id;
+ U16 PeConfig;
+ U16 Led;
+ U16 TempSensor;
+ U16 LaserId;
+ U16 RtcReg;
+ U16 Reset;
+
+ U16 filler1[9];
+
+ U16 InterruptMap[7 ][2 ];
+
+ U16 filler2[2];
+
+ U16 Id_Struc[8];
+
+ U16 filler3[8];
+
+ U16 Control[2];
+ U16 Status[2];
+
+ U16 filler4[12];
+
+ U16 Ds3BitsLed;
+ U16 Ds3Led1;
+ U16 Ds3Led2;
+ U16 Ds3Led3;
+ U16 Ds3ClkCtrl;
+
+} Cupid_Registers_T;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct Cupid_CIB_Ver1_S
+{
+ U8 cib_version;
+ U8 blade_id;
+ U8 pe_id;
+ U8 blade_type;
+ U8 pe_type;
+ U8 Fpga_Set_Id[4];
+ U8 Fpga_Set_Rev[6];
+
+ U8 Expansion_TLV[17];
+} Cupid_CIB_Ver1_T;
+
+extern Cupid_CIB_Ver1_T *find_cib_ptr();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 15 "/root/root4/orion/hw/orion.hw.init.c" 2
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char UCHAR;
+ipsx_pe_type_t local_pe_type;
+
+
+address_space_t local_address_space_id;
+ ipsx_slot_id_t local_slot_id;
+ipsx_pe_id_t local_pe_id;
+ ipsx_blade_type_t local_blade_type;
+
+
+
+
+
+
+extern U32 GetRamBanks(U32 *base_array, U32 *top_array);
+
+
+
+
+
+
+typedef struct ChipSelect_S
+{
+ U8 cs_number;
+ U16 cs_config;
+} ChipSelect_T;
+
+
+
+typedef struct InterruptMap_S
+{
+ U8 cpu_int;
+ U32 int_mapping;
+} InterruptMap_T;
+
+
+
+
+typedef unsigned long ULONG;
+
+
+
+ULONG cpuClkRate;
+
+
+
+
+void InitCIB(void);
+void InitQpic(void);
+void InitCupid(void);
+
+
+
+
+
+extern ulong_t memsize;
+
+
+
+extern void SerChipInit();
+extern long SerChipOpen();
+extern long SerChipSend();
+extern long SerChipIoctl();
+extern long SerChipClose();
+
+
+
+
+
+
+static ChipSelect_T EthernetChipSelectConfig[] =
+{
+ {0 , (0x0008 | 0x0000 )},
+ {6 , (0x0010 | 0x0000 )},
+ {7 , (0x0004 | 0x0000 )},
+ {8 , (0x0000 | 0x0000 )},
+ {9 , (0x0000 | 0x0000 )},
+ {10 , (0x0000 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0004 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+static ChipSelect_T CryptoChipSelectConfig[] =
+{
+ {6 , (0x0000 | 0x0000 )},
+ {7 , (0x0000 | 0x0000 )},
+ {8 , (0x0000 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0000 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+static ChipSelect_T Ds3ChipSelectConfig[] =
+{
+ {0 , (0x0008 | 0x0000 )},
+ {1 , (0x0008 | 0x0000 )},
+ {2 , (0x0008 | 0x0000 )},
+ {3 , (0x0008 | 0x0000 )},
+ {4 , (0x0008 | 0x0000 )},
+ {5 , (0x0008 | 0x0000 )},
+ {8 , (0x0000 | 0x0000 )},
+ {10 , (0x0000 | 0x0000 )},
+ {6 , (0x0008 | 0x0000 )},
+ {11 , (0x0008 | 0x0000 )},
+ {12 , (0x0008 | 0x0000 )},
+ {13 , (0x0008 | 0x0000 )},
+ {15 , (0x0008 | 0x0004 | 0x0000 )},
+ {14 , (0x0008 | 0x0004 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0000 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+static ChipSelect_T SearchChipSelectConfig[] =
+{
+ {6 , (0x0000 | 0x0000 )},
+ {7 , (0x0000 | 0x0000 )},
+ {8 , (0x0000 | 0x0000 )},
+ {9 , (0x0000 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0000 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+static ChipSelect_T ProcessorChipSelectConfig[] =
+{
+ {0 , (0x0008 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0000 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+static ChipSelect_T Oc3ChipSelectConfig[] =
+{
+ {0 , (0x0008 | 0x0000 )},
+ {10 , (0x0000 | 0x0000 )},
+ {16 , (0x0000 | 0x0000 )},
+ {17 , (0x0000 | 0x0000 )},
+ {18 , (0x0000 | 0x0000 )},
+ {27 , (0x0000 | 0x0000 )},
+ {28 , (0x0000 | 0x0000 )},
+ {0xff , 0}
+};
+
+
+
+
+
+
+
+
+
+
+
+static InterruptMap_T EthernetIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 | 0x02000000 | 0x04000000 )},
+ {(4 -2), (0x00080000 | 0x00100000 | 0x00200000 )},
+ {3 , (0x00000800 | 0x00001000 )},
+ {4 , (0x00008000 | 0x00020000 )},
+ {0xff , 0}
+};
+
+
+static InterruptMap_T CryptoIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 | 0x00000008 | 0x00000010 )},
+ {(4 -2), (0x00080000 | 0x00100000 | 0x00200000 )},
+ {3 , (0x00000002 | 0x00000004 )},
+ {4 , (0x00020000 )},
+ {0xff , 0}
+};
+
+
+static InterruptMap_T Ds3ChanIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 | 0x02000000 | 0x04000000 )},
+ {(4 -2), (0x00080000 | 0x00100000 | 0x00200000 )},
+ {2 , (0x00000001 | 0x00000002 )},
+ {3 , (0x00000200 | 0x00000100 | 0x00000080 | 0x00000040 | 0x00000020 | 0x00000010 | 0x00000008 )},
+ {4 , (0x00008000 | 0x00020000 )},
+ {0xff , 0}
+};
+static InterruptMap_T Ds3UnchanIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 | 0x00000400 )},
+ {(4 -2), (0x00080000 | 0x00100000 | 0x00200000 )},
+ {2 , (0x00000002 )},
+ {3 , (0x00000400 )},
+ {4 , (0x00008000 | 0x00020000 )},
+ {0xff , 0}
+};
+
+
+static InterruptMap_T SearchIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 )},
+ {0xff , 0}
+};
+
+
+static InterruptMap_T ProcessorIntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 )},
+ {4 , (0x00008000 | 0x00020000 )},
+ {0xff , 0}
+};
+
+
+static InterruptMap_T Oc3IntMap[] =
+{
+ {(2 -2), (0x00010000 )},
+ {(3 -2), (0x00040000 | 0x00000004 )},
+ {(4 -2), (0x00080000 | 0x00100000 | 0x00000040 )},
+ {3 , (0x00000008 )},
+ {4 , (0x00008000 | 0x00020000 )},
+ {0xff , 0}
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void InitQpic(void)
+{
+ Qpic_Registers_T *regs;
+ U32 i = 0;
+ ChipSelect_T *ChipSelectConfig;
+ U32 bank_cnt;
+ U32 bank_base[4], bank_top[4];
+
+ regs = (Qpic_Registers_T *)((unsigned)( 0x17B00000 )|0xA0000000) ;
+
+
+ switch (local_pe_type)
+ {
+ case 1 :
+ ChipSelectConfig = (ChipSelect_T *)&EthernetChipSelectConfig[0].cs_number;
+ break;
+ case 2 :
+ ChipSelectConfig = (ChipSelect_T *)&EthernetChipSelectConfig[0].cs_number;
+ break;
+ case 3 :
+ case 12 :
+ ChipSelectConfig = (ChipSelect_T *)&ProcessorChipSelectConfig[0].cs_number;
+ break;
+ case 4 :
+ ChipSelectConfig = (ChipSelect_T *)&SearchChipSelectConfig[0].cs_number;
+ break;
+ case 5 :
+ ChipSelectConfig = (ChipSelect_T *)&CryptoChipSelectConfig[0].cs_number;
+ break;
+ case 6 :
+ case 7 :
+ ChipSelectConfig = (ChipSelect_T *)&Ds3ChipSelectConfig[0].cs_number;
+ break;
+ case 8 :
+ case 9 :
+ case 10 :
+ case 11 :
+ ChipSelectConfig = (ChipSelect_T *)&Oc3ChipSelectConfig[0].cs_number;
+ break;
+ default:
+ while(1 );
+
+ break;
+ }
+
+
+ while(ChipSelectConfig[i].cs_number != 0xff )
+ {
+ regs->LocalBusConfig[ChipSelectConfig[i].cs_number] =
+ ChipSelectConfig[i].cs_config;
+ i++;
+ }
+
+
+ if ( (regs->Status & 0x0001 ) == 0x0001 )
+ regs->LocalBusConfig[28 ] |= 0x0004 ;
+ else
+ regs->LocalBusConfig[28 ] &= ~0x0004 ;
+
+
+ regs->MiscCtrl = 0x0001 ;
+
+
+ bank_cnt = GetRamBanks(bank_base, bank_top);
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void InitCupid(void)
+{
+ U32 i;
+ Cupid_Registers_T *regs;
+ InterruptMap_T *CupidIntMap;
+
+ regs = (Cupid_Registers_T *)((unsigned)( 0x17100000 )|0xA0000000) ;
+
+
+ switch (local_pe_type)
+ {
+ case 1 :
+ CupidIntMap = (InterruptMap_T *)&EthernetIntMap[0].cpu_int;
+ break;
+ case 2 :
+ CupidIntMap = (InterruptMap_T *)&EthernetIntMap[0].cpu_int;
+ break;
+ case 3 :
+ case 12 :
+ CupidIntMap = (InterruptMap_T *)&ProcessorIntMap[0].cpu_int;
+ break;
+ case 4 :
+ CupidIntMap = (InterruptMap_T *)&SearchIntMap[0].cpu_int;
+ break;
+ case 5 :
+ CupidIntMap = (InterruptMap_T *)&CryptoIntMap[0].cpu_int;
+ break;
+ case 6 :
+ CupidIntMap = (InterruptMap_T *)&Ds3ChanIntMap[0].cpu_int;
+ break;
+ case 7 :
+ CupidIntMap = (InterruptMap_T *)&Ds3UnchanIntMap[0].cpu_int;
+ break;
+ case 8 :
+ case 9 :
+ case 10 :
+ case 11 :
+ CupidIntMap = (InterruptMap_T *)&Oc3IntMap[0].cpu_int;
+ break;
+ default:
+ while(1 );
+
+
+ break;
+ }
+
+
+ for(i = 0; i < 7 ; i++)
+ {
+ regs->InterruptMap[i][0 ] = 0;
+ regs->InterruptMap[i][1 ] = 0;
+ }
+
+ i = 0;
+ while(CupidIntMap[i].cpu_int != 0xff )
+ {
+ regs->InterruptMap[CupidIntMap[i].cpu_int][0 ] |=
+ (U16)(CupidIntMap[i].int_mapping & 0xffff);
+ regs->InterruptMap[CupidIntMap[i].cpu_int][1 ] |=
+ (U16)(CupidIntMap[i].int_mapping >> 16);
+ i++;
+ }
+
+ return;
+}
+
+
+
+
+
+
+void InitCIB()
+{
+ Cupid_CIB_Ver1_T *cib_p;
+
+ cib_p = find_cib_ptr() ;
+
+ local_address_space_id = (cib_p->blade_id << 3) | cib_p->pe_id;
+ local_slot_id = cib_p->blade_id;
+ local_pe_id = cib_p->pe_id;
+ local_blade_type = cib_p->blade_type;
+ local_pe_type = cib_p->pe_type;
+
+}
+
+
+
+
+
+
+
+
+
+unsigned long BspRamBase(void)
+{
+return ((unsigned)( 0x00000000 )|0x80000000) ;
+}
+
+
+
+
+
+
+
+
+unsigned long BspCpuType(void)
+{
+ return(4 );
+}
+
+
+
+
+
+
+
+
+
+
+
+
+void BoardSysStartCO(void)
+{
+}
+
+U32 GetRamBanks(U32 *base_array, U32 *top_array)
+{
+ U32 bank_count = 0;
+ U32 i;
+ U32 gt_base_reg, gt_top_reg;
+
+
+ if ( (((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x400) )&0xff)<<24)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x400) )&0xff00)<<8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x400) )&0xff0000)>>8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x400) )&0xff000000)>>24)) != 0x000000ff)
+ {
+ bank_count++;
+ if ( (((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x408) )&0xff)<<24)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x408) )&0xff00)<<8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x408) )&0xff0000)>>8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x408) )&0xff000000)>>24)) != 0x000000ff)
+ {
+ bank_count++;
+ if ( (((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x410) )&0xff)<<24)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x410) )&0xff00)<<8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x410) )&0xff0000)>>8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x410) )&0xff000000)>>24)) != 0x000000ff)
+ {
+ bank_count++;
+ if ( (((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x418) )&0xff)<<24)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x418) )&0xff00)<<8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x418) )&0xff0000)>>8)+ ((( *(U32 *)(((unsigned)( 0x14000000 )|0xA0000000) + 0x418) )&0xff000000)>>24)) != 0x000000ff)
+ bank_count++;
+ }
+ }
+ }
+
+ if (bank_count > 4)
+ return(0);
+
+
+ for (i = 0; i < bank_count; i++)
+ {
+ switch (i)
+ {
+ case 0:
+ gt_base_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x400) ;
+ gt_top_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x404) ;
+ break;
+
+ case 1:
+ gt_base_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x408) ;
+ gt_top_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x40C) ;
+ break;
+
+ case 2:
+ gt_base_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x410) ;
+ gt_top_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x414) ;
+ break;
+
+ case 3:
+ gt_base_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x418) ;
+ gt_top_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x41C) ;
+ break;
+
+ default:
+ gt_base_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x400) ;
+ gt_top_reg = (((unsigned)( 0x14000000 )|0xA0000000) + 0x404) ;
+ break;
+ }
+ base_array[i] = ((unsigned)( (((( *(U32 *)gt_base_reg )&0xff)<<24)+ ((( *(U32 *)gt_base_reg )&0xff00)<<8)+ ((( *(U32 *)gt_base_reg )&0xff0000)>>8)+ ((( *(U32 *)gt_base_reg )&0xff000000)>>24)) << 20 )|0x80000000) ;
+ top_array[i] = ((unsigned)( ((((( *(U32 *)gt_top_reg )&0xff)<<24)+ ((( *(U32 *)gt_top_reg )&0xff00)<<8)+ ((( *(U32 *)gt_top_reg )&0xff0000)>>8)+ ((( *(U32 *)gt_top_reg )&0xff000000)>>24)) << 20) | 0x000fffff )|0x80000000) ;
+ }
+
+ return(bank_count);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+Cupid_CIB_Ver1_T *cib;
+
+
+
+
+void read_fpga_revs();
+Cupid_CIB_Ver1_T *find_cib_ptr();
+
+
+
+
+
+
+
+
+
+
+
+# 606 "/root/root4/orion/hw/orion.hw.init.c"
+
+Cupid_CIB_Ver1_T *find_cib_ptr()
+{
+ return ((Cupid_CIB_Ver1_T *)(((unsigned)( 0x17100000 )|0xA0000000) + 0x220 ) );
+}
+
+
+
+struct fpga_header_s {
+ uchar_t x1;
+ uchar_t t1[3];
+ uchar_t x2;
+ uchar_t t2;
+ uchar_t lhi[2];
+ uchar_t x3;
+ uchar_t llo[2];
+ uchar_t z1;
+ uchar_t x4;
+ uchar_t z2[3];
+};
+typedef struct fpga_header_s fpga_header_t;
+
+struct fpga_tlv_s {
+ ulong_t length;
+ ulong_t tag;
+};
+typedef struct fpga_tlv_s fpga_tlv_t;
+
+
+
+char fpga_rev_str[0x1000];
diff --git a/arch/mips/orion/promcon.c b/arch/mips/orion/promcon.c
index 29b702f7f..de5b0ea00 100644
--- a/arch/mips/orion/promcon.c
+++ b/arch/mips/orion/promcon.c
@@ -7,16 +7,13 @@
* Derived from DECstation promcon.c
* Copyright (c) 1998 Harald Koerfgen
*/
-
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/ptrace.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/fs.h>
-/*
-#include <asm/sgialib.h>
-*/
+
extern void prom_printf(char *fmt, ...);
unsigned long splx(unsigned long mask){return 0;}
#if 0
@@ -34,67 +31,69 @@ extern void SerialPollConout(unsigned char c);
static void prom_console_write(struct console *co, const char *s,
unsigned count)
{
- unsigned i;
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++) {
- if (*s == 10)
- SerialPollConout(13);
- SerialPollConout(*s++);
- }
+ unsigned i;
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++) {
+ if (*s == 10)
+ SerialPollConout(13);
+ SerialPollConout(*s++);
+ }
}
+
extern int prom_getchar(void);
static int prom_console_wait_key(struct console *co)
{
- return prom_getchar();
+ return prom_getchar();
}
extern void SerialPollInit(void);
extern void SerialSetup(unsigned long baud, unsigned long console, unsigned long host, unsigned long intr_desc);
static int __init prom_console_setup(struct console *co, char *options)
{
- SerialSetup(19200,1,1,3);
- SerialPollInit();
- SerialPollOn();
- return 0;
+ SerialSetup(19200,1,1,3);
+ SerialPollInit();
+ SerialPollOn();
+
+ return 0;
}
static kdev_t prom_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return MKDEV(TTY_MAJOR, 64 + c->index);
}
static struct console sercons =
{
- "ttyS",
- prom_console_write,
- NULL,
- prom_console_device,
- prom_console_wait_key,
- NULL,
- prom_console_setup,
- CON_PRINTBUFFER,
- -1,
- 0,
- NULL
+ "ttyS",
+ prom_console_write,
+ NULL,
+ prom_console_device,
+ prom_console_wait_key,
+ NULL,
+ prom_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
};
/*
* Register console.
*/
-
+extern void zs_serial_console_init();
void serial_console_init(void)
{
register_console(&sercons);
+ /*zs_serial_console_init();*/
}
-extern void prom_putchar(int mychar);
+void prom_putchar(char c);
static char ppbuf[1000];
-
void prom_printf(char *fmt, ...)
{
va_list args;
@@ -116,10 +115,73 @@ void prom_printf(char *fmt, ...)
return;
}
+#define kSCC_Control 0xbf200008
+#define kSCC_Data (kSCC_Control + 4)
+
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+
+static inline void RegisterDelay(void)
+{
+ int delay = 2*125; /* Assuming 4us clock. */
+ while (delay--);
+}
+
+static inline unsigned char read_zsreg(unsigned char reg)
+{
+ unsigned char retval;
+
+ if (reg != 0) {
+ *(volatile unsigned char *)kSCC_Control = reg & 0xf;
+ RegisterDelay();
+ }
+
+ retval = *(volatile unsigned char *) kSCC_Control;
+ RegisterDelay();
+ return retval;
+}
+
+static inline void write_zsreg(unsigned char reg, unsigned char value)
+{
+ if (reg != 0) {
+ *((volatile unsigned char *) (kSCC_Control)) = reg & 0xf ;
+ RegisterDelay();
+ }
+
+ *((volatile unsigned char *) (kSCC_Control)) = value ;
+ RegisterDelay();
+}
+
+static inline unsigned char read_zsdata(void)
+{
+ unsigned char retval;
+
+ retval = *(volatile unsigned char *)kSCC_Data;
+ RegisterDelay();
+
+ return retval;
+}
+
+static inline void write_zsdata(unsigned char value)
+{
+ *(volatile unsigned char *)kSCC_Data = value;
+ RegisterDelay();
+
+ return;
+}
+
+void prom_putchar(char c)
+{
+ while ((read_zsreg(0) & Tx_BUF_EMP) == 0)
+ RegisterDelay();
+ write_zsdata(c);
+}
+
+int prom_getchar(void)
+{
+ return 0;
+}
-void prom_putchar(int mychar){}
-int prom_getchar(void){return 0;}
struct app_header_s {
unsigned long MAGIC_JMP;
unsigned long MAGIC_NOP;
@@ -139,6 +201,7 @@ struct app_header_s {
unsigned long crc;
unsigned long reserved;
};
+
typedef struct app_header_s app_header_t;
char linked_app_name[]="linux";
char *linked_app_name_p=&linked_app_name[0];
diff --git a/arch/mips/orion/serial.8530.c b/arch/mips/orion/serial.8530.c
new file mode 100644
index 000000000..69394f8dd
--- /dev/null
+++ b/arch/mips/orion/serial.8530.c
@@ -0,0 +1,815 @@
+# 1 "/root/root4/orion/os/regaeos/sys/libsys/serial.8530.c"
+
+
+
+
+
+
+# 1 "/root/root4/orion/os/regaeos/sys/include/basics.h" 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef char S8;
+typedef unsigned char U8;
+typedef short S16;
+typedef unsigned short U16;
+typedef int S32;
+typedef unsigned int U32;
+typedef int BOOL;
+
+
+
+
+
+
+
+
+
+
+
+typedef U32 (*U32FUNC)();
+typedef S32 (*S32FUNC)();
+typedef void (*VFUNC)();
+
+
+
+
+extern void SerialSetup(U32 baud, U32 console, U32 host, U32 intr_desc);
+extern void SerialPollOn(void);
+extern void SerialPollOff(void);
+extern void SerialPollInit(void);
+extern U32 SerialPollConsts(U32 typecode);
+extern U8 SerialPollConin(void);
+extern void SerialPollConout(U8 c);
+extern U32 SerialPollHststs(U32 typecode);
+extern U8 SerialPollHstin(void);
+void SerialPollHstout(U8 c);
+void *SerialIntInit(U32 channel,
+ void (*rx_isr)(U32 channel),
+ void (*tx_char)(U32 unit, U32 isr_flag));
+U32 SerialIntBaud(U32 channel, void *hdp, U32 baudrate);
+void SerialIntRxioff(U32 channel, void *hdp);
+void SerialIntRxion(U32 channel, void *hdp);
+void SerialIntTxioff(U32 channel, void *hdp);
+void SerialIntTxion(U32 channel, void *hdp);
+U32 SerialIntRead(U32 channel, void *hdp, U8 *ch_ptr);
+U32 SerialIntWrite(U32 channel, void *hdp, U8 ch);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef U32 instr_t;
+
+
+
+
+
+
+
+typedef volatile struct
+{
+ U8 control;
+ U8 pad1[3];
+ U8 data;
+ U8 pad2[3];
+} Z8530_SCC;
+
+
+
+
+
+
+
+static Z8530_SCC * const scc_port[2 + 1] = { 0, ((Z8530_SCC *) ((unsigned)( 0x1F200108 )|0xA0000000) ) , ((Z8530_SCC *) ((unsigned)( 0x1F200108 )|0xA0000000) ) };
+static U8 pin;
+
+
+
+
+
+
+
+
+
+
+typedef volatile struct
+{
+ U16 time_const;
+ U8 int_mode;
+ U8 rxint_mask;
+ U8 txint_mask;
+ U8 wr3_val;
+ U8 wr5_val;
+} SCC_DATA;
+
+
+
+
+static SCC_DATA scc_data[2 + 1];
+static U32 pROBE_console, pROBE_host;
+
+
+
+
+
+static U8 Break_Recorded[2 + 1];
+
+
+
+
+
+
+static void (*Rx_Isr[2 + 1])(U32 channel);
+static void (*Tx_Isr[2 + 1])(U32 channel, U32 isr_flag);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static U8 rd_ctrl(U32 channel, U8 regnum);
+static void wr_ctrl(U32 channel, U8 regnum, U8 value);
+static void isr_uart(void);
+static void dummy_isr(void);
+
+
+
+
+
+volatile U32 serial_unused;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static void wr_ctrl(U32 channel, U8 regnum, U8 value)
+{
+ U32 imask;
+ char tmp;
+
+ if (regnum == 0)
+ {
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ scc_port[channel]->control = value;
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ }
+ else
+ {
+
+ imask = splx(7);
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ scc_port[channel]->control = regnum;
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ scc_port[channel]->control = value;
+ splx(imask);
+ }
+}
+
+
+
+
+
+
+
+
+static U8 rd_ctrl(U32 channel, U8 regnum)
+{
+ U32 imask;
+ U8 value;
+ char tmp;
+
+ if (regnum == 0)
+ {
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ value = scc_port[channel]->control;
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ }
+ else
+ {
+ imask = splx(7);
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ scc_port[channel]->control = regnum;
+
+ tmp = *(char *)(((unsigned)( 0x1FC00000 )|0xA0000000) );
+ value = scc_port[channel]->control;
+ splx(imask);
+ }
+
+ return value;
+}
+
+
+
+
+
+
+
+static void Channel_Enable(U32 channel)
+{
+
+
+
+ wr_ctrl(channel, 12 , scc_data[channel].time_const & 0xFF);
+ wr_ctrl(channel, 13 , scc_data[channel].time_const >> 8);
+
+
+
+
+ wr_ctrl(channel, 14 , 0x01 );
+
+
+
+
+ wr_ctrl(channel, 3 , scc_data[channel].wr3_val | 1);
+
+
+
+
+ wr_ctrl(channel, 5 , scc_data[channel].wr5_val | 8);
+
+
+
+
+
+ wr_ctrl(channel, 0 , 0x10 );
+ wr_ctrl(channel, 9 , 0x0A );
+}
+
+
+
+
+
+
+
+static void Channel_Disable(U32 channel)
+{
+
+
+
+ wr_ctrl(channel, 14 , 0x00 );
+
+
+
+
+ wr_ctrl(channel, 3 , scc_data[channel].wr3_val & ~1);
+
+
+
+
+ wr_ctrl(channel, 5 , scc_data[channel].wr5_val & ~8);
+}
+
+
+
+
+
+
+
+
+
+
+static U16 Baud_to_TC(U32 baud_rate)
+{
+ int i;
+
+
+
+
+ const static U32 baudtable[9][2] =
+ {
+ {300, (3686400 /(32*300)-2)},
+ {600, (3686400 /(32*600)-2)},
+ {1200, (3686400 /(32*1200)-2)},
+ {2400, (3686400 /(32*2400)-2)},
+ {4800, (3686400 /(32*4800)-2)},
+ {9600, (3686400 /(32*9600)-2)},
+ {19200, (3686400 /(32*19200)-2)},
+ {38400, (3686400 /(32*38400)-2)},
+ {0, (3686400 /(32*9600)-2)}
+ };
+
+
+
+
+ for (i = 0; baudtable[i][0] && (baudtable[i][0] != baud_rate); i++)
+ ;
+
+ return baudtable[i][1];
+}
+
+
+
+
+static void dummy_rx_isr(U32 channel) { serial_unused = channel; }
+
+
+
+
+
+
+static void isr_uart(void)
+{
+ U8 ipend;
+ U32 channel_A, channel_B;
+ U32 chipNo;
+
+
+
+
+
+ for (chipNo = 1; chipNo <= (2 /2); chipNo++)
+ {
+ channel_A = ((chipNo - 1) << 1) + 1;
+ channel_B = ((chipNo - 1) << 1) + 2;
+
+
+
+ if ((ipend = rd_ctrl(channel_A, 3 )) != 0)
+ {
+
+
+
+ if (ipend & 0x08 )
+ {
+
+
+
+ wr_ctrl(channel_A, 15 , 0x00 );
+ Break_Recorded[channel_A] = 1;
+ wr_ctrl(channel_A, 0 , 0x10 );
+ }
+ else if (ipend & scc_data[channel_A].rxint_mask)
+ {
+ (*Rx_Isr[channel_A])(channel_A);
+ }
+
+ if (ipend & scc_data[channel_A].txint_mask)
+ (*Tx_Isr[channel_A])(channel_A, 1);
+
+
+
+
+ if (ipend & 0x01 )
+ {
+ wr_ctrl(channel_B, 15 , 0x00 );
+ Break_Recorded[channel_B] = 1;
+ wr_ctrl(channel_B, 0 , 0x10 );
+ }
+ else if (ipend & scc_data[channel_B].rxint_mask)
+ {
+ (*Rx_Isr[channel_B])(channel_B);
+ }
+
+ if (ipend & scc_data[channel_B].txint_mask)
+ (*Tx_Isr[channel_B])(channel_B, 1);
+
+
+
+
+
+ wr_ctrl(channel_A, 0 , 0x38 );
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+unsigned short save_time_const;
+
+void SerialSetup(U32 baud_rate, U32 cnsl_chnl, U32 host_chnl, U32 intr_desc)
+{
+ int channel;
+
+ pin = 0;
+
+
+
+ pROBE_console = cnsl_chnl;
+ pROBE_host = host_chnl;
+
+
+
+
+ for (channel = 1; channel <= 2 ; channel++)
+ {
+ scc_data[channel].int_mode = 0;
+ if ((channel == 1) || (channel == 3))
+ {
+ scc_data[channel].rxint_mask = 0x20;
+ scc_data[channel].txint_mask = 0x10;
+ }
+ else
+ {
+ scc_data[channel].rxint_mask = 0x04;
+ scc_data[channel].txint_mask = 0x02;
+ }
+ scc_data[channel].time_const = Baud_to_TC(baud_rate);
+ save_time_const = scc_data[channel].time_const;
+
+
+
+
+
+
+
+
+ if ((channel == 1) || (channel == 3))
+ wr_ctrl(channel, 9 , 0x80);
+ else
+ wr_ctrl(channel, 9 , 0x40);
+
+
+
+
+ wr_ctrl(channel, 4 , 0x44);
+
+ wr_ctrl(channel, 1 , 0);
+
+
+
+
+
+
+ wr_ctrl(channel, 3 , scc_data[channel].wr3_val = 0xC0);
+
+
+
+
+ wr_ctrl(channel, 5 , scc_data[channel].wr5_val = 0xE2);
+
+ wr_ctrl(channel, 6 , 0);
+
+ wr_ctrl(channel, 7 , 0);
+
+ wr_ctrl(channel, 9 , 0);
+
+ wr_ctrl(channel, 10 , 0);
+
+ wr_ctrl(channel, 11 , 0x52);
+
+
+
+ if (channel == pROBE_console)
+ {
+ Rx_Isr[channel] = dummy_rx_isr;
+ wr_ctrl(channel, 15 , 0x80 );
+ scc_data[channel].int_mode = 0x01 ;
+ wr_ctrl(channel, 1 , 0x01 );
+ }
+ else
+ wr_ctrl(channel, 15 , 0x00 );
+ }
+
+
+
+
+ Break_Recorded[1] = Break_Recorded[2] = 0;
+ Break_Recorded[3] = Break_Recorded[4] = 0;
+
+}
+
+
+
+
+
+
+
+
+void SerialPollOn(void)
+{
+
+
+
+ wr_ctrl(pROBE_console, 9 , 0);
+}
+
+
+
+
+
+
+
+
+
+void SerialPollOff(void)
+{
+ wr_ctrl(pROBE_console, 9 , 0x0A );
+}
+
+
+
+
+
+void SerialPollInit(void)
+{
+ Channel_Enable(pROBE_console);
+
+ if (pROBE_host)
+ {
+ Channel_Enable(pROBE_host);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+U32 SerialPollChanSts(long channel)
+{
+ U8 reg_val;
+
+
+
+
+ if (Break_Recorded[channel])
+ {
+
+
+
+
+
+ do {
+ wr_ctrl(channel, 0 , 0x30 );
+ wr_ctrl(channel, 0 , 0x10 );
+ }
+ while (rd_ctrl(channel, 0 ) & 0x80 );
+
+ Break_Recorded[channel] = 0;
+ wr_ctrl(channel, 15 , 0x80 );
+ return 2;
+ }
+
+ for (;;)
+ {
+ reg_val = rd_ctrl(channel, 0 );
+
+ if (reg_val & 0x80 )
+ {
+
+
+
+
+ do {
+ wr_ctrl(channel, 0 , 0x30 );
+ wr_ctrl(channel, 0 , 0x10 );
+ }
+ while (rd_ctrl(channel, 0 ) & 0x80 );
+
+ reg_val = scc_port[channel]->data;
+ return 2;
+ }
+ else if (reg_val & 0x01 )
+ {
+
+
+
+
+
+
+ reg_val = rd_ctrl(channel, 1 );
+
+ if ((reg_val & 0x70 ) == 0)
+ {
+ rd_ctrl(channel, 0 );
+ return 1;
+ }
+ else
+ {
+ SerialPollConin();
+ wr_ctrl(channel, 0 , 0x30 );
+ }
+ }
+ else
+
+
+
+ return 0;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+U32 SerialPollConsts(U32 typecode)
+{
+ serial_unused = typecode;
+ return (SerialPollChanSts(pROBE_console));
+}
+
+
+
+
+
+
+
+
+
+U8 SerialPollChanIn(long channel)
+{
+ return scc_port[channel]->data;
+}
+
+
+
+
+
+
+
+
+
+U8 SerialPollConin(void)
+{
+ return (SerialPollChanIn(pROBE_console));
+}
+
+
+
+
+
+
+
+void SerialPollChanOut(U32 channel, U8 c)
+{
+ while ((rd_ctrl(channel, 0 ) & 0x04 ) == 0)
+ ;
+
+ scc_port[channel]->data = c;
+}
+
+
+
+
+
+
+
+extern char* mem2hex( char* mem,
+ char* buf,
+ int count);
+extern void putpacket(char * buffer);
+
+
+void SerialPollConout(U8 c)
+{
+ SerialPollChanOut(pROBE_console, c);
+}
+
+
+
+
+
+
+
+
+
+
+U32 SerialPollHststs(U32 typecode)
+{
+ U8 reg_val;
+ U32 ret_code;
+
+ serial_unused = typecode;
+
+
+
+
+
+ ret_code = 3;
+
+ while (ret_code == 3)
+ {
+ reg_val = rd_ctrl(pROBE_host, 0 );
+
+ if (reg_val & 0x01 )
+ {
+
+
+
+
+
+
+ reg_val = rd_ctrl(pROBE_host, 1 );
+
+ if ((reg_val & 0x20 ) == 0)
+ {
+ reg_val = rd_ctrl(pROBE_host, 0 );
+ ret_code = 1;
+ }
+ else
+ SerialPollHstin();
+ }
+ else
+
+
+
+ ret_code = 0;
+ }
+
+ return ret_code;
+}
+
+
+
+
+
+
+
+
+
+U8 SerialPollHstin(void)
+{
+ return scc_port[pROBE_host]->data;
+}
+
+
+
+
+
+
+
+void SerialPollHstout(U8 c)
+{
+ while ((rd_ctrl(pROBE_host, 0 ) & 0x04 ) == 0)
+ ;
+
+ scc_port[pROBE_host]->data = c;
+}
+
+# 1015 "/root/root4/orion/os/regaeos/sys/libsys/serial.8530.c"
+
+
+void SerialBreak(int channel)
+{
+ Break_Recorded[channel] = 1;
+}
+
+
+
+
+
diff --git a/arch/mips/orion/setup.c b/arch/mips/orion/setup.c
index c247d6b52..b9af10c47 100644
--- a/arch/mips/orion/setup.c
+++ b/arch/mips/orion/setup.c
@@ -20,6 +20,7 @@
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
+#include <linux/fs.h>
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
@@ -35,8 +36,10 @@
#include <asm/stackframe.h>
#include <asm/system.h>
#include <asm/cpu.h>
+#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
#include <asm/mc146818rtc.h>
#include <asm/orion.h>
@@ -89,6 +92,7 @@ int __init prom_init(int a, char **b, char **c, int *d)
{
unsigned long free_start, free_end, start_pfn, bootmap_size;
extern unsigned long orion_initrd_start[], orion_initrd_size;
+ extern int rd_size;
mips_machgroup = MACH_GROUP_ORION;
/* 64 MB non-upgradable */
@@ -109,7 +113,13 @@ int __init prom_init(int a, char **b, char **c, int *d)
initrd_start = (ulong)orion_initrd_start;
initrd_end = (ulong)orion_initrd_start + (ulong)orion_initrd_size;
initrd_below_start_ok = 1;
-
+ real_root_dev = 0x0100; /* ramdisk */
+ /*
+ * Change the ramdisk size to 12M since we only have a ramdisk
+ * root on the orion and need a decent size.
+ * -- Cort <cort@fsmlabs.com>
+ */
+ rd_size = 22<<10;
return 0;
}
diff --git a/arch/mips/orion/zs.c b/arch/mips/orion/zs.c
new file mode 100644
index 000000000..d4a8a03c4
--- /dev/null
+++ b/arch/mips/orion/zs.c
@@ -0,0 +1,2182 @@
+
+/*
+ * decserial.c: Serial port driver for IOASIC DECsatations.
+ *
+ * Derived from drivers/macintosh/macserial.c by Harald Koerfgen.
+ * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
+ *
+ * DECstation changes
+ * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de)
+ * Copyright (C) 2000 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *
+ * For the rest of the code the original Copyright applies:
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Keyboard and mouse are not supported right now. If you want to change this,
+ * you might want to have a look at drivers/sbus/char/sunserial.c to see
+ * how this might be done. HK
+ *
+ * Swiped from the DEC for the Orion. -- Cort Dougan <cort@fsmlabs.com>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/wbflush.h>
+#include <asm/dec/interrupts.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/tc.h>
+#include <asm/dec/ioasic_addrs.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
+#include "zs.h"
+
+int speed_already_set=1;
+
+/*
+ * It would be nice to dynamically allocate everything that
+ * depends on NUM_SERIAL, so we could support any number of
+ * Z8530s, but for now...
+ */
+#define NUM_SERIAL 2 /* Max number of ZS chips supported */
+#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */
+
+#define RECOVERY_DELAY udelay(2)
+
+struct dec_zschannel zs_channels[NUM_CHANNELS];
+
+struct dec_serial zs_soft[NUM_CHANNELS];
+int zs_channels_found;
+struct dec_serial *zs_chain; /* list of all channels */
+
+struct tty_struct zs_ttys[NUM_CHANNELS];
+
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console sercons;
+#endif
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \
+ && !defined(MODULE)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
+#ifdef CONFIG_KGDB
+struct dec_zschannel *zs_kgdbchan;
+static unsigned char scc_inittab[] = {
+ 9, 0x80, /* reset A side (CHRA) */
+ 13, 0, /* set baud rate divisor */
+ 12, 1,
+ 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */
+ 11, 0x50, /* clocks = br gen (RCBR | TCBR) */
+ 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */
+ 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/
+ 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/
+};
+#endif
+
+static unsigned char zs_init_regs[16] __initdata = {
+ 0, /* write 0 */
+ 0, /* write 1 */
+ 0xf0, /* write 2 */
+ (Rx8), /* write 3 */
+ (X16CLK | SB1), /* write 4 */
+ (Tx8), /* write 5 */
+ 0, 0, 0, /* write 6, 7, 8 */
+ (VIS), /* write 9 */
+ (NRZ), /* write 10 */
+ (TCBR | RCBR), /* write 11 */
+ 0, 0, /* BRG time constant, write 12 + 13 */
+ (BRSRC | BRENABL), /* write 14 */
+ 0 /* write 15 */
+};
+
+#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */
+
+DECLARE_TASK_QUEUE(tq_zs_serial);
+
+struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* serial subtype definitions */
+#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * Debugging.
+ */
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_THROTTLE
+#undef SERIAL_PARANOIA_CHECK
+
+#define RS_STROBE_TIME 10
+#define RS_ISR_PASS_LIMIT 256
+
+#define _INLINE_ inline
+
+static void probe_sccs(void);
+static void change_speed(struct dec_serial *info);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static struct tty_struct *serial_table[NUM_CHANNELS];
+static struct termios *serial_termios[NUM_CHANNELS];
+static struct termios *serial_termios_locked[NUM_CHANNELS];
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char tmp_buf[4096]; /* This is cheating */
+static DECLARE_MUTEX(tmp_buf_sem);
+
+static inline int serial_paranoia_check(struct dec_serial *info,
+ dev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char *badmagic =
+ "Warning: bad magic number for serial struct (%d, %d) in %s\n";
+ static const char *badinfo =
+ "Warning: null mac_serial for (%d, %d) in %s\n";
+
+ if (!info) {
+ printk(badinfo, MAJOR(device), MINOR(device), routine);
+ return 1;
+ }
+ if (info->magic != SERIAL_MAGIC) {
+ printk(badmagic, MAJOR(device), MINOR(device), routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 0, 0 };
+
+/*
+ * Reading and writing Z8530 registers.
+ */
+static inline unsigned char read_zsreg(struct dec_zschannel *channel,
+ unsigned char reg)
+{
+ unsigned char retval;
+
+ if (reg != 0) {
+ *channel->control = reg & 0xf;
+ wbflush(); RECOVERY_DELAY;
+ }
+
+ retval = *channel->control;
+ RECOVERY_DELAY;
+ return retval;
+}
+
+static inline void write_zsreg(struct dec_zschannel *channel,
+ unsigned char reg, unsigned char value)
+{
+ if (reg != 0) {
+ *channel->control = reg & 0xf ;
+ wbflush(); RECOVERY_DELAY;
+ }
+ *channel->control = value ;
+ wbflush(); RECOVERY_DELAY;
+ return;
+}
+
+static inline unsigned char read_zsdata(struct dec_zschannel *channel)
+{
+ unsigned char retval;
+
+ retval = *channel->data;
+ RECOVERY_DELAY;
+ return retval;
+}
+
+static inline void write_zsdata(struct dec_zschannel *channel,
+ unsigned char value)
+{
+ *channel->data = value;
+ wbflush(); RECOVERY_DELAY;
+ return;
+}
+
+static inline void load_zsregs(struct dec_zschannel *channel,
+ unsigned char *regs)
+{
+/* ZS_CLEARERR(channel);
+ ZS_CLEARFIFO(channel); */
+ /* Load 'em up */
+ write_zsreg(channel, R4, regs[R4]);
+ write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
+ write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+ write_zsreg(channel, R9, regs[R9]);
+ write_zsreg(channel, R1, regs[R1]);
+ write_zsreg(channel, R2, regs[R2]);
+ write_zsreg(channel, R10, regs[R10]);
+ write_zsreg(channel, R11, regs[R11]);
+ write_zsreg(channel, R12, regs[R12]);
+ write_zsreg(channel, R13, regs[R13]);
+ write_zsreg(channel, R14, regs[R14]);
+ write_zsreg(channel, R15, regs[R15]);
+ write_zsreg(channel, R3, regs[R3]);
+ write_zsreg(channel, R5, regs[R5]);
+ return;
+}
+
+/* Sets or clears DTR/RTS on the requested line */
+static void zs_rtsdtr(struct dec_serial *ss, int set)
+{
+ return;
+ if (ss->zs_channel != ss->zs_chan_a) {
+ if (set)
+ ss->zs_chan_a->curregs[5] |= (RTS | DTR);
+ else
+ ss->zs_chan_a->curregs[5] &= ~(RTS | DTR);
+
+ write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]);
+
+ }
+ return;
+}
+
+/* Utility routines for the Zilog */
+static inline int get_zsbaud(struct dec_serial *ss)
+{
+ struct dec_zschannel *channel = ss->zs_channel;
+ int brg;
+
+ /* The baud rate is split up between two 8-bit registers in
+ * what is termed 'BRG time constant' format in my docs for
+ * the chip, it is a function of the clk rate the chip is
+ * receiving which happens to be constant.
+ */
+ brg = (read_zsreg(channel, 13) << 8);
+ brg |= read_zsreg(channel, 12);
+ return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor)));
+}
+
+/* On receive, this clears errors and the receiver interrupts */
+static inline void rs_recv_clear(struct dec_zschannel *zsc)
+{
+ write_zsreg(zsc, 0, ERR_RES);
+ write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines. All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt(). They were separated out for readability's sake.
+ *
+ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+static int tty_break; /* Set whenever BREAK condition is detected. */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct dec_serial *info,
+ int event)
+{
+ info->event |= 1 << event;
+ queue_task(&info->tqueue, &tq_zs_serial);
+ mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(struct dec_serial *info,
+ struct pt_regs *regs)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch, stat, flag;
+
+ while ((read_zsreg(info->zs_channel, R0) & Rx_CH_AV) != 0) {
+
+ stat = read_zsreg(info->zs_channel, R1);
+ ch = read_zsdata(info->zs_channel);
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel) {
+ if (ch == 0x03 || ch == '$')
+ breakpoint();
+ if (stat & (Rx_OVR|FRM_ERR|PAR_ERR))
+ write_zsreg(info->zs_channel, R0, ERR_RES);
+ return;
+ }
+#endif
+ if (!tty)
+ continue;
+
+ if (tty_break) {
+ tty_break = 0;
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+ if (info->line == sercons.index) {
+ if (!break_pressed) {
+ break_pressed = jiffies;
+ goto ignore_char;
+ }
+ break_pressed = 0;
+ }
+#endif
+ flag = TTY_BREAK;
+ if (info->flags & ZILOG_SAK)
+ do_SAK(tty);
+ } else {
+ if (stat & Rx_OVR) {
+ flag = TTY_OVERRUN;
+ } else if (stat & FRM_ERR) {
+ flag = TTY_FRAME;
+ } else if (stat & PAR_ERR) {
+ flag = TTY_PARITY;
+ } else
+ flag = 0;
+ if (flag)
+ /* reset the error indication */
+ write_zsreg(info->zs_channel, R0, ERR_RES);
+ }
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+ if (break_pressed && info->line == sercons.index) {
+ if (ch != 0 &&
+ time_before(jiffies, break_pressed + HZ*5)) {
+ handle_sysrq(ch, regs, NULL, NULL);
+ break_pressed = 0;
+ goto ignore_char;
+ }
+ break_pressed = 0;
+ }
+#endif
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ static int flip_buf_ovf;
+ ++flip_buf_ovf;
+ continue;
+ }
+ tty->flip.count++;
+ {
+ static int flip_max_cnt;
+ if (flip_max_cnt < tty->flip.count)
+ flip_max_cnt = tty->flip.count;
+ }
+ if (stat & Rx_OVR) {
+ flag = TTY_OVERRUN;
+ } else if (stat & FRM_ERR) {
+ flag = TTY_FRAME;
+ } else if (stat & PAR_ERR) {
+ flag = TTY_PARITY;
+ } else
+ flag = 0;
+ if (flag)
+ /* reset the error indication */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ *tty->flip.flag_buf_ptr++ = flag;
+ *tty->flip.char_buf_ptr++ = ch;
+ }
+ tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct dec_serial *info)
+{
+ if ((read_zsreg(info->zs_channel, R0) & Tx_BUF_EMP) == 0)
+ return;
+ info->tx_active = 0;
+
+ if (info->x_char) {
+ /* Send next char */
+ write_zsdata(info->zs_channel, info->x_char);
+ info->x_char = 0;
+ info->tx_active = 1;
+ return;
+ }
+
+ if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) {
+ write_zsreg(info->zs_channel, R0, RES_Tx_P);
+ return;
+ }
+ /* Send char */
+ write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]);
+ info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+ info->tx_active = 1;
+
+ if (info->xmit_cnt < WAKEUP_CHARS)
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+}
+
+static _INLINE_ void status_handle(struct dec_serial *info)
+{
+ unsigned char status;
+
+ /* Get status from Read Register 0 */
+ status = read_zsreg(info->zs_channel, R0);
+
+ /* FIXEM: Check for DCD transitions */
+ if (((status ^ info->read_reg_zero) & DCD) != 0
+ && info->tty && !C_CLOCAL(info->tty)) {
+ if (status & DCD) {
+ wake_up_interruptible(&info->open_wait);
+ } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) {
+ if (info->tty)
+ tty_hangup(info->tty);
+ }
+ }
+
+ /* Check for CTS transitions */
+ if (info->tty && C_CRTSCTS(info->tty)) {
+ /*
+ * For some reason, on the Power Macintosh,
+ * it seems that the CTS bit is 1 when CTS is
+ * *negated* and 0 when it is asserted.
+ * The DCD bit doesn't seem to be inverted
+ * like this.
+ */
+ if ((status & CTS) != 0) {
+ if (info->tx_stopped) {
+ info->tx_stopped = 0;
+ if (!info->tx_active)
+ transmit_chars(info);
+ }
+ } else {
+ info->tx_stopped = 1;
+ }
+ }
+
+ /* Clear status condition... */
+ write_zsreg(info->zs_channel, R0, RES_EXT_INT);
+ info->read_reg_zero = status;
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct dec_serial *info = (struct dec_serial *) dev_id;
+ unsigned char zs_intreg;
+
+ zs_intreg = read_zsreg(info->zs_channel, R3);
+
+ /* NOTE: The read register 3, which holds the irq status,
+ * does so for both channels on each chip. Although
+ * the status value itself must be read from the A
+ * channel and is only valid when read from channel A.
+ * Yes... broken hardware...
+ */
+#define CHAN_A_IRQMASK (CHARxIP | CHATxIP | CHAEXT)
+#define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
+
+ /* Channel A -- /dev/ttya, could be the console */
+ if(zs_intreg & CHAN_A_IRQMASK) {
+ if (zs_intreg & CHARxIP)
+ receive_chars(info, regs);
+ if (zs_intreg & CHATxIP)
+ transmit_chars(info);
+ if (zs_intreg & CHAEXT)
+ status_handle(info);
+ }
+
+ info=info->zs_next;
+
+ /* Channel B -- /dev/ttyb, could be the console */
+ if(zs_intreg & CHAN_B_IRQMASK) {
+ if (zs_intreg & CHBRxIP)
+ receive_chars(info, regs);
+ if (zs_intreg & CHBTxIP)
+ transmit_chars(info);
+ if (zs_intreg & CHBEXT)
+ status_handle(info);
+ }
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+#if 1
+ save_flags(flags); cli();
+ if (info->zs_channel->curregs[5] & TxENAB) {
+ info->zs_channel->curregs[5] &= ~TxENAB;
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ }
+ restore_flags(flags);
+#endif
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_start"))
+ return;
+
+ save_flags(flags); cli();
+#if 1
+ if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
+ info->zs_channel->curregs[5] |= TxENAB;
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ }
+#else
+ if (info->xmit_cnt && info->xmit_buf && !info->tx_active) {
+ transmit_chars(info);
+ }
+#endif
+ restore_flags(flags);
+}
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+ run_task_queue(&tq_zs_serial);
+}
+
+static void do_softint(void *private_)
+{
+ struct dec_serial *info = (struct dec_serial *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+static int startup(struct dec_serial * info)
+{
+ unsigned long flags;
+
+
+ if (info->flags & ZILOG_INITIALIZED)
+ return 0;
+
+
+ if (!info->xmit_buf) {
+ info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
+ if (!info->xmit_buf)
+ return -ENOMEM;
+ }
+
+ save_flags(flags); cli();
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
+#endif
+
+ /*
+ * Clear the receive FIFO.
+ */
+ ZS_CLEARFIFO(info->zs_channel);
+ info->xmit_fifo_size = 1;
+
+ /*
+ * Clear the interrupt registers.
+ */
+
+
+
+
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+
+ write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+
+ /*
+ * Turn on RTS and DTR.
+ */
+
+ zs_rtsdtr(info, 1);
+ /*
+ * Finally, enable sequencing and interrupts
+ */
+ info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
+ info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
+ info->zs_channel->curregs[5] |= (TxENAB | Tx8);
+ info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
+ info->zs_channel->curregs[9] |= (VIS | MIE);
+ write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
+ write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]);
+ write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+
+ /*
+ * And clear the interrupt registers again for luck.
+ */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ /*
+ * Set the speed of the serial port
+ */
+ change_speed(info);
+
+ /* Save the current value of RR0 */
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+
+ info->flags |= ZILOG_INITIALIZED;
+ restore_flags(flags);
+ return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct dec_serial * info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ZILOG_INITIALIZED))
+ return;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("Shutting down serial port %d (irq %d)....", info->line,
+ info->irq);
+#endif
+
+ save_flags(flags); cli(); /* Disable interrupts */
+
+ if (info->xmit_buf) {
+ free_page((unsigned long) info->xmit_buf);
+ info->xmit_buf = 0;
+ }
+
+ info->zs_channel->curregs[1] = 0;
+ write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); /* no interrupts */
+
+ info->zs_channel->curregs[3] &= ~RxENABLE;
+ write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+
+ info->zs_channel->curregs[5] &= ~TxENAB;
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ if (!info->tty || C_HUPCL(info->tty)) {
+ info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
+ write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+ }
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ZILOG_INITIALIZED;
+ restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct dec_serial *info)
+{
+ unsigned short port;
+ unsigned cflag;
+ int i;
+ int brg;
+ unsigned long flags;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ cflag = info->tty->termios->c_cflag;
+ if (!(port = info->port))
+ return;
+ i = cflag & CBAUD;
+
+ if (speed_already_set)
+ return;
+ save_flags(flags); cli();
+ info->zs_baud = baud_table[i];
+ info->clk_divisor = 16;
+
+ switch (info->zs_baud) {
+ default:
+ info->zs_channel->curregs[4] = X16CLK;
+ brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+ info->zs_channel->curregs[12] = (brg & 255);
+ info->zs_channel->curregs[13] = ((brg >> 8) & 255);
+ }
+
+ /* byte size and parity */
+ info->zs_channel->curregs[3] &= ~RxNBITS_MASK;
+ info->zs_channel->curregs[5] &= ~TxNBITS_MASK;
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->zs_channel->curregs[3] |= Rx5;
+ info->zs_channel->curregs[5] |= Tx5;
+ break;
+ case CS6:
+ info->zs_channel->curregs[3] |= Rx6;
+ info->zs_channel->curregs[5] |= Tx6;
+ break;
+ case CS7:
+ info->zs_channel->curregs[3] |= Rx7;
+ info->zs_channel->curregs[5] |= Tx7;
+ break;
+ case CS8:
+ default: /* defaults to 8 bits */
+ info->zs_channel->curregs[3] |= Rx8;
+ info->zs_channel->curregs[5] |= Tx8;
+ break;
+ }
+
+ info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
+ if (cflag & CSTOPB) {
+ info->zs_channel->curregs[4] |= SB2;
+ } else {
+ info->zs_channel->curregs[4] |= SB1;
+ }
+ if (cflag & PARENB) {
+ info->zs_channel->curregs[4] |= PAR_ENA;
+ }
+ if (!(cflag & PARODD)) {
+ info->zs_channel->curregs[4] |= PAR_EVEN;
+ }
+
+ if (!(cflag & CLOCAL)) {
+ if (!(info->zs_channel->curregs[15] & DCDIE))
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+ info->zs_channel->curregs[15] |= DCDIE;
+ } else
+ info->zs_channel->curregs[15] &= ~DCDIE;
+ if (cflag & CRTSCTS) {
+ info->zs_channel->curregs[15] |= CTSIE;
+ if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)
+ info->tx_stopped = 1;
+ } else {
+ info->zs_channel->curregs[15] &= ~CTSIE;
+ info->tx_stopped = 0;
+ }
+
+ /* Load up the new values */
+ load_zsregs(info->zs_channel, info->zs_channel->curregs);
+
+ restore_flags(flags);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+ return;
+
+ if (info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped ||
+ !info->xmit_buf)
+ return;
+
+ /* Enable transmitter */
+ save_flags(flags); cli();
+ transmit_chars(info);
+ restore_flags(flags);
+}
+
+static int rs_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
+{
+ int c, total = 0;
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write"))
+ return 0;
+
+ if (!tty || !info->xmit_buf)
+ return 0;
+
+ save_flags(flags);
+ while (1) {
+ cli();
+ c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+
+ if (from_user) {
+ down(&tmp_buf_sem);
+ copy_from_user(tmp_buf, buf, c);
+ c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ up(&tmp_buf_sem);
+ } else
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ total += c;
+ }
+
+ if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
+ && !info->tx_active)
+ transmit_chars(info);
+
+ restore_flags(flags);
+ return total;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ int ret;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+ return 0;
+ ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+ return 0;
+ return info->xmit_cnt;
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+ return;
+ cli();
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ sti();
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("throttle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ save_flags(flags); cli();
+ info->x_char = STOP_CHAR(tty);
+ if (!info->tx_active)
+ transmit_chars(info);
+ restore_flags(flags);
+ }
+
+ if (C_CRTSCTS(tty)) {
+ /*
+ * Here we want to turn off the RTS line. On Macintoshes,
+ * we only get the DTR line, which goes to both DTR and
+ * RTS on the modem. RTS doesn't go out to the serial
+ * port socket. So you should make sure your modem is
+ * set to ignore DTR if you're using CRTSCTS.
+ */
+ save_flags(flags); cli();
+ info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
+ write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+ restore_flags(flags);
+ }
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ save_flags(flags); cli();
+ if (info->x_char)
+ info->x_char = 0;
+ else {
+ info->x_char = START_CHAR(tty);
+ if (!info->tx_active)
+ transmit_chars(info);
+ }
+ restore_flags(flags);
+ }
+
+ if (C_CRTSCTS(tty)) {
+ /* Assert RTS and DTR lines */
+ save_flags(flags); cli();
+ info->zs_chan_a->curregs[5] |= DTR | RTS;
+ write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+ restore_flags(flags);
+ }
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct dec_serial * info,
+ struct serial_struct * retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = info->type;
+ tmp.line = info->line;
+ tmp.port = info->port;
+ tmp.irq = info->irq;
+ tmp.flags = info->flags;
+ tmp.baud_base = info->baud_base;
+ tmp.close_delay = info->close_delay;
+ tmp.closing_wait = info->closing_wait;
+ tmp.custom_divisor = info->custom_divisor;
+ return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
+}
+
+static int set_serial_info(struct dec_serial * info,
+ struct serial_struct * new_info)
+{
+ struct serial_struct new_serial;
+ struct dec_serial old_info;
+ int retval = 0;
+
+ if (!new_info)
+ return -EFAULT;
+ copy_from_user(&new_serial,new_info,sizeof(new_serial));
+ old_info = *info;
+
+ if (!suser()) {
+ if ((new_serial.baud_base != info->baud_base) ||
+ (new_serial.type != info->type) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ZILOG_USR_MASK) !=
+ (info->flags & ~ZILOG_USR_MASK)))
+ return -EPERM;
+ info->flags = ((info->flags & ~ZILOG_USR_MASK) |
+ (new_serial.flags & ZILOG_USR_MASK));
+ info->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ if (info->count > 1)
+ return -EBUSY;
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+
+ info->baud_base = new_serial.baud_base;
+ info->flags = ((info->flags & ~ZILOG_FLAGS) |
+ (new_serial.flags & ZILOG_FLAGS));
+ info->type = new_serial.type;
+ info->close_delay = new_serial.close_delay;
+ info->closing_wait = new_serial.closing_wait;
+
+check_and_exit:
+ retval = startup(info);
+ return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct dec_serial * info, unsigned int *value)
+{
+ unsigned char status;
+
+ cli();
+ status = read_zsreg(info->zs_channel, 0);
+ sti();
+ put_user(status,value);
+ return 0;
+}
+
+static int get_modem_info(struct dec_serial *info, unsigned int *value)
+{
+ unsigned char control, status;
+ unsigned int result;
+
+ cli();
+ control = info->zs_chan_a->curregs[5];
+ status = read_zsreg(info->zs_channel, 0);
+ sti();
+ result = ((control & RTS) ? TIOCM_RTS: 0)
+ | ((control & DTR) ? TIOCM_DTR: 0)
+ | ((status & DCD) ? TIOCM_CAR: 0)
+ | ((status & CTS) ? 0: TIOCM_CTS);
+ put_user(result,value);
+ return 0;
+}
+
+static int set_modem_info(struct dec_serial *info, unsigned int cmd,
+ unsigned int *value)
+{
+ int error;
+ unsigned int arg, bits;
+
+ error = verify_area(VERIFY_READ, value, sizeof(int));
+ if (error)
+ return error;
+ get_user(arg, value);
+ bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
+ cli();
+ switch (cmd) {
+ case TIOCMBIS:
+ info->zs_chan_a->curregs[5] |= bits;
+ break;
+ case TIOCMBIC:
+ info->zs_chan_a->curregs[5] &= ~bits;
+ break;
+ case TIOCMSET:
+ info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits;
+ break;
+ default:
+ sti();
+ return -EINVAL;
+ }
+ write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+ sti();
+ return 0;
+}
+
+/*
+ * rs_break - turn transmit break condition on/off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+ struct dec_serial *info = (struct dec_serial *) tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_break"))
+ return;
+ if (!info->port)
+ return;
+
+ save_flags(flags); cli();
+ if (break_state == -1)
+ info->zs_channel->curregs[5] |= SND_BRK;
+ else
+ info->zs_channel->curregs[5] &= ~SND_BRK;
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ restore_flags(flags);
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ int error;
+ struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+ return -ENODEV;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
+ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TIOCMGET:
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int));
+ if (error)
+ return error;
+ return get_modem_info(info, (unsigned int *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return set_modem_info(info, cmd, (unsigned int *) arg);
+ case TIOCGSERIAL:
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct));
+ if (error)
+ return error;
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int));
+ if (error)
+ return error;
+ else
+ return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ error = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct dec_serial));
+ if (error)
+ return error;
+ copy_from_user((struct dec_serial *) arg,
+ info, sizeof(struct dec_serial));
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+ int was_stopped;
+
+ if (tty->termios->c_cflag == old_termios->c_cflag)
+ return;
+ was_stopped = info->tx_stopped;
+
+ change_speed(info);
+
+ if (was_stopped && !info->tx_stopped)
+ rs_start(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed.
+ * Wait for the last remaining data to be sent.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+ return;
+
+ save_flags(flags); cli();
+
+ if (tty_hung_up_p(filp)) {
+ restore_flags(flags);
+ return;
+ }
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_close ttys%d, count = %d\n", info->line, info->count);
+#endif
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("rs_close: bad serial port count; tty->count is 1, "
+ "info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+ printk("rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, info->count);
+ info->count = 0;
+ }
+ if (info->count) {
+ restore_flags(flags);
+ return;
+ }
+ info->flags |= ZILOG_CLOSING;
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ZILOG_NORMAL_ACTIVE)
+ info->normal_termios = *tty->termios;
+ if (info->flags & ZILOG_CALLOUT_ACTIVE)
+ info->callout_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receiver and receive interrupts.
+ */
+ info->zs_channel->curregs[3] &= ~RxENABLE;
+ write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+ info->zs_channel->curregs[1] = 0; /* disable any rx ints */
+ write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
+ ZS_CLEARFIFO(info->zs_channel);
+ if (info->flags & ZILOG_INITIALIZED) {
+ /*
+ * Before we drop DTR, make sure the SCC transmitter
+ * has completely drained.
+ */
+ rs_wait_until_sent(tty, info->timeout);
+ }
+
+ shutdown(info);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(info->close_delay);
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
+ ZILOG_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+ restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct dec_serial *info = (struct dec_serial *) tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+
+ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+ return;
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ */
+ char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+ if (timeout)
+ char_time = MIN(char_time, timeout);
+ while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && ((orig_jiffies + timeout) < jiffies))
+ break;
+ }
+ current->state = TASK_RUNNING;
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+void rs_hangup(struct tty_struct *tty)
+{
+ struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+ return;
+
+ rs_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ info->count = 0;
+ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE);
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ struct dec_serial *info)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+ int do_clocal = 0;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (info->flags & ZILOG_CLOSING) {
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ return ((info->flags & ZILOG_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+#else
+ return -EAGAIN;
+#endif
+ }
+
+ /*
+ * If this is a callout device, then just make sure the normal
+ * device isn't being used.
+ */
+ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+ if (info->flags & ZILOG_NORMAL_ACTIVE)
+ return -EBUSY;
+ if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ (info->flags & ZILOG_SESSION_LOCKOUT) &&
+ (info->session != current->session))
+ return -EBUSY;
+ if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ (info->flags & ZILOG_PGRP_LOCKOUT) &&
+ (info->pgrp != current->pgrp))
+ return -EBUSY;
+ info->flags |= ZILOG_CALLOUT_ACTIVE;
+ return 0;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ if (info->flags & ZILOG_CALLOUT_ACTIVE)
+ return -EBUSY;
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (info->flags & ZILOG_CALLOUT_ACTIVE) {
+ if (info->normal_termios.c_cflag & CLOCAL)
+ do_clocal = 1;
+ } else {
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+ }
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready before block: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ cli();
+ if (!tty_hung_up_p(filp))
+ info->count--;
+ sti();
+ info->blocked_open++;
+ while (1) {
+ cli();
+ if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ (tty->termios->c_cflag & CBAUD))
+ zs_rtsdtr(info, 1);
+ sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ZILOG_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ZILOG_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#else
+ retval = -EAGAIN;
+#endif
+ break;
+ }
+ if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
+ !(info->flags & ZILOG_CLOSING) &&
+ (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD)))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ info->count++;
+ info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready after blocking: ttys%d, count = %d\n",
+ info->line, info->count);
+#endif
+ if (retval)
+ return retval;
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its ZILOG structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ struct dec_serial *info;
+ int retval, line;
+
+ line = MINOR(tty->device) - tty->driver.minor_start;
+ if ((line < 0) || (line >= zs_channels_found))
+ return -ENODEV;
+ info = zs_soft + line;
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->device, "rs_open"))
+ return -ENODEV;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+ info->count);
+#endif
+
+ info->count++;
+ tty->driver_data = info;
+ info->tty = tty;
+
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ZILOG_CLOSING)) {
+ if (info->flags & ZILOG_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ return ((info->flags & ZILOG_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+#else
+ return -EAGAIN;
+#endif
+ }
+
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval)
+ return retval;
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open returning after block_til_ready with %d\n",
+ retval);
+#endif
+ return retval;
+ }
+
+ if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->normal_termios;
+ else
+ *tty->termios = info->callout_termios;
+ change_speed(info);
+ }
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (sercons.cflag && sercons.index == line) {
+ tty->termios->c_cflag = sercons.cflag;
+ sercons.cflag = 0;
+ change_speed(info);
+ }
+#endif
+
+ info->session = current->session;
+ info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open ttys%d successful...", info->line);
+#endif
+/* tty->low_latency = 1; */
+ return 0;
+}
+
+/* Finally, routines used to initialize the serial driver. */
+
+static void __init show_serial_version(void)
+{
+ printk("Orion Z8530 serial driver version 0.01\n");
+}
+
+/*
+ * Initialize Z8530s zs_channels
+ */
+unsigned long system_base;
+static void __init probe_sccs(void)
+{
+ struct dec_serial **pp;
+ int i, n, n_chips = 0, n_channels, chip, channel;
+
+ /*
+ * When serial console is activated, tc_init has not been called yet
+ * and system_base is undefined. Unfortunately we have to hardcode
+ * system_base for this case :-(. HK
+ */
+ system_base = 0x1f200000|0xa0000000;
+ n_chips = 1;
+
+ pp = &zs_chain;
+
+ n_channels = 0;
+
+ for (chip = 0; chip < n_chips; chip++) {
+ for (channel = 0; channel <= 1; channel++) {
+ /*
+ * The sccs reside on the high byte of the 16 bit IOBUS
+
+ zs_channels[n_channels].control =
+ (volatile unsigned char *)
+ system_base
+ + (0 == chip ? SCC0 : SCC1)
+ + (0 == channel ? 1 : 9);
+ */
+
+ /* just hardcode the address -- Cort */
+ zs_channels[n_channels].control =
+ (volatile unsigned char *)
+ (0x1F200008|0xA0000000);
+
+ zs_channels[n_channels].data =
+ zs_channels[n_channels].control + 4;
+
+ zs_soft[n_channels].zs_channel =
+ &zs_channels[n_channels];
+
+ zs_soft[n_channels].irq = SERIAL;
+
+ if (0 == channel)
+ zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1];
+ else
+ zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels];
+
+ *pp = &zs_soft[n_channels];
+
+ pp = &zs_soft[n_channels].zs_next;
+
+ n_channels++;
+ }
+ }
+
+ *pp = 0;
+ zs_channels_found = n_channels;
+
+ for (n = 0; n < zs_channels_found; n++) {
+ for (i = 0; i < 16; i++) {
+ zs_soft[n].zs_channel->curregs[i] = zs_init_regs[i];
+ }
+ }
+
+/* save_and_cli(flags);
+ for (n = 0; n < zs_channels_found; n++) {
+ if (((int)zs_channels[n].control & 0xf) == 1) {
+ write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES);
+ udelay(10000);
+ write_zsreg(zs_soft[channel].zs_chan_a, R9, 0);
+ }
+ load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs);
+ }
+ restore_flags(flags); */
+}
+
+extern irq_desc_t *irq_desc_base;
+
+static void serial_ack(unsigned int irq_nr)
+{
+}
+
+struct hw_interrupt_type serial_pic = {
+ " serial ack ",
+ NULL,
+ NULL,
+ NULL, /* unmask_irq */
+ NULL, /* mask_irq */
+ serial_ack, /* mask_and_ack */
+ 0
+};
+
+struct irqaction irq1 = {
+ rs_interrupt,
+ SA_INTERRUPT,
+ 0,
+ "serial",
+ NULL,
+ NULL
+};
+
+int __init orion_rs_init(void)
+{
+ int channel, i;
+ unsigned long flags;
+ struct dec_serial *info;
+
+ /* Setup base handler, and timer table. */
+ init_bh(SERIAL_BH, do_serial_bh);
+
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+ /* Not all of this is exactly right for us. */
+
+ memset(&serial_driver, 0, sizeof(struct tty_driver));
+ serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.name = "ttyS";
+ serial_driver.major = TTY_MAJOR;
+ serial_driver.minor_start = 64;
+ serial_driver.num = zs_channels_found;
+ serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver.subtype = SERIAL_TYPE_NORMAL;
+ serial_driver.init_termios = tty_std_termios;
+
+ serial_driver.init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver.flags = TTY_DRIVER_REAL_RAW;
+ serial_driver.refcount = &serial_refcount;
+ serial_driver.table = serial_table;
+ serial_driver.termios = serial_termios;
+ serial_driver.termios_locked = serial_termios_locked;
+
+ serial_driver.open = rs_open;
+ serial_driver.close = rs_close;
+ serial_driver.write = rs_write;
+ serial_driver.flush_chars = rs_flush_chars;
+ serial_driver.write_room = rs_write_room;
+ serial_driver.chars_in_buffer = rs_chars_in_buffer;
+ serial_driver.flush_buffer = rs_flush_buffer;
+ serial_driver.ioctl = rs_ioctl;
+ serial_driver.throttle = rs_throttle;
+ serial_driver.unthrottle = rs_unthrottle;
+ serial_driver.set_termios = rs_set_termios;
+ serial_driver.stop = rs_stop;
+ serial_driver.start = rs_start;
+ serial_driver.hangup = rs_hangup;
+ serial_driver.break_ctl = rs_break;
+ serial_driver.wait_until_sent = rs_wait_until_sent;
+
+ /*
+ * The callout device is just like normal device except for
+ * major number and the subtype code.
+ */
+ callout_driver = serial_driver;
+ callout_driver.name = "cua";
+ callout_driver.major = TTYAUX_MAJOR;
+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+ if (tty_register_driver(&serial_driver))
+ panic("Couldn't register serial driver\n");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver\n");
+
+ save_flags(flags); cli();
+
+ for (channel = 0; channel < zs_channels_found-1; ++channel) {
+#ifdef CONFIG_KGDB
+ if (zs_soft[channel].kgdb_channel) {
+ continue;
+ }
+#endif
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+ irq_desc_base[3].handler=&serial_pic;
+#if 0
+
+ if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ,
+ "SCC", &zs_soft[channel]))
+ printk(KERN_ERR "orion serial: can't get irq %d\n",
+ SERIAL);
+#endif
+ irq1.dev_id = &zs_soft[channel];
+ irq_desc_base[3].action=&irq1;
+ printk("orion serial: GOT irq %d\n", SERIAL);
+
+ /* If console serial line, then enable interrupts. */
+/* if (zs_soft[channel].is_cons) {
+ write_zsreg(zs_soft[channel].zs_channel, R1,
+ (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
+ write_zsreg(zs_soft[channel].zs_channel, R9,
+ (VIS | MIE));
+ }
+*/
+ }
+
+ for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
+ {
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel) {
+ continue;
+ }
+#endif
+ info->magic = SERIAL_MAGIC;
+ info->port = (int) info->zs_channel->control;
+ info->line = i;
+ info->tty = 0;
+ info->custom_divisor = 16;
+ info->close_delay = 50;
+ info->closing_wait = 3000;
+ info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+ info->tqueue.routine = do_softint;
+ info->tqueue.data = info;
+ info->callout_termios =callout_driver.init_termios;
+ info->normal_termios = serial_driver.init_termios;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ printk("tty%02d at 0x%08x (irq = %d)", info->line,
+ info->port, info->irq);
+ printk(" is a **FAKE** Z85C30 SCC\n");
+ }
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+/* PowerMac: Unused at this time, just here to make things link. */
+int register_serial(struct serial_struct *req)
+{
+ return -1;
+}
+
+void unregister_serial(int line)
+{
+ return;
+}
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ */
+
+/* This is for console output */
+static void
+zs_console_putchar(struct dec_serial *info, char ch)
+{
+ int loops = 10000;
+ unsigned long flags;
+
+ if(!info->zs_channel)
+ return;
+
+ save_flags(flags); cli();
+
+ while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops)
+ RECOVERY_DELAY;
+ *(info->zs_channel->data) = ch;
+ wbflush(); RECOVERY_DELAY;
+
+ restore_flags(flags);
+}
+
+static void serial_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ struct dec_serial *info;
+ int i;
+
+ info = zs_soft + co->index;
+
+ for (i = 0; i < count; i++, s++) {
+ if(*s == '\n')
+ zs_console_putchar(info, '\r');
+ zs_console_putchar(info, *s);
+ }
+}
+
+/*
+ * Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+ return 0;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+int serial_console_is_setup=0;
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ struct dec_serial *info;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int cflag = CREAD | HUPCL | CLOCAL;
+ char *s;
+ unsigned long flags;
+
+ if(!IOASIC)
+ return -ENODEV;
+
+ info = zs_soft + co->index;
+
+ if (zs_chain == 0)
+ probe_sccs();
+
+ info->is_cons = 1;
+
+ baud = 19200;
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+ s = options;
+ while(*s >= '0' && *s <= '9')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s)
+ bits = *s - '0';
+ }
+
+ /*
+ * Now construct a cflag setting.
+ */
+ switch(baud) {
+ case 1200:
+ cflag |= B1200;
+ break;
+ case 2400:
+ cflag |= B2400;
+ break;
+ case 4800:
+ cflag |= B4800;
+ break;
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 38400:
+ cflag |= B38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ case 9600:
+ default:
+ cflag |= B9600;
+ break;
+ }
+ switch(bits) {
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
+ }
+ switch(parity) {
+ case 'o': case 'O':
+ cflag |= PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
+ }
+ co->cflag = cflag;
+ save_and_cli(flags);
+
+ /*
+ * Turn on RTS and DTR.
+ */
+ zs_rtsdtr(info, 1);
+
+ /*
+ * Finally, enable sequencing
+ */
+ info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
+ info->zs_channel->curregs[5] |= (TxENAB | Tx8);
+ info->zs_channel->curregs[9] |= (VIS);
+ write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+ write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+ write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+ /*
+ * Set the speed of the serial port
+ */
+ change_speed(info);
+
+ speed_already_set=1;
+ /* Save the current value of RR0 */
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+
+ zs_soft[co->index].clk_divisor = 16;
+ zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
+
+ restore_flags(flags);
+ serial_console_is_setup=1;
+ return 0;
+}
+
+static struct console sercons = {
+ "ttyS",
+ serial_console_write,
+ NULL,
+ serial_console_device,
+ serial_console_wait_key,
+ NULL,
+ serial_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+/*
+ * Register console.
+ */
+
+void __init zs_serial_console_init(void)
+{
+ register_console(&sercons);
+}
+
+#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+
+#ifdef CONFIG_KGDB
+/* These are for receiving and sending characters under the kgdb
+ * source level kernel debugger.
+ */
+void putDebugChar(char kgdb_char)
+{
+ struct dec_zschannel *chan = zs_kgdbchan;
+ while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0)
+ RECOVERY_DELAY;
+ write_zsdata(chan, kgdb_char);
+}
+
+char getDebugChar(void)
+{
+ struct dec_zschannel *chan = zs_kgdbchan;
+ while((read_zsreg(chan, 0) & Rx_CH_AV) == 0)
+ eieio(); /*barrier();*/
+ return read_zsdata(chan);
+}
+
+void kgdb_interruptible(int yes)
+{
+ struct dec_zschannel *chan = zs_kgdbchan;
+ int one, nine;
+ nine = read_zsreg(chan, 9);
+ if (yes == 1) {
+ one = EXT_INT_ENAB|INT_ALL_Rx;
+ nine |= MIE;
+ printk("turning serial ints on\n");
+ } else {
+ one = RxINT_DISAB;
+ nine &= ~MIE;
+ printk("turning serial ints off\n");
+ }
+ write_zsreg(chan, 1, one);
+ write_zsreg(chan, 9, nine);
+}
+/* This sets up the serial port we're using, and turns on
+ * interrupts for that channel, so kgdb is usable once we're done.
+ */
+static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps)
+{
+ int brg;
+ int i, x;
+ volatile char *sccc = ms->control;
+ brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
+ printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg);
+ for (i = 20000; i != 0; --i) {
+ x = *sccc; eieio();
+ }
+ for (i = 0; i < sizeof(scc_inittab); ++i) {
+ write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]);
+ i++;
+ }
+}
+
+/* This is called at boot time to prime the kgdb serial debugging
+ * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1
+ * for /dev/ttyb which is determined in setup_arch() from the
+ * boot command line flags.
+ */
+void __init zs_kgdb_hook(int tty_num)
+{
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+ zs_soft[tty_num].zs_channel = &zs_channels[tty_num];
+ zs_kgdbchan = zs_soft[tty_num].zs_channel;
+ zs_soft[tty_num].change_needed = 0;
+ zs_soft[tty_num].clk_divisor = 16;
+ zs_soft[tty_num].zs_baud = 38400;
+ zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */
+ zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */
+ /* Turn on transmitter/receiver at 8-bits/char */
+ kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400);
+ printk("KGDB: on channel %d initialized\n", tty_num);
+ set_debug_traps(); /* init stub */
+}
+#endif /* ifdef CONFIG_KGDB */
diff --git a/arch/mips/orion/zs.h b/arch/mips/orion/zs.h
new file mode 100644
index 000000000..e10e1c3d2
--- /dev/null
+++ b/arch/mips/orion/zs.h
@@ -0,0 +1,405 @@
+/*
+ * macserial.h: Definitions for the Macintosh Z8530 serial driver.
+ *
+ * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
+ *
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _DECSERIAL_H
+#define _DECSERIAL_H
+
+#define NUM_ZSREGS 16
+
+struct serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait; /* time to wait before closing */
+ unsigned short closing_wait2; /* no longer used... */
+ int reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output. 65535 means don't wait at all.
+ */
+#define ZILOG_CLOSING_WAIT_INF 0
+#define ZILOG_CLOSING_WAIT_NONE 65535
+
+/*
+ * Definitions for ZILOG_struct (and serial_struct) flags field
+ */
+#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+ on the callout port */
+#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
+#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */
+#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ZILOG_SPD_MASK 0x0030
+#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
+
+#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
+#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */
+
+#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
+#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
+#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
+
+#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */
+#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */
+#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
+#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
+#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
+#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */
+#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */
+#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct dec_zschannel {
+ volatile unsigned char *control;
+ volatile unsigned char *data;
+
+ /* Current write register values */
+ unsigned char curregs[NUM_ZSREGS];
+};
+
+struct dec_serial {
+ struct dec_serial *zs_next; /* For IRQ servicing chain */
+ struct dec_zschannel *zs_channel; /* Channel registers */
+ struct dec_zschannel *zs_chan_a; /* A side registers */
+ unsigned char read_reg_zero;
+
+ char soft_carrier; /* Use soft carrier on this channel */
+ char break_abort; /* Is serial console in, so process brk/abrt */
+ char kgdb_channel; /* Kgdb is running on this channel */
+ char is_cons; /* Is this our console. */
+ unsigned char tx_active; /* character is being xmitted */
+ unsigned char tx_stopped; /* output is suspended */
+
+ /* We need to know the current clock divisor
+ * to read the bps rate the chip has currently
+ * loaded.
+ */
+ unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
+ int zs_baud;
+
+ char change_needed;
+
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+ int flags; /* defined in tty.h */
+ int type; /* UART type */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct tq_struct tqueue;
+ struct tq_struct tqueue_hangup;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+};
+
+
+#define SERIAL_MAGIC 0x5301
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+/* 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)
+
+/* 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 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 WT_RDY_RT 0x20 /* Wait/Ready on R/T */
+#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
+#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
+
+/* 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 RxNBITS_MASK 0xc0
+
+/* Write Register 4 */
+
+#define PAR_ENA 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 TxENAB 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 TxNBITS_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 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 SOFTACK 0x20 /* Software Interrupt Acknowledge */
+#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 BRENABL 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 ZCIE 2 /* Zero count IE */
+#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 FRM_ERR 0x40 /* CRC/Framing Error */
+#define END_FR 0x80 /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+
+/* 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(channel) (write_zsreg(channel, 0, ERR_RES))
+#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
+ garbage = read_zsdata(channel); \
+ garbage = read_zsdata(channel); \
+ garbage = read_zsdata(channel); \
+ } while(0)
+
+#endif /* !(_DECSERIAL_H) */