#ifndef lint static char sccsid[] = "@(#)cgeight.c 1.1 94/10/31 SMI"; #endif /****************************************************************************** * ************************************************************************** * * *"cgeight.c * * * * * * * * Device driver for the True Color (TC) Family of Frame Buffers * * * * For The Sun Microsystems SBus. * * * * * * * * Conventions: * * * * (1) File is formatted assuming tab stops every four characters. * * * * (2) Routines are in alphabetical order. * * * * (3) Prefix conventions for routine names: * * * * (a) cgeightxxx - external entry point for driver. * * * * (b) cg8_xxx - internal pixrect related code. * * * * (c) pip_xxx - routine common to all pip implementations. * * * * (d) tc_xxx - routine common to all hardware configurations* * * * (e) tcp_xxx - routine for TC and TCP products. * * * * (f) tcs_xxx - routine for TCS product. * * * * * * * * Copyright 1991, Sun Microsystems, Inc. * * * ************************************************************************** * ******************************************************************************/ #include /* General type defs. */ #include /* General system parameters and limits. */ #include /* General timer parameters. */ #include /* Input / Output buffer defs. */ #include /* Kernel error defs. */ #include /* Ioctl registery and macros. */ #include /* Resource allocation map information. */ #include /* Process data structures and defs. */ #include /* User management and accounting defs. */ #include /* Virtual memory related macros. */ #include /* Non-volatile ram software defs. */ #include /* Enable register defs. */ #include /* Memory management unit defs. */ #include /* Page table entry defs. */ #include /* Rom monitor interface definition. */ #include /* General pixrect related defs. */ #include /* Pixrect implementatino utilities. */ #include /* Bit plane manipulation defs. */ #include /* General frame buffer ioctl defs. */ #include /* Main bus interface defs. */ #include /* SBus memory mapped frame buf layout. */ #include /* Colormapseg, cms_map */ #include /* Memory pixrect structural defs. */ #include /* Need some defs from this device. */ #include /* Device dependent memory layouts, etc. */ #include /* Pixrect related variables for our card */ #include /* Definition of Rect data structure. */ #include "win.h" /* # of windows(non-zero => sunview) */ /* * Debugging equates and macros */ #ifndef TC_DEBUG #define TC_DEBUG 0 #endif TC_DEBUG #define TEST_NEW_HARDWARE 1 #if TC_DEBUG int tc1_debug = 5; /* Debugging level. */ #define DEBUGF(level, args) _STMT(if (tc1_debug >= (level)) printf args;) #define DEBUG_LEVEL(level) {extern int tc1_debug; tc1_debug = level;} #else TC_DEBUG #define DEBUGF(level, args) /* nothing */ #define DEBUG_OFF #define DEBUG_LEVEL(level) #endif TC_DEBUG /* * Information telling how and when to memory map a frame buffer: */ typedef struct Mmap_Info { /* Frame buffer memory map region info: */ int group; /* Type of frame buffer to memory map. */ u_int bgn_offset; /* Offset in vm of start of frame buffer. */ u_int end_offset; /* Offset in vm of 1st word not in frame buffer. */ u_int sbus_delta; /* Offset in SBus slot (from device regs) of fb. */ } Mmap_Info; /* * Per-Unit Device Data Definitions: */ typedef struct Tc1_Softc { int basepage; /* Physical page # of mmap base addr. */ #ifdef TEST_NEW_HARDWARE int test_basepage; /* Base page of slot 3 for testing h/w. */ #endif TEST_NEW_HARDWARE int cmap_begin; /* Starting index for color map load. */ int cmap_count; /* # of entries to load. */ u_char cmap_blue[TC_CMAP_SIZE]; /* Blue components for color map. */ u_char cmap_green[TC_CMAP_SIZE]; /* Green components for color map. */ u_char cmap_red[TC_CMAP_SIZE]; /* Red components for color map. */ Tc1_Device_Map *device_reg; /* Device register area virt. address. */ int dev_reg_mmap_offset; /* Device regs memory offset from selves. */ int dev_reg_mmap_size; /* Device register area size in bytes. */ int dev_reg_sbus_base; /* Device register area SBus phys. offset */ int dev_reg_sbus_delta; /* SBus offset from dev. regs. (=0). */ Tcs_Device_Map *device_tcs; /* Device register are on TCS card. */ u_char em_blue[TC_CMAP_SIZE]; /* Indexed color map emulation : blue. */ u_char em_green[TC_CMAP_SIZE]; /* Indexed color map emulation : green. */ u_char em_red[TC_CMAP_SIZE]; /* Indexed color map emulation : red. */ u_char *fb_8bit; /* Eight-bit buffer virt. address. */ int fb_8bit_mmap_size; /* Size of region mmapped into virt memory */ int fb_8bit_sbus_delta; /* Eight bit SBus offset from device regs. */ u_char fb_model; /* Frame buffer model. */ u_char *fb_mono; /* Overlay (monochrome) buffer virt. addr. */ int fb_mono_mmap_size; /* Size of region mmapped into virt memory */ int fb_mono_sbus_delta; /* Monochrome SBus offset from device regs */ u_char *fb_sel; /* Enable (selection) memory virt. addr. */ int fb_sel_mmap_size; /* Size of region mmapped into virt memory */ int fb_sel_sbus_delta; /* Selection SBus offset from device regs. */ long *fb_tc; /* True color buffer virt. address. */ int fb_tc_mmap_size; /* Size of region mmapped into virt memory */ int fb_tc_sbus_delta; /* True color SBus offset from device regs */ u_char *fb_video; /* Video enable buffer virt. address. */ int fb_video_mmap_size; /* Size of region mmapped into vir. memory */ int fb_video_sbus_delta; /* SBus offset of video enable. */ int flags; /* Miscellaneous flags. */ int height; /* Height of display in scan lines. */ int linebytes1; /* # of bytes in a monochrome scan line. */ int linebytes8; /* # of bytes in an eight bit scan line. */ int linebytes32; /* # of bytes in a true color scan line. */ int memory_map_end; /* Total size of mapping of regions. */ int mmap_count; /* # of entries in use in mmap_info. */ Mmap_Info mmap_info[5]; /* Information on how to mmap fbs. */ int omap_begin; /* Starting index for overlay map load. */ int omap_count; /* # of entries to load. */ u_char omap_blue[TC_OMAP_SIZE]; /* Monochrome overlay color map: blue */ u_char omap_green[TC_OMAP_SIZE]; /* Monochrome overlay color map: green */ u_char omap_red[TC_OMAP_SIZE]; /* Monochrome overlay color map: red */ u_char pg_possible[FB_NPGS]; /* Plane groups which are possible. */ u_char pg_enabled[FB_NPGS]; /* Plane groups enabled for use. */ int pip_on_off_semaphore; /* -1 if on, else # of suspensions */ u_char sw_cursor_color_frozen; /* Berthold: cursor color is frozen. */ #if NWIN > 0 Pixrect pr; /* Kernel pixrect for this unit. */ struct cg8_data tc1d; /* Frame buffer specific data. */ #endif NWIN > 0 int timing_regimen; /* Current timing regimen (TCS card.) */ int width; /* Width of display in pixels. */ } Tc1_Softc; #define SOFTC register Tc1_Softc /* Forward references for kernel routines used by this device driver: */ addr_t kmem_zalloc(); addr_t map_regs(); void report_dev(); /* Compilation configuration switches and macros: */ #ifndef OLDDEVSW #define OLDDEVSW 1 #endif OLDDEVSW #ifndef NOHWINIT #define NOHWINIT 0 #endif NOHWINIT #if NOHWINIT int tc1_hwinit = 1; int tc1_small = 0; int tc1_on = 1; /* Must be 1 to enable tc1 */ #endif NOHWINIT #define TC_CMAP_ENTRIES MFB_CMAP_ENTRIES #if OLDDEVSW #define STATIC /* nothing */ #else OLDDEVSW #define STATIC static #endif OLDDEVSW /* Configuration information (device driver operations vector) */ static int cgeightattach(); STATIC int cgeightclose(); static int cgeightindentify(); STATIC int cgeightioctl(); STATIC int cgeightmmap(); STATIC int cgeightopen(); static int cgeightpoll(); struct dev_ops cgeight_ops = { 0, /* revision */ cgeightindentify, /* Device driver indentification routine. */ cgeightattach, /* Attach this device as a slave. */ cgeightopen, /* Open the device. */ cgeightclose, /* Close the device. */ 0, 0, 0, 0, 0, cgeightioctl, /* Perform a control operation. */ 0, cgeightmmap, /* Map a page of the device's address space. */ }; /* * Information kept on a per-unit basis for our device type. */ static int num_tc; /* # of frame buffers present. */ static Tc1_Softc *tc1_softc; /* Array of per unit data structures. */ #define TC_FB_ATTR 0x9C000001 /* Original SBus TC frame buffer attributes. */ /* Handy macros: */ #define SOFTC register Tc1_Softc /* Short hand for oft-used declaration. */ #define getsoftc(unit) (&tc1_softc[unit]) #define btob(n) ctob(btoc(n)) /* XXX */ #define BCOPY(s,d,c) bcopy((caddr_t) (s), (caddr_t) (d), (u_int) (c)) #define COPYIN(s,d,c) copyin((caddr_t) (s), (caddr_t) (d), (u_int) (c)) #define COPYOUT(s,d,c) copyout((caddr_t) (s), (caddr_t) (d), (u_int) (c)) /* Forward routine references: */ static int tcp_attach(); static int tcs_attach(); /* Default data structures for various ioctl requests. */ static struct fbgattr tc1_attrdefault={ /* Default for FBIOGATTR ioctl: */ FBTYPE_MEMCOLOR, /* . Actual type. */ 0, /* . Owner. */ { /* . Frm buffer type(matchs tc1typedefault)*/ FBTYPE_MEMCOLOR, /* . . Type. */ 0, /* . . Height. */ 0, /* . . Width. */ 32, /* . . Depth. */ 256, /* . . Color map size. */ 0 /* . . Size. */ }, /* . . */ { /* . Frame buffer attributes (flags): */ FB_ATTR_AUTOINIT, /* . . Flags. */ FBTYPE_SUN2BW, /* . . Emu type. */ { 0 } /* . . Device specific information. */ }, /* . . */ { /* . Emu types. */ FBTYPE_MEMCOLOR, FBTYPE_SUN2BW, -1, -1 } }; static struct fbgattr cg4_attrdefault={ /* Default for FBIOGATTR ioctl in cg4 mode: */ FBTYPE_SUN4COLOR, /* . Actual type. */ 0, /* . Owner. */ { /* . Frm buffer type(match tc1typedefault) */ FBTYPE_SUN4COLOR, /* . . Type. */ 0, /* . . Height. */ 0, /* . . Width. */ 8, /* . . Depth. */ 256, /* . . Color map size. */ 0 /* . . Size. */ }, /* . . */ { /* . Frame buffer attributes (flags): */ FB_ATTR_AUTOINIT, /* . . Flags. */ FBTYPE_SUN2BW, /* . . Emu type. */ { 0 } /* . . Device specific information. */ }, /* . . */ { /* . Emu types. */ FBTYPE_SUN4COLOR, FBTYPE_SUN2BW, -1, -1 } }; static struct fbtype tc1typedefault={ /* Default for FBIOGTYPE ioctl for cg4, cg8: */ FBTYPE_SUN2BW, /* . Type. */ 0, /* . Height. */ 0, /* . Width. */ 1, /* . Depth. */ 0, /* . Color map size. */ 0 /* . Size. */ }; static int cmsize = -1; #if NWIN > 0 /* SunWindows related: Kernel pixrects operations vector definition. */ static int cg8_ioctl(); static int cg8_putattributes(); static int cg8_putcolormap(); static int cg8_rop(); static struct pixrectops tcp_ops={/* Pip option present kernel pixrect ops vector: */ cg8_rop, /* . Raster operation. */ cg8_putcolormap, /* . Write the color map. */ cg8_putattributes, /* . Set the attributes. */ cg8_ioctl /* . Perform an ioctl operation. */ }; #endif NWIN > 0 /* * Table to translate Sun overlay index into a SBus TC overlay index. * * Note that our overlay map works in a different manner from Sun's cg8, so a * translation must be done (using translate_omap data structure): * Function Sun LUT index SBus TC LUT index * -------- ------------- ------------------ * True color 0 0 * Window system foreground 1 2 * Current window foreground 2 1 * Window system background 3 3 * */ static u_char translate_omap[] = /* Translate caller's omap index to match hardware */ { 0, 2, 1, 3}; /*"cgeightattach" * * Perform device specific initializations. (Called during autoconfiguration * process.) This routine allocates the per-unit data structure associated * with the device and initializes it from the properties exported by the * on-board PROM. In addition it maps the device's memory regions into * virtual memory and performs hardware specific initializations. * * = 1 if success * = 0 if failure * */ static cgeightattach(devi) struct dev_info *devi; /* ->dev info struct w/node id...(rest filled here)*/ { FB_Attributes fb_attr; /* Attributes about fb from on-board PROM. */ SOFTC *softc; /* Pointer to per-unit data for this device */ static int unit; /* Unit # to use.(NOTE VALUE INCREMENTS!) */ DEBUGF(1, ("cgeightattach num_tc=%d unit=%d\n", num_tc, unit)); /* If this is the first time attach has ever been called, allocate * softc structures for the frame buffers. */ if (!tc1_softc) { tc1_softc = (struct Tc1_Softc *) kmem_zalloc((u_int) sizeof (Tc1_Softc) * num_tc); } softc = getsoftc(unit); /* SET UP PROPERTIES RELATED TO DEVICE REGISTER AREA AND MEMORIES * * Get properties from the on-board PROM (set up by Forth code at ipl time) * Fill in the switches related to them. (Note we default enabled to * possible here, but enabled bits are related to the type of device * being emulated.) */ fb_attr.integer = (int)getprop(devi->devi_nodeid, "depth", TC_FB_ATTR); if ( fb_attr.integer <= 1 ) fb_attr.integer = TC_FB_ATTR; DEBUGF(5, (" PROM frame buffer attributes are %x\n", fb_attr.integer)); softc->pg_possible[PIXPG_OVERLAY] = fb_attr.flags.monochrome; softc->pg_possible[PIXPG_OVERLAY_ENABLE] = fb_attr.flags.selection; softc->pg_possible[PIXPG_8BIT_COLOR] = fb_attr.flags.eight_bit_hardware; softc->pg_possible[PIXPG_24BIT_COLOR] = fb_attr.flags.true_color; softc->pg_possible[PIXPG_VIDEO_ENABLE] = fb_attr.flags.pip_possible; BCOPY(softc->pg_possible, softc->pg_enabled, FB_NPGS); softc->fb_model = fb_attr.flags.model; if ( softc->fb_model == 0 ) { softc->fb_model = ( softc->pg_possible[PIXPG_8BIT_COLOR] ) ? RASTEROPS_TCP : RASTEROPS_TC; } softc->timing_regimen = NATIVE_TIMING; /* Get display image dimensions, and number of bytes between rows in a * 1-bit pixel scan line. Use this information to generate the inter-row * spacing for 8-bit and 32-bit scan lines. */ softc->width = getprop(devi->devi_nodeid, "width", 1152); softc->height = getprop(devi->devi_nodeid, "height", 900); softc->linebytes1 = getprop(devi->devi_nodeid, "linebytes", mpr_linebytes(1152, 8)); softc->linebytes8 = softc->linebytes1 * 8; softc->linebytes32 = softc->linebytes1 * 32; /* PERFORM BOARD SPECIFIC PROCESSING BASED ON THE TYPE OF BOARD SPECIFIED * * The depth attribrute from the PROMs specifies the SBus Card model * being used. Use this information to perform model specific * initializations. A return code of zero indicates an error occurred, in * which case this routine should signal a failure. */ switch(softc->fb_model) { default: case RASTEROPS_TC: case RASTEROPS_TCP: if ( tcp_attach(devi, softc) == 0 ) return 0; break; case RASTEROPS_TCS: if ( tcs_attach(devi, softc) == 0 ) return 0; break; } /* REGISTER OUR DEVICE * * Save unit number in device information area we were passed. * Attach interrupt routine. Save back pointer to softc in device * information area. Increment the unit number for the next attach, * and report the device. */ devi->devi_unit = unit; addintr(devi->devi_intr[0].int_pri, cgeightpoll, devi->devi_name, unit); devi->devi_data = (addr_t) softc; unit++; report_dev(devi); return 1; } /*"cgeightclose" * * Close down operations on a SBus TC board * * = 0 */ /*ARGSUSED*/ STATIC cgeightclose(dev, flag) dev_t dev; /* = device specification for device to be closed. */ int flag; /* = read/write flags (unused in this routine. */ { DEBUGF(2, ("cgeightclose(%d)\n", minor(dev))); return 0; } /*"cgeightindentify" * * Check if a name matches that of our device, and if so update the * count of devices we maintain. * * = number of devices present * = 0 if name passed does not match, or this device type is disabled */ static cgeightindentify(name) char *name; /* -> name to be tested. */ { DEBUGF(1, ("cgeightindentify(%s)\n", name)); # if NOHWINIT if (!tc1_on) return 0; # endif NOHWINIT return (strcmp(name, "cgeight") == 0) ? ++num_tc : 0; } /*"cgeightioctl" * * Perform an input / output control operation on a SBus TC card * or associated driver code. * * = 0 if successful operation * ~= 0 if error detected */ cgeightioctl(dev, cmd, data, flag) dev_t dev; /* = device specification for device to operate upon. */ int cmd; /* = opcode for operation to be performed. */ caddr_t data; /* -> data area for the operation . (may be in or out). */ int flag; /* = modifier info. for operation to be performed. */ { SOFTC *softc = getsoftc(minor(dev)); /* Pointer to per-unit info. */ # ifdef TC_DEBUG DEBUGF(5, ("tconeioctl: cmd = ")); switch (cmd) { case FBIOSATTR: DEBUGF(5, ("FBIOSATTR\n")); break; case FBIOGATTR: DEBUGF(5, ("FBIOGATTR\n")); break; case FBIOGETCMAP: DEBUGF(6, ("FBIOGETCMAP\n")); break; case FBIOPUTCMAP: DEBUGF(6, ("FBIOPUTCMAP\n")); break; case FBIOGTYPE: DEBUGF(5, ("FBIOGTYPE\n")); break; case FBIOGPIXRECT: DEBUGF(5, ("FBIOGPIXRECT\n")); break; case FBIOSVIDEO: DEBUGF(5, ("FBIOSVIDEO\n")); break; case FBIOGVIDEO: DEBUGF(5, ("FBIOGVIDEO\n")); break; case PIPIO_G_CURSOR_COLOR_FREEZE: DEBUGF(5, ("PIPIO_G_CURSOR_COLOR_FREEZE\n")); break; case PIPIO_G_EMULATION_MODE: DEBUGF(5, ("PIPIO_G_EMULATION_MODE\n")); break; case PIPIO_G_FB_INFO: DEBUGF(5, ("PIPIO_G_FB_INFO\n")); break; case PIPIO_S_CURSOR_COLOR_FREEZE: DEBUGF(5, ("PIPIO_S_CURSOR_COLOR_FREEZE\n")); break; case PIPIO_S_EMULATION_MODE: DEBUGF(5, ("PIPIO_S_EMULATION_MODE\n")); break; default: DEBUGF(5, ("not supported (0x%x)\n", cmd)); break; } # endif TC_DEBUG /* Process request based on its type. Cases are alphabetical. */ switch (cmd) { case FBIOGATTR: return x_g_attr( softc, (struct fbgattr *)data ); case FBIOGETCMAP: return x_getcmap( softc, (struct fbcmap *)data ); #if NWIN > 0 case FBIOGPIXRECT: return x_g_pixrect( softc, dev, (struct fbpixrect *)data ); #endif NWIN > 0 case FBIOGTYPE: return x_g_type( softc, (struct fbtype *)data ); case FBIOGVIDEO: switch(softc->fb_model) { default: *(int *)data = mfb_get_video(&softc->device_reg->sun_mfb_reg) ? FBVIDEO_ON : FBVIDEO_OFF; break; case RASTEROPS_TCS: break; } break; case FBIOPUTCMAP: switch(softc->fb_model) { default: return tc_putcmap( softc, (struct fbcmap *)data ); case RASTEROPS_TCS: return tcs_putcmap( softc, (struct fbcmap *)data ); } case FBIOSVIDEO: switch(softc->fb_model) { default: mfb_set_video(&softc->device_reg->sun_mfb_reg, *(int *)data & FBVIDEO_ON); break; case RASTEROPS_TCS: break; } break; /* Ioctls placed under the guise of the PIP which should always be * handled. */ case PIPIO_G_CURSOR_COLOR_FREEZE: *(int *)data = softc->sw_cursor_color_frozen; break; case PIPIO_G_EMULATION_MODE: return x_g_emulation_mode( softc, (Pipio_Emulation *)data ); case PIPIO_G_FB_INFO: return x_g_fb_info( softc, (Pipio_Fb_Info *)data ); case PIPIO_S_CURSOR_COLOR_FREEZE: softc->sw_cursor_color_frozen = *(int *)data; break; case PIPIO_S_EMULATION_MODE: return x_s_emulation_mode( softc, (Pipio_Emulation *)data ); #ifdef TEST_NEW_HARDWARE case PIPIO_S_MAP_SLOT: return x_s_map_slot( softc, (u_int *)data ); #endif TEST_NEW_HARDWARE /*- Unknown request, see if the pip knows about it... */ default: #ifndef NO_PIP if ( (pip_ioctl(softc, cmd, data, flag) != 0) ) { DEBUGF(5, ("not supported (0x%x)\n", cmd)); return EINVAL; } #else NO_PIP return EINVAL; #endif !NO_PIP } /* switch(cmd) */ return 0; } /*"cgeightmmap" * * Provide physical page address associated with a memory map offset. This * routine determines which of the six discontiguous physical memory * regions the offset passed to it is associated with. Based on that * determination a physical page address is calculated and returned. * * = PTE subset for the page in question * = -1 if off is not within the memory space for one of the frame buffers * * Notes: * (1) The value given by "off" is relative to the device register area * (since its address was given in the map_regs call to allocate * virtual memory for the mapping.) * (2) See the description "Physical to virtual memory mapping for devices * on the tc1" near the end of this file for further details of the * mapping process. */ /*ARGSUSED*/ STATIC cgeightmmap(dev, off, prot) dev_t dev; /* = device which is to be memory mapped. */ register off_t off; /* = offset into memory map for page to be mapped. */ int prot; /* (unused) */ { int mmi; /* Index: # of mmap_info entry examining. */ Mmap_Info *mmp; /* Cursor: mmap_info entry examining. */ off_t phys_off; /* Physical offset from base page of page. */ SOFTC *softc = /* Pointer to per-unit info. */ getsoftc(minor(dev)); DEBUGF(off ? 9 : 1, ("cgeightmmap(%d, 0x%x)\n", minor(dev), (u_int) off)); #ifdef TEST_NEW_HARDWARE if ( off >= 0x00900000 ) { if ( softc->test_basepage == 0 ) return -1; phys_off = (off-0x900000); printf("Returning offset %x as phys_off %x and address %x\n", off, phys_off, softc->test_basepage+btop(phys_off)); return softc->test_basepage + btop(phys_off); } #endif TEST_NEW_HARDWARE /* It's not us, it's an interesting approach, but its not us! */ if ( (off < 0) || (off > softc->memory_map_end) ) { return -1; } /* From "off" determine which physical memory is being referenced. * Recalculate "off" as a physical offset relative to base page (that was * mapped with map_regs). */ if ( off >= softc->dev_reg_mmap_offset ) /* DEVICE MAP */ { phys_off = (off-softc->dev_reg_mmap_offset) + softc->dev_reg_sbus_delta; return softc->basepage + btop(phys_off); } for ( mmi=0, mmp=softc->mmap_info; mmi < softc->mmap_count; mmi++, mmp++ ) { if ( off >= mmp->bgn_offset && off < mmp->end_offset ) { phys_off = (off - mmp->bgn_offset) + mmp->sbus_delta; #if TC_DEBUG DEBUGF((mmp->group==PIXPG_OVERLAY && off==mmp->bgn_offset) ? 1 : 9, ("cgeightmmap returning 0x%x (0x%x)\n", ptob(softc->basepage)+phys_off, softc->basepage+btop(phys_off))); if ( off == mmp->bgn_offset ) { switch (mmp->group) { case PIXPG_8BIT_COLOR: printf("cgeightmmap returning eight bit color"); break; case PIXPG_OVERLAY: printf("cgeightmmap returning monochrome"); break; case PIXPG_OVERLAY_ENABLE: printf("cgeightmmap returning selection"); break; case PIXPG_24BIT_COLOR: printf("cgeightmmap returning true color"); break; case PIXPG_VIDEO_ENABLE: printf("cgeightmmap returning video enable"); break; } printf(" start at 0x%x (0x%x)\n", ptob(softc->basepage)+phys_off, softc->basepage+btop(phys_off)); } #endif TC_DEBUG return softc->basepage + btop(phys_off); } } return -1; } /*"cgeightopen" * * Open a SBus TC board "device" for use. * * Parameters: * dev = device to be opened * flag = flags indicating access method (e.g., read, write) * * Function value: * = return code from frame buffer driver open routine */ STATIC cgeightopen(dev, flag) dev_t dev; /* = device specification giving what device instance to open */ int flag; /* = flags indicating access method (e.g., read, write). */ { #ifdef LOADABLE extern dev_t fbdev; /* Unit # of /dev/fb. */ #endif LOADABLE DEBUGF(2, ("cgeightopen(%d,%d)\n", major(dev), minor(dev))); #ifdef LOADABLE /* This driver is dynamically loaded, so if the value for /dev/fb has * not been set, make ourselves the default frame buffer. NOTE hardwire * of /dev/fb's major device number! */ if ( (fbdev < 1) || (fbdev == 22) ) { fbdev = dev; } #endif LOADABLE return fbopen(dev, flag, num_tc); } /*"cgeightpoll" * * Interrupt service routine for vertical retrace interrupts * on this device type. Loop through each device instance * looking for one with an interrupt pending. * * = number of interrupts serviced */ static cgeightpoll() { Tcs_Device_Map *device_tcs; /* Poniter to tcs device register area. */ int instance; /* Index: instance now examining interrupt on*/ int serviced; /* Number of interrupts serviced. */ SOFTC *softc; /* Pointer to characteristics for our unit. */ serviced = 0; for (softc = tc1_softc, instance = num_tc; --instance >= 0; softc++) { switch(softc->fb_model) { default: if ( mfb_int_pending((struct mfb_reg *)softc->device_reg) ) { mfb_int_disable( ((struct mfb_reg *)softc->device_reg) ); serviced++; } break; case RASTEROPS_TCP: case RASTEROPS_TC: mfb_int_disable( ((struct mfb_reg *)softc->device_reg) ); serviced++; break; case RASTEROPS_TCS: device_tcs = softc->device_tcs; if ( device_tcs->tc_venus.status & VENUS_VERT_INT ) { tcs_update_cmap(softc); device_tcs->tc_venus.control4 = 0; device_tcs->tc_venus.status = 0; serviced++; } break; } } return serviced; } /*"cg8_ioctl" */ static int cg8_ioctl(pr, cmd, data) Pixrect *pr; int cmd; caddr_t data; { static int save_window_fd; switch (cmd) { case FBIOGPLNGRP: *(int *) data = PIX_ATTRGROUP(cg8_d(pr)->planes); break; case FBIOAVAILPLNGRP: { static int cg4groups = MAKEPLNGRP(PIXPG_OVERLAY) | MAKEPLNGRP(PIXPG_OVERLAY_ENABLE) | MAKEPLNGRP(PIXPG_24BIT_COLOR); struct cg8_data *cg8d; int fbi; int group_mask = 0; cg8d = cg8_d(pr); for (fbi = 0; fbi < cg8d->num_fbs; fbi++) { group_mask |= MAKEPLNGRP(cg8d->fb[fbi].group); } *(int *) data = group_mask; break; } case FBIO_FULLSCREEN_ELIMINATION_GROUPS: { struct cg8_data *cg8d; char *elim_groups = (char *)data; bzero(elim_groups, PIXPG_LAST_PLUS_ONE); if ( cg8d->flags & CG8_EIGHT_BIT_PRESENT ) { elim_groups[PIXPG_24BIT_COLOR] = 1; } else { elim_groups[PIXPG_8BIT_COLOR] = 1; } } break; case FBIOGCMSIZE: if (cmsize < 0) return -1; *(int *) data = cmsize; break; case FBIOSCMSIZE: cmsize = *(int *) data; break; case FBIOSCMS: cg8_d(pr)->cms = *(struct colormapseg *) data; break; case FBIOSWINFD: cg8_d(pr)->windowfd = *(int *) data; break; case FBIOSAVWINFD: if (cg8_d(pr)->windowfd >= -1) { save_window_fd = cg8_d(pr)->windowfd; cg8_d(pr)->windowfd = -2; } break; case FBIORESWINFD: cg8_d(pr)->windowfd = save_window_fd; break; default: return ENOTTY; } return 0; } /*"cg8_putattributes" */ static int cg8_putattributes (pr, planesp) Pixrect *pr; /* -> pixrect to set plane group of. */ u_int *planesp; /* -> encoded group and plane mask */ { struct cg8_data *cg8d; /* private data */ int dont_set_planes; u_int planes, group; dont_set_planes = *planesp & PIX_DONT_SET_PLANES; planes = *planesp & PIX_ALL_PLANES;/* the plane mask */ group = PIX_ATTRGROUP(*planesp); /* extract the group part */ cg8d = cg8_d (pr); /* * User is trying to set the group to something else. We'll see if the * group is supported. If does, do as he wishes. */ if (group != PIXPG_CURRENT || group == PIXPG_INVALID) { int active = 0, found = 0, cm_size; /* kernel should not access the color frame buffer */ if (group == PIXPG_TRANSPARENT_OVERLAY) { group = PIXPG_OVERLAY; cg8d->flags |= CG8_COLOR_OVERLAY; } else { cg8d->flags &= ~CG8_COLOR_OVERLAY; } for (; active < cg8d->num_fbs && !found; active++) { if (found = (group == cg8d->fb[active].group)) { cg8d->mprp = cg8d->fb[active].mprp; cg8d->planes = PIX_GROUP (group) | (cg8d->mprp.planes & PIX_ALL_PLANES); cg8d->active = active; pr->pr_depth = cg8d->fb[active].depth; switch (group) { default: case PIXPG_8BIT_COLOR: case PIXPG_24BIT_COLOR: cm_size = TC_CMAP_SIZE; if (cg8d->flags&CG8_PIP_PRESENT) cg8d->flags|=CG8_STOP_PIP; break; case PIXPG_OVERLAY: cm_size = 4; cg8d->flags &= ~CG8_STOP_PIP; break; case PIXPG_OVERLAY_ENABLE: cm_size = 0; cg8d->flags &= ~CG8_STOP_PIP; break; case PIXPG_VIDEO_ENABLE: cm_size = 0; if (cg8d->flags&CG8_PIP_PRESENT) cg8d->flags|=CG8_STOP_PIP; break; } cg8_ioctl(pr, FBIOSCMSIZE, (caddr_t) &cm_size); } } } /* group is PIXPG_CURRNT here */ if (!dont_set_planes) { cg8d->planes = cg8d->mprp.planes = cg8d->fb[cg8d->active].mprp.planes = PIX_GROUP(group) | planes; } return 0; } /*"cg8_putcolormap" */ static int cg8_putcolormap(pr, index, count, red, green, blue) Pixrect *pr; int index, count; unsigned char *red, *green, *blue; { struct cg8_data *cg8d; struct fbcmap fbmap; int cc,i,plane; /* * Set "cg8d" to the cg8 private data structure. If the plane * is not specified in the index, then use the currently active * plane. ### Does this conflict with the cg4 model? */ cg8d = cg8_d(pr); if (PIX_ATTRGROUP(index)) { plane = PIX_ATTRGROUP(index) & PIX_GROUP_MASK; index &= PR_FORCE_UPDATE | PIX_ALL_PLANES; } else plane = cg8d->fb[cg8d->active].group; /* If updates are to be forced, or the plane groups are 8 or 24 set * the colormap via ioctl. Otherwise, use the emulation approach. */ if (index & PR_FORCE_UPDATE || plane == PIXPG_24BIT_COLOR || plane == PIXPG_8BIT_COLOR) { cg8d->flags |= CG8_KERNEL_UPDATE; /* BCOPY vs. COPYIN */ fbmap.index = index | PIX_GROUP(plane); fbmap.count = count; fbmap.red = red; fbmap.green = green; fbmap.blue = blue; return cgeightioctl(cg8d->fd, FBIOPUTCMAP, (caddr_t) &fbmap, 0); } else /* emulated index */ { if (plane == PIXPG_OVERLAY_ENABLE) return 0; if (plane == PIXPG_OVERLAY) { for (cc=i=0; count && !cc; i++,index++,count--) { cg8d->flags |= CG8_KERNEL_UPDATE; /* BCOPY vs. COPYIN */ /* Index 0 is mapped to 1. All others mapped to 3. */ fbmap.index = (index ? 3 : 1) | PIX_GROUP(plane); fbmap.count = 1; fbmap.red = red+i; fbmap.green = green+i; fbmap.blue = blue+i; cc = cgeightioctl(cg8d->fd, FBIOPUTCMAP, (caddr_t) &fbmap, 0); } return cc; } } return PIX_ERR; } /* Macros to change a cg8 pixrect into a memory pixrect */ #define PR_TO_MEM(src, mem) \ if (src && src->pr_ops != &mem_ops) \ { \ mem.pr_ops = &mem_ops; \ mem.pr_size = src->pr_size; \ mem.pr_depth = src->pr_depth; \ mem.pr_data = (char *) &cg8_d(src)->mprp; \ src = &mem; \ } /*"cg8_rop" */ static int cg8_rop(dpr, dx, dy, w, h, op, spr, sx, sy) Pixrect *dpr, *spr; int dx, dy, w, h, op, sx, sy; { struct cg8_data *cg8d; /* Pointer to cg8 private data. */ Pixrect dmempr; /* Scratch area to build mem pixrect for dst. in. */ Pixrect smempr; /* Scratch area to build mem pixrect for src in. */ if (dpr->pr_depth>8 || (spr && spr->pr_depth>8)) { printf("kernel: cg8_rop error: attempt at 32 bit rop\n"); return 0; } /* If the video enable plane group is being written to, ignore the * call since, we do not map it in the kernel. */ cg8d = (dpr->pr_ops != &mem_ops ) ? cg8_d(dpr) : cg8_d(spr); if ( cg8d->fb[cg8d->active].group == PIXPG_VIDEO_ENABLE ) { return 0; } PR_TO_MEM(dpr, dmempr); PR_TO_MEM(spr, smempr); return pr_rop(dpr, dx, dy, w, h, op, spr, sx, sy); } #ifndef NO_PIP /* Routines to support Picture In A Picture Option card. * * * Notes: * (1) Control status register zero has one bit which is shared, that is, * it has different meanings on input and output. If the bit is written * it directs that a one-shot grab should be done. If the bit is read * it indicates if the pip has been turned on. Because of this sharing * it is not possible to use read modify write cycles in "pip_off". * * (2) The TCP_CSR0_TURN_PIP_ON bit is used to set the pip on or off. Its * value when read (TCP_CSR0_PIP_IS_ACTIVE) indicates if the pip is * actively writing data, NOT necessarily if the pip is on. The * TCP_CSR0_PIP_IS_ON bit indicates the the pip has been turned on, or * is running. The cycle looks like: * * PIP_ON set Field start PIP_OFF set Field end * | | | | * | V V V * V ____________...________________________ * PIP_IS_ACTIVE ________/ \_________ * __________________...________________________ * PIP_IS_ON __/ \_________ * * (3) In addition, TCP_CSR0_PIP_IS_ACTIVE will drop if the input source is * not present, even though it is "ON". So TCP_CSR0_PIP_IS_ON should be * examined to determine the state of the pip, not * TCP_CSR0_PIP_IS_ACTIVE. * * (4) When turning off the pip it will continue until the end of the field * as shown above. So TCP_CSR0_PIP_IS_ACTIVE may be polled to see if * the pip is off. * * 2 * I C Bus Programming Considerations And Details: * * (1) The i2c bus is implemented on the PIP as two contiguous bits in a * single register. Thus read-modify writes are used to set and clear * the bits. This can cause a problem during acknowledgement cycles * since the receiver of data (one of the devices on the i2c bus) will * hold the data line low during the acknowledgement cycle, which is * ended with the clock being set high by us. However, since the clock * is set high with a read-modify-write we pick up a low setting for * the data bit and store it back. To get around this we explicitly set * the data bit back to high after, or while, setting the clock. This * actions are flagged with comments in the code below. * * (2) The standard cycle for sending the first data byte is as follows: * * Start * | * | * | * V 1 2 3 4 5 6 7 8 ack * Clock: ____ __ __ __ __ __ __ __ __ __ * \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__ * * Sender: __ _____ _____ _____ _____ _____ _____ _____ ____________ * Data \___/_____X_____X_____X_____X_____X_____X_____X_____/ * * Reciever: ____________________________________________________ __ * Data \_____/ * * (3) The standard cycle for sending subsequent bytes is: * * * 1 2 3 4 5 6 7 8 ack * Clock: __ __ __ __ __ __ __ __ __ * ____/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__ * * Sender: _________ _____ _____ _____ _____ _____ _____ ___________ * Data \_____X_____X_____X_____X_____X_____X_____X_____/ * * Reciever: __________________________________________________ ___ * Data \____/ * * (4) The standard cycle for stop at the end of data transmission is: * * * Clock: ______ * ____/ * * Sender: ___ ____ * Data \__/ * * (5) The standard cycle for reading a byte is: * * * 1 2 3 4 5 6 7 8 stop * Clock: __ __ __ __ __ __ __ __ _____ * ____/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ * * Sender: __________________________________________________ ____ * Data \__/ * * Receiver: _________ _____ _____ _____ _____ _____ _____ ____ * Data \_____X_____X_____X_____X_____X_____X_____X____\____ * */ /*"pip_ioctl" * * Perform a pip-related input / output control operation on a * SBus TC Card or its associated driver code * * = 0 if successful operation * ~= 0 if error detected */ /*ARGSUSED*/ pip_ioctl(softc, cmd, data, flag) SOFTC *softc; /* -> instance dependent storage. */ int cmd; /* = opcode for operation to be performed. */ caddr_t data; /* -> data area for the operation (may be in or out). */ int flag; /* = modifier info. for operation to be performed. */ { # ifdef TC_DEBUG DEBUGF(5, ("tconeioctl: cmd = ")); switch (cmd) { case PIPIO_G_EMULATION_MODE: DEBUGF(5, ("PIPIO_G_EMULATION_MODE\n")); break; case PIPIO_G_PIP_ON_OFF: DEBUGF(5, ("PIPIO_G_PIP_ON_OFF\n")); break; case PIPIO_G_PIP_ON_OFF_SUSPEND: DEBUGF(5, ("PIP_G_PIP_ON_OFF_SUSPEND\n")); break; case PIPIO_G_PIP_ON_OFF_RESUME: DEBUGF(5, ("PIP_G_PIP_ON_OFF_RESUME\n")); break; case PIPIO_S_EMULATION_MODE: DEBUGF(5, ("PIPIO_S_EMULATION_MODE\n")); break; case PIPIO_S_PIP_ON_OFF: DEBUGF(5, ("PIP_S_PIP_ON_OFF\n")); break; default: DEBUGF(5, ("not supported (0x%x)\n", cmd)); break; } # endif TC_DEBUG /* Make sure pip operations are possible, then process request based on its * type. Cases are alphabetical. */ if ( softc->pg_possible[PIXPG_VIDEO_ENABLE] == 0 ) { return EINVAL; } switch (cmd) { case PIPIO_G_PIP_ON_OFF: *(int *)data = (softc->device_reg->control_status&TCP_CSR0_PIP_IS_ON) ? 1 : 0; break; case PIPIO_G_PIP_ON_OFF_RESUME: softc->pip_on_off_semaphore--; if ( softc->pip_on_off_semaphore < 0 ) { softc->pip_on_off_semaphore = -1; /* In case too many resumes */ pip_on(softc->device_reg); *(int *)data = 1; } else { *(int *)data = 0; } break; case PIPIO_G_PIP_ON_OFF_SUSPEND: *(int *)data = pip_off(softc, 0); softc->pip_on_off_semaphore++; break; case PIPIO_S_PIP_ON_OFF: if ( *(int *)data ) { pip_on(softc->device_reg); softc->pip_on_off_semaphore = -1; } else { pip_off(softc, 0); softc->pip_on_off_semaphore = 0; } break; /*- Unknown request, return fact we could not process it. */ default: return ENOTTY; } /* switch(cmd) */ return 0; } /*"pip_off" * * Turn off live video generation, returning the previous state of the bit. * * * Notes: * (1) See notes 2 and 3 at the beginning of this file for a detailed * explanation of all the shenanigans with bits in control status * register 0 that occur here. * * = 1 if pip was on * = 0 if pip was off */ int pip_off(softc, wait_for_inactive) SOFTC *softc; /* -> device instance dependent data. */ int wait_for_inactive; /* = 1 if wait for pip to actually turn off */ { int i; /* Index: # of times gone around wait loop. */ int pip_was_on; /* Indicates if pip was active. */ Tc1_Device_Map *dmap; /* -> device area on TCPIP card. */ dmap = softc->device_reg; pip_was_on = dmap->control_status & TCP_CSR0_PIP_IS_ON; dmap->control_status&=(u_char)~(TCP_CSR0_TURN_PIP_ON|TCP_CSR0_PIP_ONE_SHOT); if ( wait_for_inactive && (dmap->control_status & TCP_CSR0_PIP_IS_ACTIVE) ) { printf("Waiting for inactive\n"); for (i = 0; i < 10000000; i++) { if ( !(dmap->control_status & TCP_CSR0_PIP_IS_ACTIVE) ) break; } if ( i >= 10000000 ) { printf(" Pip did not turn off in %d loops!!!!\n", i); } } return (pip_was_on) ? 1 : 0; } /*"pip_on" * * Turn on live video generation. (Don't do it unless there * is an active data source connected. */ int pip_on(dmap) Tc1_Device_Map *dmap; /* -> device area on TCPIP card. */ { if ( dmap->control_status1 & TCP_CSR1_INPUT_CONNECTED ) { dmap->control_status = ((u_int)dmap->control_status&~TCP_CSR0_PIP_ONE_SHOT) | TCP_CSR0_TURN_PIP_ON; } } #endif !NO_PIP /*"tc_putcmap" * * Local routine to set the color map values for either the 24-bit or the * monochrome frame buffer on a TC or TCP card. In addition to real lookup * table manipulation, emulation of 8-bit indexed color maps is done for * 24-bit mode. (Called by tcone_ioctl). * = 0 if success * = error indication otherwise */ static int tc_putcmap( softc, cmap ) SOFTC *softc; /* -> characteristics for our unit. */ struct fbcmap *cmap; /* -> where to get colormap(data area from ioctl). */ { u_int count; /* # of color map entries to set. */ Tc1_Device_Map *device_reg; /* Pointer to the Brooktrees. */ int force_update; /* Indicates if should access real luts */ u_int index; /* Index of first entry to access. */ int n_entry; /* Loop index: current color map entry. */ int plane_group; /* Top 7 bits of index = plane group. */ device_reg = softc->device_reg; /* * Verify we need to actually move some data.Initialize variables * from caller's parameters, etc. If the plane group is zero, use * the 24 bit group. */ if ( (cmap->count == 0) || !cmap->red || !cmap->green || !cmap->blue ) { return 0; } count = cmap->count; index = cmap->index & PIX_ALL_PLANES; if (index+count > TC_CMAP_SIZE) { return EINVAL; } force_update = cmap->index & PR_FORCE_UPDATE; if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) ) { plane_group = PIXPG_24BIT_COLOR; } /* Move caller's data, there are 2 cases: kernel space and user space. */ if (softc->tc1d.flags & CG8_KERNEL_UPDATE) { DEBUGF(6, ("Kernel putcmap\n", 0) ); softc->tc1d.flags &= ~CG8_KERNEL_UPDATE; BCOPY( cmap->red, softc->cmap_red, count ); BCOPY( cmap->green, softc->cmap_green, count); BCOPY( cmap->blue, softc->cmap_blue, count ); } else { DEBUGF(6, ("User putcmap, index=%x, count=%d, pg=%d\n", index, count, plane_group) ); if ( COPYIN( cmap->red, softc->cmap_red, count ) || COPYIN( cmap->green, softc->cmap_green, count) || COPYIN( cmap->blue, softc->cmap_blue, count ) ) { return EFAULT; } } /* If there is no eight bit buffer and hardware update is not forced, * set 8-bit index emulation color table entries for 24-bit buffer. * (The check for the 8-bit plane group is here in case the kernel * knows 8-bit h'ware exists, but the driver didn't export it to Sunview.) */ if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0) && ((plane_group==PIXPG_24BIT_COLOR) || (plane_group==PIXPG_8BIT_COLOR)) ) { for (n_entry = 0; n_entry < count; n_entry++, index++) { softc->em_red[index] = softc->cmap_red[n_entry]; softc->em_green[index] = softc->cmap_green[n_entry]; softc->em_blue[index] = softc->cmap_blue[n_entry]; } } /* Set entries in actual Brooktree lookup tables for 8/24-bit buffer. */ else if ( plane_group == PIXPG_24BIT_COLOR || plane_group == PIXPG_8BIT_COLOR ) { DEBUGF(6, ("Real pcmap: group=%d flags=%x", plane_group, softc->tc1d.flags) ); DEBUGF(6, (" first = %d", index) ); DEBUGF(6, (" count = %d\n", count) ); device_reg->dacs.bt457.all_address = index; for (n_entry = 0; n_entry < count; n_entry++) { device_reg->dacs.bt457.red_color = softc->cmap_red[n_entry]; device_reg->dacs.bt457.green_color = softc->cmap_green[n_entry]; device_reg->dacs.bt457.blue_color = softc->cmap_blue[n_entry]; } } else if (plane_group != PIXPG_OVERLAY ) { printf("Illegal plane group %d encountered\n", plane_group); return EINVAL; } /* Set entries in actual Brooktree lookup tables for monochrome overlay. * At the same time write the shadow color map which fbiogetcmap gets * values from. Note that our overlay map works in a different manner from * Sun's cg8, so a translation must be done (using translate_omap data * structure): * Function Sun LUT index SBus TC LUT index * -------- ------------- ------------------ * True color 0 0 * Window system foreground 1 2 * Current window foreground 2 1 * Window system background 3 3 * * Note we only write the overlay if 24-bit enabled to get around * a problem with cg4 emulation. Also we implement cursor color * freezing here for true color! */ else if ( softc->pg_enabled[PIXPG_24BIT_COLOR] ) { DEBUGF(6, ("Overlay pcmap: flags=%x", softc->tc1d.flags) ); DEBUGF(6, (" first = %d", index) ); DEBUGF(6, (" count = %d\n", count) ); for (n_entry = 0; n_entry < count; n_entry++, index++) { if ( !softc->sw_cursor_color_frozen || index != 2 ) { device_reg->dacs.bt457.all_address = translate_omap[index]; device_reg->dacs.bt457.red_overlay = softc->omap_red[index] = softc->cmap_red[n_entry]; device_reg->dacs.bt457.green_overlay = softc->omap_green[index] = softc->cmap_green[n_entry]; device_reg->dacs.bt457.blue_overlay = softc->omap_blue[index] = softc->cmap_blue[n_entry]; } } } return 0; } /*"tcp_attach" * * Perform device specific initializations for TC or TCP frame buffer. * (Called from cgeightattach().) This routine initializes parts of the * per-unit data structure. In addition it maps the device's memory regions * into virtual memory and performs hardware specific initializations. * A number of per-unit data items have already been initialized from PROMs * in cgeightattach(). * * = 1 if success * = 0 if failure */ static int tcp_attach(devi, softc) struct dev_info *devi; /* -> device info structure w/node id... (rest filled here). */ SOFTC *softc; /* -> per-unit data structure to be filled in. */ { int color; /* Index: next color to set in lut ramp. */ Tc1_Device_Map *dmap; /* Fast pointer to device register area. */ int fb_map_bytes; /* # of bytes needed to map frame buffers. */ addr_t reg; /* Virt. addr of device map(&optionally fbs)*/ register u_long *sel_addr; /* Cursor: selection memory word to init. */ register int sel_cnt; /* Index: # of words initialized in sel mem */ int sel_max; /* # of words in sel. mem. to initialize. */ /* PROCESS REMAINING PROM PARAMETERS: * * Pick up the device specific parameters exported by the on-board PROMs. * Use this information to set up memory mapping characteristics of the * board. */ DEBUGF(5, ("tcp_attach softc at %x\n", softc)); /* Device register area parameters: */ softc->dev_reg_sbus_base = getprop(devi->devi_nodeid, "device-map-offset", 0x400000); softc->dev_reg_mmap_offset = CG8_VADDR_DAC; softc->dev_reg_sbus_delta = 0; softc->dev_reg_mmap_size = ptob(btopr(NBPG)); softc->memory_map_end = softc->dev_reg_mmap_offset + softc->dev_reg_mmap_size; DEBUGF(5, (" dev_reg_sbus_base is %x\n", softc->dev_reg_sbus_base)); /* Monochrome frame buffer parameters: */ softc->fb_mono_sbus_delta = getprop(devi->devi_nodeid, "monochrome-offset", 0x00C00000); softc->fb_mono_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_mono_mmap_size = getprop(devi->devi_nodeid, "monochrome-size", 1152*900/8); softc->fb_mono_mmap_size = ptob(btopr(softc->fb_mono_mmap_size)); DEBUGF(5, ("monochrome sbus delta %x mmap offset %x size %x\n", softc->fb_mono_sbus_delta, 0, softc->fb_mono_mmap_size)); /* Selection memory parameters: */ softc->fb_sel_sbus_delta = getprop(devi->devi_nodeid, "selection-offset", 0x00D00000); softc->fb_sel_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_sel_mmap_size = getprop(devi->devi_nodeid, "selection-size", 1152*900/8); softc->fb_sel_mmap_size = ptob(btopr(softc->fb_sel_mmap_size)); DEBUGF(5, ("selection sbus delta %x mmap offset %x size %x\n", softc->fb_sel_sbus_delta, softc->fb_mono_mmap_size, softc->fb_sel_mmap_size)); /* Eight bit frame buffer parameters (set them up even if don't use them): */ softc->fb_8bit_sbus_delta = 0x00700000 - softc->dev_reg_sbus_base; softc->fb_8bit_mmap_size = ptob(btopr(1152*900)); DEBUGF(5, ("eight_bit sbus delta %x mmap offset %x size %x\n", softc->fb_8bit_sbus_delta, softc->fb_mono_mmap_size+softc->fb_sel_mmap_size, softc->fb_8bit_mmap_size)); /* True color frame buffer parameters: */ softc->fb_tc_sbus_delta = getprop(devi->devi_nodeid, "true-color-offset", 0x00800000); softc->fb_tc_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_tc_mmap_size = getprop(devi->devi_nodeid, "true-color-size", 1152*900*4); softc->fb_tc_mmap_size = ptob(btopr(softc->fb_tc_mmap_size)); DEBUGF(5, ("true_color sbus delta %x size %x\n", softc->fb_tc_sbus_delta, softc->fb_tc_mmap_size)); /* Video enable memory parameters (set them up even if we don't use them): */ softc->fb_video_sbus_delta = 0x00E00000 - softc->dev_reg_sbus_base; softc->fb_video_mmap_size = ptob(btopr(1152*900/8)); DEBUGF(5, ("video_enable sbus delta %x size %x\n", softc->fb_video_sbus_delta, softc->fb_video_mmap_size)); /* ALLOCATE SPACE IN KERNEL VIRTUAL MEMORY FOR THE DEVICE REGISTERS AND * MONOCHROME OPERATIONS, BUILD THE TABLE USED FOR USER SPACE MAPPING * * Allocate space in virtual memory for the device register area (and * possibly the frame buffers.) Remember the virtual address of the device * register area, and its physical address, which will be used by * cgeightmmap as the base mapping for all physical pages. * * #### The |= 18000000 kludge is because the 4.1.1 code on a SS2 does * not return the correct address for the Sbus slot! (Bug 1046449) * This can be removed when that is fixed. */ # if NWIN > 0 fb_map_bytes = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size; if ( softc->pg_possible[PIXPG_8BIT_COLOR] ) { fb_map_bytes += softc->fb_8bit_mmap_size; } # else NWIN > 0 fb_map_bytes = 0; # endif NWIN > 0 #ifdef sun4c (u_int)devi->devi_reg[0].reg_addr |= 0x18000000; /* SEE NOTE ABOVE */ #endif sun4c if ( !(reg = (addr_t)map_regs( (addr_t)(devi->devi_reg[0].reg_addr + softc->dev_reg_sbus_base), (u_int)(fb_map_bytes + softc->dev_reg_mmap_size), devi->devi_reg[0].reg_bustype))) { return 0; } softc->device_reg = (Tc1_Device_Map *) reg; dmap = softc->device_reg; softc->basepage = fbgetpage(reg); DEBUGF(5, ("tcp_attach reg=0x%x basepage=0x%x (0x%x)\n", (u_int)reg, ptob(softc->basepage), softc->basepage)); /* Default operations to emulate a Sun CG8 card (this may be modified later * via the PIPIO_S_EMULATION_MODE ioctl.) * Determine if there is a pip and/or eight bit memory present. If this is * an old style frame buffer set the register to enable use of selection * memory. */ softc->pg_enabled[PIXPG_8BIT_COLOR] = 0; #ifndef NO_PIP if ( softc->pg_possible[PIXPG_VIDEO_ENABLE] ) { if ( (dmap->control_status1 & TCP_CSR1_NO_PIP) == 0 ) { softc->pip_on_off_semaphore = 0; pip_off(softc, 0); } else { softc->pg_possible[PIXPG_VIDEO_ENABLE] = 0; softc->pg_enabled[PIXPG_VIDEO_ENABLE] = 0; } } #endif !NO_PIP if ( softc->fb_model == RASTEROPS_TC ) { dmap->control_status |= TC1_SELECTION_ENABLE; } /* For the kernel's use map in the monochrome frame buffer, selection * memory, and if present the eight bit memory after the device registers. * For each buffer calculate its virtual address, and place this * information into the device-dependent structure. Note in the kernel the * the device register appears before the frame buffer so we are constantly * adding in NBPG to the virtual offsets. In user mode the opposite is * true, because of the way cg8_make maps things. */ #if NWIN > 0 if (fb_map_bytes) { fbmapin(reg + NBPG, (int) (softc->basepage + btop(softc->fb_mono_sbus_delta)), softc->fb_mono_mmap_size); softc->fb_mono = (u_char *)reg + NBPG; DEBUGF(5, ("tcp_attach fb_mono= 0x%x/0x%x (0x%x)\n", (u_int) softc->fb_mono, fbgetpage((addr_t) softc->fb_mono) << PGSHIFT, fbgetpage((addr_t) softc->fb_mono))); fbmapin(reg + NBPG + softc->fb_mono_mmap_size, (int) (softc->basepage + btop(softc->fb_sel_sbus_delta)), softc->fb_sel_mmap_size); softc->fb_sel = (u_char *)reg + NBPG + softc->fb_mono_mmap_size; DEBUGF(5, ("tcp_attach fb_sel= 0x%x/0x%x (0x%x)\n", (u_int) softc->fb_sel, fbgetpage((addr_t) softc->fb_sel) << PGSHIFT, fbgetpage((addr_t) softc->fb_sel))); if ( softc->pg_possible[PIXPG_8BIT_COLOR] ) { fbmapin(reg+NBPG+softc->fb_mono_mmap_size+softc->fb_sel_mmap_size, (int) (softc->basepage + btop(softc->fb_8bit_sbus_delta)), softc->fb_8bit_mmap_size); softc->fb_8bit = (u_char *)reg + NBPG + softc->fb_mono_mmap_size + softc->fb_sel_mmap_size; DEBUGF(5, ("tcp_attach fb_8bit= 0x%x/0x%x (0x%x)\n", (u_int) softc->fb_8bit, fbgetpage((addr_t) softc->fb_8bit) << PGSHIFT, fbgetpage((addr_t) softc->fb_8bit))); } } #endif NWIN > 0 /* Build the memory mapping information used to map in the various frame * buffers in user (process) space. */ x_build_mmap_info(softc); /* INITIALIZE RAMDACs AND SELECTION MEMORY IN PREPARATION FOR WINDOW USAGE * * Before initializing the Brooktree's make sure the selection memory * indicates that the monochrome plane is visible. This is necessary * because we are about to enable the selection memory as an input into the * overlay port on the RAMDACs. */ #if NWIN > 0 sel_max = 900*softc->linebytes1 / sizeof(u_long); for(sel_addr=(u_long *)softc->fb_sel, sel_cnt=0; sel_cnt 0 /* Initialize the 3 Brooktree 457s for: * (1) 4:1 multiplexing (since we are not 1280x1024) * (2) Transparent overlay for overlay color 0. * (3) Display the overlay plane * Enable read and write to all planes, turn off blinking, and set * control register. */ DEBUGF(5, ("TCONE: Initializing Brooktrees\n") ); dmap->dacs.bt457.all_address = BT457_COMMAND; dmap->dacs.bt457.all_control = 0x43; dmap->dacs.bt457.all_address = BT457_READ_MASK; dmap->dacs.bt457.all_control = 0xff; dmap->dacs.bt457.all_address = BT457_BLINK_MASK; dmap->dacs.bt457.all_control = 0; dmap->dacs.bt457.all_address = BT457_CONTROL; dmap->dacs.bt457.all_control = 0; /* Initialize overlay plane color map and load Brooktree 457's as a group * with that map. (See tc_putcmap routine below for description of this * funny mapping.) */ dmap->dacs.bt457.all_address = 0; dmap->dacs.bt457.all_overlay = /* Unused, this is transparency value! */ softc->omap_red[0] = softc->omap_green[0] = softc->omap_blue[0] = 0x00; dmap->dacs.bt457.all_address = 2; dmap->dacs.bt457.all_overlay = /* Window system background: white guardian*/ softc->omap_red[1] = softc->omap_green[1] = softc->omap_blue[1] = 0xff; dmap->dacs.bt457.all_address = 1; dmap->dacs.bt457.all_overlay = /* Current window foreground. */ softc->omap_red[2] = softc->omap_green[2] = softc->omap_blue[2] = 0xff; dmap->dacs.bt457.all_address = 3; dmap->dacs.bt457.all_overlay = /* Window system foreground: black guardian*/ softc->omap_red[3] = softc->omap_green[3] = softc->omap_blue[3] = 0x00; softc->sw_cursor_color_frozen = 0; /*Allow cursor color to be set normally*/ /* Load Brooktree 457's as a group with a linear ramp for the 24-bit true * color frame buffer. */ for (color=0, dmap->dacs.bt457.all_address=0; color < TC_CMAP_SIZE; color++) { dmap->dacs.bt457.all_color = color; } return 1; } /*"tcs_attach" * * Perform device specific initializations for TCS frame buffer. * (Called from cgeightattach().) This routine initializes parts of the * per-unit data structure. In addition it maps the device's memory regions * into virtual memory and performs hardware specific initializations. * A number of per-unit data items have already been initialized from PROMs * in cgeightattach(). * * = 1 if success * = 0 if failure */ static int tcs_attach(devi, softc) struct dev_info *devi; /* -> device info struct w/node id...(rest filled here) */ SOFTC *softc; /* -> per-unit data structure to be filled in. */ { int color; /* Index: next color to set in lut ramp. */ Tcs_Device_Map *dmap; /* Fast pointer to device register area. */ int fb_map_bytes; /* # of bytes needed to map frame buffers. */ addr_t reg; /* Virt addr of device map(&optionally fbs) */ register u_long *sel_addr; /* Cursor: selection memory word to init. */ register int sel_cnt; /* Index: # of sel. mem. words initialized */ int sel_max; /* # of words in selection memory to init. */ /* PROCESS REMAINING PROM PARAMETERS: * * Pick up the device specific parameters exported by the on-board PROMs. * Use this information to set up memory mapping characteristics of the * board. */ DEBUG_LEVEL(5); DEBUGF(5, ("tcs_attach softc at %x\n", softc)); /* Device register area parameters: */ softc->dev_reg_sbus_base = getprop(devi->devi_nodeid, "device-map-offset", 0x00040000); softc->dev_reg_mmap_offset = CG8_VADDR_DAC; softc->dev_reg_sbus_delta = 0; softc->dev_reg_mmap_size = ptob(btopr(NBPG)); softc->memory_map_end = softc->dev_reg_mmap_offset+softc->dev_reg_mmap_size; DEBUGF(5, (" dev_reg_sbus_base is %x\n", softc->dev_reg_sbus_base)); /* Monochrome frame buffer parameters: */ softc->fb_mono_sbus_delta = getprop(devi->devi_nodeid, "monochrome-offset", 0x00100000); softc->fb_mono_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_mono_mmap_size = getprop(devi->devi_nodeid, "monochrome-size", 0x40000); softc->fb_mono_mmap_size = ptob(btopr(softc->fb_mono_mmap_size)); DEBUGF(5, ("monochrome sbus delta %x mmap offset %x size %x\n", softc->fb_mono_sbus_delta, 0, softc->fb_mono_mmap_size)); /* Selection memory parameters: */ softc->fb_sel_sbus_delta = getprop(devi->devi_nodeid, "selection-offset", 0x00140000); softc->fb_sel_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_sel_mmap_size = getprop(devi->devi_nodeid, "selection-size", 0x40000); softc->fb_sel_mmap_size = ptob(btopr(softc->fb_sel_mmap_size)); DEBUGF(5, ("selection sbus delta %x mmap offset %x size %x\n", softc->fb_sel_sbus_delta, softc->fb_mono_mmap_size, softc->fb_sel_mmap_size)); /* Eight bit frame buffer parameters (set them up even if don't use them): */ softc->fb_8bit_sbus_delta = 0x00180000 - softc->dev_reg_sbus_base; softc->fb_8bit_mmap_size = ptob(btopr(0x80000)); softc->pg_possible[PIXPG_8BIT_COLOR] = 0; DEBUGF(5, ("eight_bit sbus delta %x mmap offset %x size %x\n", softc->fb_8bit_sbus_delta, softc->fb_mono_mmap_size + softc->fb_sel_mmap_size, softc->fb_8bit_mmap_size)); /* True color frame buffer parameters: */ softc->fb_tc_sbus_delta = getprop(devi->devi_nodeid, "true-color-offset", 0x00200000); softc->fb_tc_sbus_delta -= softc->dev_reg_sbus_base; softc->fb_tc_mmap_size = getprop(devi->devi_nodeid, "true-color-size", 0x200000); softc->fb_tc_mmap_size = ptob(btopr(softc->fb_tc_mmap_size)); DEBUGF(5, ("true_color sbus delta %x size %x\n", softc->fb_tc_sbus_delta, softc->fb_tc_mmap_size)); /* ALLOCATE SPACE IN KERNEL VIRTUAL MEMORY FOR THE DEVICE REGISTERS AND * MONOCHROME OPERATIONS * * Allocate space in virtual memory for the device register area (and * possibly the frame buffers.) Remember the virtual address of the device * register area, and its physical address, which will be used by * cgeightmmap as the base mapping for all physical pages. * * #### The |= 18000000 kludge is because the 4.1.1 code on a SS2 does * not return the correct address for the Sbus slot! (Bug 1046449) * This can be removed when that is fixed. */ # if NWIN > 0 fb_map_bytes = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size; # else NWIN > 0 fb_map_bytes = 0; # endif NWIN > 0 #ifdef sun4c (u_int)devi->devi_reg[0].reg_addr |= 0x18000000; /* SEE NOTE ABOVE */ #endif sun4c if ( !(reg = (addr_t)map_regs( (addr_t)(devi->devi_reg[0].reg_addr + softc->dev_reg_sbus_base), (u_int)(fb_map_bytes + softc->dev_reg_mmap_size), devi->devi_reg[0].reg_bustype))) { return 0; } softc->device_tcs = (Tcs_Device_Map *) reg; dmap = softc->device_tcs; softc->basepage = fbgetpage(reg); DEBUGF(5, ("tcs_attach reg=0x%x basepage=0x%x (0x%x)\n", (u_int)reg, ptob(softc->basepage), softc->basepage)); /* Default operations to emulate a Sun CG8 card (this may be modified later * via the PIPIO_S_EMULATION_MODE ioctl.) */ softc->pg_enabled[PIXPG_8BIT_COLOR] = 0; /* For the kernel's use map in the monochrome frame buffer, and selection * memory after the device registers. For each buffer calculate its virtual * address, and place this information into the device-dependent structure. * Note in the kernel the the device register appears before the frame * buffer so we are constantly adding in NBPG to the virtual offsets. In * user mode the opposite is true, because of the way cg8_make maps things. */ #if NWIN > 0 if (fb_map_bytes) { fbmapin(reg + NBPG, (int) (softc->basepage + btop(softc->fb_mono_sbus_delta)), softc->fb_mono_mmap_size); softc->fb_mono = (u_char *)reg + NBPG; DEBUGF(5, ("tcs_attach fb_mono= 0x%x/0x%x (0x%x)\n", (u_int) softc->fb_mono, fbgetpage((addr_t) softc->fb_mono) << PGSHIFT, fbgetpage((addr_t) softc->fb_mono))); fbmapin(reg + NBPG + softc->fb_mono_mmap_size, (int) (softc->basepage + btop(softc->fb_sel_sbus_delta)), softc->fb_sel_mmap_size); softc->fb_sel = (u_char *)reg + NBPG + softc->fb_mono_mmap_size; DEBUGF(5, ("tcs_attach fb_sel= 0x%x/0x%x (0x%x)\n", (u_int) softc->fb_sel, fbgetpage((addr_t) softc->fb_sel) << PGSHIFT, fbgetpage((addr_t) softc->fb_sel))); } #endif NWIN > 0 /* Build the memory mapping information used to map in the various frame * buffers in user (process) space. */ x_build_mmap_info(softc); /* INITIALIZE VENUS CHIPS, RAMDAC AND SELECTION MEMORY IN PREPARATION FOR * WINDOW USAGE * * Initialize venus chips to turn on operation of Brooktree, memory timing, * etc. Use the switch settings if this is not a model a board. * * Before initializing the Brooktree make sure the selection memory * indicates that the monochrome plane is visible. This is necessary * because we are about to enable the selection memory as an input into the * overlay port on the RAMDACs. */ if ( softc->device_tcs->tc_venus.io_general & VENUS_TCS_MODEL_A ) { tcs_init_native(softc); } else { switch( softc->device_tcs->tc_venus.io_general & VENUS_TIMING_MASK ) { default: printf("Unknown switch setting: defaulting to native timing.\n"); case VENUS_TIMING_NATIVE: tcs_init_native(softc); break; case VENUS_TIMING_NTSC: tcs_init_ntsc(softc); break; case VENUS_TIMING_PAL: tcs_init_pal(softc); break; } softc->linebytes1 = softc->width / 8; softc->linebytes32 = softc->width * 4; } sel_max = softc->width*softc->linebytes1 / sizeof(u_long); for(sel_addr=(u_long *)softc->fb_sel, sel_cnt=0; sel_cntdac.control = 0x30; /* 8-bit pixels, NTSC timing (IRE = 7.5) */ dmap->dac.read_mask = 0xff; /* Initialize overlay plane color map. */ dmap->dac.overlay_write_addr = 0; /* Overlay colors: */ dmap->dac.overlay = 0x00; /* 00: transparent pass-through. */ dmap->dac.overlay = 0x00; /* ... */ dmap->dac.overlay = 0x00; /* ... */ dmap->dac.overlay = 0xff; /* 01: true color cursor value: white. */ dmap->dac.overlay = 0xff; /* ... */ dmap->dac.overlay = 0xff; /* ... */ dmap->dac.overlay = 0xff; /* 10: window background color: white. */ dmap->dac.overlay = 0xff; /* ... */ dmap->dac.overlay = 0xff; /* ... */ dmap->dac.overlay = 0x00; /* 11: window foreground color: black. */ dmap->dac.overlay = 0x00; /* ... */ dmap->dac.overlay = 0x00; /* ... */ softc->omap_red[0] = softc->omap_green[0] = softc->omap_blue[0] = 0x00; softc->omap_red[1] = softc->omap_green[1] = softc->omap_blue[1] = 0xff; softc->omap_red[2] = softc->omap_green[2] = softc->omap_blue[2] = 0xff; softc->omap_red[3] = softc->omap_green[3] = softc->omap_blue[3] = 0x00; /* Load Brooktree 473 as a group with a linear ramp for the 24-bit true * color frame buffer. Use cmap_xxx as a shadow table since we load the * entire lut in tcs_putcmap(). (See note 1 in tcs_putcmap.) */ for (color = 0, dmap->dac.ram_write_addr = 0; color < TC_CMAP_SIZE; color++) { softc->cmap_red[color] = dmap->dac.color = color; softc->cmap_green[color] = dmap->dac.color = color; softc->cmap_blue[color] = dmap->dac.color = color; } DEBUG_LEVEL(0); return 1; } /*"tcs_init_native" * * Initialize venus chips on SBus TCS Card to operate at * Apple 13" monitor scan rates (60Hz non-interlaced, 640 x 480.) */ tcs_init_native(softc) SOFTC *softc; /* characteristics for our unit. */ { Tcs_Device_Map *dmap; /* -> device register area on TCS card. */ u_int io_conf; /* Value to load into io config register. */ u_int io_gen; /* Value to load into io general register. */ dmap = softc->device_tcs; softc->timing_regimen = NATIVE_TIMING; softc->width = 640; softc->height = 480; softc->linebytes1 = softc->width / 8; softc->linebytes8 = softc->width; softc->linebytes32 = softc->width * 4; io_gen = (dmap->tc_venus.io_general & VENUS_TCS_MODEL_A) ? 0x001c : 0x781c; io_conf = (dmap->tc_venus.io_general & VENUS_TCS_MODEL_A) ? 0x00df : 0x1fdf; /* * Initialize venus chip 0 which affects Brooktree operations and color * buffer operations. Configure the system as a 24-bit true color card. */ dmap->tc_venus.control1 = 0x00; dmap->tc_venus.control2 = 0x00; dmap->tc_venus.control3 = 0x00; dmap->tc_venus.control4 = 0x00; dmap->tc_venus.refresh_interval = 0x70; dmap->tc_venus.control1 = 0x11; dmap->tc_venus.io_general = io_gen; dmap->tc_venus.io_config = io_conf; dmap->tc_venus.display_start = 0x00000000; dmap->tc_venus.half_row_incr = 0x00000100; dmap->tc_venus.display_pitch = 0x00000140; dmap->tc_venus.cas_mask = 0x7f; dmap->tc_venus.horiz_latency = 0x00; dmap->tc_venus.horiz_end_sync = 0x000c; dmap->tc_venus.horiz_end_blank = 0x0024; dmap->tc_venus.horiz_start_blank = 0x00c4; dmap->tc_venus.horiz_total = 0x00d4; dmap->tc_venus.horiz_half_line = 0x0000; dmap->tc_venus.horiz_count_load = 0x0000; dmap->tc_venus.vert_end_sync = 0x02; dmap->tc_venus.vert_end_blank = 0x29; dmap->tc_venus.vert_start_blank = 0x0209; dmap->tc_venus.vert_total = 0x020c; dmap->tc_venus.vert_count_load = 0x0000; dmap->tc_venus.vert_interrupt = 0x020a; dmap->tc_venus.y_zoom = 0x01; dmap->tc_venus.soft_register = 0x00; dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET; dmap->tc_venus.io_general = io_gen; dmap->tc_venus.control3 = 0x73; dmap->tc_venus.control1 = 0xf1; /* Enable video. */ /* * Initialize venus chip 1 which affects 1-bit monochrome and selection * memory operations. */ dmap->mono_venus.control1 = 0x00; dmap->mono_venus.control2 = 0x00; dmap->mono_venus.control3 = 0x00; dmap->mono_venus.control4 = 0x00; dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */ dmap->mono_venus.control1 = 0x13; dmap->mono_venus.io_config = 0x00; dmap->mono_venus.display_start = 0x00000000; dmap->mono_venus.half_row_incr = 0x00000080; dmap->mono_venus.display_pitch = 0x00000050; dmap->mono_venus.cas_mask = 0x3f; dmap->mono_venus.horiz_latency = 0x00; dmap->mono_venus.horiz_end_sync = 0x000c; dmap->mono_venus.horiz_end_blank = 0x0024; dmap->mono_venus.horiz_start_blank = 0x00c4; dmap->mono_venus.horiz_total = 0x00d4; dmap->mono_venus.horiz_half_line = 0x0000; dmap->mono_venus.horiz_count_load = 0x0000; dmap->mono_venus.vert_end_sync = 0x02; dmap->mono_venus.vert_end_blank = 0x29; dmap->mono_venus.vert_start_blank = 0x0209; dmap->mono_venus.vert_total = 0x020c; dmap->mono_venus.vert_count_load = 0x0000; dmap->mono_venus.vert_interrupt = 0x0000; dmap->mono_venus.y_zoom = 0x01; dmap->mono_venus.soft_register = 0xf0; dmap->mono_venus.control3 = 0xf3; dmap->mono_venus.control1 = 0xf3; } /*"tcs_init_ntsc" * * Initialize venus chips on SBus TCS Card to operate at NTSC scan rates. * (30Hz interlaced 640 x 480.) * If a genlock device is connected external (genlock) sync will be used. */ tcs_init_ntsc(softc) SOFTC *softc; /* characteristics for our unit. */ { Tcs_Device_Map *dmap; /* -> device register area on TCS card. */ u_int io_conf; /* Value to load into io config register. */ u_int io_gen; /* Value to load into io general register. */ dmap = softc->device_tcs; softc->timing_regimen = NTSC_TIMING; softc->width = 640; softc->height = 480; softc->linebytes1 = softc->width / 8; softc->linebytes8 = softc->width; softc->linebytes32 = softc->width * 4; if ( dmap->tc_venus.io_general & VENUS_TCS_MODEL_A ) { io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ? 0x007c : 0x0074; io_conf = 0x00df; } else { io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ? 0x78bc : 0x78f4; io_conf = 0x1fdf; } /* * Initialize venus chip 0 which affects Brooktree operations and color * buffer operations. Configure the system as a 24-bit true color card. */ dmap->tc_venus.control1 = 0x00; dmap->tc_venus.control2 = 0x00; dmap->tc_venus.control3 = 0x00; dmap->tc_venus.control4 = 0x00; dmap->tc_venus.refresh_interval = 0x70; /* Set refresh interval. */ dmap->tc_venus.control1 = 0x11; dmap->tc_venus.control2 = 0x00; dmap->tc_venus.control3 = 0x7b; dmap->tc_venus.control4 = 0x00; dmap->tc_venus.io_general = io_gen; dmap->tc_venus.io_config = io_conf; dmap->tc_venus.display_start = 0x00000000; dmap->tc_venus.half_row_incr = 0x00000100; dmap->tc_venus.display_pitch = 0x00000140; dmap->tc_venus.cas_mask = 0x7f; dmap->tc_venus.horiz_latency = 0x00; dmap->tc_venus.horiz_end_sync = 0x000d; dmap->tc_venus.horiz_half_line = 0x0060; dmap->tc_venus.horiz_count_load = 0x0000; dmap->tc_venus.vert_end_sync = 0x02; dmap->tc_venus.vert_end_blank = 0x12; dmap->tc_venus.vert_start_blank = 0x0102; dmap->tc_venus.vert_count_load = 0x0000; dmap->tc_venus.vert_interrupt = 0x0103; if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) { dmap->tc_venus.horiz_end_blank = 0x001c; dmap->tc_venus.horiz_start_blank = 0x00bc; dmap->tc_venus.horiz_total = 0x00c1; dmap->tc_venus.vert_total = 0x0105; } else { dmap->tc_venus.horiz_end_blank = 0x001b; dmap->tc_venus.horiz_start_blank = 0x00bb; dmap->tc_venus.horiz_total = 0x00ff; dmap->tc_venus.vert_total = 0x01ff; } dmap->tc_venus.y_zoom = 0x01; dmap->tc_venus.soft_register = 0xf0; dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET; dmap->tc_venus.io_general = io_gen; if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) { dmap->tc_venus.control3 = 0x7b; dmap->tc_venus.control1 = 0xf9; } else { dmap->tc_venus.control3 = 0xfb; dmap->tc_venus.control1 = 0xf1; } /* * Initialize venus chip 1 which affects 1-bit monochrome and selection * memory operations. */ dmap->mono_venus.control1 = 0x00; dmap->mono_venus.control2 = 0x00; dmap->mono_venus.control3 = 0x00; dmap->mono_venus.control4 = 0x00; dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */ dmap->mono_venus.control1 = 0x13; dmap->mono_venus.io_config = 0x0000; dmap->mono_venus.display_start = 0x00000000; dmap->mono_venus.half_row_incr = 0x00000080; dmap->mono_venus.display_pitch = 0x00000050; dmap->mono_venus.cas_mask = 0x3f; dmap->mono_venus.horiz_latency = 0x00; dmap->mono_venus.horiz_end_sync = 0x000d; dmap->mono_venus.horiz_end_blank = 0x001b; dmap->mono_venus.horiz_start_blank = 0x00bb; dmap->mono_venus.horiz_total = 0x00ff; dmap->mono_venus.horiz_half_line = 0x0000; dmap->mono_venus.horiz_count_load = 0x0000; dmap->mono_venus.vert_end_sync = 0x02; dmap->mono_venus.vert_end_blank = 0x12; dmap->mono_venus.vert_start_blank = 0x0102; dmap->mono_venus.vert_total = 0x01ff; dmap->mono_venus.vert_count_load = 0x0000; dmap->mono_venus.vert_interrupt = 0x0000; dmap->mono_venus.y_zoom = 0x01; dmap->mono_venus.soft_register = 0xf0; dmap->mono_venus.control3 = 0xfb; if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) { dmap->mono_venus.control1 = 0xfb; } else { dmap->mono_venus.control1 = 0xf3; } } /*"tcs_init_pal" * * Initialize venus chips on SBus TCS Card to operate at PAL scan rates. * (25Hz interlaced 768 x 592.) * If a genlock device is connected external (genlock) sync will be used. */ tcs_init_pal(softc) SOFTC *softc; /* characteristics for our unit. */ { Tcs_Device_Map *dmap; /* -> device register area on TCS card. */ u_int io_conf; /* Value to load into io config register. */ u_int io_gen; /* Value to load into io general register. */ dmap = softc->device_tcs; softc->timing_regimen = PAL_TIMING; softc->width = 768; softc->height = 592; softc->linebytes1 = softc->width / 8; softc->linebytes8 = softc->width; softc->linebytes32 = softc->width * 4; if ( dmap->tc_venus.io_general & VENUS_TCS_MODEL_A ) { io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ? 0x00bc : 0x00b4; io_conf = 0x00df; } else { io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ? 0x787c : 0x78f4; io_conf = 0x1fdf; } /* * Initialize venus chip 0 which affects Brooktree operations and color * buffer operations. Configure the system as a 24-bit true color card. */ dmap->tc_venus.control1 = 0x00; dmap->tc_venus.control2 = 0x00; dmap->tc_venus.control3 = 0x00; dmap->tc_venus.control4 = 0x00; dmap->tc_venus.refresh_interval = 0x70; dmap->tc_venus.control1 = 0x11; dmap->tc_venus.control2 = 0x00; dmap->tc_venus.control3 = 0x00; dmap->tc_venus.control4 = 0x00; dmap->tc_venus.io_general = io_gen; dmap->tc_venus.io_config = io_conf; dmap->tc_venus.display_start = 0x00000000; dmap->tc_venus.half_row_incr = 0x00000100; dmap->tc_venus.display_pitch = 0x00000180; dmap->tc_venus.cas_mask = 0x7f; dmap->tc_venus.horiz_latency = 0x00; dmap->tc_venus.horiz_end_sync = 0x0010; dmap->tc_venus.horiz_end_blank = 0x0024; dmap->tc_venus.horiz_start_blank = 0x00e4; dmap->tc_venus.horiz_total = 0x00ea; dmap->tc_venus.horiz_half_line = 0x0075; dmap->tc_venus.horiz_count_load = 0x0000; dmap->tc_venus.vert_end_sync = 0x02; dmap->tc_venus.vert_end_blank = 0x16; dmap->tc_venus.vert_start_blank = 0x0136; dmap->tc_venus.vert_total = 0x0138; dmap->tc_venus.vert_count_load = 0x0000; dmap->tc_venus.vert_interrupt = 0x0137; dmap->tc_venus.y_zoom = 0x01; dmap->tc_venus.soft_register = 0xf0; dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET; dmap->tc_venus.io_general = io_gen; if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) { dmap->tc_venus.control3 = 0x7b; dmap->tc_venus.control1 = 0xf9; } else { dmap->tc_venus.control3 = 0xfb; dmap->tc_venus.control1 = 0xf1; } /* * Initialize venus chip 1 which affects 1-bit monochrome and selection * memory operations. */ dmap->mono_venus.control1 = 0x00; dmap->mono_venus.control2 = 0x00; dmap->mono_venus.control3 = 0x00; dmap->mono_venus.control4 = 0x00; dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */ dmap->mono_venus.control1 = 0x13; dmap->mono_venus.io_config = 0x0000; dmap->mono_venus.display_start = 0x00000000; dmap->mono_venus.half_row_incr = 0x00000080; dmap->mono_venus.display_pitch = 0x00000060; dmap->mono_venus.cas_mask = 0x3f; dmap->mono_venus.horiz_latency = 0x00; dmap->mono_venus.horiz_end_sync = 0x0010; dmap->mono_venus.horiz_end_blank = 0x0024; dmap->mono_venus.horiz_start_blank = 0x00e4; dmap->mono_venus.horiz_total = 0x00ff; dmap->mono_venus.horiz_half_line = 0x0075; dmap->mono_venus.horiz_count_load = 0x0000; dmap->mono_venus.vert_end_sync = 0x02; dmap->mono_venus.vert_end_blank = 0x16; dmap->mono_venus.vert_start_blank = 0x0136; dmap->mono_venus.vert_total = 0x01ff; dmap->mono_venus.vert_count_load = 0x0000; dmap->mono_venus.vert_interrupt = 0x0000; dmap->mono_venus.y_zoom = 0x01; dmap->mono_venus.soft_register = 0xf0; dmap->mono_venus.control3 = 0xfb; if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) { dmap->mono_venus.control1 = 0xfb; } else { dmap->mono_venus.control1 = 0xf3; } } /*"tcs_putcmap" * * Local routine to set the color map values for either the 24-bit or the * monochrome frame buffer for RASTEROPS_TCS card. In addition to real * lookup table manipulation, emulation of 8-bit indexed color maps is * done for 24-bit mode. * * Note that for this card the lut load must occur during vertical retrace, * so the vertical retrace interrupt is used. Since the SPARCstation is really * quite fast relative to the loading of the lut we always load the entire lut. * This is possible because we maintain the whole lut in cmap_xxx within softc. * * = 0 if success * = error indication otherwise */ static int tcs_putcmap( softc, cmap ) SOFTC *softc; /* -> characteristics for our unit. */ struct fbcmap *cmap; /* -> where to get color map (ioctl data area). */ { u_int count; /* # of color map entries to set. */ int force_update; /* Indicates if access real luts. */ u_int index; /* Index: entry in cmap_xxx to access. */ int n_entry; /* Index: ordinal # of current map entry. */ int plane_group; /* Top 7 bits of index = plane group. */ /* * Verify we need to actually move some data. Initialize variables from * caller's parameters, etc. If the plane group is zero, default an * appropriate plane group. */ if ( (cmap->count == 0) || !cmap->red || !cmap->green || !cmap->blue ) { return 0; } count = cmap->count; index = cmap->index & PIX_ALL_PLANES; if (index+count > TC_CMAP_SIZE) { return EINVAL; } force_update = cmap->index & PR_FORCE_UPDATE; if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) ) { plane_group = softc->pg_enabled[PIXPG_24BIT_COLOR] ? PIXPG_24BIT_COLOR : PIXPG_8BIT_COLOR; } /* If interruts are enabled disable so we can update things in peace. */ #ifdef NOTDEF if ( softc->device_tcs->tc_venus.control4 & VENUS_VERT_INT_ENA ) { softc->device_tcs->tc_venus.control4 = 0; softc->device_tcs->tc_venus.status = 0; } #endif NOTDEF /* Move caller's data, there are 4 cases: kernel space and user space * in overlay or colormap luts. * Note we move the data into the proper index location RASTEROPS_TCS * (see note 1 above.) */ if ( plane_group == PIXPG_OVERLAY ) { if (softc->tc1d.flags & CG8_KERNEL_UPDATE) { softc->tc1d.flags &= ~CG8_KERNEL_UPDATE; BCOPY( cmap->red, &softc->omap_red[index], count ); BCOPY(cmap->green,&softc->omap_green[index],count); BCOPY(cmap->blue,&softc->omap_blue[index], count ); } else { if ( COPYIN(cmap->red,&softc->omap_red[index], count ) || COPYIN(cmap->green,&softc->omap_green[index], count) || COPYIN( cmap->blue, &softc->omap_blue[index], count ) ) { return EFAULT; } } } else { if (softc->tc1d.flags & CG8_KERNEL_UPDATE) { softc->tc1d.flags &= ~CG8_KERNEL_UPDATE; BCOPY( cmap->red, &softc->cmap_red[index], count ); BCOPY( cmap->green, &softc->cmap_green[index], count); BCOPY( cmap->blue, &softc->cmap_blue[index], count ); } else { if ( COPYIN( cmap->red, &softc->cmap_red[index], count ) || COPYIN(cmap->green,&softc->cmap_green[index], count) || COPYIN( cmap->blue, &softc->cmap_blue[index], count ) ) { return EFAULT; } } } /* If we are doing cg8 emulation, and hardware update is not forced, * set 8-bit index emulation color table entries for 24-bit buffer. * (The check for the 8-bit plane group is here in case the kernel * knows 8-bit hardware exists, but the driver did not export it to * Sunview.) */ if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0) && ((plane_group==PIXPG_24BIT_COLOR) || (plane_group==PIXPG_8BIT_COLOR)) ) { for (n_entry = 0; n_entry < count; n_entry++, index++) { softc->em_red[index] = softc->cmap_red[index]; softc->em_green[index] = softc->cmap_green[index]; softc->em_blue[index] = softc->cmap_blue[index]; } } /* * Set entries in actual Brooktree lookup tables for 8/24-bit buffer. */ else if ( plane_group==PIXPG_24BIT_COLOR || plane_group==PIXPG_8BIT_COLOR ) { softc->tc1d.flags |= CG8_24BIT_CMAP; softc->device_tcs->tc_venus.control4 = 5; } /* * Set entries in actual Brooktree lookup tables for monochrome overlay. */ else if ( plane_group == PIXPG_OVERLAY ) { if ( softc->pg_enabled[PIXPG_24BIT_COLOR] != 0 ) { softc->tc1d.flags |= CG8_OVERLAY_CMAP; softc->device_tcs->tc_venus.control4 = 5; } } else { printf("Illegal plane group %d encountered\n", plane_group); return EINVAL; } return 0; } /*"tcs_update_cmap" * * For a TCS card update the color maps (color and overlay) if * required. This routine is called from cgeightpoll() when * a vertical interrupt is detected on a tcs board. It does * not clear the interrupt, as this is done in cgeightpoll(). */ static tcs_update_cmap(softc) SOFTC *softc; /* -> to characteristics for our unit. */ { Tcs_Device_Map *device_tcs; /* Pointer to tcs device register area. */ int n_entry; /* Index: entry in cmap_xxx now accessing. */ device_tcs = softc->device_tcs; if ( softc->tc1d.flags & CG8_24BIT_CMAP ) { device_tcs->dac.ram_write_addr = 0; for (n_entry=0; n_entry < TC_CMAP_SIZE; n_entry++) { device_tcs->dac.color = softc->cmap_red[n_entry]; device_tcs->dac.color = softc->cmap_green[n_entry]; device_tcs->dac.color = softc->cmap_blue[n_entry]; } softc->tc1d.flags &= ~CG8_24BIT_CMAP; } if ( softc->tc1d.flags & CG8_OVERLAY_CMAP ) { for (n_entry=0; n_entry < TC_OMAP_SIZE; n_entry++) { if ( !softc->sw_cursor_color_frozen || n_entry != 2 ) { device_tcs->dac.overlay_write_addr = translate_omap[n_entry]; device_tcs->dac.overlay = softc->omap_red[n_entry]; device_tcs->dac.overlay = softc->omap_green[n_entry]; device_tcs->dac.overlay = softc->omap_blue[n_entry]; } } softc->tc1d.flags &= ~CG8_OVERLAY_CMAP; } } /*"x_build_mmap_info" * * Local routine to build table used to memory map frame buffers into * user space (as opposed to kernel space which is done using fb_mapin). * Note the order of mapping will properly map a traditional cg8 card * (if other extraneous plane groups are not present.) */ x_build_mmap_info( softc ) SOFTC *softc; /* -> characteristics for this instance. */ { int mmi; /* Index: number of entries in mmap_info set up. */ Mmap_Info *mmp; /* Cursor: entry in mmap_info to initialize. */ u_int offset; /* Offset into virtual memory of next fb. */ mmi = 0; mmp = softc->mmap_info; offset = 0; if ( softc->pg_enabled[PIXPG_OVERLAY] ) { mmp->group = PIXPG_OVERLAY; mmp->bgn_offset = offset; mmp->end_offset = offset + softc->fb_mono_mmap_size; mmp->sbus_delta = softc->fb_mono_sbus_delta; offset = mmp->end_offset; mmp++; mmi++; } if ( softc->pg_enabled[PIXPG_OVERLAY_ENABLE] ) { mmp->group = PIXPG_OVERLAY_ENABLE; mmp->bgn_offset = offset; mmp->end_offset = offset + softc->fb_sel_mmap_size; mmp->sbus_delta = softc->fb_sel_sbus_delta; offset = mmp->end_offset; mmp++; mmi++; } if ( softc->pg_enabled[PIXPG_24BIT_COLOR] ) { mmp->group = PIXPG_24BIT_COLOR; mmp->bgn_offset = offset; mmp->end_offset = offset + softc->fb_tc_mmap_size; mmp->sbus_delta = softc->fb_tc_sbus_delta; offset = mmp->end_offset; mmp++; mmi++; } if ( softc->pg_enabled[PIXPG_8BIT_COLOR] ) { mmp->group = PIXPG_8BIT_COLOR; mmp->bgn_offset = offset; mmp->end_offset = offset + softc->fb_8bit_mmap_size; mmp->sbus_delta = softc->fb_8bit_sbus_delta; offset = mmp->end_offset; mmp++; mmi++; } if ( softc->pg_enabled[PIXPG_VIDEO_ENABLE] ) { mmp->group = PIXPG_VIDEO_ENABLE; mmp->bgn_offset = offset; mmp->end_offset = offset + softc->fb_video_mmap_size; mmp->sbus_delta = softc->fb_video_sbus_delta; offset = mmp->end_offset; mmp++; mmi++; } softc->mmap_count = mmi; } /*"x_g_attr" * * Local routine to return the characteristics (attributes) associated * with the current frame buffer. (Called by tcone_ioctl). * * = 0 if success * = error indication otherwise */ static int x_g_attr( softc, gattr ) SOFTC *softc; /* -> characteristics for our unit. */ struct fbgattr *gattr; /* -> where to put attributes(data area from ioctl) */ { /* Return the characteristics of the frame buffer being emulated. Fill in * the characteristics which were received from the PROMs. */ if ( softc->pg_enabled[PIXPG_24BIT_COLOR] ) { *gattr = tc1_attrdefault; gattr->fbtype.fb_height = softc->height; gattr->fbtype.fb_width = softc->width; gattr->fbtype.fb_size = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size + softc->fb_tc_mmap_size; } else { *gattr = cg4_attrdefault; gattr->fbtype.fb_height = softc->height; gattr->fbtype.fb_width = softc->width; gattr->fbtype.fb_size = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size + softc->fb_8bit_mmap_size; } return 0; } /*"x_g_emulation_mode" * * Local routine to get emulation mode of driver operations. * * = 0 if success * = error indication otherwise */ static int x_g_emulation_mode( softc, mode ) SOFTC *softc; /* -> characteristics for our unit. */ Pipio_Emulation *mode; /* -> where to put mode of emulation. */ { int pgi; /* Index: next entry in pg_enabled to access. */ /* * Set up plane group information based on softc entries. * Get timing regimen. */ for ( pgi = 0; pgi < FB_NPGS; pgi++ ) { if ( softc->pg_enabled[pgi] ) { mode->plane_groups[pgi] = 1; } else if ( softc->pg_possible[pgi] ) { mode->plane_groups[pgi] = 2; } else { mode->plane_groups[pgi] = 0; } } mode->timing = softc->timing_regimen; return 0; } /*"x_getcmap" * * Local routine to return color map values for either the 24-bit or the * monochrome frame buffer. In addition to real lookup table manipulation, * emulation of 8-bit indexed color maps is done for 24-bit mode. * (Called by tcone_ioctl). * * = 0 if success * = error indication otherwise */ static int x_getcmap( softc, cmap ) SOFTC *softc; /* -> characteristics for our unit. */ struct fbcmap *cmap; /* -> where to return the color map values. */ { u_int count; /* # of color map entries to return. */ Tc1_Device_Map *device_reg; /* Pointer to the Brooktrees. */ Tcs_Device_Map *device_tcs; /* Pointer to the TCS card device regs. */ int force_update; /* Indicates if should access real luts. */ u_int index; /* Index of first entry to access. */ int n_entry; /* Loop index: current color map entry. */ int plane_group; /* Top 7 bits of index = plane group. */ u_char tmp_blue[TC_CMAP_SIZE]; /* Temporary for blue values. */ u_char tmp_green[TC_CMAP_SIZE]; /* Temporary for green values. */ u_char tmp_red[TC_CMAP_SIZE]; /* Temporary for red values. */ /* * Initialize variables from caller's parameters, etc. Verify we need to * actually move some data. A zero plane group defaults based on emulation * type. */ count = cmap->count; if ( (count == 0) || !cmap->red || !cmap->green || !cmap->blue ) { return 0; } index = cmap->index & PIX_ALL_PLANES; if (index+count > TC_CMAP_SIZE) { return EINVAL; } force_update = cmap->index & PR_FORCE_UPDATE; if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) ) { plane_group = softc->pg_enabled[PIXPG_24BIT_COLOR] ? PIXPG_24BIT_COLOR : PIXPG_8BIT_COLOR; } /* If there is no 8-bit frame buffer, and an update is not forced, * get 8-bit index emulation color table entries for 24-bit buffer. */ if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0) && (plane_group == PIXPG_24BIT_COLOR) ) { if ( COPYOUT( &softc->em_red[index], cmap->red, count) || COPYOUT( &softc->em_green[index], cmap->green, count) || COPYOUT( &softc->em_blue[index], cmap->blue, count) ) { return EFAULT; } } /* Get entries for the actual Brooktree lookup tables for 8/24-bit buffer. */ else if ( plane_group == PIXPG_24BIT_COLOR || plane_group == PIXPG_8BIT_COLOR ) { switch(softc->fb_model) { default: case RASTEROPS_TC: case RASTEROPS_TCP: device_reg = softc->device_reg; device_reg->dacs.bt457.all_address = index; for (n_entry = 0; n_entry < count; n_entry++) { tmp_red[n_entry] = device_reg->dacs.bt457.red_color; tmp_green[n_entry] = device_reg->dacs.bt457.green_color; tmp_blue[n_entry] = device_reg->dacs.bt457.blue_color; } break; case RASTEROPS_TCS: device_tcs = softc->device_tcs; device_tcs->dac.ram_read_addr = index; for (n_entry = 0; n_entry < count; n_entry++) { tmp_red[n_entry] = device_tcs->dac.color; tmp_green[n_entry] = device_tcs->dac.color; tmp_blue[n_entry] = device_tcs->dac.color; } break; case RASTEROPS_TCL: break; } if ( COPYOUT( tmp_red, cmap->red, count) || COPYOUT( tmp_green, cmap->green, count) || COPYOUT( tmp_blue, cmap->blue, count) ) { return EFAULT; } } /* * Get entries for the actual Brooktree lookup tables for monochrome * overlay. (A shadow color map is accessed rather than hardware.) */ else if (plane_group == PIXPG_OVERLAY) { if ( COPYOUT( &softc->omap_red[index], cmap->red, count) || COPYOUT( &softc->omap_green[index], cmap->green, count) || COPYOUT( &softc->omap_blue[index], cmap->blue, count) ) { return EFAULT; } } else { printf("Illegal plane group %d encountered\n", plane_group); return EINVAL; } return 0; } /*"x_g_fb_info" * * Local routine to return a description of the frame buffers supported * by this device instance. The plane groups are processed in order of * their virtual address so that total_mmap_bytes can be properly calculated. * * = 0 if success * = error indication otherwise */ static int x_g_fb_info( softc, info ) SOFTC *softc; /* -> characteristics for our unit. */ Pipio_Fb_Info *info; /* -> where to place frame buffer info. */ { int fbi; /* Index: next frame buffer description to move. */ int mmi; /* Index: # of mmap_info entry looking at. */ Mmap_Info *mmp; /* Cursor: mmap_info entry looking at. */ fbi = 0; for ( mmi=0, mmp=softc->mmap_info; mmi < softc->mmap_count; mmi++, mmp++ ) { info->fb_descriptions[fbi].group = mmp->group; info->fb_descriptions[fbi].width = softc->width; info->fb_descriptions[fbi].height = softc->height; info->fb_descriptions[fbi].mmap_size = mmp->end_offset-mmp->bgn_offset; info->fb_descriptions[fbi].mmap_offset = mmp->bgn_offset; switch(mmp->group) { case PIXPG_24BIT_COLOR: info->fb_descriptions[fbi].depth = 32; info->fb_descriptions[fbi].linebytes = softc->linebytes32; break; case PIXPG_8BIT_COLOR: info->fb_descriptions[fbi].depth = 8; info->fb_descriptions[fbi].linebytes = softc->linebytes8; break; default: info->fb_descriptions[fbi].depth = 1; info->fb_descriptions[fbi].linebytes = softc->linebytes1; break; } fbi++; } info->frame_buffer_count = softc->mmap_count; info->total_mmap_size = softc->mmap_info[softc->mmap_count-1].end_offset; return 0; } #if NWIN > 0 /*"x_g_pixrect" * * Local routine to return the pixrect structure for use by the kernel to * access this device instance. * * = 0 if success * = error indication otherwise */ static int x_g_pixrect( softc, dev, fbpr ) SOFTC *softc; /* -> characteristics for our unit. */ dev_t dev; /* = device number. */ struct fbpixrect *fbpr; /* -> where to return pixrect info (ioctl data)*/ { struct cg8_data *cg8d; /* Pointer to pixrect private data area. */ Pipio_Fb_Info fb_info; /* Frame buffer info about this device instance. */ struct cg4fb *fbp; /* Index: fb in pixrect private area now init'ing */ int i; /* Index: # of frame buffer now initializing. */ u_int initplanes; /* Plane group/mask for current plane group. */ Pixrect *tmppr; /* Pointer to pixrect (to call cg8_putattributes). */ tmppr = &softc->pr; /* "Allocate" pixrect by pointing into our instance's private storage (the * kernel will use this pixrect, so access is certainly possible!). Set the * private data pointer. */ fbpr->fbpr_pixrect = &softc->pr; softc->pr.pr_data = (caddr_t) & softc->tc1d; /* Initialize pixrect area within our software characteristics area * now that we are allocated. Also default driver's private data. */ softc->pr.pr_ops = &tcp_ops; softc->pr.pr_size.x = softc->width; softc->pr.pr_size.y = softc->height; softc->tc1d.flags = 0; softc->tc1d.planes = 0; softc->tc1d.fd = minor (dev); /* Get the information about the frame buffers and memories this instance * supports. Then for each frame buffer provided by this device, initialize * its characteristics (other than image pointers) in the pixrect private * data area. */ x_g_fb_info(softc, &fb_info); softc->tc1d.num_fbs = fb_info.frame_buffer_count; DEBUGF(4, ("ioctl GPIXRECT num fbs = %d\n", softc->tc1d.num_fbs)); for (fbp=softc->tc1d.fb, i=0; i < fb_info.frame_buffer_count; fbp++, i++) { fbp->group = fb_info.fb_descriptions[i].group; fbp->depth = fb_info.fb_descriptions[i].depth; switch(fb_info.fb_descriptions[i].depth) { case 1: fbp->mprp.mpr.md_linebytes = softc->linebytes1; break; case 8: fbp->mprp.mpr.md_linebytes = softc->linebytes8; break; case 32: fbp->mprp.mpr.md_linebytes = softc->linebytes32; break; default: printf("Error unsupported depth %d encountered for plane group %i in GPIXRECT\n", fb_info.fb_descriptions[i].depth, fb_info.fb_descriptions[i].group); break; } fbp->mprp.mpr.md_offset.x = 0; fbp->mprp.mpr.md_offset.y = 0; fbp->mprp.mpr.md_primary = 0; fbp->mprp.mpr.md_flags = fb_info.fb_descriptions[i].depth != 1 ? MP_DISPLAY | MP_PLANEMASK : MP_DISPLAY; fbp->mprp.planes = fb_info.fb_descriptions[i].depth != 1 ? PIX_ALL_PLANES : 0; DEBUGF(5, ("ioctl GPIXRECT group %d depth %d\n", fbp->group, fbp->depth)); } /* The majority of the pixrect structure is now set up, so initialize the * image pointers and perform any memory initializations which are * necessary. We loop backwards to guarantee that the last frame buffer * accessed is the monochrome. */ for (cg8d = cg8_d(tmppr), i = fb_info.frame_buffer_count-1; i >= 0; i--) { switch ( cg8d->fb[i].group ) { case PIXPG_OVERLAY: initplanes = PIX_GROUP(PIXPG_OVERLAY); cg8_putattributes (tmppr, &initplanes); DEBUGF(5, ("ioctl GPIXRECT monochrome pr_depth = %d\n", tmppr->pr_depth)); cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image = (short *) softc->fb_mono; pr_rop (tmppr, 0, 0, softc->pr.pr_size.x, softc->pr.pr_size.y, PIX_SRC, (Pixrect *) 0, 0, 0); break; case PIXPG_OVERLAY_ENABLE: initplanes = PIX_GROUP(PIXPG_OVERLAY_ENABLE); cg8_putattributes (tmppr, &initplanes); DEBUGF(5, ("ioctl GPIXRECT selection pr_depth = %d\n", tmppr->pr_depth)); cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image = (short *) softc->fb_sel; pr_rop(tmppr, 0, 0, softc->pr.pr_size.x, softc->pr.pr_size.y, PIX_SRC | PIX_COLOR (1), (Pixrect *) 0, 0, 0); break; case PIXPG_8BIT_COLOR: cg8d->flags |= CG8_EIGHT_BIT_PRESENT; cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image = (short *) softc->fb_8bit; cg8d->mprp.mpr.md_linebytes = 0; break; case PIXPG_24BIT_COLOR: cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image = (short *) -1; cg8d->mprp.mpr.md_linebytes = 0; break; case PIXPG_VIDEO_ENABLE: cg8d->flags |= CG8_PIP_PRESENT; cg8d->fb[i].mprp.mpr.md_image = cg8_d (tmppr)->mprp.mpr.md_image = (short *) -1; cg8d->mprp.mpr.md_linebytes = 0; break; } } /* Enable video display. */ switch(softc->fb_model) { default: mfb_set_video(&softc->device_reg->sun_mfb_reg, FBVIDEO_ON); break; case RASTEROPS_TCS: break; } return 0; } #endif NWIN > 0 /*"x_g_type" * * Local routine to return the type of the active frame buffer and its * resolution, etc. * * = 0 if success * = error indication otherwise */ static int x_g_type( softc, fb ) SOFTC *softc; /* -> characteristics for our unit. */ struct fbtype *fb; /* -> where to put type info (ioctl data area). */ { /* Return information based on the type of frame buffer being emulated. */ if ( softc->pg_enabled[PIXPG_24BIT_COLOR] ) { /* If we are emulating a Sun monochrome BW2 return that data, otherwise * return the actual information about the current frame buffer. */ switch (tc1_attrdefault.sattr.emu_type) { case FBTYPE_SUN2BW: *fb = tc1typedefault; fb->fb_height = softc->height; fb->fb_width = softc->width; fb->fb_size = softc->fb_mono_mmap_size; break; default: *fb = tc1_attrdefault.fbtype; fb->fb_height = softc->height; fb->fb_width = softc->width; fb->fb_size = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size + softc->fb_8bit_mmap_size + softc->fb_tc_mmap_size; break; } } else { *fb = cg4_attrdefault.fbtype; fb->fb_height = softc->height; fb->fb_width = softc->width; fb->fb_size = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size + softc->fb_8bit_mmap_size; } return 0; } /*"x_s_emulation_mode" * * Local routine to set emulation mode for driver operations. * Use the mode specification to determine how to configure the * system. * * = 0 if success * = error indication otherwise */ static int x_s_emulation_mode( softc, mode ) SOFTC *softc; /* characteristics for our unit. */ Pipio_Emulation *mode; /* -> mode of emulation to set. */ { int color; /* Index: color to put into look-up table. */ Tc1_Device_Map *device_reg; /* Quick pointer to device registers. */ Tcs_Device_Map *device_tcs; /* Quick pointer to tcs device registers. */ int pgi; /* Index: entry in pg_enabled to access. */ /* * Process the emulation timing and size specified by the caller. * If our device is not capable of providing the specified timing * or size return an error. */ switch ( mode->timing ) { case NATIVE_TIMING: if ( softc->fb_model == RASTEROPS_TCS ) { tcs_init_native(softc); } break; case NTSC_TIMING: if ( softc->fb_model != RASTEROPS_TCS ) return EINVAL; tcs_init_ntsc(softc); break; case PAL_TIMING: if ( softc->fb_model != RASTEROPS_TCS ) return EINVAL; tcs_init_pal(softc); break; default: return EINVAL; } /* * Set only the plane groups specified by the caller. */ for ( pgi = 0; pgi < FB_NPGS; pgi++ ) { if ( mode->plane_groups[pgi] == 1 ) { if ( softc->pg_possible[pgi] == 0 ) return EINVAL; softc->pg_enabled[pgi] = 1; } else { softc->pg_enabled[pgi] = 0; } } /* * If 24-bit memory is enabled, reset true color ramp in luts. */ if ( softc->pg_enabled[PIXPG_24BIT_COLOR] ) { switch(softc->fb_model) { default: device_reg = softc->device_reg; device_reg->dacs.bt457.all_address = 0; for (color = 0; color < TC_CMAP_SIZE; color++) { device_reg->dacs.bt457.red_color = color; device_reg->dacs.bt457.green_color = color; device_reg->dacs.bt457.blue_color = color; } break; case RASTEROPS_TCS: device_tcs = softc->device_tcs; device_tcs->dac.ram_write_addr = 0; for (color = 0; color < TC_CMAP_SIZE; color++) { device_tcs->dac.color = color; device_tcs->dac.color = color; device_tcs->dac.color = color; } break; case RASTEROPS_TCL: break; } } /* * Recompute the memory mapping information, so new configuration * will be mapped properly. */ x_build_mmap_info(softc); return 0; } /*"x_s_map_slot" * * Local routine to return information using test ioctl entry * point. * * = 0 if success * = error indication otherwise */ static int x_s_map_slot( softc, phys_addr ) SOFTC *softc; /* -> characteristics for our unit. */ u_int *phys_addr; /* -> where to put attributes(data area from ioctl) */ { addr_t reg; /* Mapping point for region. */ if ( softc->test_basepage ) return 0; if ( !(reg = (addr_t)map_regs( (addr_t)*phys_addr, (u_int)0x1000, 0x01)) ) { return -1; } softc->test_basepage = fbgetpage(reg); return 0; } /* * OVERVIEW OF TC BOARD HARDWARE * * (1) The SBus TC Card product * contains two frame buffers. One frame buffer is 24 bits deep, * and its pixel values are treated as 3 8-bit indices into 3 separate * 8-in-8-out lookup tables to yield 8 bits for each of the red, green, * and blue guns of the monitor. Each of the 8-in-8-out lookup tables * is loaded with a linear ramp (or possibly a gamma corrected ramp) * yielding a true color display of pixel values. * * +------------+ * | | +---+ * | |---/--->|vlt|---/---> red * | 24 | 8 +---+ 8 * | + * | bit | +---+ * ---/--->| |---/--->|vlt|---/---> green * 24 | frame | 8 +---+ 8 * | + * | buffer | +---+ * | |---/--->|vlt|---/---> blue * | | 8 +---+ 8 * +------------+ * * (2) The other frame buffer is monochrome and is 1 bit deep. * Its pixel values are treated as inputs into the overlay * of the 8-in-8-out lookup tables associated with the * 24-bit frame buffer. Thus, the 1-bit frame buffer appears * as an overlay over the 24-bit frame buffer on the screen. * For each pixel, if the overlay is visible the 24-bit value * is not and vice-versa. Whether the overlay is visible or not * is controlled by a separate 1-bit deep selection memory. The * output of this memory is the input for the overlay transparency * bit on each of the 8-in-8-out lookup tables. Thus, the value in * the selection memory associated with a pixel specifies which * value is displayed for a given pixel, the one from the 24-bit * memory or the monochrome overlay. * * +--------+ +--------+ * | | +-----------+ | | * | 1 |--/-->| red vlt |<--/--| 1 | * | | 1 +-----------+ 1 | | * | bit | +-----------+ | bit | * ---/--->| |--/-->| green vlt |<--/--| | * 1 | frame | 1 +-----------+ 1 |select. | * | | +-----------+ | | * | buffer |--/-->| blue vlt |<--/--| memory | * | | 1 +-----------+ 1 | | * +--------+ +--------+ * * */ /* * INDEXED COLOR MAP EMULATION * * The SBus TCP support provides emulation of indexed color maps for both * the 24-bit true color frame buffer and the monochrome overlay frame buffer. * This support is done jointly by this kernel pixrect driver (tcone.c) and * the normal pixrect driver colormap support (tc1_colormap.c). * * For indexed color map emulation in the 24-bit buffer the kernel level * driver for the tc1 maintains a main memory color map with 256 entries. When * pixels are written or read in emulation mode the entries in this color map * are accessed to perform a mapping between the 8-bit value used by the user, * and the 24-bit true color value actually written to frame buffer memory. * This mapping is performed by routines in this module, which are called from * other modules (e.g., cg8_getput.c). In emulation mode the actual lookup * table entries in the 3 Brooktree 457 RAMDACs are not touched, only the * separate main memory color map. However, it is also possible to actually * access the look up table entries in the RAMDACs. This is done by specifying * the PR_FORCE_UPDATE flag in the plane parameter passed to cg8_getcolormap * or cg8_putcolormap. * * The monochrome overlay emulation is handled in tc1_colormap.c. It is also * possible to by-pass the emulation and actually write the four overlay color * values. */ /*"" * PHYSICAL TO VIRTUAL MEMORY MAPPING FOR DEVICES ON THE SBus TC Card * * This driver performs mapping for the devices on the SBus TC Card. The * mapping makes the physical devices appear to be contiguous with each other * within the virtual space * * Virtual Space Physical Space * * Physical Offset from * address: device registers * xx000000+------------------+ * | On-board PROMs | * +------------------+ * * xx400000+------------------+00000000 * | Device registers | * Offset from device +------------------+ * registers * 00000000+------------------+ xx800000+------------------+00400000 * | Monochrome buffer| | True color buffer| * 00020000+------------------+ +------------------+ * | Selection memory | * 00040000+------------------+ xxC00000+------------------+00800000 * | True color buffer| | Monochrome buffer| * 00435000+------------------+ +------------------+ * | Device registers | * +------------------+ xxD00000+------------------+00900000 * | Selection memory | * +------------------+ * * The offset from the device registers in virtual space is defined near the * beginning of this file in constants of the form TCP_xxx_VADDR_OFFSET, where * xxx is MONOCHROME, TRUE_COLOR, etc. * * The offset from the device registers in physical space is defined near the * beginning of this file in constants of the form TCP_xxx_PADDR_OFFSET. * * The offset from the beginning of the SBus physical device space (and thus * the on-board PROMs) is defined in constants of the form * TCP_xxx_sbus_delta_offset. * * The mapping from virtual to physical space is accomplished in cgeightmmap, * and is based on an offset relative to the beginning of the device registers * in virtual address space. The reason the offset is based on the device * registers is that the device registers where passed into map_regs to set up * the virtual space. * * ADDITIONAL DEVICES ON THE SBus TCP Card (w/pip option) * * The SBus TCP Card provides two additional buffers which must be mapped * these are the 8-bit view of the 24-bit true color memory and the video * enable memory. This results in a virtual space which looks like: * * Virtual Space Physical Space * * Physical Offset from * address: device registers * xx000000+------------------+ * | On-board PROMs | * +------------------+ * * xx400000+------------------+00000000 * | Device registers | * +------------------+ * * xx700000+------------------+00000000 * | 8-bit buffer | * Offset presented to cgeightmmap for +------------------+ * mapping * 00000000+------------------+ xx800000+------------------+00400000 * | Monochrome buffer| | True color buffer| * 00020000+------------------+ +------------------+ * | Selection memory | * 00040000+------------------+ xxC00000+------------------+00800000 * | True color memory| | Monochrome buffer| * 00435000+------------------+ +------------------+ * | 8-bit buffer | * 00533000+------------------+ xxD00000+------------------+00900000 * | Video enable mem.| | Selection memory | * 00553000+------------------+ +------------------+ * | Device Registers | * +------------------+ xxE00000+------------------+00A00000 * | Video enable mem.| * +------------------+ */