//------------------------------------------------------------------- // sisaccel.cpp // // This demo illustrates two capabilities of the SiS 315 GPU's // 2D graphics engine: drawing rectangles and linear segments. // (Other manufacturers of SVGA hardware provide such features // using programming interfaces which are roughly similar, but // different in their implementation details.) // // Some supporting software is needed to run this demo: // (1) our Linux device-driver module 'vram.c' // (2) our Linux device-driver module 'engine2d.c' // (3) our 'sisaccel.h' header (from cs686 website) // (4) the 'mode3' utility from the SVGALIB package // // programmer: ALLAN CRUSE // date begun: 02 NOV 2003 // completion: 03 NOV 2003 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for tcgetattr(), tcsetattr() #include // for mmap() #include // for iopl() #include "sisaccel.h" // for map_engine_memory() #define VRAM_BASE_ADDRESS 0xA0000000 #define VGA_MEMORY_LENGTH ( 4 << 20) #define SIS315_CMD_BITBLT 0x00 #define SIS315_CMD_LINE_DRAW 0x04 #define ROP_COPY_SRC_PAT 0xF0 #define SIS315_CTL_CFB_32 0x00020000 unsigned long *vram = (unsigned long*)VRAM_BASE_ADDRESS; const int display_mode = 0x413B, hres = 800, vres = 600; void enable_graphics_engine( void ); void rectangle( int x, int y, int h, int v, int color, u8 rop ); void line(int x0, int y0, int x1, int y1, int c0, int c1, u8 rop); void draw_rectangle( int x, int y, int h, int v, int color ) { int minx = x, miny = y, maxx = h-1, maxy = v-1; do { vram[ y*hres + x ] = color; ++x; } while ( x < maxx ); do { vram[ y*hres + x ] = color; ++y; } while ( y < maxy ); do { vram[ y*hres + x ] = color; --x; } while ( x > minx ); do { vram[ y*hres + x ] = color; --y; } while ( y > miny ); } int main( int argc, char **argv ) { if ( iopl( 3 ) ) { perror( "iopl" ); exit(1); } system( "/sbin/insmod engine2d.o" ); map_engine_memory( MMIO_BASE_ADDRESS, MMIO_MEMORY_RANGE ); system( "/sbin/insmod vram.o" ); map_screen_memory( VRAM_BASE_ADDRESS, VGA_MEMORY_LENGTH ); struct termios otty; tcgetattr( 0, &otty ); struct termios tty = otty; tty.c_lflag &= ~( ICANON | ECHO | ISIG ); tty.c_cc[ VMIN ] = 1; tty.c_cc[ VTIME ] = 0; tcsetattr( 0, TCSAFLUSH, &tty ); char command[ 40 ]; sprintf( command, " clear ; mode3 %d ", display_mode ); system( command ); int white = 0xFFFFFF, purple = 0xFF00FF, rop = 0xF0; int red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF; draw_rectangle( 0, 0, hres, vres, white ); getchar(); enable_graphics_engine(); draw_rectangle( 2, 2, hres-2, vres-2, white ); getchar(); rectangle( hres/4, vres/4, hres/2, vres/2, red, rop ); getchar(); rectangle( 170, 130, 320, 240, purple, rop ); getchar(); line( hres/4, vres/4, 3*hres/4, 3*vres/4, blue, green, rop ); getchar(); system( " mode3 3 " ); tcsetattr( 0, TCSAFLUSH, &otty ); } void enable_graphics_engine( void ) { outw( 0x8605, TSEQ ); // unlock SiS registers outw( 0xA120, TSEQ ); // enable memory-map io outw( 0x401E, TSEQ ); // enable SiS 2D-engine outw( 0xAE08, TSEQ ); // ?? outw( 0x060C, TSEQ ); // ?? outw( 0x0F11, TSEQ ); // disables power-management mode outw( 0x1F27, TSEQ ); // set max cmd-queue threshhold outw( 0x0126, TSEQ ); // synchronous reset *cmd_queue_wr = *cmd_queue_rd; outw( 0x2226, TSEQ ); // enable command-queue and mmio // set the command-queue base-address u32 tqueue_size = (512 << 10); // 512K u32 tqueue_base = ( 32 << 20); // 32MB tqueue_base -= tqueue_size; *queue_origin = tqueue_base; // wait until the command queue is idle int counter = 16; volatile u32 dummy = 0; while (( dummy != 0x80000000 )&&( --counter > 0 )) { dummy = *queue_status; dummy &= 0x80000000; } } void rectangle( int x, int y, int h, int v, int color, u8 rop ) { *agp_baseword = 0xC000; *src_pitchval = hres*4; *dst_pitchval = hres*4; *mergecontrol = ~0; *src_baseaddr = 0; *dst_baseaddr = 0; *src_origin_x = 0; *src_origin_y = 0; *dst_origin_x = x; *dst_origin_y = y; *rect_size_hz = h; *rect_size_vt = v; *pat_fg_color = color; *monomask_reg = ~0LL; // ??? *clip_lft_reg = 0; *clip_top_reg = 0; *clip_rht_reg = ~0; *clip_bot_reg = ~0; u32 command = SIS315_CMD_BITBLT; command |= ( (u32)rop << 8 ); command |= SIS315_CTL_CFB_32; *exec_command = command; *exec_command = command; } void line( int x0, int y0, int x1, int y1, int c0, int c1, u8 rop ) { *agp_baseword = 0xC000; *src_pitchval = hres*4; *dst_pitchval = hres*4; *mergecontrol = ~0; *src_baseaddr = 0; *dst_baseaddr = 0; *line_x0 = x0; *line_y0 = y0; *line_x1 = x1; *line_y1 = y1; *line_style_0 = ~0; *line_style_1 = ~0; *pat_fg_color = c0; *pat_bg_color = c1; *src_fg_color = c0; *src_fg_color = c1; *line_count = 1; *line_style_period = 0; *monomask_reg = ~0LL; // ??? *clip_lft_reg = 0; *clip_top_reg = 0; *clip_rht_reg = ~0; *clip_bot_reg = ~0; u32 command = SIS315_CMD_LINE_DRAW; command |= ( (u32)rop << 8 ); command |= SIS315_CTL_CFB_32; *exec_command = command; *exec_command = command; }