/* * @DEC_COPYRIGHT@ */ /* * HISTORY * $Log: myvga.c,v $ * Revision 1.1.2.2 1997/04/24 20:01:23 Paul_Grist * Initial submit of myvga example to ddk pool * [1997/04/24 19:37:22 Paul_Grist] * * $EndLog$ */ #pragma ident "@(#)$RCSfile: myvga.c,v $ $Revision: 1.1.2.2 $ (DEC) $Date: 1997/04/24 20:01:23 $" /***************************************************************************** * * myvga - Standard VGA graphics device driver * for Digital UNIX V4.0 or greater * * * This driver and its DDX (/usr/shlib/X11/lib_dec_gen.so) should operate * on any VGA-based graphics card because they all minimally support * the standard VGA modes as a subset of their available graphics modes. * * This example driver and its corresponding DDX are written to support * just standard VGA graphics mode (mode 0x12 - 640x480x16) on a VGA-based * graphics controller. This is the maximum resoultion mode of the VGA * standard which all PC graphics cards supply. The VGA standard for PCs only * supplied a single range of resources for graphics, so in this mode only one * graphics controller can be operational in the system or resource conflicts * arise. * * To expand support to this driver and its DDX for enhanced graphics modes * and features the DDX needs to be modified to support the higher resolution * graphics modes and any corresponding changes to the screen, cursor, * and colormap functions for those modes need to be made to the driver. * The DDX contains support for setting graphics modes and all drawing * functionality for X11. It can optionally also handle cursor and colormap * operation directly. * ****************************************************************************/ #include #include /* graphics header files */ #include #include #include #include #include #include /* bus header files */ #include #include #include /* header for this driver with internal information only*/ #include /* header for this driver with external interfaces */ #include /* Only one adapter can be supported using the VGA standard. However, this example shows the framework for multiple SVGA adapters */ #define MAX_MYVGA_CONTROLLERS 4 #define MYVGA_NAME "myvga" struct controller *myvgainfo[MAX_MYVGA_CONTROLLERS]; struct myvga_type *myvga_softc[MAX_MYVGA_CONTROLLERS]; int myvgaprobe(); int myvgaintr(); int myvga_console_attach(); void myvga_do_configuration(); int myvga_fill_softc(struct myvga_type *scp, struct controller *ctlr); caddr_t myvgastd[] = { 0 }; struct driver myvgadriver = { myvgaprobe, 0, 0, 0, 0, myvgastd, 0, 0, MYVGA_NAME, myvgainfo }; /* * macros for I/O register access */ #define IOH_SPARSE_BYTE (HANDLE_BYTE | HANDLE_SPARSE_SPACE) #define IOH_DENSE_BYTE (HANDLE_BYTE | HANDLE_DENSE_SPACE) #define INB(a) READ_BUS_D8((a)+scp->iobase) #define OUTB(a,v) {WRITE_BUS_D8((a)+scp->iobase,(v));mb();} #define OUTW(a,v) {WRITE_BUS_D16((a)+scp->iobase,(v));mb();} /* extern globals */ extern int vga_use_orig_state; /* TRUE is we have been configured */ int myvga_config = FALSE; /* Tells myvgaprobe() if myvga_configure() has failed any setup */ short myvga_failed_config = FALSE; /**************************************************************************** * * Kernel Device-Driver Entrypoints * ****************************************************************************/ /* * Configuration Attribute Table: * The values in these attributes marked CFG_OP_CONFIGURE * can be initialized via sysconfigtab, over-riding the * values initialized here. Attributes with the CFG_OP_QUERY * can be viewed during run-time with 'sysconfig -q'. * Attributes with the CFG_OP_RECONFIGURE can be changed * during run-time with 'sysconfig -r'. */ static int myvga_num_installed = 1; static int myvga_num_probed = 0; static int myvga_intr_enable = 1; static unsigned char mcfgname[40] = MYVGA_NAME; static unsigned char subsys_desc[100] = "myvga example driver"; static unsigned char unused[400] = ""; static int myvga_developer_debug = 1; char myvga_version[] = "1.00"; /* keep track of your version# here */ cfg_subsys_attr_t myvga_attributes[] = { {"Module_Config_Name", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY, (caddr_t)mcfgname,2,80,0}, {"Subsystem_Description", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY, (caddr_t)subsys_desc,2, 80,0}, {"PCI_Option", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE, (caddr_t)unused,2,399,0}, {"ISA_Option", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE, (caddr_t)unused,2,399,0}, {"EISA_Option", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE, (caddr_t)unused,2,399,0}, {"Version",CFG_ATTR_STRTYPE,CFG_OP_QUERY, (caddr_t)myvga_version,0,5,0}, {"Num_Units_Installed", CFG_ATTR_INTTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY, (caddr_t)&myvga_num_installed,0,MAX_MYVGA_CONTROLLERS,0}, {"Num_Units_Probed", CFG_ATTR_INTTYPE, CFG_OP_QUERY, (caddr_t)&myvga_num_probed,0,MAX_MYVGA_CONTROLLERS,0}, {"Interrupt_Enable", CFG_ATTR_INTTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY, (caddr_t)&myvga_intr_enable,0,1,0}, {"MYVGA_Developer_Debug", CFG_ATTR_INTTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY | CFG_OP_RECONFIGURE, (caddr_t)&myvga_developer_debug,0,1,0}, {"", 0, 0, 0, 0, 0, 0} /* must be the last element */ }; /*---------------------------------------------------------- * Check if the attributes passed by cfgmgr are valid. * called by myvga_configure. * return 1 if error *---------------------------------------------------------*/ int myvga_check_attribute(cfg_attr_t *attribute) { if (attribute->type == CFG_ATTR_STRTYPE || attribute->status == CFG_FRAME_SUCCESS) return 0; printf("%s:",attribute->name); switch(attribute->status) { case CFG_ATTR_EEXISTS: printf("Attribute does not exist\n"); break; case CFG_ATTR_EOP: printf("Attribute does not support operation\n"); break; case CFG_ATTR_ESUBSYS: printf("Subsystem failure\n"); break; case CFG_ATTR_ESMALL: printf("Attribute size/value too small\n"); break; case CFG_ATTR_ELARGE: printf("Attribute size/value too large\n"); break; case CFG_ATTR_ETYPE: printf("Attribute invalid type\n"); break; case CFG_ATTR_EINDEX: printf("Attribute invalid index\n"); break; case CFG_ATTR_EMEM: printf("Attribute memory allocation error\n"); default: printf("**Unknown attribute: %x",attribute->status); } return 0; } int myvga_configure(cfg_op_t op, caddr_t indata, ulong indatalen, caddr_t outdata, ulong outdatalen) { int ret = -1; cfg_attr_t *attrptr; int i; if (myvga_developer_debug) printf("myvga_configure: op=%d in=%x[%d], out=%x[%d]\n", op, indata, indatalen, outdata, outdatalen); switch (op) { case CFG_OP_CONFIGURE: if (myvga_developer_debug) printf("myvga: configure entrypoint\n"); /* check attributes */ attrptr = (cfg_attr_t *)indata; for(i=0;ictlr_name,ctlr->bus_hd->bus_name); if (ctlr->ctlr_num > MAX_MYVGA_CONTROLLERS) return 0; /* invalid controller number*/ if(myvga_failed_config == TRUE) return 0; /* allocate memory for softc struct associated with this controller # */ MALLOC(myvga_softc[ctlr->ctlr_num],struct myvga_type *, sizeof(struct myvga_type),M_HWINTR, (M_NOWAIT | M_ZERO)); if (myvga_softc[ctlr->ctlr_num] == (struct myvga_type *)NULL) { printf("myvgaprobe: Unable to MALLOC softc[%d]\n",ctlr->ctlr_num); return 0; } scp = myvga_softc[ctlr->ctlr_num]; /* Point to the controller structure of this controller * so we can use it conveniently */ myvgainfo[ctlr->ctlr_num] = ctlr; /* Initialize common vga console support I/O handles */ VGA_io_base_handle = busphys_to_iohandle(0, BUS_IO, ctlr); VGA_mem_base_handle = busphys_to_iohandle(0, BUS_MEMORY, ctlr); switch(ctlr->bus_hd->bus_type){ case BUS_PCI: /* We do I/O accesses to the generic VGA offsets from the bus address. You can alternatively use the csr address contained in pci_cfg_hdr->bar0 */ scp->iobase = busphys_to_iohandle(0, BUS_IO, ctlr); scp->membase = pci_cfg_hdr->bar1; /* hardwire the video memory, since it is the same * for all standard VGA's */ scp->mem_phys = HIGHMAP_BASE; scp->mem_handle = busphys_to_iohandle(scp->mem_phys, BUS_MEMORY, ctlr); scp->mem_size = 0x20000; /* get and print PCI vendorID and deviceID */ /* sometimes used to validate device. */ if (myvga_developer_debug) { printf("myvga: PCI vendor ID: 0x%x\n", pci_cfg_hdr->vendor_id); printf("myvga: PCI device ID: 0x%x\n", pci_cfg_hdr->device_id); } command_reg = pci_cfg_hdr->command; base_class_code = pci_cfg_hdr->class_code.base; sub_class_code = pci_cfg_hdr->class_code.sub_class; if ((command_reg & CMD_IO_SPACE) && (base_class_code == BASE_DISPLAY) && (sub_class_code == SUB_VGA)) { if (myvga_developer_debug) { printf("myvga: PCI base class code: 0x%x (Display)\n", base_class_code); printf("myvga: PCI sub class code: 0x%x (VGA)\n", sub_class_code); } } else { printf("myvga: PCI class codes not VGA or I/O disabled\n"); printf("myvga: PCI base class code: 0x%x\n", base_class_code); printf("myvga: PCI sub class code: 0x%x\n", sub_class_code); FREE(scp,M_DEVBUF); return(0); /* fail */ } break; case BUS_ISA: case BUS_EISA: scp->iobase = busphys_to_iohandle(0, BUS_IO, ctlr); /* video memory information is to be configured with isacfg or ECU. */ status = get_config(ctlr,RES_MEM,"",&mem_info,0); if (status == -1) { printf("myvgaprobe:Unable to get ISA/EISA memory information\n"); FREE(scp,M_DEVBUF); return 0; } scp->mem_size = mem_info.size; scp->mem_handle = (io_handle_t)mem_info.start_addr; scp->mem_phys = iohandle_to_phys(scp->mem_handle,HANDLE_BUSPHYS_ADDR); if(myvga_developer_debug) printf("myvgaprobe: frame buffer at 0x%lx, %d bytes\n", scp->mem_phys,scp->mem_size); break; default: printf("myvgaprobe: Unsupported bus type: %d\n", ctlr->bus_hd->bus_type); FREE(scp,M_DEVBUF); return 0; } /* * put in some code to identify whenever * a standard VGA controller is present... * * for now, use CURSOR_START and CURSOR_END registers... */ OUTB(MYVGA_CRTC_ADDRESS, 0x0a); start = INB(MYVGA_CRTC_DATA); OUTB(MYVGA_CRTC_ADDRESS, 0x0b); end = INB(MYVGA_CRTC_DATA); OUTB(MYVGA_CRTC_ADDRESS, 0x0a); OUTB(MYVGA_CRTC_DATA, VAL1); OUTB(MYVGA_CRTC_ADDRESS, 0x0b); OUTB(MYVGA_CRTC_DATA, VAL2); OUTB(MYVGA_CRTC_ADDRESS, 0x0a); data1 = INB(MYVGA_CRTC_DATA); OUTB(MYVGA_CRTC_ADDRESS, 0x0b); data2 = INB(MYVGA_CRTC_DATA); OUTB(MYVGA_CRTC_ADDRESS, 0x0a); OUTB(MYVGA_CRTC_DATA, start); OUTB(MYVGA_CRTC_ADDRESS, 0x0b); OUTB(MYVGA_CRTC_DATA, end); if (data1 != VAL1 || data2 != VAL2) { /* failed VGA test */ myvga_softc[ctlr->ctlr_num]->ctlr_type = -1; printf("myvga0: generic vga probe failed\n"); FREE(scp,M_DEVBUF); return(0); } /* Allocate register state data structures */ MALLOC(scp->orig_state, vgaHWRec *, sizeof (vgaHWRec), M_HWINTR, (M_NOWAIT | M_ZERO)); if (!scp->orig_state) { printf("myvgaprobe: failed malloc of register structs\n"); FREE(scp,M_DEVBUF); return(0); } MALLOC(scp->new_state, vgaHWRec *, sizeof (vgaHWRec), M_HWINTR, (M_NOWAIT | M_ZERO)); if (!scp->new_state) { printf("myvgaprobe: failed malloc of register structs\n"); FREE(scp,M_DEVBUF); return(0); } myvga_fill_softc(scp,ctlr); /* Initialize function handles */ scp->sf.screen_handle = (*(scp->sf.init_screen_handle)) ((caddr_t)myvga_softc,ctlr->physaddr,ctlr->ctlr_num,0); scp->cf.cursor_handle = (*(scp->cf.init_cursor_handle)) ((caddr_t)myvga_softc, ctlr->physaddr, ctlr->ctlr_num, 0); scp->cmf.colormap_handle = (*(scp->cmf.init_colormap_handle)) ((caddr_t)myvga_softc,ctlr->physaddr,ctlr->ctlr_num,0); status = ws_register_screen(&scp->screen, scp->visual, scp->depth, &scp->sf, &scp->cmf, &scp->cf, ctlr); if (status == -1) { printf("myvga driver: could not register screen\n"); FREE(scp,M_DEVBUF); return 0; } /* set the global display type for sizer */ if (ws_display_units < 8) { ws_display_type = (ws_display_type << 8) | WS_DTYPE; ws_display_units = (ws_display_units << 1) | 1; } /* Initialize console_attach entrypoint */ ctlr->console_attach = (caddr_t)myvga_console_attach; if (myvga_intr_enable) { /* setup information to register interrupt handler */ handler.ih_bus = ctlr->bus_hd; handler_info.configuration_st = (caddr_t)ctlr; handler_info.config_type = CONTROLLER_CONFIG_TYPE; handler_info.intr = myvgaintr; handler_info.param = (caddr_t)ctlr->ctlr_num; handler.ih_bus_info = (char *)&handler_info; /* try to register interrupt handler, keeping the handle in the softc structure. We need this handle to remove the handler. */ scp->intr_handle = handler_add(&handler); if (scp->intr_handle == NULL) { if (myvga_developer_debug) printf("myvgaprobe: could not add interrupt handler\n"); FREE(scp,M_DEVBUF); return 0; } if (handler_enable(scp->intr_handle) != 0) { if (myvga_developer_debug) printf("myvgaprobe: could not enable interrupt handler\n"); handler_del(scp->intr_handle); FREE(scp,M_DEVBUF); return 0; } } /* * Print clear Indication of graphics option being attached. * This may be very important for identifying the exact option * (revision, variant, video memory) for problem reports. */ printf(" %dx%d %s\n", scp->screen.width, scp->screen.height, scp->screen.moduleID); printf("%s%d: MYVGA example driver - version %s\n", ctlr->ctlr_name, ctlr->ctlr_num, myvga_version); if (myvga_developer_debug) printf("myvgaprobe: successful\n"); /* keep track of the # of myvga controllers probed */ myvga_num_probed++; return(1); /* success */ } int myvga_fill_softc(register struct myvga_type *scp, struct controller *ctlr) { int m_type = ctlr->flags; ws_monitor tmp_monitor_type = MONITOR_VRC16; scp->unit = ctlr->ctlr_num; /* initialize screen structure */ scp->screen.screen = ctlr->ctlr_num; scp->screen.monitor_type = tmp_monitor_type; strcpy(scp->screen.moduleID,"VGA "); scp->screen.width = 640; scp->screen.height = 480; scp->screen.root_depth = 0; scp->screen.allowed_depths = 1; scp->screen.nvisuals = 1; scp->screen.x = 0; scp->screen.y = 0; scp->screen.row = 0; scp->screen.col =0; scp->screen.max_row = 24; scp->screen.max_col = 80; scp->screen.f_width = 8; scp->screen.f_height = 16; scp->screen.cursor_width = 32; scp->screen.cursor_height = 32; scp->screen.min_installed_maps = 1; scp->screen.max_installed_maps = 1; /* * default to monitor type in screen structure unless flags set */ if (ctlr->flags != 0) { if ((m_type < 0) || (m_type >= nmon_types)) m_type = 0; scp->screen.monitor_type = monitor_type[m_type]; } /* init depth structures */ scp->depth[0].screen = 0; scp->depth[0].which_depth = 0; scp->depth[0].fb_width = 640; scp->depth[0].fb_height = 480; scp->depth[0].depth = 8; scp->depth[0].bits_per_pixel = 8; scp->depth[0].scanline_pad = 32; scp->depth[0].physaddr = 0; scp->depth[0].pixmap = 0; scp->depth[0].plane_mask_phys = 0; scp->depth[0].plane_mask = 0; /* set visual structures */ scp->visual[0].screen = 0; scp->visual[0].which_visual = 0; scp->visual[0].screen_class = PseudoColor; scp->visual[0].depth = 8; scp->visual[0].red_mask = 0; /* masks are 0 for pseudo color */ scp->visual[0].green_mask = 0; scp->visual[0].blue_mask = 0; scp->visual[0].bits_per_rgb = 8; scp->visual[0].color_map_entries = 256; /* set cursor functions */ scp->cf.init_cursor_handle = myvga_init_cursor_handle; scp->cf.load_cursor = myvga_load_cursor; scp->cf.recolor_cursor = myvga_recolor_cursor; scp->cf.set_cursor_position = myvga_set_cursor_position; scp->cf.cursor_on_off = myvga_cursor_on_off; scp->cf.cursor_private = NULL; /* set color_map functions*/ scp->cmf.init_colormap_handle = myvga_init_color_map_handle; scp->cmf.init_color_map = myvga_init_color_map; scp->cmf.load_color_map_entry = myvga_load_color_map_entry_6bit; scp->cmf.clean_color_map = myvga_clean_color_map; scp->cmf.video_on = myvga_video_on; scp->cmf.video_off = myvga_video_off; scp->cmf.cmap_private = NULL; /* set screen functions */ scp->sf.init_screen_handle = myvga_init_screen_handle; scp->sf.init_screen = myvga_init_screen; scp->sf.clear_screen = myvga_clear_screen; scp->sf.scroll_screen = myvga_scroll_screen; scp->sf.blitc = myvga_blitc; scp->sf.map_unmap_screen = myvga_map_unmap_screen; scp->sf.ioctl = myvga_ioctl; scp->sf.close = myvga_close; scp->sf.set_get_power_level = NULL; scp->sf.screen_private = NULL; scp->sf.screen_private2 = NULL; } /************************************************************************** * * myvga_console_attach * * Driver entrypoint to attach this controller as the kernel console * driver. * * - Set board to operate in console mode * - call common VGA console support * **************************************************************************/ int myvga_console_attach(struct controller *ctlr) { int status = -1; /* Failure */ if (myvga_developer_debug) printf("MYVGA_console_attach entrypoint\n"); /* * use standard VGA console support. * set global to indicate use of * current board VGA register state * to be used for setting text mode 3. * The default is to re-initialize the * board/VGA to text-book VGA mode 3 settings * */ vga_use_orig_state = 1; status = install_vga_console(ctlr); if (status == -1) { printf("myvga: could not install vga console support\n"); } return(status); } int myvga_enable_interrupt(struct myvga_type *scp) { int data, s; if (!myvga_intr_enable) return; /* * Use standard VGA code */ s = splbio(); OUTB(MYVGA_CRTC_ADDRESS, 0x11); data = INB(MYVGA_CRTC_DATA); /* clear disable bit, and set Normal */ OUTB(MYVGA_CRTC_ADDRESS, 0x11); OUTB(MYVGA_CRTC_DATA, (data | 0x10) & ~0x20); splx(s); } void myvga_disable_interrupt(struct myvga_type *scp) { int data; if (myvga_developer_debug) printf("myvga_disable_interrupt: entry\n"); /* * Use standard VGA code */ OUTB(MYVGA_CRTC_ADDRESS, 0x11); data = INB(MYVGA_CRTC_DATA); /* set disable/normal bits */ OUTB(MYVGA_CRTC_ADDRESS, 0x11); OUTB(MYVGA_CRTC_DATA, data | 0x30); } void myvga_clear_interrupt(struct myvga_type *scp) { int data; if (myvga_developer_debug) printf("myvga_clear_interrupt: entry\n"); /* * Use standard VGA code */ OUTB(MYVGA_CRTC_ADDRESS, 0x11); data = INB(MYVGA_CRTC_DATA); OUTB(MYVGA_CRTC_ADDRESS, 0x11); OUTB(MYVGA_CRTC_DATA, data & ~0x10); /* clear */ OUTB(MYVGA_CRTC_ADDRESS, 0x11); OUTB(MYVGA_CRTC_DATA, data | 0x10); /* normal */ } /* * Interrupt service routine */ int myvgaintr(int unit) { register struct myvga_type *scp = myvga_softc[unit]; register struct controller *ctlr = myvgainfo[unit]; myvga_clear_interrupt(scp); #if MYVGA_DRIVER_DOES_CURSOR /* * generic MYVGA driver has no hardware cursor in graphics mode, * its done by the DDX */ if (IS_MYVGA_DIRTY_CURSOR(scp)) CLR_MYVGA_DIRTY_CURSOR(scp); #endif /*MYVGA_DRIVER_DOES_CURSOR */ if (IS_MYVGA_DIRTY_CMAP(scp)) myvga_clean_color_map((char *)scp); /* if the user changed the enable flag during run-time * disable the interrupt */ if (!myvga_intr_enable) myvga_disable_interrupt(scp); } /************************************************************************/ /* */ /* SCREEN FUNCTIONS */ /* */ /************************************************************************/ /* * Init Handle Function * * Initializes driver-specific pointer which is passed by * WS on calls to screen functions * */ caddr_t myvga_init_screen_handle (caddr_t screen_handle,caddr_t address, int unit,int type) { register struct myvga_type *scp = ((struct myvga_type **)screen_handle)[unit]; register int i; scp->unit = unit; if (myvga_developer_debug) printf("myvga_init_screen_handle: screen=%d entry\n", scp->screen.screen); /* * Do some 1-time initialization */ for (i = 0; i < scp->screen.allowed_depths; i++) { scp->depth[i].physaddr = (caddr_t) scp->mem_phys; scp->depth[i].plane_mask_phys = (caddr_t) IOREGS_BASE; } return (caddr_t) scp; } /* * Init_Screen function * * Graphics screen init_screen function called to cleanly initialize * the graphics board for graphics operation by the X server. * */ myvga_init_screen(caddr_t screen_handle, ws_screen_descriptor *screen) { register struct myvga_type *scp = (struct myvga_type *)screen_handle; register ws_screen_descriptor *sp = &scp->screen; if (myvga_developer_debug) printf("myvga_init_screen: entry\n"); /* * save and restore the standard VGA registers * to ensure they get set-up, particularly for * the case we are in serial console and the * X server is started */ /* * save the MYVGA register contents left behind by the console */ VGA_save_registers(scp->orig_state); /* * Re-set the registers to text-book text mode 3 values */ VGA_restore_registers(scp->new_state); return 0; } /* * stub routines for console functions. This driver * uses the standard myvga console support, so these * are not needed. */ int myvga_clear_screen(caddr_t screen_handle,ws_screen_descriptor *screen) { return; } int myvga_scroll_screen(caddr_t screen_handle, ws_screen_descriptor *screen) { return; } int myvga_blitc(caddr_t screen_handle, register ws_screen_descriptor *sp, register int row, register int col, register int ch) { return; } /* * Map/Unmap Screen function * * Called via wsioctl to map the VGA frame buffer * and I/O registers for direct use by the DDX */ int myvga_map_unmap_screen(caddr_t screen_handle, ws_depth_descriptor *depths, ws_screen_descriptor *screen, ws_map_control *mp) { register struct myvga_type *scp = (struct myvga_type *)screen_handle; register ws_depth_descriptor *dp; io_handle_t handle; caddr_t temp; int nbytes; register struct controller *ctlr = myvgainfo[scp->unit]; if (myvga_developer_debug) printf("myvga_map_unmap_screen: entry\n"); /* unmap not yet (if ever) implemented) */ if (mp->map_unmap == UNMAP_SCREEN) return (EINVAL); /* * only do the mapping the first time for each; otherwise, assume * the info is available and will be returned... */ if ((IS_MYVGA_MAPPED(scp)) && (scp->mapped_pid == u.u_procp->p_pid)) { return(0); } dp = depths + mp->which_depth; /* MAPPING NOTE: * * The frame buffer address (mem_phys) is "handled" * using bytes; this is so that no low-order bits are present * in the swizzled address that (eventually) gets passed into * "ws_map_region" and thence into the VM subsystem */ handle = scp->mem_handle; temp = (caddr_t) iohandle_to_phys(handle, IOH_SPARSE_BYTE); temp = (caddr_t) PHYS_TO_KSEG(temp); /* * swizzle the size of the frame buffer, to get the address space * size which is appropriate for the machine we are running on */ nbytes = iohandle_to_phys(handle + HIGHMAP_SIZE, IOH_SPARSE_BYTE) - iohandle_to_phys(handle + 0, IOH_SPARSE_BYTE); dp->pixmap = ws_map_region(temp, NULL, nbytes, 0600, (int *)NULL); if (myvga_developer_debug) printf("myvga_map_unmap_screen: fb: nbytes 0x%x handle 0x%lx kseg 0x%lx virt 0x%lx\n", nbytes, handle, temp, dp->pixmap); if (dp->pixmap == (caddr_t) NULL) return(ENOMEM); /* * register set is IOREGS_SIZE of IO space; swizzle as appropriate for * the machine we are running on */ /* For now, map the entire register space... :-( */ handle = busphys_to_iohandle(IOREGS_BASE, BUS_IO, ctlr); temp = (caddr_t) iohandle_to_phys(handle, IOH_SPARSE_BYTE); temp = (caddr_t) PHYS_TO_KSEG(temp); nbytes = iohandle_to_phys(handle + IOREGS_SIZE, IOH_SPARSE_BYTE) - iohandle_to_phys(handle + 0, IOH_SPARSE_BYTE); dp->plane_mask = ws_map_region(temp, NULL, nbytes, 0600, (int *)NULL); if (myvga_developer_debug) printf("myvga_map_unmap_screen: regs: nbytes 0x%x handle 0x%lx kseg 0x%lx virt 0x%lx\n", nbytes, handle, temp, dp->plane_mask); if (dp->plane_mask == (caddr_t)NULL) return(ENOMEM); SET_MYVGA_MAPPED(scp); scp->mapped_pid = u.u_procp->p_pid; return (0); } int myvga_ioctl(caddr_t screen_handle, int request, caddr_t data) { int i,j; int status = 0; struct myvga_ioc_type *ioctp = (struct myvga_ioc_type *)data; if (myvga_developer_debug) printf("myvga_ioctl:\n"); switch(request) { case MYVGA_IOC_FLASH: if (myvga_developer_debug) printf("\tMYVGA_IOC_FLASH\n"); myvga_video_off(screen_handle); DELAY(10000); myvga_video_on(screen_handle); break; default: if (myvga_developer_debug) printf("\tUnsupported ioctl command\n"); break; } return status; } /* * Close * * Called when the X server closes, or the system panics, * to put the board back into a state where the VGA common * console driver can resume operation. * * Nothing to do in close because vga_console will handle * restoring text mode. Nothing special needed to set-up * hardware to transition from graphics mode to text modes * on a completely standard VGA * * NOTE: If for some reason, close or a particular function is * needed to re-set the board for halt-button operation * (typcially used to force crashdumps on system hangs), * the drvr_register_saveterm interface must be used. * This is common on designs involving a separate VGA * chip only used for console operation * */ void myvga_close(caddr_t screen_handle) { register struct myvga_type *scp = (struct myvga_type *)screen_handle; if (myvga_developer_debug) printf("myvga_close: entry\n"); } /************************************************************************/ /* */ /* CURSOR FUNCTIONS */ /* */ /************************************************************************/ caddr_t myvga_init_cursor_handle(caddr_t cursor_handle, caddr_t address, int unit, int type) { struct myvga_type *scp = ((struct myvga_type **)cursor_handle)[unit]; if (myvga_developer_debug) printf("myvga_cursor_init_cursor_handle: entry\n"); return (caddr_t)scp ; } int myvga_load_cursor(caddr_t cursor_handle, ws_screen_descriptor *screen, ws_cursor_data *cursor) { register struct myvga_type *scp = (struct myvga_type *)cursor_handle; scp->x_hot = cursor->x_hot; scp->y_hot = cursor->y_hot; if (myvga_developer_debug) printf("myvga_load_cursor: entry: screen=%d hot (%d,%d)\n", scp->screen.screen, scp->x_hot, scp->y_hot); myvga_set_cursor_position(cursor_handle, screen, screen->x, screen->y); return(0); } int myvga_recolor_cursor(caddr_t cursor_handle, ws_screen_descriptor *screen, ws_color_cell *fg, ws_color_cell *bg) { if (myvga_developer_debug) printf("myvga_recolor_cursor: entry\n"); return(0); } int myvga_cursor_on_off(caddr_t cursor_handle, int on_off) { if (myvga_developer_debug) printf("myvga_cursor_on_off: entry\n"); return(0); } /* * this is a stubs because console * support comes from vga_support.c */ int myvga_set_cursor_position(caddr_t cursor_handle, ws_screen_descriptor *sp, register int x, register int y) { return(0); } /************************************************************************/ /* */ /* COLOR MAP FUNCTIONS */ /* */ /************************************************************************/ caddr_t myvga_init_color_map_handle (caddr_t colormap_handle, caddr_t address, int unit, int type) { struct myvga_type *scp = ((struct myvga_type **)colormap_handle)[unit]; if (myvga_developer_debug) printf("myvga_color_map_init_colormap_handle: entry\n"); return (caddr_t)scp ; } int myvga_init_color_map(caddr_t colormap_handle) { register struct myvga_type *scp = (struct myvga_type *)colormap_handle; register unsigned char *cp = &((vgaHWPtr)scp->new_state)->DAC[0]; register int i; if (myvga_developer_debug) printf("myvga_init_color_map: entry\n"); /* NOTE: using 8-bit values */ OUTB(MYVGA_PEL_MASK, 0xff); OUTB(MYVGA_PEL_ADDR_WMODE, 0); for (i = 0; i < 768; i++) OUTB(MYVGA_PEL_DATA, *cp++); return(0); } /* * Real entry point for "generic" MYVGA driver, assumes 6-bit DAC */ int myvga_load_color_map_entry_6bit(caddr_t colormap_handle, int map, /* not used; only single map in this device */ register ws_color_cell *entry) { struct myvga_type *scp = (struct myvga_type *)colormap_handle; int shift = 10; register int index = entry->index; register unsigned int mask = 0x0000ffff >> shift; int s; if (myvga_developer_debug) printf("myvga_load_color_map_entry_6bit: entry 0x%x = (0x%x, 0x%x, 0x%x)\n", entry->index, entry->red, entry->green, entry->blue); SET_MYVGA_6BIT_DAC(scp); /* update CLUT database with 6-bit DAC values */ if (index >= 256 || index < 0) return(-1); s = splbio(); scp->cells[index].red = (entry->red >> shift) & mask; scp->cells[index].green = (entry->green >> shift) & mask; scp->cells[index].blue = (entry->blue >> shift) & mask; scp->cells[index].dirty_cell = 1; if (index < scp->min_dirty) scp->min_dirty = index; if (index > scp->max_dirty) scp->max_dirty = index; splx(s); /* * this enables a VBLANK intr to load dirty color cells. * if VBLANK intr's aren't being used, do it now... */ if (!IS_MYVGA_DIRTY_CMAP(scp)) { SET_MYVGA_DIRTY_CMAP(scp); if (!myvga_enable_interrupt(scp)) myvga_clean_color_map(colormap_handle); } return (0); } void myvga_clean_color_map(caddr_t colormap_handle) { register struct myvga_type *scp = (struct myvga_type *)colormap_handle; register struct myvga_color_cell *entry; register int i, s, lasti; if (myvga_developer_debug) printf("myvga_clean_color_map: entry\n"); if (!IS_MYVGA_DIRTY_CMAP(scp)) return; /* * no interrupts when we're using autoinc mode of VDAC */ s = splbio(); /* * change the "dirty" entries... */ entry = &scp->cells[scp->min_dirty]; lasti = -2; for (i = scp->min_dirty; i <= scp->max_dirty ; i++, entry++) { if (entry->dirty_cell) { if (i != (lasti + 1)) OUTB(MYVGA_PEL_ADDR_WMODE, i); OUTB(MYVGA_PEL_DATA, entry->red); OUTB(MYVGA_PEL_DATA, entry->green); OUTB(MYVGA_PEL_DATA, entry->blue); entry->dirty_cell = 0; lasti = i; } } /* * reset to "clean" status */ scp->min_dirty = 256; scp->max_dirty = 0; CLR_MYVGA_DIRTY_CMAP(scp); splx(s); } /* * Video On/Off * * Used by screen-saver via wsioctl * to turn screen on and off. * * NOTE: this is not used by DPMS * power-management, DPMS uses * the get_set_power_level screen * function. */ int myvga_video_on(caddr_t colormap_handle) { register struct myvga_type *scp = (struct myvga_type *)colormap_handle; unsigned char state; OUTB(MYVGA_SEQ_ADDRESS, 0x01); state = INB(MYVGA_SEQ_DATA); state &= 0xDF; /* * turn on video in Clocking Mode register */ OUTB(MYVGA_SEQ_ADDRESS, 0x01); OUTB(MYVGA_SEQ_DATA, state); /* change mode */ return(0); } int myvga_video_off(caddr_t colormap_handle) { register struct myvga_type *scp = (struct myvga_type *)colormap_handle; unsigned char state; OUTB(MYVGA_SEQ_ADDRESS, 0x01); state = INB(MYVGA_SEQ_DATA); state |= 0x20; /* * turn off video in Clocking Mode register */ OUTB(MYVGA_SEQ_ADDRESS, 0x01); OUTB(MYVGA_SEQ_DATA, state); /* change mode */ return(0); }