diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-09-15 00:18:23 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-09-15 00:18:23 +0000 |
commit | 5fe1122075a91dd9427cde8baa9eefbdc3f28107 (patch) | |
tree | e80b2954f2c7c4be92e75efbd7a572cdd409e3c8 | |
parent | 44990ac744d55caf3033500f7b131e85548e5bb7 (diff) |
Orion update.
-rw-r--r-- | arch/mips/orion/Makefile | 18 | ||||
-rw-r--r-- | arch/mips/orion/char.c | 844 | ||||
-rw-r--r-- | arch/mips/orion/irq.c | 44 | ||||
-rw-r--r-- | arch/mips/orion/misc.c | 2 | ||||
-rw-r--r-- | arch/mips/orion/orion.hw.init.c | 4140 | ||||
-rw-r--r-- | arch/mips/orion/promcon.c | 135 | ||||
-rw-r--r-- | arch/mips/orion/serial.8530.c | 815 | ||||
-rw-r--r-- | arch/mips/orion/setup.c | 12 | ||||
-rw-r--r-- | arch/mips/orion/zs.c | 2182 | ||||
-rw-r--r-- | arch/mips/orion/zs.h | 405 |
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) */ |