diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-03 16:57:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-03 16:57:24 +0000 |
commit | af7e00d6f82e2d2a46cb7390bb447e8ec2d118a2 (patch) | |
tree | 60e611dfbd4b4fdf8acf5533096cf4c40c233e50 /drivers/sgi/char | |
parent | f9bbe9da79dbc8557c74efeb158b431cd67ace52 (diff) |
Cache fixes, part #1.
Diffstat (limited to 'drivers/sgi/char')
-rw-r--r-- | drivers/sgi/char/Makefile | 18 | ||||
-rw-r--r-- | drivers/sgi/char/cons_newport.c | 613 | ||||
-rw-r--r-- | drivers/sgi/char/gconsole.h | 33 | ||||
-rw-r--r-- | drivers/sgi/char/graphics.c | 329 | ||||
-rw-r--r-- | drivers/sgi/char/graphics.h | 28 | ||||
-rw-r--r-- | drivers/sgi/char/newport.c | 217 | ||||
-rw-r--r-- | drivers/sgi/char/rrm.c | 70 | ||||
-rw-r--r-- | drivers/sgi/char/sgicons.c | 188 | ||||
-rw-r--r-- | drivers/sgi/char/sgiserial.c | 2019 | ||||
-rw-r--r-- | drivers/sgi/char/shmiq.c | 460 | ||||
-rw-r--r-- | drivers/sgi/char/streamable.c | 363 | ||||
-rw-r--r-- | drivers/sgi/char/usema.c | 191 | ||||
-rw-r--r-- | drivers/sgi/char/vga_font.c | 346 |
13 files changed, 1 insertions, 4874 deletions
diff --git a/drivers/sgi/char/Makefile b/drivers/sgi/char/Makefile index 3ccaafd9e..7032c700c 100644 --- a/drivers/sgi/char/Makefile +++ b/drivers/sgi/char/Makefile @@ -16,21 +16,3 @@ ifeq ($(CONFIG_SGI_SERIAL),y) endif include $(TOPDIR)/Rules.make -# -# Makefile for the linux kernel. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - -O_TARGET := sgichar.o -O_OBJS := graphics.o streamable.o newport.o cons_newport.o sgicons.o \ - vga_font.o rrm.o shmiq.o usema.o - -ifeq ($(CONFIG_SGI_SERIAL),y) - O_OBJS += sgiserial.o -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/sgi/char/cons_newport.c b/drivers/sgi/char/cons_newport.c index 30aa1f3b7..b8a7f958d 100644 --- a/drivers/sgi/char/cons_newport.c +++ b/drivers/sgi/char/cons_newport.c @@ -3,618 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: cons_newport.c,v 1.1 1997/12/02 02:28:23 ralf Exp $ - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/kd.h> -#include <linux/tty.h> -#include <linux/malloc.h> -#include <linux/major.h> -#include <linux/mm.h> -#include <linux/version.h> - -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/bitops.h> -#include <asm/sgialib.h> -#include <asm/ptrace.h> - -#include <linux/kbd_kern.h> -#include <linux/vt_kern.h> -#include <linux/consolemap.h> -#include <linux/selection.h> -#include <linux/console_struct.h> - -#include "gconsole.h" -#include "newport.h" -#include "graphics.h" /* Just for now */ -#include <asm/gfx.h> -#include <asm/ng1.h> - -#if 0 -#include "linux_logo.h" -#endif - -#define BMASK(c) (c << 24) - -#define RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \ -(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \ -(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \ -(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \ -(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \ -(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \ -(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \ -(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \ -} while(0) - -#define REVERSE_RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((~(cp)[0x0])); (regs)->go.zpattern = BMASK((~(cp)[0x1])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x2])); (regs)->go.zpattern = BMASK((~(cp)[0x3])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x4])); (regs)->go.zpattern = BMASK((~(cp)[0x5])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x6])); (regs)->go.zpattern = BMASK((~(cp)[0x7])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x8])); (regs)->go.zpattern = BMASK((~(cp)[0x9])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xa])); (regs)->go.zpattern = BMASK((~(cp)[0xb])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xc])); (regs)->go.zpattern = BMASK((~(cp)[0xd])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xe])); (regs)->go.zpattern = BMASK((~(cp)[0xf])); \ -} while(0) - -extern int default_red[16], default_grn[16], default_blu[16]; -extern unsigned char video_type; - -static int cursor_pos = -1; -struct newport_regs *npregs; - -#define TESTVAL 0xdeadbeef -#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11) - -static inline void -newport_disable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO))); -} - -static inline void -newport_enable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO)); -} - -static inline void -newport_disable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP))); -} - -#if 0 -static inline void -newport_enable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); -} -#endif - -static inline void -newport_init_cmap(void) -{ - unsigned short i; - - for(i = 0; i < 16; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, color_table[i]); - newport_cmap_setrgb(npregs, - default_red[i], - default_grn[i], - default_blu[i]); - } -} - -#if 0 -static inline void -newport_init_cursor(void) -{ - unsigned char cursor[256]; - unsigned short *cookie; - int i; - - for(i = 0; i < 256; i++) - cursor[i] = 0x0; - for(i = 211; i < 256; i+=4) { - cursor[i] = 0xff; -#if 0 - cursor[(i + 128) << 2] = 0xff; - cursor[((i + 128) << 2) + 1] = 0xff; -#endif - } - - /* Load the SRAM on the VC2 for this new GLYPH. */ - cookie = (unsigned short *) cursor; - newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | - NPORT_DMODE_W2 | VC2_PROTOCOL); - for(i = 0; i < 128; i++) { - newport_bfwait(); - npregs->set.dcbdata0.hwords.s1 = *cookie++; - } - - /* Place the cursor at origin. */ - newport_vc2_set(npregs, VC2_IREG_CURSX, 0); - newport_vc2_set(npregs, VC2_IREG_CURSY, 0); - newport_enable_cursor(); -} -#endif - -static inline void -newport_clear_screen(void) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = 0; - npregs->set.xystarti = 0; - npregs->go.xyendi = (((1280 + 63) << 16)|(1024)); - newport_bfwait(); -} - -static inline void -newport_render_version(void) -{ -#if 0 - unsigned short *ush; - int currcons = 0; - char *p; - - ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20; - for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) { - *ush = (attr << 8) + *p; - newport_blitc (*ush, (unsigned long) ush); - } -#endif -} - -#if 0 -static inline void -newport_render_logo(void) -{ - int i, xpos, ypos; - unsigned char *bmap; - - xpos = 8; - ypos = 18; - - newport_wait(); - npregs->set.colori = 9; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - for(i = 0; i < 80; i+=8) { - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = ((xpos + i) << 16) | ypos; - npregs->set.xyendi = (((xpos + i) + 7) << 16); - newport_wait(); - - bmap = linux_logo + (i * 80); - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); - } - prom_getchar(); - prom_imode(); -} -#endif - -static inline void -newport_render_background(int xpos, int ypos, int ci) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = ci; - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->go.xyendi = ((xpos + 7) << 16) | (ypos + 15); -} - -void -newport_set_origin(unsigned short offset) -{ - /* maybe this works... */ - __origin = offset; -} - -void -newport_hide_cursor(void) -{ - int xpos, ypos, idx; - unsigned long flags; - - if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return; - save_and_cli(flags); - - idx = cursor_pos; - if(idx == -1) { - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - newport_render_background(xpos, ypos, 0); - restore_flags(flags); -} - -void -newport_set_cursor(int currcons) -{ - int xpos, ypos, idx, oldpos; - unsigned short *sp, *osp, cattr; - unsigned long flags; - unsigned char *p; - - if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) - return; - - if (__real_origin != __origin) - __set_origin(__real_origin); - - save_and_cli(flags); - - idx = (pos - video_mem_base) >> 1; - sp = (unsigned short *) pos; - oldpos = cursor_pos; - cursor_pos = idx; - if(!deccm) { - hide_cursor(); - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - if(oldpos != -1) { - int oxpos, oypos; - - /* Restore old location. */ - osp = (unsigned short *) ((oldpos << 1) + video_mem_base); - oxpos = 8 + ((oldpos % video_num_columns) << 3); - oypos = 18 + ((oldpos / video_num_columns) << 4); - cattr = *osp; - newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (oxpos << 16) | oypos; - npregs->set.xyendi = ((oxpos + 7) << 16); - newport_wait(); - RENDER(npregs, p); - } - cattr = *sp; - newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - REVERSE_RENDER(npregs, p); - restore_flags (flags); - return; -} - -void -newport_get_scrmem(int currcons) -{ - memcpyw((unsigned short *)vc_scrbuf[currcons], - (unsigned short *)origin, video_screen_size); - origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; - scr_end = video_mem_end = video_mem_start + video_screen_size; - pos = origin + y*video_size_row + (x<<1); -} - -void -newport_set_scrmem(int currcons, long offset) -{ - if (video_mem_term - video_mem_base < offset + video_screen_size) - offset = 0; - memcpyw((unsigned short *)(video_mem_base + offset), - (unsigned short *) origin, video_screen_size); - video_mem_start = video_mem_base; - video_mem_end = video_mem_term; - origin = video_mem_base + offset; - scr_end = origin + video_screen_size; - pos = origin + y*video_size_row + (x<<1); - has_wrapped = 0; -} - -int -newport_set_get_cmap(unsigned char * arg, int set) -{ - unsigned short ent; - int i; - - i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3); - if (i) - return i; - - for (i=0; i<16; i++) { - if (set) { - __get_user(default_red[i], arg++); - __get_user(default_grn[i], arg++); - __get_user(default_blu[i], arg++); - } else { - __put_user (default_red[i], arg++); - __put_user (default_grn[i], arg++); - __put_user (default_blu[i], arg++); - } - } - if (set) { - for (i=0; i<MAX_NR_CONSOLES; i++) { - if (vc_cons_allocated(i)) { - int j, k; - for (j = k = 0; j<16; j++) { - vc_cons[i].d->vc_palette[k++] = - default_red[j]; - vc_cons[i].d->vc_palette[k++] = - default_grn[j]; - vc_cons[i].d->vc_palette[k++] = - default_blu[j]; - } - } - } - if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return 0; - for(ent = 0; ent < 16; ent++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, ent); - newport_cmap_setrgb(npregs, - default_red[ent], - default_grn[ent], - default_blu[ent]); - } - } - - return 0; -} - -void -newport_blitc(unsigned short charattr, unsigned long addr) -{ - int idx, xpos, ypos; - unsigned char *p; - - idx = (addr - (video_mem_base + (__origin<<1))) >> 1; - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - - p = &vga_font[(charattr & 0xff) << 4]; - charattr = (charattr >> 8) & 0xff; - - newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4); - - /* Set the color and drawing mode. */ - newport_wait(); - npregs->set.colori = charattr & 0xf; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - - /* Go, baby, go... */ - RENDER(npregs, p); -} - -void -newport_memsetw(void * s, unsigned short c, unsigned int count) -{ - unsigned short * addr = (unsigned short *) s; - - count /= 2; - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - while (count) { - count--; - *addr++ = c; - } - return; - } - if ((unsigned long) addr + count > video_mem_term || - (unsigned long) addr < video_mem_base) { - if ((unsigned long) addr + count <= video_mem_term || - (unsigned long) addr > video_mem_base) { - while (count) { - count--; - *addr++ = c; - } - return; - } else { - while (count) { - count--; - scr_writew(c, addr++); - } - } - } else { - while (count) { - count--; - if (*addr != c) { - newport_blitc(c, (unsigned long)addr); - *addr++ = c; - } else - addr++; - } - } -} - -void -newport_memcpyw(unsigned short *to, unsigned short *from, unsigned int count) -{ - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - memcpy(to, from, count); - return; - } - if ((unsigned long) to + count > video_mem_term || - (unsigned long) to < video_mem_base) { - if ((unsigned long) to + count <= video_mem_term || - (unsigned long) to > video_mem_base) - memcpy(to, from, count); - else { - count /= 2; - while (count) { - count--; - scr_writew(scr_readw(from++), to++); - } - } - } else { - count /= 2; - while (count) { - count--; - if (*to != *from) { - newport_blitc(*from, (unsigned long)to); - *to++ = *from++; - } else { - from++; - to++; - } - } - } -} - -struct console_ops newport_console = { - newport_set_origin, - newport_hide_cursor, - newport_set_cursor, - newport_get_scrmem, - newport_set_scrmem, - newport_set_get_cmap, - newport_blitc, - newport_memsetw, - newport_memcpyw -}; - -/* Currently hard-coded values that are the same as those found on my system */ -struct ng1_info newport_board_info = { - { "NG1", "" /* what is the label? */, 1280, 1024, sizeof (struct ng1_info) }, - 6, /* boardrev */ - 1, /* rex3rev */ - 0, /* vc2rev */ - 2, /* monitor type */ - 0, /* videoinstalled */ - 3, /* mcrev */ - 24, /* bitplanes */ - 0, /* xmap9rev */ - 2, /* cmaprev */ - { 256, 1280, 1024, 76}, /* ng1_vof_info */ - 13, /* paneltype */ - 0 -}; - -void -newport_reset (void) -{ - newport_wait(); - newport_enable_video(); - - /* Init the cursor disappear. */ - newport_wait(); -#if 0 - newport_init_cursor(); -#else - newport_disable_cursor(); -#endif - - newport_init_cmap(); - - /* Clear the screen. */ - newport_clear_screen(); -} - -/* right now the newport does not do anything at all */ -struct graphics_ops newport_graphic_ops = { - 0, /* owner */ - 0, /* current user */ - (void *) &newport_board_info, /* board info */ - sizeof (struct ng1_info), /* size of our data structure */ - 0, 0, /* g_regs, g_regs_size */ - newport_save, newport_restore, /* g_save_context, g_restore_context */ - newport_reset, newport_ioctl /* g_reset_console, g_ioctl */ -}; - -struct graphics_ops * -newport_probe (int slot, const char **name) -{ - struct newport_regs *p; - - npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); - - p = npregs; - p->cset.config = NPORT_CFG_GD0; - - if(newport_wait()) { - prom_printf("whoops, timeout, no NEWPORT there?"); - return 0; - } - - p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) { - prom_printf("newport_probe: read back wrong value ;-(\n"); - return 0; - } - - if (slot == 0){ - register_gconsole (&newport_console); - video_type = VIDEO_TYPE_SGI; - can_do_color = 1; - *name = "NEWPORT"; - } - - newport_reset (); - newport_render_version(); -#if 0 - newport_render_logo(); -#endif - newport_graphic_ops.g_regs = 0x1f0f0000; - newport_graphic_ops.g_regs_size = sizeof (struct newport_regs); - return &newport_graphic_ops; -} -/* - * cons_newport.c: Newport graphics console code for the SGI. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: cons_newport.c,v 1.6 1997/09/21 23:00:01 miguel Exp $ + * $Id: cons_newport.c,v 1.7 1998/03/03 01:23:05 ralf Exp $ */ #include <linux/kernel.h> diff --git a/drivers/sgi/char/gconsole.h b/drivers/sgi/char/gconsole.h index 89fd84f2b..7bc9794bb 100644 --- a/drivers/sgi/char/gconsole.h +++ b/drivers/sgi/char/gconsole.h @@ -31,36 +31,3 @@ extern unsigned char vga_font[]; extern void disable_gconsole (void); extern void enable_gconsole (void); -/* - * This is a temporary measure, we should eventually migrate to - * Gert's generic graphic console code. - */ - -#define cmapsz 8192 -#define CHAR_HEIGHT 16 - -struct console_ops { - void (*set_origin)(unsigned short offset); - void (*hide_cursor)(void); - void (*set_cursor)(int currcons); - void (*get_scrmem)(int currcons); - void (*set_scrmem)(int currcons, long offset); - int (*set_get_cmap)(unsigned char *arg, int set); - void (*blitc)(unsigned short charattr, unsigned long addr); - void (*memsetw)(void *s, unsigned short c, unsigned int count); - void (*memcpyw)(unsigned short *to, unsigned short *from, unsigned int count); -}; - -void register_gconsole (struct console_ops *); - -/* This points to the system console */ -extern struct console_ops *gconsole; - -extern void gfx_init (const char **name); - -extern void __set_origin (unsigned short offset); -extern void hide_cursor (void); -extern unsigned char vga_font[]; - -extern void disable_gconsole (void); -extern void enable_gconsole (void); diff --git a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c index 9d55e4867..6dff314e7 100644 --- a/drivers/sgi/char/graphics.c +++ b/drivers/sgi/char/graphics.c @@ -323,332 +323,3 @@ gfx_init (const char **name) prom_halt (); } } - - -/* - * gfx.c: support for SGI's /dev/graphics, /dev/opengl - * - * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * On IRIX, /dev/graphics is [10, 146] - * /dev/opengl is [10, 147] - * - * From a mail with Mark J. Kilgard, /dev/opengl and /dev/graphics are - * the same thing, the use of /dev/graphics seems deprecated though. - * - * The reason that the original SGI programmer had to use only one - * device for all the graphic cards on the system will remain a - * mistery for the rest of our lives. Why some ioctls take a board - * number and some others not? Mistery. Why do they map the hardware - * registers into the user address space with an ioctl instead of - * mmap? Mistery too. Why they did not use the standard way of - * making ioctl constants and instead sticked a random constant? - * Mistery too. - * - * We implement those misterious things, and tried not to think about - * the reasons behind them. - */ -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <asm/uaccess.h> -#include "gconsole.h" -#include "graphics.h" -#include <asm/gfx.h> -#include <asm/rrm.h> -#include <asm/page.h> -#include <asm/pgtable.h> - -/* The boards */ -#include "newport.h" - -#ifdef PRODUCTION_DRIVER -#define enable_gconsole() -#define disable_gconsole() -#endif - -static struct graphics_ops cards [MAXCARDS]; -static int boards; - -#define GRAPHICS_CARD(inode) 0 - -int -sgi_graphics_open (struct inode *inode, struct file *file) -{ - return 0; -} - -int -sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned int board; - unsigned int devnum = GRAPHICS_CARD (inode->i_rdev); - int i; - - if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT)) - return rrm_command (cmd-RRM_BASE, (void *) arg); - - switch (cmd){ - case GFX_GETNUM_BOARDS: - return boards; - - case GFX_GETBOARD_INFO: { - struct gfx_getboardinfo_args *bia = (void *) arg; - void *dest_buf; - int max_len; - - i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct gfx_getboardinfo_args)); - if (i) return i; - - __get_user_ret (board, &bia->board, -EFAULT); - __get_user_ret (dest_buf, &bia->buf, -EFAULT); - __get_user_ret (max_len, &bia->len, -EFAULT); - - if (board >= boards) - return -EINVAL; - if (max_len < sizeof (struct gfx_getboardinfo_args)) - return -EINVAL; - if (max_len > cards [board].g_board_info_len) - max_len = cards [boards].g_board_info_len; - i = verify_area (VERIFY_WRITE, dest_buf, max_len); - if (i) return i; - if (copy_to_user (dest_buf, cards [board].g_board_info, max_len)) - return -EFAULT; - return max_len; - } - - case GFX_ATTACH_BOARD: { - struct gfx_attach_board_args *att = (void *) arg; - void *vaddr; - int r; - - i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct gfx_attach_board_args)); - if (i) return i; - - __get_user_ret (board, &att->board, -EFAULT); - __get_user_ret (vaddr, &att->vaddr, -EFAULT); - - /* Ok for now we are assuming /dev/graphicsN -> head N even - * if the ioctl api suggests that this is not quite the case. - * - * Otherwise we fail, we use this assumption in the mmap code - * below to find our board information. - */ - if (board != devnum){ - printk ("Parameter board does not match the current board\n"); - return -EINVAL; - } - - if (board >= boards) - return -EINVAL; - - /* If it is the first opening it, then make it the board owner */ - if (!cards [board].g_owner) - cards [board].g_owner = current; - - /* - * Ok, we now call mmap on this file, which will end up calling - * sgi_graphics_mmap - */ - disable_gconsole (); - r = do_mmap (file, (unsigned long)vaddr, cards [board].g_regs_size, - PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, 0); - if (r) - return r; - - } - - /* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD, - * GFX_MAPALL is not even used by IRIX X server - */ - case GFX_MAPALL: - return 0; - - case GFX_LABEL: - return 0; - - /* Version check - * for my IRIX 6.2 X server, this is what the kernel returns - */ - case 1: - return 3; - - /* Xsgi does not use this one, I assume minor is the board being queried */ - case GFX_IS_MANAGED: - if (devnum > boards) - return -EINVAL; - return (cards [devnum].g_owner != 0); - - default: - if (cards [devnum].g_ioctl) - return (*cards [devnum].g_ioctl)(devnum, cmd, arg); - - } - return -EINVAL; -} - -int -sgi_graphics_close (struct inode *inode, struct file *file) -{ - int board = GRAPHICS_CARD (inode->i_rdev); - - /* Tell the rendering manager that one client is going away */ - rrm_close (inode, file); - - /* Was this file handle from the board owner?, clear it */ - if (current == cards [board].g_owner){ - cards [board].g_owner = 0; - (*cards [board].g_reset_console)(); - enable_gconsole (); - } - return 0; -} - -/* - * This is the core of the direct rendering engine. - */ - -unsigned long -sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int write_access) -{ - unsigned long page; - int board = GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev); - -#ifdef DEBUG_GRAPHICS - printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, address, - cards [board].g_user); -#endif - - /* 1. figure out if another process has this mapped, - * and revoke the mapping in that case. - */ - if (cards [board].g_user && cards [board].g_user != current){ - /* FIXME: save graphics context here, dump it to rendering node? */ - remove_mapping (cards [board].g_user, vma->vm_start, vma->vm_end); - } - cards [board].g_user = current; -#if DEBUG_GRAPHICS - printk ("Registers: 0x%lx\n", cards [board].g_regs); - printk ("vm_start: 0x%lx\n", vma->vm_start); - printk ("address: 0x%lx\n", address); - printk ("diff: 0x%lx\n", (address - vma->vm_start)); - - printk ("page/pfn: 0x%lx\n", page); - printk ("TLB entry: %lx\n", pte_val (mk_pte (page + PAGE_OFFSET, PAGE_USERIO))); -#endif - - /* 2. Map this into the current process address space */ - page = ((cards [board].g_regs) + (address - vma->vm_start)); - return page + PAGE_OFFSET; -} - -/* - * We convert a GFX ioctl for mapping hardware registers, in a nice sys_mmap - * call, which takes care of everything that must be taken care of. - * - */ - -static struct vm_operations_struct graphics_mmap = { - NULL, /* no special mmap-open */ - NULL, /* no special mmap-close */ - NULL, /* no special mmap-unmap */ - NULL, /* no special mmap-protect */ - NULL, /* no special mmap-sync */ - NULL, /* no special mmap-advise */ - sgi_graphics_nopage, /* our magic no-page fault handler */ - NULL, /* no special mmap-wppage */ - NULL, /* no special mmap-swapout */ - NULL /* no special mmap-swapin */ -}; - -int -sgi_graphics_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) -{ - uint size; - - size = vma->vm_end - vma->vm_start; - if (vma->vm_offset & ~PAGE_MASK) - return -ENXIO; - - /* 1. Set our special graphic virtualizer */ - vma->vm_ops = &graphics_mmap; - - /* 2. Set the special tlb permission bits */ - vma->vm_page_prot = PAGE_USERIO; - - /* final setup */ - vma->vm_dentry = dget (file->f_dentry); - return 0; -} - -/* Do any post card-detection setup on graphics_ops */ -static void -graphics_ops_post_init (int slot) -{ - /* There is no owner for the card initially */ - cards [slot].g_owner = (struct task_struct *) 0; - cards [slot].g_user = (struct task_struct *) 0; -} - -struct file_operations sgi_graphics_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - sgi_graphics_ioctl, /* ioctl */ - sgi_graphics_mmap, /* mmap */ - sgi_graphics_open, /* open */ - sgi_graphics_close, /* release */ - NULL, /* fsync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL /* lock */ -}; - -/* /dev/graphics */ -static struct miscdevice dev_graphics = { - SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops -}; - -/* /dev/opengl */ -static struct miscdevice dev_opengl = { - SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops -}; - -/* This is called later from the misc-init routine */ -void -gfx_register (void) -{ - misc_register (&dev_graphics); - misc_register (&dev_opengl); -} - -void -gfx_init (const char **name) -{ - struct console_ops *console; - struct graphics_ops *g; - - printk ("GFX INIT: "); - shmiq_init (); - usema_init (); - - if ((g = newport_probe (boards, name)) != 0){ - cards [boards] = *g; - graphics_ops_post_init (boards); - boards++; - console = 0; - } - /* Add more graphic drivers here */ - /* Keep passing console around */ - - if (boards > MAXCARDS){ - printk ("Too many cards found on the system\n"); - prom_halt (); - } -} - - diff --git a/drivers/sgi/char/graphics.h b/drivers/sgi/char/graphics.h index c8ad7e318..d5a8d2979 100644 --- a/drivers/sgi/char/graphics.h +++ b/drivers/sgi/char/graphics.h @@ -26,31 +26,3 @@ struct graphics_ops { void shmiq_init (void); void streamable_init (void); void usema_init (void); -#define MAXCARDS 4 - -struct graphics_ops { - /* SGIism: Board owner, gets the shmiq requests from the kernel */ - struct task_struct *g_owner; - - /* Last process that got the graphics registers mapped */ - struct task_struct *g_user; - - /* Board info */ - void *g_board_info; - int g_board_info_len; - - /* These point to hardware registers that should be mapped with - * GFX_ATTACH_BOARD and the size of the information pointed to - */ - unsigned long g_regs; - int g_regs_size; - - void (*g_save_context)(void *); - void (*g_restore_context)(void *); - void (*g_reset_console)(void); - int (*g_ioctl)(int device, int cmd, unsigned long arg); -}; - -void shmiq_init (void); -void streamable_init (void); -void usema_init (void); diff --git a/drivers/sgi/char/newport.c b/drivers/sgi/char/newport.c index e617ddd99..756aec709 100644 --- a/drivers/sgi/char/newport.c +++ b/drivers/sgi/char/newport.c @@ -215,220 +215,3 @@ newport_ioctl (int card, int cmd, unsigned long arg) } return -EINVAL; } -/* - * newport.c: context switching the newport graphics card and - * newport graphics support. - * - * Author: Miguel de Icaza - */ -#include <linux/errno.h> -#include <linux/sched.h> -#include <asm/types.h> -#include <asm/gfx.h> -#include <asm/ng1.h> -#include <asm/uaccess.h> -#include "newport.h" - -/* Kernel routines for supporting graphics context switching */ - -void newport_save (void *y) -{ - newport_ctx *x = y; - newport_wait (); - -#define LOAD(val) x->val = npregs->set.val; -#define LOADI(val) x->val = npregs->set.val.i; -#define LOADC(val) x->val = npregs->cset.val; - - LOAD(drawmode1); - LOAD(drawmode0); - LOAD(lsmode); - LOAD(lspattern); - LOAD(lspatsave); - LOAD(zpattern); - LOAD(colorback); - LOAD(colorvram); - LOAD(alpharef); - LOAD(smask0x); - LOAD(smask0y); - LOADI(_xstart); - LOADI(_ystart); - LOADI(_xend); - LOADI(_yend); - LOAD(xsave); - LOAD(xymove); - LOADI(bresd); - LOADI(bress1); - LOAD(bresoctinc1); - LOAD(bresrndinc2); - LOAD(brese1); - LOAD(bress2); - LOAD(aweight0); - LOAD(aweight1); - LOADI(colorred); - LOADI(coloralpha); - LOADI(colorgrn); - LOADI(colorblue); - LOADI(slopered); - LOADI(slopealpha); - LOADI(slopegrn); - LOADI(slopeblue); - LOAD(wrmask); - LOAD(hostrw0); - LOAD(hostrw1); - - /* configregs */ - - LOADC(smask1x); - LOADC(smask1y); - LOADC(smask2x); - LOADC(smask2y); - LOADC(smask3x); - LOADC(smask3y); - LOADC(smask4x); - LOADC(smask4y); - LOADC(topscan); - LOADC(xywin); - LOADC(clipmode); - LOADC(config); - - /* Mhm, maybe I am missing something, but it seems that - * saving/restoring the DCB is only a matter of saving these - * registers - */ - - newport_bfwait (); - LOAD (dcbmode); - newport_bfwait (); - x->dcbdata0 = npregs->set.dcbdata0.all; - newport_bfwait (); - LOAD(dcbdata1); -} - -/* - * Importat things to keep in mind when restoring the newport context: - * - * 1. slopered register is stored as a 2's complete (s12.11); - * needs to be converted to a signed magnitude (s(8)12.11). - * - * 2. xsave should be stored after xstart. - * - * 3. None of the registers should be written with the GO address. - * (read the docs for more details on this). - */ -void newport_restore (void *y) -{ - newport_ctx *x = y; -#define STORE(val) npregs->set.val = x->val -#define STOREI(val) npregs->set.val.i = x->val -#define STOREC(val) npregs->cset.val = x->val - newport_wait (); - - STORE(drawmode1); - STORE(drawmode0); - STORE(lsmode); - STORE(lspattern); - STORE(lspatsave); - STORE(zpattern); - STORE(colorback); - STORE(colorvram); - STORE(alpharef); - STORE(smask0x); - STORE(smask0y); - STOREI(_xstart); - STOREI(_ystart); - STOREI(_xend); - STOREI(_yend); - STORE(xsave); - STORE(xymove); - STOREI(bresd); - STOREI(bress1); - STORE(bresoctinc1); - STORE(bresrndinc2); - STORE(brese1); - STORE(bress2); - STORE(aweight0); - STORE(aweight1); - STOREI(colorred); - STOREI(coloralpha); - STOREI(colorgrn); - STOREI(colorblue); - STOREI(slopered); - STOREI(slopealpha); - STOREI(slopegrn); - STOREI(slopeblue); - STORE(wrmask); - STORE(hostrw0); - STORE(hostrw1); - - /* configregs */ - - STOREC(smask1x); - STOREC(smask1y); - STOREC(smask2x); - STOREC(smask2y); - STOREC(smask3x); - STOREC(smask3y); - STOREC(smask4x); - STOREC(smask4y); - STOREC(topscan); - STOREC(xywin); - STOREC(clipmode); - STOREC(config); - - /* FIXME: restore dcb thingies */ -} - -int -newport_ioctl (int card, int cmd, unsigned long arg) -{ - switch (cmd){ - case NG1_SETDISPLAYMODE: { - int i; - struct ng1_setdisplaymode_args request; - - if (copy_from_user (&request, (void *) arg, sizeof (request))) - return -EFAULT; - - newport_wait (); - newport_bfwait (); - npregs->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL | - DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL; - xmap9FIFOWait (npregs); - - /* FIXME: timing is wrong, just be extracted from - * the per-board timing table. I still have to figure - * out where this comes from - * - * This is used to select the protocol used to talk to - * the xmap9. For now I am using 60, selecting the - * WSLOW_DCB_XMAP9_PROTOCOL. - * - * Robert Tray comments on this issue: - * - * cfreq refers to the frequency of the monitor - * (ie. the refresh rate). Our monitors run typically - * between 60 Hz and 76 Hz. But it will be as low as - * 50 Hz if you're displaying NTSC/PAL and as high as - * 120 Hz if you are runining in stereo mode. You - * might want to try the WSLOW values. - */ - xmap9SetModeReg (npregs, request.wid, request.mode, 60); - return 0; - } - case NG1_SET_CURSOR_HOTSPOT: { - struct ng1_set_cursor_hotspot request; - - if (copy_from_user (&request, (void *) arg, sizeof (request))) - return -EFAULT; - /* FIXME: make request.xhot, request.yhot the hot spot */ - return 0; - } - - case NG1_SETGAMMARAMP0: - /* FIXME: load the gamma ramps :-) */ - return 0; - - } - return -EINVAL; -} diff --git a/drivers/sgi/char/rrm.c b/drivers/sgi/char/rrm.c index 507299354..199d923d7 100644 --- a/drivers/sgi/char/rrm.c +++ b/drivers/sgi/char/rrm.c @@ -66,73 +66,3 @@ rrm_close (struct inode *inode, struct file *file) /* This routine is invoked when the device is closed */ return 0; } - -/* - * Linux Rendering Resource Manager - * - * Implements the SGI-compatible rendering resource manager. - * This takes care of implementing the virtualized video hardware - * access required for OpenGL direct rendering. - * - * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * Fixes: - */ -#include <asm/uaccess.h> -#include <asm/rrm.h> - -int -rrm_open_rn (int rnid, void *arg) -{ - return 0; -} - -int -rrm_close_rn (int rnid, void *arg) -{ - return 0; -} - -int -rrm_bind_proc_to_rn (int rnid, void *arg) -{ - return 0; -} - -typedef int (*rrm_function )(void *arg); - -struct { - int (*r_fn)(int rnid, void *arg); - int arg_size; -} rrm_functions [] = { - { rrm_open_rn, sizeof (struct RRM_OpenRN) }, - { rrm_close_rn, sizeof (struct RRM_CloseRN) }, - { rrm_bind_proc_to_rn, sizeof (struct RRM_BindProcToRN) } -}; - -#define RRM_FUNCTIONS (sizeof (rrm_functions)/sizeof (rrm_functions [0])) - -/* cmd is a number in the range [0..RRM_CMD_LIMIT-RRM_BASE] */ -int -rrm_command (unsigned int cmd, void *arg) -{ - int i, rnid; - - if (cmd > RRM_FUNCTIONS){ - printk ("Called unimplemented rrm ioctl: %d\n", cmd + RRM_BASE); - return -EINVAL; - } - i = verify_area (VERIFY_READ, arg, rrm_functions [cmd].arg_size); - if (i) return i; - - __get_user_ret (rnid, (int *) arg, -EFAULT); - return (*(rrm_functions [cmd].r_fn))(rnid, arg); -} - -int -rrm_close (struct inode *inode, struct file *file) -{ - /* This routine is invoked when the device is closed */ - return 0; -} - diff --git a/drivers/sgi/char/sgicons.c b/drivers/sgi/char/sgicons.c index 069b8dbe1..fb937679b 100644 --- a/drivers/sgi/char/sgicons.c +++ b/drivers/sgi/char/sgicons.c @@ -181,191 +181,3 @@ __initfunc(unsigned long con_type_init(unsigned long start_mem, const char **nam __initfunc(void con_type_init_finish(void)) { } -/* - * sgicons.c: Setting up and registering console I/O on the SGI. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * This implement a virtual console interface. - * - * This should be replaced with Gert's all-singing all-dancing - * graphics console code in the future - * - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <asm/uaccess.h> -#include "gconsole.h" - -/* To make psaux code cleaner */ -int aux_device_present = 0xaa; - -/* This is the system graphics console (the first adapter found) */ -struct console_ops *gconsole = 0; -struct console_ops *real_gconsole = 0; - -void -enable_gconsole (void) -{ - if (!gconsole) - gconsole = real_gconsole; -} - -void -disable_gconsole (void) -{ - if (gconsole){ - real_gconsole = gconsole; - gconsole = 0; - } -} - -void -register_gconsole (struct console_ops *gc) -{ - if (gconsole) - return; - gconsole = gc; -} - -void -__set_origin (unsigned short offset) -{ - if (gconsole) - (*gconsole->set_origin)(offset); -} - -void -hide_cursor (void) -{ - - if (gconsole) - (*gconsole->hide_cursor)(); -} - -void -set_cursor (int currcons) -{ - if (gconsole) - (*gconsole->set_cursor)(currcons); -} - -void -get_scrmem (int currcons) -{ - if (gconsole) - (*gconsole->get_scrmem)(currcons); -} - -void -set_scrmem (int currcons, long offset) -{ - if (gconsole) - (*gconsole->set_scrmem)(currcons, offset); -} - -int -set_get_cmap (unsigned char *arg, int set) -{ - if (gconsole) - return (*gconsole->set_get_cmap)(arg, set); - return 0; -} - -void -blitc (unsigned short charattr, unsigned long addr) -{ - if (gconsole) - (*gconsole->blitc)(charattr, addr); -} - -void -memsetw (void *s, unsigned short c, unsigned int count) -{ - if (gconsole) - (*gconsole->memsetw)(s, c, count); -} - -void -memcpyw (unsigned short *to, unsigned short *from, unsigned int count) -{ - if (gconsole) - (*gconsole->memcpyw)(to, from, count); -} - -int -con_adjust_height (unsigned long fontheight) -{ - return -EINVAL; -} - -int -set_get_font (char *arg, int set, int ch512) -{ - int error, i, line; - - if (!arg) - return -EINVAL; - error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg, - ch512 ? 2* cmapsz : cmapsz); - if (error) - return error; - - /* download the current font */ - if (!set) { - memset (arg, 0, cmapsz); - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) - __put_user (vga_font [i], arg+(i*32+line)); - } - return 0; - } - - /* set the font */ - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) { - __get_user(vga_font [i*CHAR_HEIGHT + line], - arg + (i * 32 + line)); - } - } - return 0; -} - -/* - * dummy routines for the VESA blanking code, which is VGA only, - * so we don't have to carry that stuff around for the Sparc... */ -void vesa_blank(void) { } -void vesa_unblank(void) { } -void set_vesa_blanking(const unsigned long arg) { } -void vesa_powerdown(void) { } -void set_palette (void) { } - -__initfunc(int con_is_present()) -{ - return 1; -} - -extern unsigned long video_mem_base, video_screen_size, video_mem_term; - -__initfunc(unsigned long con_type_init(unsigned long start_mem, const char **name)) -{ - extern int serial_console; - - if (serial_console) - *name = "NONE"; - else { - gfx_init (name); - printk("Video screen size is %08lx at %08lx\n", - video_screen_size, start_mem); - video_mem_base = start_mem; - start_mem += (video_screen_size * 2); - video_mem_term = start_mem; - } - return start_mem; -} - -__initfunc(void con_type_init_finish(void)) -{ -} diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c index b6a3effc6..c8d4d7e54 100644 --- a/drivers/sgi/char/sgiserial.c +++ b/drivers/sgi/char/sgiserial.c @@ -1601,2025 +1601,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && !(info->flags & ZILOG_CLOSING) && do_clocal) break; - if (current->signal & ~current->blocked) { - 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 sgi_serial *info; - int retval, line; - - line = MINOR(tty->device) - tty->driver.minor_start; - /* The zilog lines for the mouse/keyboard must be - * opened using their respective drivers. - */ - if ((line < 0) || (line >= NUM_CHANNELS)) - return -ENODEV; - info = zs_soft + line; - /* Is the kgdb running over this line? */ - if (info->kgdb_channel) - return -ENODEV; - 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; - - /* - * 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); - } - - info->session = current->session; - info->pgrp = current->pgrp; - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); -#endif - return 0; -} - -/* Finally, routines used to initialize the serial driver. */ - -static void show_serial_version(void) -{ - printk("SGI Zilog8530 serial driver version 1.00\n"); -} - -/* Return layout for the requested zs chip number. */ -static inline struct sgi_zslayout *get_zs(int chip) -{ - extern struct hpc3_miscregs *hpc3mregs; - - if(chip > 0) { - prom_printf("Wheee, bogus zs chip number requested.\n"); - prom_getchar(); - romvec->imode(); - } - return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd); - -} - -extern void register_console(void (*proc)(const char *)); - -static inline void -rs_cons_check(struct sgi_serial *ss, int channel) -{ - int i, o, io; - static consout_registered = 0; - static msg_printed = 0; - - i = o = io = 0; - - /* Is this one of the serial console lines? */ - if((zs_cons_chanout != channel) && - (zs_cons_chanin != channel)) - return; - zs_conschan = ss->zs_channel; - zs_consinfo = ss; - - /* Register the console output putchar, if necessary */ - if((zs_cons_chanout == channel)) { - o = 1; - /* double whee.. */ - if(!consout_registered) { - register_console(zs_console_print); - consout_registered = 1; - } - } - - /* If this is console input, we handle the break received - * status interrupt on this line to mean prom_halt(). - */ - if(zs_cons_chanin == channel) { - ss->break_abort = 1; - i = 1; - } - if(o && i) - io = 1; - if(ss->zs_baud != 9562) { /* Don't ask... */ - prom_printf("BAD console baud rate %d\n", ss->zs_baud); - prom_getchar(); - prom_imode(); - panic("Console baud rate weirdness"); - } - - /* Set flag variable for this port so that it cannot be - * opened for other uses by accident. - */ - ss->is_cons = 1; - - if(io) { - if(!msg_printed) { - printk("zs%d: console I/O\n", ((channel>>1)&1)); - msg_printed = 1; - } - } else { - printk("zs%d: console %s\n", ((channel>>1)&1), - (i==1 ? "input" : (o==1 ? "output" : "WEIRD"))); - } -} - -volatile int test_done; - -/* rs_init inits the driver */ -int rs_init(void) -{ - int chip, channel, i, flags; - struct sgi_serial *info; - - /* Setup base handler, and timer table. */ - init_bh(SERIAL_BH, do_serial_bh); - timer_table[RS_TIMER].fn = rs_timer; - timer_table[RS_TIMER].expires = 0; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - /* SGI: 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 = NUM_CHANNELS; - 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; - - /* - * 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(); - - /* Set up our interrupt linked list */ - zs_chain = &zs_soft[0]; - zs_soft[0].zs_next = &zs_soft[1]; - zs_soft[1].zs_next = 0; - - for(chip = 0; chip < NUM_SERIAL; chip++) { - /* If we are doing kgdb over one of the channels on - * chip zero, kgdb_channel will be set to 1 by the - * rs_kgdb_hook() routine below. - */ - if(!zs_chips[chip]) { - zs_chips[chip] = get_zs(chip); - /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; - zs_soft[(chip*2)].kgdb_channel = 0; - zs_soft[(chip*2)+1].kgdb_channel = 0; - } - /* First, set up channel A on this chip. */ - channel = chip * 2; - zs_soft[channel].zs_channel = zs_channels[channel]; - zs_soft[channel].change_needed = 0; - zs_soft[channel].clk_divisor = 16; - zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - zs_soft[channel].cons_mouse = 0; - /* If not keyboard/mouse and is console serial - * line, then enable receiver interrupts. - */ - if(zs_soft[channel].is_cons) { - write_zsreg(zs_soft[channel].zs_channel, R1, - (EXT_INT_ENAB | INT_ALL_Rx)); - write_zsreg(zs_soft[channel].zs_channel, R9, (NV | MIE)); - write_zsreg(zs_soft[channel].zs_channel, R10, (NRZ)); - write_zsreg(zs_soft[channel].zs_channel, R3, (Rx8|RxENABLE)); - write_zsreg(zs_soft[channel].zs_channel, R5, (Tx8 | TxENAB)); - } - /* If this is the kgdb line, enable interrupts because we - * now want to receive the 'control-c' character from the - * client attached to us asynchronously. - */ - if(zs_soft[channel].kgdb_channel) - kgdb_chaninit(&zs_soft[channel], 1, - zs_soft[channel].zs_baud); - - /* Now, channel B */ - channel++; - zs_soft[channel].zs_channel = zs_channels[channel]; - zs_soft[channel].change_needed = 0; - zs_soft[channel].clk_divisor = 16; - zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - zs_soft[channel].cons_keyb = 0; - /* If console serial line, then enable receiver interrupts. */ - if(zs_soft[channel].is_cons) { - write_zsreg(zs_soft[channel].zs_channel, R1, - (EXT_INT_ENAB | INT_ALL_Rx)); - write_zsreg(zs_soft[channel].zs_channel, R9, - (NV | MIE)); - write_zsreg(zs_soft[channel].zs_channel, R10, - (NRZ)); - write_zsreg(zs_soft[channel].zs_channel, R3, - (Rx8|RxENABLE)); - write_zsreg(zs_soft[channel].zs_channel, R5, - (Tx8 | TxENAB | RTS | DTR)); - } - } - - for(info=zs_chain, i=0; info; info = info->zs_next, i++) - { - info->magic = SERIAL_MAGIC; - info->port = (int) info->zs_channel; - info->line = i; - info->tty = 0; - info->irq = zilog_irq; - 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->tqueue_hangup.routine = do_serial_hangup; - info->tqueue_hangup.data = info; - info->callout_termios =callout_driver.init_termios; - info->normal_termios = serial_driver.init_termios; - info->open_wait = 0; - info->close_wait = 0; - printk("tty%02d at 0x%04x (irq = %d)", info->line, - info->port, info->irq); - printk(" is a Zilog8530\n"); - } - - if (request_irq(zilog_irq, rs_interrupt, (SA_INTERRUPT), - "Zilog8530", zs_chain)) - panic("Unable to attach zs intr\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. - */ -/* SGI: 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; -} - -/* Hooks for running a serial console. con_init() calls this if the - * console is being run over one of the ttya/ttyb serial ports. - * 'chip' should be zero, as chip 1 drives the mouse/keyboard. - * 'channel' is decoded as 0=TTYA 1=TTYB, note that the channels - * are addressed backwards, channel B is first, then channel A. - */ -void -rs_cons_hook(int chip, int out, int line) -{ - int channel; - - if(chip) - panic("rs_cons_hook called with chip not zero"); - if(line != 1 && line != 2) - panic("rs_cons_hook called with line not ttya or ttyb"); - channel = line - 1; - if(!zs_chips[chip]) { - zs_chips[chip] = get_zs(chip); - /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; - } - zs_soft[channel].zs_channel = zs_channels[channel]; - zs_soft[channel].change_needed = 0; - zs_soft[channel].clk_divisor = 16; - zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - if(out) - zs_cons_chanout = ((chip * 2) + channel); - else - zs_cons_chanin = ((chip * 2) + channel); - rs_cons_check(&zs_soft[channel], channel); -} - -/* This is called at boot time to prime the kgdb serial debugging - * serial line. The 'tty_num' argument is 0 for /dev/ttyd2 and 1 for - * /dev/ttyd1 (yes they are backwards on purpose) which is determined - * in setup_arch() from the boot command line flags. - */ -void -rs_kgdb_hook(int tty_num) -{ - int chip = 0; - - if(!zs_chips[chip]) { - zs_chips[chip] = get_zs(chip); - /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; - } - 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 = get_zsbaud(&zs_soft[tty_num]); - 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], 0, 9600); - ZS_CLEARERR(zs_kgdbchan); - udelay(5); - ZS_CLEARFIFO(zs_kgdbchan); -} -/* sgiserial.c: Serial port driver for SGI machines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ - -#include <linux/errno.h> -#include <linux/signal.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 <asm/io.h> -#include <asm/irq.h> -#include <asm/sgialib.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/sgihpc.h> -#include <asm/sgint23.h> -#include <asm/uaccess.h> - -#include "sgiserial.h" - -#define NUM_SERIAL 1 /* One chip on board. */ -#define NUM_CHANNELS (NUM_SERIAL * 2) - -extern struct wait_queue * keypress_wait; - -struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, }; -struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, }; -struct sgi_zschannel *zs_conschan; -struct sgi_zschannel *zs_kgdbchan; -int zs_nodes[NUM_SERIAL] = { 0, }; - -struct sgi_serial zs_soft[NUM_CHANNELS]; -struct sgi_serial *zs_chain; /* IRQ servicing chain */ -static int zilog_irq = 21; - -struct tty_struct zs_ttys[NUM_CHANNELS]; -/** struct tty_struct *zs_constty; **/ - -/* Console hooks... */ -static int zs_cons_chanout = 0; -static int zs_cons_chanin = 0; -struct sgi_serial *zs_consinfo = 0; - -static unsigned char kgdb_regs[16] = { - 0, 0, 0, /* write 0, 1, 2 */ - (Rx8 | RxENABLE), /* write 3 */ - (X16CLK | SB1 | PAR_EVEN), /* write 4 */ - (Tx8 | TxENAB), /* write 5 */ - 0, 0, 0, /* write 6, 7, 8 */ - (NV), /* write 9 */ - (NRZ), /* write 10 */ - (TCBR | RCBR), /* write 11 */ - 0, 0, /* BRG time constant, write 12 + 13 */ - (BRENABL), /* write 14 */ - (DCDIE) /* write 15 */ -}; - -#define ZS_CLOCK 3672000 /* Zilog input clock rate */ - -DECLARE_TASK_QUEUE(tq_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... DEBUG_INTR is bad to use when one of the zs - * lines is your console ;( - */ -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW - -#define RS_STROBE_TIME 10 -#define RS_ISR_PASS_LIMIT 256 - -#define _INLINE_ inline - -static void change_speed(struct sgi_serial *info); - -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 memcpy_fromfs 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 struct semaphore tmp_buf_sem = MUTEX; - -static inline int serial_paranoia_check(struct sgi_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 sun_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, 115200, 0 }; - -/* - * Reading and writing Zilog8530 registers. The delays are to make this - * driver work on the Sun4 which needs a settling delay after each chip - * register access, other machines handle this in hardware via auxiliary - * flip-flops which implement the settle time we do in software. - */ -static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg) -{ - unsigned char retval; - volatile unsigned char junk; - - udelay(2); - channel->control = reg; - junk = ioc_icontrol->istat0; - udelay(1); - retval = channel->control; - return retval; -} - -static inline void write_zsreg(struct sgi_zschannel *channel, unsigned char reg, unsigned char value) -{ - volatile unsigned char junk; - - udelay(2); - channel->control = reg; - junk = ioc_icontrol->istat0; - udelay(1); - channel->control = value; - junk = ioc_icontrol->istat0; - return; -} - -static inline void load_zsregs(struct sgi_zschannel *channel, unsigned char *regs) -{ - ZS_CLEARERR(channel); - ZS_CLEARFIFO(channel); - /* Load 'em up */ - write_zsreg(channel, R4, regs[R4]); - write_zsreg(channel, R10, regs[R10]); - write_zsreg(channel, R3, regs[R3] & ~RxENABLE); - write_zsreg(channel, R5, regs[R5] & ~TxENAB); - write_zsreg(channel, R1, regs[R1]); - write_zsreg(channel, R9, regs[R9]); - 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 inline void zs_rtsdtr(struct sgi_serial *ss, int set) -{ - if(set) { - ss->curregs[5] |= (RTS | DTR); - ss->pendregs[5] = ss->curregs[5]; - write_zsreg(ss->zs_channel, 5, ss->curregs[5]); - } else { - ss->curregs[5] &= ~(RTS | DTR); - ss->pendregs[5] = ss->curregs[5]; - write_zsreg(ss->zs_channel, 5, ss->curregs[5]); - } - return; -} - -static inline void kgdb_chaninit(struct sgi_serial *ss, int intson, int bps) -{ - int brg; - - if(intson) { - kgdb_regs[R1] = INT_ALL_Rx; - kgdb_regs[R9] |= MIE; - } else { - kgdb_regs[R1] = 0; - kgdb_regs[R9] &= ~MIE; - } - brg = BPS_TO_BRG(bps, ZS_CLOCK/16); - kgdb_regs[R12] = (brg & 255); - kgdb_regs[R13] = ((brg >> 8) & 255); - load_zsregs(ss->zs_channel, kgdb_regs); -} - -/* Utility routines for the Zilog */ -static inline int get_zsbaud(struct sgi_serial *ss) -{ - struct sgi_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)&0xff) << 8); - brg |= (read_zsreg(channel, 12)&0xff); - return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_stop")) - return; - - save_flags(flags); cli(); - if (info->curregs[5] & TxENAB) { - info->curregs[5] &= ~TxENAB; - info->pendregs[5] &= ~TxENAB; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - } - restore_flags(flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_start")) - return; - - save_flags(flags); cli(); - if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { - info->curregs[5] |= TxENAB; - info->pendregs[5] = info->curregs[5]; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - } - restore_flags(flags); -} - -/* Drop into either the boot monitor or kadb upon receiving a break - * from keyboard/console input. - */ -static void batten_down_hatches(void) -{ - prom_imode(); -#if 0 - /* If we are doing kadb, we call the debugger - * else we just drop into the boot monitor. - * Note that we must flush the user windows - * first before giving up control. - */ - printk("\n"); - if((((unsigned long)linux_dbvec)>=DEBUG_FIRSTVADDR) && - (((unsigned long)linux_dbvec)<=DEBUG_LASTVADDR)) - sp_enter_debugger(); - else - prom_halt(); - - /* XXX We want to notify the keyboard driver that all - * XXX keys are in the up state or else weird things - * XXX happen... - */ -#endif - return; -} - -/* On receive, this clears errors and the receiver interrupts */ -static inline void rs_recv_clear(struct sgi_zschannel *zsc) -{ - volatile unsigned char junk; - - udelay(2); - zsc->control = ERR_RES; - junk = ioc_icontrol->istat0; - udelay(2); - zsc->control = RES_H_IUS; - junk = ioc_icontrol->istat0; -} - -/* - * ---------------------------------------------------------------------- - * - * 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. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * 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 sgi_serial *info, - int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - -#ifdef CONFIG_REMOTE_DEBUG -extern void set_async_breakpoint(unsigned int epc); -#endif - -static _INLINE_ void receive_chars(struct sgi_serial *info, struct pt_regs *regs) -{ - struct tty_struct *tty = info->tty; - volatile unsigned char junk; - unsigned char ch, stat; - - udelay(2); - ch = info->zs_channel->data; - junk = ioc_icontrol->istat0; - udelay(2); - stat = read_zsreg(info->zs_channel, R1); - - /* If this is the console keyboard, we need to handle - * L1-A's here. - */ - if(info->is_cons) { - if(ch==0) { /* whee, break received */ - batten_down_hatches(); - rs_recv_clear(info->zs_channel); - return; - } else if (ch == 1) { - show_state(); - return; - } else if (ch == 2) { - show_buffers(); - return; - } - /* It is a 'keyboard interrupt' ;-) */ - wake_up(&keypress_wait); - } - /* Look for kgdb 'stop' character, consult the gdb documentation - * for remote target debugging and arch/sparc/kernel/sparc-stub.c - * to see how all this works. - */ -#ifdef CONFIG_REMOTE_DEBUG - if((info->kgdb_channel) && (ch =='\003')) { - set_async_breakpoint(read_32bit_cp0_register(CP0_EPC)); - goto clear_and_exit; - } -#endif - if(!tty) - goto clear_and_exit; - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - queue_task(&tty->flip.tqueue, &tq_timer); - tty->flip.count++; - if(stat & PAR_ERR) - *tty->flip.flag_buf_ptr++ = TTY_PARITY; - else if(stat & Rx_OVR) - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - else if(stat & CRC_ERR) - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - else - *tty->flip.flag_buf_ptr++ = 0; /* XXX */ - *tty->flip.char_buf_ptr++ = ch; - - queue_task(&tty->flip.tqueue, &tq_timer); - -clear_and_exit: - rs_recv_clear(info->zs_channel); - return; -} - -static _INLINE_ void transmit_chars(struct sgi_serial *info) -{ - volatile unsigned char junk; - - /* P3: In theory we have to test readiness here because a - * serial console can clog the chip through rs_put_char(). - * David did not do this. I think he relies on 3-chars FIFO in 8530. - * Let's watch for lost _output_ characters. XXX - */ - - /* SGI ADDENDUM: On most SGI machines, the Zilog does possess - * a 16 or 17 byte fifo, so no worries. -dm - */ - - if (info->x_char) { - /* Send next char */ - udelay(2); - info->zs_channel->data = info->x_char; - junk = ioc_icontrol->istat0; - - info->x_char = 0; - goto clear_and_return; - } - - if((info->xmit_cnt <= 0) || info->tty->stopped) { - /* That's peculiar... */ - udelay(2); - info->zs_channel->control = RES_Tx_P; - junk = ioc_icontrol->istat0; - goto clear_and_return; - } - - /* Send char */ - udelay(2); - info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; - junk = ioc_icontrol->istat0; - - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - - if (info->xmit_cnt < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - - if(info->xmit_cnt <= 0) { - udelay(2); - info->zs_channel->control = RES_Tx_P; - junk = ioc_icontrol->istat0; - goto clear_and_return; - } - -clear_and_return: - /* Clear interrupt */ - udelay(2); - info->zs_channel->control = RES_H_IUS; - junk = ioc_icontrol->istat0; - return; -} - -static _INLINE_ void status_handle(struct sgi_serial *info) -{ - volatile unsigned char junk; - unsigned char status; - - /* Get status from Read Register 0 */ - udelay(2); - status = info->zs_channel->control; - junk = ioc_icontrol->istat0; - /* Clear status condition... */ - udelay(2); - info->zs_channel->control = RES_EXT_INT; - junk = ioc_icontrol->istat0; - /* Clear the interrupt */ - udelay(2); - info->zs_channel->control = RES_H_IUS; - junk = ioc_icontrol->istat0; - -#if 0 - if(status & DCD) { - if((info->tty->termios->c_cflag & CRTSCTS) && - ((info->curregs[3] & AUTO_ENAB)==0)) { - info->curregs[3] |= AUTO_ENAB; - info->pendregs[3] |= AUTO_ENAB; - write_zsreg(info->zs_channel, 3, info->curregs[3]); - } - } else { - if((info->curregs[3] & AUTO_ENAB)) { - info->curregs[3] &= ~AUTO_ENAB; - info->pendregs[3] &= ~AUTO_ENAB; - write_zsreg(info->zs_channel, 3, info->curregs[3]); - } - } -#endif - /* Whee, if this is console input and this is a - * 'break asserted' status change interrupt, call - * the boot prom. - */ - if((status & BRK_ABRT) && info->break_abort) - batten_down_hatches(); - - /* XXX Whee, put in a buffer somewhere, the status information - * XXX whee whee whee... Where does the information go... - */ - return; -} - -/* - * This is the serial driver's generic interrupt routine - */ -void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - struct sgi_serial * info = (struct sgi_serial *) dev_id; - unsigned char zs_intreg; - - zs_intreg = read_zsreg(info->zs_channel, 3); - - /* 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) - - /* *** Chip 1 *** */ - /* 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. - * ------------------------------------------------------------------- - */ - -/* - * 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_serial); -} - -static void do_softint(void *private_) -{ - struct sgi_serial *info = (struct sgi_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); - } -} - -/* - * This routine is called from the scheduler tqueue when the interrupt - * routine has signalled that a hangup has occurred. The path of - * hangup processing is: - * - * serial interrupt routine -> (scheduler tqueue) -> - * do_serial_hangup() -> tty->hangup() -> rs_hangup() - * - */ -static void do_serial_hangup(void *private_) -{ - struct sgi_serial *info = (struct sgi_serial *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); -} - - -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * by the serial driver to handle ports that do not have an interrupt - * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530. - */ - -static void rs_timer(void) -{ - printk("rs_timer called\n"); - prom_halt(); - return; -} - -static int startup(struct sgi_serial * info) -{ - volatile unsigned char junk; - 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 FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - ZS_CLEARFIFO(info->zs_channel); - info->xmit_fifo_size = 1; - - /* - * Clear the interrupt registers. - */ - udelay(2); - info->zs_channel->control = ERR_RES; - junk = ioc_icontrol->istat0; - udelay(2); - info->zs_channel->control = RES_H_IUS; - junk = ioc_icontrol->istat0; - - /* - * Now, initialize the Zilog - */ - zs_rtsdtr(info, 1); - - /* - * Finally, enable sequencing and interrupts - */ - info->curregs[1] |= (info->curregs[1] & ~0x18) | (EXT_INT_ENAB|INT_ALL_Rx); - info->pendregs[1] = info->curregs[1]; - info->curregs[3] |= (RxENABLE | Rx8); - info->pendregs[3] = info->curregs[3]; - /* We enable Tx interrupts as needed. */ - info->curregs[5] |= (TxENAB | Tx8); - info->pendregs[5] = info->curregs[5]; - info->curregs[9] |= (NV | MIE); - info->pendregs[9] = info->curregs[9]; - write_zsreg(info->zs_channel, 3, info->curregs[3]); - write_zsreg(info->zs_channel, 5, info->curregs[5]); - write_zsreg(info->zs_channel, 9, info->curregs[9]); - - /* - * And clear the interrupt registers again for luck. - */ - udelay(2); - info->zs_channel->control = ERR_RES; - junk = ioc_icontrol->istat0; - udelay(2); - info->zs_channel->control = RES_H_IUS; - junk = ioc_icontrol->istat0; - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * Set up serial timers... - */ -#if 0 /* Works well and stops the machine. */ - timer_table[RS_TIMER].expires = jiffies + 2; - timer_active |= 1 << RS_TIMER; -#endif - - /* - * and set the speed of the serial port - */ - change_speed(info); - - 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 sgi_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; - } - - 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 sgi_serial *info) -{ - unsigned short port; - unsigned cflag; - int i; - int brg; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!(port = info->port)) - return; - i = cflag & CBAUD; - if (i & CBAUDEX) { - /* XXX CBAUDEX is not obeyed. - * It is impossible at a 32bits SPARC. - * But we have to report this to user ... someday. - */ - i = B9600; - } - if (i == 0) { - /* XXX B0, hangup the line. */ - do_serial_hangup(info); - } else if (baud_table[i]) { - info->zs_baud = baud_table[i]; - info->clk_divisor = 16; - - info->curregs[4] = X16CLK; - info->curregs[11] = TCBR | RCBR; - brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); - info->curregs[12] = (brg & 255); - info->curregs[13] = ((brg >> 8) & 255); - info->curregs[14] = BRENABL; - } - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: - info->curregs[3] &= ~(0xc0); - info->curregs[3] |= Rx5; - info->pendregs[3] = info->curregs[3]; - info->curregs[5] &= ~(0xe0); - info->curregs[5] |= Tx5; - info->pendregs[5] = info->curregs[5]; - break; - case CS6: - info->curregs[3] &= ~(0xc0); - info->curregs[3] |= Rx6; - info->pendregs[3] = info->curregs[3]; - info->curregs[5] &= ~(0xe0); - info->curregs[5] |= Tx6; - info->pendregs[5] = info->curregs[5]; - break; - case CS7: - info->curregs[3] &= ~(0xc0); - info->curregs[3] |= Rx7; - info->pendregs[3] = info->curregs[3]; - info->curregs[5] &= ~(0xe0); - info->curregs[5] |= Tx7; - info->pendregs[5] = info->curregs[5]; - break; - case CS8: - default: /* defaults to 8 bits */ - info->curregs[3] &= ~(0xc0); - info->curregs[3] |= Rx8; - info->pendregs[3] = info->curregs[3]; - info->curregs[5] &= ~(0xe0); - info->curregs[5] |= Tx8; - info->pendregs[5] = info->curregs[5]; - break; - } - info->curregs[4] &= ~(0x0c); - if (cflag & CSTOPB) { - info->curregs[4] |= SB2; - } else { - info->curregs[4] |= SB1; - } - info->pendregs[4] = info->curregs[4]; - if (cflag & PARENB) { - info->curregs[4] |= PAR_ENA; - info->pendregs[4] |= PAR_ENA; - } else { - info->curregs[4] &= ~PAR_ENA; - info->pendregs[4] &= ~PAR_ENA; - } - if (!(cflag & PARODD)) { - info->curregs[4] |= PAR_EVEN; - info->pendregs[4] |= PAR_EVEN; - } else { - info->curregs[4] &= ~PAR_EVEN; - info->pendregs[4] &= ~PAR_EVEN; - } - - /* Load up the new values */ - load_zsregs(info->zs_channel, info->curregs); - - return; -} - -/* This is for console output over ttya/ttyb */ -static void rs_put_char(char ch) -{ - struct sgi_zschannel *chan = zs_conschan; - volatile unsigned char junk; - int flags, loops = 0; - - save_flags(flags); cli(); - while(((junk = chan->control) & Tx_BUF_EMP)==0 && loops < 10000) { - loops++; - udelay(2); - } - - udelay(2); - chan->data = ch; - junk = ioc_icontrol->istat0; - restore_flags(flags); -} - -/* These are for receiving and sending characters under the kgdb - * source level kernel debugger. - */ -void putDebugChar(char kgdb_char) -{ - struct sgi_zschannel *chan = zs_kgdbchan; - volatile unsigned char junk; - unsigned long flags; - - save_flags(flags); cli(); - udelay(2); - while((chan->control & Tx_BUF_EMP)==0) - udelay(2); - - udelay(2); - chan->data = kgdb_char; - junk = ioc_icontrol->istat0; - restore_flags(flags); -} - -char getDebugChar(void) -{ - struct sgi_zschannel *chan = zs_kgdbchan; - unsigned char junk; - - while((chan->control & Rx_CH_AV)==0) - udelay(2); - - junk = ioc_icontrol->istat0; - udelay(2); - return chan->data; -} - -/* - * Fair output driver allows a process to speak. - */ -static void rs_fair_output(void) -{ - int left; /* Output no more than that */ - unsigned long flags; - struct sgi_serial *info = zs_consinfo; - volatile unsigned char junk; - char c; - - if (info == 0) return; - if (info->xmit_buf == 0) return; - - save_flags(flags); cli(); - left = info->xmit_cnt; - while (left != 0) { - c = info->xmit_buf[info->xmit_tail]; - info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - restore_flags(flags); - - rs_put_char(c); - - save_flags(flags); cli(); - left = MIN(info->xmit_cnt, left-1); - } - - /* Last character is being transmitted now (hopefully). */ - udelay(2); - zs_conschan->control = RES_Tx_P; - junk = ioc_icontrol->istat0; - - restore_flags(flags); - return; -} - -/* - * zs_console_print is registered for printk. - */ -static void zs_console_print(const char *p) -{ - char c; - - while((c=*(p++)) != 0) { - if(c == '\n') - rs_put_char('\r'); - rs_put_char(c); - } - - /* Comment this if you want to have a strict interrupt-driven output */ - rs_fair_output(); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_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 || tty->hw_stopped || - !info->xmit_buf) - return; - - /* Enable transmitter */ - save_flags(flags); cli(); - info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - write_zsreg(info->zs_channel, 1, info->curregs[1]); - info->curregs[5] |= TxENAB; - info->pendregs[5] |= TxENAB; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - - /* - * Send a first (bootstrapping) character. A best solution is - * to call transmit_chars() here which handles output in a - * generic way. Current transmit_chars() not only transmits, - * but resets interrupts also what we do not desire here. - * XXX Discuss with David. - */ - if (info->zs_channel->control & Tx_BUF_EMP) { - volatile unsigned char junk; - - /* Send char */ - udelay(2); - info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; - junk = ioc_icontrol->istat0; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - 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 sgi_serial *info = (struct sgi_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 && !tty->hw_stopped && - !(info->curregs[5] & TxENAB)) { - /* Enable transmitter */ - info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - write_zsreg(info->zs_channel, 1, info->curregs[1]); - info->curregs[5] |= TxENAB; - info->pendregs[5] |= TxENAB; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - } - restore_flags(flags); - return total; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_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 sgi_serial *info = (struct sgi_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 sgi_serial *info = (struct sgi_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 sgi_serial *info = (struct sgi_serial *)tty->driver_data; -#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)) - info->x_char = STOP_CHAR(tty); - - /* Turn off RTS line */ - cli(); - info->curregs[5] &= ~RTS; - info->pendregs[5] &= ~RTS; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - sti(); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; -#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)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } - - /* Assert RTS line */ - cli(); - info->curregs[5] |= RTS; - info->pendregs[5] |= RTS; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - sti(); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct sgi_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 sgi_serial * info, - struct serial_struct * new_info) -{ - struct serial_struct new_serial; - struct sgi_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 sgi_serial * info, unsigned int *value) -{ - volatile unsigned char junk; - unsigned char status; - - cli(); - udelay(2); - status = info->zs_channel->control; - junk = ioc_icontrol->istat0; - sti(); - return put_user(status,value); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break( struct sgi_serial * info, int duration) -{ - if (!info->port) - return; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; - cli(); - write_zsreg(info->zs_channel, 5, (info->curregs[5] | SND_BRK)); - schedule(); - write_zsreg(info->zs_channel, 5, info->curregs[5]); - sti(); -} - -static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int error; - struct sgi_serial * info = (struct sgi_serial *)tty->driver_data; - int retval; - - 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 TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, HZ/4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg*(HZ/10) : HZ/4); - return 0; - case TIOCGSOFTCAR: - error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); - if (error) - return error; - put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); - return 0; - case TIOCSSOFTCAR: - error = get_user(arg, (unsigned long *)arg); - if (error) - return error; - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - return 0; - 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 sgi_serial)); - if (error) - return error; - copy_to_user((struct sun_serial *) arg, - info, sizeof(struct sgi_serial)); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; - - if (tty->termios->c_cflag == old_termios->c_cflag) - return; - - change_speed(info); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * ZILOG structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct sgi_serial * info = (struct sgi_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 receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - /** if (!info->iscons) ... **/ - info->curregs[3] &= ~RxENABLE; - info->pendregs[3] = info->curregs[3]; - write_zsreg(info->zs_channel, 3, info->curregs[3]); - info->curregs[1] &= ~(0x18); - info->pendregs[1] = info->curregs[1]; - write_zsreg(info->zs_channel, 1, info->curregs[1]); - ZS_CLEARFIFO(info->zs_channel); - - 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 (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); - } - 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_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void rs_hangup(struct tty_struct *tty) -{ - struct sgi_serial * info = (struct sgi_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 sgi_serial *info) -{ - struct wait_queue wait = { current, NULL }; - 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 - if (info->flags & ZILOG_HUP_NOTIFY) - return -EAGAIN; - else - return -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 - info->count--; - info->blocked_open++; - while (1) { - cli(); - if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) - zs_rtsdtr(info, 1); - sti(); - 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) - break; if (signal_pending(current)) { retval = -ERESTARTSYS; break; diff --git a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c index 623f34abe..37a8b9bf9 100644 --- a/drivers/sgi/char/shmiq.c +++ b/drivers/sgi/char/shmiq.c @@ -47,466 +47,6 @@ #include <linux/sched.h> #include <linux/file.h> #include <linux/interrupt.h> -#include <linux/vmalloc.h> -#include <linux/wait.h> -#include <linux/major.h> - -#include <asm/smp_lock.h> -#include <asm/shmiq.h> -#include <asm/mman.h> -#include <asm/uaccess.h> -#include <asm/poll.h> -#include "graphics.h" - -/* we are not really getting any more than a few files in the shmiq */ -#define MAX_SHMIQ_DEVS 10 - -/* - * One per X server running, not going to get very big. - * Even if we have this we now assume just 1 /dev/qcntl can be - * active, I need to find how this works on multi-headed machines. - */ -#define MAX_SHMI_QUEUES 4 - -static struct { - int used; - struct file *filp; - struct shmiqsetcpos cpos; -} shmiq_pushed_devices [MAX_SHMIQ_DEVS]; - -/* /dev/qcntlN attached memory regions, location and size of the event queue */ -static struct { - int opened; /* if this device has been opened */ - void *shmiq_vaddr; /* mapping in kernel-land */ - int tail; /* our copy of the shmiq->tail */ - int events; - int mapped; - - struct wait_queue *proc_list; - struct fasync_struct *fasync; -} shmiqs [MAX_SHMI_QUEUES]; - -void -shmiq_push_event (struct shmqevent *e) -{ - struct sharedMemoryInputQueue *s; - int device = 0; /* FIXME: here is the assumption /dev/shmiq == /dev/qcntl0 */ - int tail_next; - - if (!shmiqs [device].mapped) - return; - s = shmiqs [device].shmiq_vaddr; - - s->flags = 0; - if (s->tail != shmiqs [device].tail){ - s->flags |= SHMIQ_CORRUPTED; - return; - } - tail_next = (s->tail + 1) % (shmiqs [device].events); - - if (tail_next == s->head){ - s->flags |= SHMIQ_OVERFLOW; - return; - } - - e->un.time = jiffies; - s->events [s->tail] = *e; - printk ("KERNEL: dev=%d which=%d type=%d flags=%d\n", - e->data.device, e->data.which, e->data.type, e->data.flags); - s->tail = tail_next; - shmiqs [device].tail = tail_next; - if (shmiqs [device].fasync) - kill_fasync (shmiqs [device].fasync, SIGIO); - wake_up_interruptible (&shmiqs [device].proc_list); -} - -static int -shmiq_manage_file (struct file *filp) -{ - int i; - - if (!filp->f_op || !filp->f_op->ioctl) - return -ENOSR; - - for (i = 0; i < MAX_SHMIQ_DEVS; i++){ - if (shmiq_pushed_devices [i].used) - continue; - if ((*filp->f_op->ioctl)(filp->f_dentry->d_inode, filp, SHMIQ_ON, i) != 0) - return -ENOSR; - shmiq_pushed_devices [i].used = 1; - shmiq_pushed_devices [i].filp = filp; - shmiq_pushed_devices [i].cpos.x = 0; - shmiq_pushed_devices [i].cpos.y = 0; - return i; - } - return -ENOSR; -} - -static int -shmiq_forget_file (unsigned long fdes) -{ - struct file *filp; - - if (fdes > MAX_SHMIQ_DEVS) - return -EINVAL; - - if (!shmiq_pushed_devices [fdes].used) - return -EINVAL; - - filp = shmiq_pushed_devices [fdes].filp; - if (filp){ - (*filp->f_op->ioctl)(filp->f_dentry->d_inode, filp, SHMIQ_OFF, 0); - shmiq_pushed_devices [fdes].filp = 0; - fput (filp); - } - shmiq_pushed_devices [fdes].used = 0; - - return 0; -} - -static int -shmiq_sioc (int device, int cmd, struct strioctl *s) -{ - switch (cmd){ - case QIOCGETINDX: - /* - * Ok, we just return the index they are providing us - */ - printk ("QIOCGETINDX: returning %d\n", *(int *)s->ic_dp); - return 0; - - case QIOCIISTR: { - struct muxioctl *mux = (struct muxioctl *) s->ic_dp; - - printk ("Double indirect ioctl: [%d, %x\n", mux->index, mux->realcmd); - return -EINVAL; - } - - case QIOCSETCPOS: { - if (copy_from_user (&shmiq_pushed_devices [device].cpos, s->ic_dp, - sizeof (struct shmiqsetcpos))) - return -EFAULT; - return 0; - } - } - printk ("Unknown I_STR request for shmiq device: 0x%x\n", cmd); - return -EINVAL; -} - -static int -shmiq_ioctl (struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg) -{ - struct file *file; - struct strioctl sioc; - int v; - - switch (cmd){ - /* - * They are giving us the file descriptor for one - * of their streams devices - */ - - case I_LINK: - file = fget (arg); - if (!file) - goto bad_file; - - v = shmiq_manage_file (file); - return v; - - /* - * Remove a device from our list of managed - * stream devices - */ - case I_UNLINK: - v = shmiq_forget_file (arg); - return v; - - case I_STR: - v = get_sioc (&sioc, arg); - if (v) - return v; - - /* FIXME: This forces device = 0 */ - return shmiq_sioc (0, sioc.ic_cmd, &sioc); - } - - return -EINVAL; -bad_file: - unlock_kernel (); - return -EBADF; -} - -extern sys_munmap(unsigned long addr, size_t len); - -static int -qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor) -{ - struct shmiqreq req; - struct vm_area_struct *vma; - int v; - - switch (cmd){ - /* - * The address space is already mapped as a /dev/zero - * mapping. FIXME: check that /dev/zero is what the user - * had mapped before :-) - */ - case QIOCATTACH: { - unsigned long vaddr; - int s; - - v = verify_area (VERIFY_READ, (void *) arg, sizeof (struct shmiqreq)); - if (v) - return v; - if (copy_from_user (&req, (void *) arg, sizeof (req))) - return -EFAULT; - /* Do not allow to attach to another region if it has been already attached */ - if (shmiqs [minor].mapped){ - printk ("SHMIQ:The thingie is already mapped\n"); - return -EINVAL; - } - - vaddr = (unsigned long) req.user_vaddr; - vma = find_vma (current->mm, vaddr); - if (!vma){ - printk ("SHMIQ: could not find %lx the vma\n", vaddr); - return -EINVAL; - } - s = req.arg * sizeof (struct shmqevent) + sizeof (struct sharedMemoryInputQueue); - v = sys_munmap (vaddr, s); - do_mmap (filp, vaddr, s, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 0); - shmiqs [minor].events = req.arg; - shmiqs [minor].mapped = 1; - return 0; - } - } - return -EINVAL; -} - -unsigned long -shmiq_nopage (struct vm_area_struct *vma, unsigned long address, int write_access) -{ - /* Do not allow for mremap to expand us */ - return 0; -} - -static struct vm_operations_struct qcntl_mmap = { - NULL, /* no special mmap-open */ - NULL, /* no special mmap-close */ - NULL, /* no special mmap-unmap */ - NULL, /* no special mmap-protect */ - NULL, /* no special mmap-sync */ - NULL, /* no special mmap-advise */ - shmiq_nopage, /* our magic no-page fault handler */ - NULL, /* no special mmap-wppage */ - NULL, /* no special mmap-swapout */ - NULL /* no special mmap-swapin */ -}; - -static int -shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma) -{ - int minor = MINOR (file->f_dentry->d_inode->i_rdev), error; - unsigned int size; - unsigned long mem, start; - - /* mmap is only supported on the qcntl devices */ - if (minor-- == 0) - return -EINVAL; - - if (vma->vm_offset != 0) - return -EINVAL; - - size = vma->vm_end - vma->vm_start; - start = vma->vm_start; - mem = (unsigned long) shmiqs [minor].shmiq_vaddr = vmalloc_uncached (size); - if (!mem) - return -EINVAL; - - /* Prevent the swapper from considering these pages for swap and touching them */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); - vma->vm_ops = &qcntl_mmap; - - /* Uncache the pages */ - vma->vm_page_prot = PAGE_USERIO; - - error = vmap_page_range (vma->vm_start, size, mem); - - shmiqs [minor].tail = 0; - /* Init the shared memory input queue */ - memset (shmiqs [minor].shmiq_vaddr, 0, size); - - return error; -} - -static int -shmiq_qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -{ - int minor = MINOR (inode->i_rdev); - - lock_kernel (); - - if (minor-- == 0) - return shmiq_ioctl (inode, filp, cmd, arg); - - return qcntl_ioctl (inode, filp, cmd, arg, minor); -} - -static unsigned int -shmiq_qcntl_poll (struct file *filp, poll_table *wait) -{ - struct sharedMemoryInputQueue *s; - int minor = MINOR (filp->f_dentry->d_inode->i_rdev); - - if (minor-- == 0) - return 0; - - if (!shmiqs [minor].mapped) - return 0; - - poll_wait (&shmiqs [minor].proc_list, wait); - s = shmiqs [minor].shmiq_vaddr; - if (s->head != s->tail) - return POLLIN | POLLRDNORM; - return 0; -} - -static int -shmiq_qcntl_open (struct inode *inode, struct file *filp) -{ - int minor = MINOR (inode->i_rdev); - - if (minor == 0) - return 0; - - minor--; - if (minor > MAX_SHMI_QUEUES) - return -EINVAL; - if (shmiqs [minor].opened) - return -EBUSY; - - lock_kernel (); - shmiqs [minor].opened = 1; - shmiqs [minor].shmiq_vaddr = 0; - unlock_kernel (); - return 0; -} - -static int -shmiq_qcntl_fasync (struct file *file, int on) -{ - int retval; - int minor = MINOR (file->f_dentry->d_inode->i_rdev); - - retval = fasync_helper (file, on, &shmiqs [minor].fasync); - if (retval < 0) - return retval; - return 0; -} - -static int -shmiq_qcntl_close (struct inode *inode, struct file *filp) -{ - int minor = MINOR (inode->i_rdev); - int j; - - if (minor-- == 0){ - for (j = 0; j < MAX_SHMIQ_DEVS; j++) - shmiq_forget_file (j); - } - - if (minor > MAX_SHMI_QUEUES) - return -EINVAL; - if (shmiqs [minor].opened == 0) - return -EINVAL; - - lock_kernel (); - shmiq_qcntl_fasync (filp, 0); - shmiqs [minor].opened = 0; - shmiqs [minor].mapped = 0; - shmiqs [minor].events = 0; - shmiqs [minor].fasync = 0; - vfree (shmiqs [minor].shmiq_vaddr); - shmiqs [minor].shmiq_vaddr = 0; - unlock_kernel (); - return 0; -} - - -static struct -file_operations shmiq_fops = -{ - NULL, /* seek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - shmiq_qcntl_poll, /* poll */ - shmiq_qcntl_ioctl, /* ioctl */ - shmiq_qcntl_mmap, /* mmap */ - shmiq_qcntl_open, /* open */ - shmiq_qcntl_close, /* close */ - NULL, /* fsync */ - shmiq_qcntl_fasync, /* fasync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ -}; - -void -shmiq_init (void) -{ - printk ("SHMIQ setup\n"); - register_chrdev (SHMIQ_MAJOR, "shmiq", &shmiq_fops); -} -/* - * shmiq.c: shared memory input queue driver - * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * We implement /dev/shmiq, /dev/qcntlN here - * this is different from IRIX that has shmiq as a misc - * streams device and the and qcntl devices as a major device. - * - * minor number 0 implements /dev/shmiq, - * any other number implements /dev/qcntl${minor-1} - * - * /dev/shmiq is used by the X server for two things: - * - * 1. for I_LINK()ing trough ioctl the file handle of a - * STREAMS device. - * - * 2. To send STREAMS-commands to the devices with the - * QIO ioctl interface. - * - * I have not yet figured how to make multiple X servers share - * /dev/shmiq for having different servers running. So, for now - * I keep a kernel-global array of inodes that are pushed into - * /dev/shmiq. - * - * /dev/qcntlN is used by the X server for two things: - * - * 1. Issuing the QIOCATTACH for mapping the shared input - * queue into the address space of the X server (yeah, yeah, - * I did not invent this interface). - * - * 2. used by select. I bet it is used for checking for events on - * the queue. - * - * Now the problem is that there does not seem anything that - * establishes a connection between /dev/shmiq and the qcntlN file. I - * need an strace from an X server that runs on a machine with more - * than one keyboard. And this is a problem since the file handles - * are pushed in /dev/shmiq, while the events should be dispatched to - * the /dev/qcntlN device. - * - * Until then, I just allow for 1 qcntl device. - * - */ - -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/sched.h> -#include <linux/file.h> -#include <linux/interrupt.h> #include <linux/poll.h> #include <linux/vmalloc.h> #include <linux/wait.h> diff --git a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c index 02e40cf05..f26aad0e2 100644 --- a/drivers/sgi/char/streamable.c +++ b/drivers/sgi/char/streamable.c @@ -361,366 +361,3 @@ streamable_init (void) misc_register (&dev_input_keyboard); misc_register (&dev_input_mouse); } -/* - * streamable.c: streamable devices. /dev/gfx - * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * Major 10 is the streams clone device. The IRIX Xsgi server just - * opens /dev/gfx and closes it inmediately. - * - */ - -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/sched.h> -#include <linux/kbd_kern.h> -#include <linux/vt_kern.h> -#include <asm/uaccess.h> -#include <asm/shmiq.h> -#include <asm/keyboard.h> -#include "graphics.h" - - -extern struct kbd_struct kbd_table [MAX_NR_CONSOLES]; - -/* console number where forwarding is enabled */ -int forward_chars; - -/* To which shmiq this keyboard is assigned */ -int kbd_assigned_device; - -/* previous kbd_mode for the forward_chars terminal */ -int kbd_prev_mode; - -/* Fetchs the strioctl information from user space for I_STR ioctls */ -int -get_sioc (struct strioctl *sioc, unsigned long arg) -{ - int v; - - v = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct strioctl)); - if (v) - return v; - if (copy_from_user (sioc, (void *) arg, sizeof (struct strioctl))) - return -EFAULT; - - v = verify_area (VERIFY_WRITE, (void *) sioc->ic_dp, sioc->ic_len); - if (v) - return v; - return 0; -} - -/* /dev/gfx device */ -static int -sgi_gfx_open (struct inode *inode, struct file *file) -{ - printk ("GFX: Opened by %d\n", current->pid); - return 0; -} - -static int -sgi_gfx_close (struct inode *inode, struct file *file) -{ - printk ("GFX: Closed by %d\n", current->pid); - return 0; -} - -static int -sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - printk ("GFX: ioctl 0x%x %ld called\n", cmd, arg); - return 0; - return -EINVAL; -} - -struct file_operations sgi_gfx_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - sgi_gfx_ioctl, /* ioctl */ - NULL, /* mmap */ - sgi_gfx_open, /* open */ - sgi_gfx_close, /* release */ - NULL, /* fsync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL /* lock */ -}; - -static struct miscdevice dev_gfx = { - SGI_GFX_MINOR, "sgi-gfx", &sgi_gfx_fops -}; - -/* /dev/input/keyboard streams device */ -static idevDesc sgi_kbd_desc = { - "keyboard", /* devName */ - "KEYBOARD", /* devType */ - 240, /* nButtons */ - 0, /* nValuators */ - 0, /* nLEDs */ - 0, /* nStrDpys */ - 0, /* nIntDpys */ - 0, /* nBells */ - IDEV_HAS_KEYMAP | IDEV_HAS_PCKBD -}; - -static int -sgi_kbd_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) -{ - *found = 1; - - switch (cmd){ - - case IDEVINITDEVICE: - return 0; - - case IDEVGETDEVICEDESC: - if (size >= sizeof (idevDesc)){ - if (copy_to_user (data, &sgi_kbd_desc, sizeof (sgi_kbd_desc))) - return -EFAULT; - return 0; - } - return -EINVAL; - - case IDEVGETKEYMAPDESC: - if (size >= sizeof (idevKeymapDesc)){ - if (copy_to_user (data, "US", 3)) - return -EFAULT; - return 0; - } - return -EINVAL; - } - *found = 0; - return -EINVAL; -} - -static int -sgi_keyb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct strioctl sioc; - int f, v; - - /* IRIX calls I_PUSH on the opened device, go figure */ - if (cmd == I_PUSH) - return 0; - - if (cmd == I_STR){ - v = get_sioc (&sioc, arg); - if (v) - return v; - - /* Why like this? Because this is a sample piece of code - * that can be copied into other drivers and shows how to - * call a stock IRIX xxx_wioctl routine - * - * The NULL is supposed to be a idevInfo, right now we - * do not support this in our kernel. - */ - return sgi_kbd_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); - } - - if (cmd == SHMIQ_ON){ - kbd_assigned_device = arg; - forward_chars = fg_console + 1; - kbd_prev_mode = kbd_table [fg_console].kbdmode; - - kbd_table [fg_console].kbdmode = VC_RAW; - } else if (cmd == SHMIQ_OFF && forward_chars){ - kbd_table [forward_chars-1].kbdmode = kbd_prev_mode; - forward_chars = 0; - } else - return -EINVAL; - return 0; -} - -void -kbd_forward_char (int ch) -{ - static struct shmqevent ev; - - ev.data.flags = (ch & 0200) ? 0 : 1; - ev.data.which = ch; - ev.data.device = kbd_assigned_device + 0x11; - shmiq_push_event (&ev); -} - -static int -sgi_keyb_open (struct inode *inode, struct file *file) -{ - /* Nothing, but required by the misc driver */ - return 0; -} - -struct file_operations sgi_keyb_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - sgi_keyb_ioctl, /* ioctl */ - NULL, /* mmap */ - sgi_keyb_open, /* open */ - NULL, /* release */ - NULL, /* fsync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL /* lock */ -}; - -static struct miscdevice dev_input_keyboard = { - SGI_STREAMS_KEYBOARD, "streams-keyboard", &sgi_keyb_fops -}; - -/* /dev/input/mouse streams device */ -#define MOUSE_VALUATORS 2 -static idevDesc sgi_mouse_desc = { - "mouse", /* devName */ - "MOUSE", /* devType */ - 3, /* nButtons */ - MOUSE_VALUATORS, /* nValuators */ - 0, /* nLEDs */ - 0, /* nStrDpys */ - 0, /* nIntDpys */ - 0, /* nBells */ - 0 /* flags */ -}; - -static idevValuatorDesc mouse_default_valuator = { - 200, /* hwMinRes */ - 200, /* hwMaxRes */ - 0, /* hwMinVal */ - 65000, /* hwMaxVal */ - IDEV_EITHER, /* possibleModes */ - IDEV_ABSOLUTE, /* default mode */ - 200, /* resolution */ - 0, /* minVal */ - 65000 /* maxVal */ -}; - -static int mouse_opened; -static idevValuatorDesc mouse_valuators [MOUSE_VALUATORS]; - -int -sgi_mouse_open (struct inode *inode, struct file *file) -{ - int i; - - if (mouse_opened) - return -EBUSY; - - mouse_opened = 1; - for (i = 0; i < MOUSE_VALUATORS; i++) - mouse_valuators [i] = mouse_default_valuator; - return 0; -} - -static int -sgi_mouse_close (struct inode *inode, struct file *filp) -{ - mouse_opened = 0; - return 0; -} - -static int -sgi_mouse_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) -{ - *found = 1; - - switch (cmd){ - case IDEVINITDEVICE: - return 0; - - case IDEVGETDEVICEDESC: - if (size >= sizeof (idevDesc)){ - if (copy_to_user (data, &sgi_mouse_desc, sizeof (sgi_mouse_desc))) - return -EFAULT; - return 0; - } - return -EINVAL; - - case IDEVGETVALUATORDESC: { - idevGetSetValDesc request, *ureq = (idevGetSetValDesc *) data; - - if (size < sizeof (idevGetSetValDesc)) - return -EINVAL; - - if (copy_from_user (&request, data, sizeof (request))) - return -EFAULT; - if (request.valNum >= MOUSE_VALUATORS) - return -EINVAL; - if (copy_to_user ((void *)&ureq->desc, - (void *)&mouse_valuators [request.valNum], - sizeof (idevValuatorDesc))) - return -EFAULT; - return 0; - } - } - *found = 0; - return -EINVAL; -} - -static int -sgi_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct strioctl sioc; - int f, v; - - /* IRIX calls I_PUSH on the opened device, go figure */ - switch (cmd){ - case I_PUSH: - return 0; - - case I_STR: - v = get_sioc (&sioc, arg); - if (v) - return v; - - /* Why like this? Because this is a sample piece of code - * that can be copied into other drivers and shows how to - * call a stock IRIX xxx_wioctl routine - * - * The NULL is supposed to be a idevInfo, right now we - * do not support this in our kernel. - */ - return sgi_mouse_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); - - case SHMIQ_ON: - case SHMIQ_OFF: - return 0; - } - return 0; -} - -struct file_operations sgi_mouse_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - sgi_mouse_ioctl, /* ioctl */ - NULL, /* mmap */ - sgi_mouse_open, /* open */ - sgi_mouse_close, /* release */ - NULL, /* fsync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL /* lock */ -}; - -/* /dev/input/mouse */ -static struct miscdevice dev_input_mouse = { - SGI_STREAMS_KEYBOARD, "streams-mouse", &sgi_mouse_fops -}; - -void -streamable_init (void) -{ - printk ("streamable misc devices registered (keyb:%d, gfx:%d)\n", - SGI_STREAMS_KEYBOARD, SGI_GFX_MINOR); - - misc_register (&dev_gfx); - misc_register (&dev_input_keyboard); - misc_register (&dev_input_mouse); -} diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c index 262f5724f..dfef772eb 100644 --- a/drivers/sgi/char/usema.c +++ b/drivers/sgi/char/usema.c @@ -27,197 +27,6 @@ #include <linux/sched.h> #include <linux/file.h> #include <linux/major.h> -#include <linux/string.h> -#include <linux/dcache.h> -#include <linux/mm.h> -#include <linux/slab.h> - -#include <asm/smp_lock.h> -#include <asm/usioctl.h> -#include <asm/mman.h> -#include <asm/uaccess.h> - -struct irix_usema { - struct file *filp; - struct wait_queue *proc_list; -}; - -static int -sgi_usema_attach (usattach_t * attach, struct irix_usema *usema) -{ - int newfd; - newfd = get_unused_fd(); - if (newfd < 0) - return newfd; - - current->files->fd [newfd] = usema->filp; - usema->filp->f_count++; - /* Is that it? */ - printk("UIOCATTACHSEMA: new usema fd is %d", newfd); - return newfd; -} - -static int -sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct irix_usema *usema = file->private_data; - int retval; - - printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)", - current->comm, current->pid, cmd, arg); - - switch(cmd) { - case UIOCATTACHSEMA: { - /* They pass us information about the semaphore to - which they wish to be attached, and we create&return - a new fd corresponding to the appropriate semaphore. - */ - usattach_t *attach = (usattach_t *)arg; - retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); - if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): " - "verify_area failure", - current->comm, current->pid); - return retval; - } - if (usema == 0) - return -EINVAL; - - printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid); - /* XXX what is attach->us_handle for? */ - return sgi_usema_attach(attach, usema); - break; - } - case UIOCABLOCK: /* XXX make `async' */ - case UIOCNOIBLOCK: /* XXX maybe? */ - case UIOCBLOCK: { - /* Block this process on the semaphore */ - usattach_t *attach = (usattach_t *)arg; - - retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); - if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " - "verify_area failure", - current->comm, current->pid); - return retval; - } - printk("UIOC*BLOCK: putting process %d to sleep on usema %p", - current->pid, usema); - if (cmd == UIOCNOIBLOCK) - interruptible_sleep_on(&usema->proc_list); - else - sleep_on(&usema->proc_list); - return 0; - } - case UIOCAUNBLOCK: /* XXX make `async' */ - case UIOCUNBLOCK: { - /* Wake up all process waiting on this semaphore */ - usattach_t *attach = (usattach_t *)arg; - - retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); - if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " - "verify_area failure", - current->comm, current->pid); - return retval; - } - - printk("[%s:%d] releasing usema %p", - current->comm, current->pid, usema); - wake_up(&usema->proc_list); - return 0; - } - } - return -ENOSYS; -} - -static unsigned int -sgi_usemaclone_poll(struct file *filp, poll_table *wait) -{ - struct irix_usema *usema = filp->private_data; - - printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema); - - return 0; -} - -static int -sgi_usemaclone_open(struct inode *inode, struct file *filp) -{ - struct irix_usema *usema; - - usema = kmalloc (sizeof (struct irix_usema), GFP_KERNEL); - if (!usema) - return -ENOMEM; - - usema->filp = filp; - usema->proc_list = NULL; - filp->private_data = usema; - return 0; -} - -static int -sgi_usemaclone_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -struct file_operations sgi_usemaclone_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - sgi_usemaclone_poll, /* poll */ - sgi_usemaclone_ioctl, /* ioctl */ - NULL, /* mmap */ - sgi_usemaclone_open, /* open */ - sgi_usemaclone_release, /* release */ - NULL, /* fsync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL /* lock */ -}; - -static struct miscdevice dev_usemaclone = { - SGI_USEMACLONE, "usemaclone", &sgi_usemaclone_fops -}; - -void -usema_init(void) -{ - printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE); - misc_register(&dev_usemaclone); -} -/* - * usema.c: software semaphore driver (see IRIX's usema(7M)) - * written 1997 Mike Shaver (shaver@neon.ingenia.ca) - * 1997 Miguel de Icaza (miguel@kernel.org) - * - * This file contains the implementation of /dev/usemaclone, - * the devices used by IRIX's us* semaphore routines. - * - * /dev/usemaclone is used to create a new semaphore device, and then - * the semaphore is manipulated via ioctls. - * - * At least for the zero-contention case, lock set and unset as well - * as semaphore P and V are done in userland, which makes things a - * little bit better. I suspect that the ioctls are used to register - * the process as blocking, etc. - * - * Much inspiration and structure stolen from Miguel's shmiq work. - * - * For more information: - * usema(7m), usinit(3p), usnewsema(3p) - * /usr/include/sys/usioctl.h - * -*/ - -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/sched.h> -#include <linux/file.h> -#include <linux/major.h> #include <linux/poll.h> #include <linux/string.h> #include <linux/dcache.h> diff --git a/drivers/sgi/char/vga_font.c b/drivers/sgi/char/vga_font.c index 2c7def4f6..2ab67797c 100644 --- a/drivers/sgi/char/vga_font.c +++ b/drivers/sgi/char/vga_font.c @@ -344,349 +344,3 @@ unsigned char vga_font[cmapsz] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -#include "gconsole.h" - -unsigned char vga_font[cmapsz] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; |